[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.14

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