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: }