[BACK]Return to edit.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sdiff

Annotation of src/usr.bin/sdiff/edit.c, Revision 1.12

1.12    ! otto        1: /*     $OpenBSD: edit.c,v 1.11 2006/02/15 06:58:06 otto Exp $ */
1.1       tedu        2:
                      3: /*
                      4:  * Written by Raymond Lai <ray@cyth.net>.
                      5:  * Public domain.
                      6:  */
                      7:
                      8: #include <sys/types.h>
                      9: #include <sys/wait.h>
                     10:
                     11: #include <ctype.h>
                     12: #include <err.h>
                     13: #include <stdio.h>
                     14: #include <stdlib.h>
                     15: #include <unistd.h>
                     16:
1.12    ! otto       17: #include "common.h"
1.1       tedu       18: #include "extern.h"
                     19:
                     20: static void edit(const char *);
                     21:
                     22: /*
                     23:  * Takes the name of a file and opens it with an editor.
                     24:  */
                     25: static void
                     26: edit(const char *filename)
                     27: {
                     28:        int status;
                     29:        pid_t pid;
                     30:        const char *editor;
                     31:
                     32:        editor = getenv("VISUAL");
                     33:        if (editor == NULL)
                     34:                editor = getenv("EDITOR");
                     35:        if (editor == NULL)
                     36:                editor = "vi";
                     37:
                     38:        /* Start editor on temporary file. */
                     39:        switch (pid = fork()) {
                     40:        case 0:
                     41:                /* child */
                     42:                execlp(editor, editor, filename, (void *)NULL);
                     43:                warn("could not execute editor: %s", editor);
                     44:                cleanup(filename);
                     45:                /* NOTREACHED */
                     46:        case -1:
                     47:                warn("could not fork");
                     48:                cleanup(filename);
                     49:                /* NOTREACHED */
                     50:        }
                     51:
                     52:        /* parent */
                     53:        /* Wait for editor to exit. */
                     54:        if (waitpid(pid, &status, 0) == -1) {
                     55:                warn("waitpid");
                     56:                cleanup(filename);
                     57:                /* NOTREACHED */
                     58:        }
                     59:
                     60:        /* Check that editor terminated normally. */
                     61:        if (!WIFEXITED(status)) {
                     62:                warn("%s terminated abnormally", editor);
                     63:                cleanup(filename);
                     64:                /* NOTREACHED */
                     65:        }
                     66: }
                     67:
                     68: /*
                     69:  * Parse edit command.  Returns 0 on success, -1 on error.
                     70:  */
                     71: int
                     72: eparse(const char *cmd, const char *left, const char *right)
                     73: {
                     74:        FILE *file;
                     75:        size_t nread, nwritten;
1.11      otto       76:        char *filename;
1.1       tedu       77:        char buf[BUFSIZ], *text;
                     78:
                     79:        /* Skip whitespace. */
                     80:        while (isspace(*cmd))
                     81:                ++cmd;
                     82:
                     83:        text = NULL;
                     84:        switch (*cmd) {
                     85:        case '\0':
                     86:                /* Edit empty file. */
                     87:                break;
                     88:
                     89:        case 'b':
                     90:                /* Both strings. */
                     91:                if (left == NULL)
                     92:                        goto RIGHT;
1.9       deraadt    93:                if (right == NULL)
1.1       tedu       94:                        goto LEFT;
                     95:
                     96:                /* Neither column is blank, so print both. */
1.10      claudio    97:                if (asprintf(&text, "%s\n%s\n", left, right) == -1)
1.1       tedu       98:                        err(2, "could not allocate memory");
                     99:                break;
                    100:
1.8       deraadt   101:        case 'l':
1.1       tedu      102: LEFT:
                    103:                /* Skip if there is no left column. */
                    104:                if (left == NULL)
                    105:                        break;
                    106:
                    107:                if (asprintf(&text, "%s\n", left) == -1)
                    108:                        err(2, "could not allocate memory");
                    109:
                    110:                break;
                    111:
1.8       deraadt   112:        case 'r':
1.1       tedu      113: RIGHT:
                    114:                /* Skip if there is no right column. */
                    115:                if (right == NULL)
                    116:                        break;
                    117:
                    118:                if (asprintf(&text, "%s\n", right) == -1)
                    119:                        err(2, "could not allocate memory");
                    120:
                    121:                break;
                    122:
                    123:        default:
                    124:                return (-1);
                    125:        }
                    126:
                    127:        /* Create temp file. */
                    128:        filename = xmktemp(text);
                    129:
                    130:        /* text is no longer used. */
                    131:        free(text);
                    132:
                    133:        /* Edit temp file. */
                    134:        edit(filename);
                    135:
                    136:        /* Open temporary file. */
                    137:        if (!(file = fopen(filename, "r"))) {
                    138:                warn("could not open edited file: %s", filename);
                    139:                cleanup(filename);
                    140:                /* NOTREACHED */
                    141:        }
                    142:
                    143:        /* Copy temporary file contents to output file. */
                    144:        for (nread = sizeof(buf); nread == sizeof(buf);) {
                    145:                nread = fread(buf, sizeof(*buf), sizeof(buf), file);
                    146:                /* Test for error or end of file. */
                    147:                if (nread != sizeof(buf) &&
                    148:                    (ferror(file) || !feof(file))) {
                    149:                        warnx("error reading edited file: %s", filename);
                    150:                        cleanup(filename);
                    151:                        /* NOTREACHED */
                    152:                }
                    153:
                    154:                /*
                    155:                 * If we have nothing to read, break out of loop
                    156:                 * instead of writing nothing.
                    157:                 */
                    158:                if (!nread)
                    159:                        break;
                    160:
                    161:                /* Write data we just read. */
                    162:                nwritten = fwrite(buf, sizeof(*buf), nread, outfile);
                    163:                if (nwritten != nread) {
                    164:                        warnx("error writing to output file");
                    165:                        cleanup(filename);
                    166:                        /* NOTREACHED */
                    167:                }
                    168:        }
                    169:
                    170:        /* We've reached the end of the temporary file, so remove it. */
                    171:        if (unlink(filename))
                    172:                warn("could not delete: %s", filename);
1.5       tedu      173:        fclose(file);
1.1       tedu      174:
                    175:        /* filename was malloc()ed in xmktemp(). */
1.11      otto      176:        free(filename);
1.1       tedu      177:
                    178:        return (0);
                    179: }