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

1.17    ! ray         1: /*     $OpenBSD: edit.c,v 1.16 2007/04/25 05:02:17 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>
1.16      ray        13: #include <errno.h>
                     14: #include <paths.h>
                     15: #include <signal.h>
1.1       tedu       16: #include <stdio.h>
                     17: #include <stdlib.h>
1.14      ray        18: #include <string.h>
1.1       tedu       19: #include <unistd.h>
                     20:
1.12      otto       21: #include "common.h"
1.1       tedu       22: #include "extern.h"
                     23:
1.16      ray        24: int editit(const char *);
1.1       tedu       25:
                     26: /*
1.17    ! ray        27:  * Execute an editor on the specified pathname, which is interpreted
        !            28:  * from the shell.  This means flags may be included.
        !            29:  *
        !            30:  * Returns -1 on error, or the exit value on success.
1.1       tedu       31:  */
1.16      ray        32: int
                     33: editit(const char *pathname)
1.1       tedu       34: {
1.16      ray        35:        char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p;
                     36:        sig_t sighup, sigint, sigquit;
1.1       tedu       37:        pid_t pid;
1.17    ! ray        38:        int saved_errno, st;
1.16      ray        39:
                     40:        ed = getenv("VISUAL");
                     41:        if (ed == NULL || ed[0] == '\0')
                     42:                ed = getenv("EDITOR");
                     43:        if (ed == NULL || ed[0] == '\0')
                     44:                ed = _PATH_VI;
                     45:        if (asprintf(&p, "%s %s", ed, pathname) == -1)
                     46:                return (-1);
                     47:        argp[2] = p;
1.1       tedu       48:
1.16      ray        49:        sighup = signal(SIGHUP, SIG_IGN);
                     50:        sigint = signal(SIGINT, SIG_IGN);
                     51:        sigquit = signal(SIGQUIT, SIG_IGN);
1.17    ! ray        52:        if ((pid = fork()) == -1)
        !            53:                goto fail;
1.16      ray        54:        if (pid == 0) {
                     55:                execv(_PATH_BSHELL, argp);
                     56:                _exit(127);
1.1       tedu       57:        }
1.17    ! ray        58:        while (waitpid(pid, &st, 0) == -1)
        !            59:                if (errno != EINTR)
        !            60:                        goto fail;
1.16      ray        61:        free(p);
                     62:        (void)signal(SIGHUP, sighup);
                     63:        (void)signal(SIGINT, sigint);
                     64:        (void)signal(SIGQUIT, sigquit);
1.17    ! ray        65:        if (!WIFEXITED(st)) {
        !            66:                errno = EINTR;
1.16      ray        67:                return (-1);
1.1       tedu       68:        }
1.17    ! ray        69:        return (WEXITSTATUS(st));
        !            70:
        !            71:  fail:
        !            72:        saved_errno = errno;
        !            73:        (void)signal(SIGHUP, sighup);
        !            74:        (void)signal(SIGINT, sigint);
        !            75:        (void)signal(SIGQUIT, sigquit);
        !            76:        free(p);
        !            77:        errno = saved_errno;
        !            78:        return (-1);
1.1       tedu       79: }
                     80:
                     81: /*
                     82:  * Parse edit command.  Returns 0 on success, -1 on error.
                     83:  */
                     84: int
                     85: eparse(const char *cmd, const char *left, const char *right)
                     86: {
                     87:        FILE *file;
1.15      steven     88:        size_t nread;
1.14      ray        89:        int fd;
1.11      otto       90:        char *filename;
1.1       tedu       91:        char buf[BUFSIZ], *text;
                     92:
                     93:        /* Skip whitespace. */
                     94:        while (isspace(*cmd))
                     95:                ++cmd;
                     96:
                     97:        text = NULL;
                     98:        switch (*cmd) {
                     99:        case '\0':
                    100:                /* Edit empty file. */
                    101:                break;
                    102:
                    103:        case 'b':
                    104:                /* Both strings. */
                    105:                if (left == NULL)
                    106:                        goto RIGHT;
1.9       deraadt   107:                if (right == NULL)
1.1       tedu      108:                        goto LEFT;
                    109:
                    110:                /* Neither column is blank, so print both. */
1.10      claudio   111:                if (asprintf(&text, "%s\n%s\n", left, right) == -1)
1.1       tedu      112:                        err(2, "could not allocate memory");
                    113:                break;
                    114:
1.8       deraadt   115:        case 'l':
1.1       tedu      116: LEFT:
                    117:                /* Skip if there is no left column. */
                    118:                if (left == NULL)
                    119:                        break;
                    120:
                    121:                if (asprintf(&text, "%s\n", left) == -1)
                    122:                        err(2, "could not allocate memory");
                    123:
                    124:                break;
                    125:
1.8       deraadt   126:        case 'r':
1.1       tedu      127: RIGHT:
                    128:                /* Skip if there is no right column. */
                    129:                if (right == NULL)
                    130:                        break;
                    131:
                    132:                if (asprintf(&text, "%s\n", right) == -1)
                    133:                        err(2, "could not allocate memory");
                    134:
                    135:                break;
                    136:
                    137:        default:
                    138:                return (-1);
                    139:        }
                    140:
                    141:        /* Create temp file. */
1.14      ray       142:        if (asprintf(&filename, "%s/sdiff.XXXXXXXXXX", tmpdir) == -1)
                    143:                err(2, "asprintf");
                    144:        if ((fd = mkstemp(filename)) == -1)
                    145:                err(2, "mkstemp");
                    146:        if (text != NULL) {
                    147:                size_t len;
1.15      steven    148:                ssize_t nwritten;
1.14      ray       149:
                    150:                len = strlen(text);
                    151:                if ((nwritten = write(fd, text, len)) == -1 ||
                    152:                    nwritten != len) {
                    153:                        warn("error writing to temp file");
                    154:                        cleanup(filename);
                    155:                }
                    156:        }
                    157:        close(fd);
1.1       tedu      158:
                    159:        /* text is no longer used. */
                    160:        free(text);
                    161:
                    162:        /* Edit temp file. */
1.16      ray       163:        if (editit(filename) == -1) {
1.17    ! ray       164:                warn("error editing %s", filename);
1.16      ray       165:                cleanup(filename);
                    166:        }
1.1       tedu      167:
                    168:        /* Open temporary file. */
                    169:        if (!(file = fopen(filename, "r"))) {
                    170:                warn("could not open edited file: %s", filename);
                    171:                cleanup(filename);
                    172:        }
                    173:
                    174:        /* Copy temporary file contents to output file. */
                    175:        for (nread = sizeof(buf); nread == sizeof(buf);) {
1.15      steven    176:                size_t nwritten;
                    177:
1.1       tedu      178:                nread = fread(buf, sizeof(*buf), sizeof(buf), file);
                    179:                /* Test for error or end of file. */
                    180:                if (nread != sizeof(buf) &&
                    181:                    (ferror(file) || !feof(file))) {
                    182:                        warnx("error reading edited file: %s", filename);
                    183:                        cleanup(filename);
                    184:                }
                    185:
                    186:                /*
                    187:                 * If we have nothing to read, break out of loop
                    188:                 * instead of writing nothing.
                    189:                 */
                    190:                if (!nread)
                    191:                        break;
                    192:
                    193:                /* Write data we just read. */
                    194:                nwritten = fwrite(buf, sizeof(*buf), nread, outfile);
                    195:                if (nwritten != nread) {
                    196:                        warnx("error writing to output file");
                    197:                        cleanup(filename);
                    198:                }
                    199:        }
                    200:
                    201:        /* We've reached the end of the temporary file, so remove it. */
                    202:        if (unlink(filename))
                    203:                warn("could not delete: %s", filename);
1.5       tedu      204:        fclose(file);
1.1       tedu      205:
1.11      otto      206:        free(filename);
1.1       tedu      207:
                    208:        return (0);
                    209: }