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