Sync usage with man page.
[netbsd-mini2440.git] / usr.bin / sdiff / edit.c
blob840c5fcb8c21f443b3b65176f6f3486c0295f73d
1 /* $NetBSD: edit.c,v 1.1 2007/02/18 22:13:42 rmind Exp $ */
2 /* $OpenBSD: edit.c,v 1.14 2006/05/25 03:20:32 ray Exp $ */
4 /*
5 * Written by Raymond Lai <ray@cyth.net>.
6 * Public domain.
7 */
9 #include <sys/types.h>
10 #include <sys/wait.h>
12 #include <ctype.h>
13 #include <err.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
19 #include "common.h"
20 #include "extern.h"
22 static void edit(const char *);
25 * Takes the name of a file and opens it with an editor.
27 static void
28 edit(const char *filename)
30 int status;
31 pid_t pid;
32 const char *editor;
34 editor = getenv("VISUAL");
35 if (editor == NULL)
36 editor = getenv("EDITOR");
37 if (editor == NULL)
38 editor = "vi";
40 /* Start editor on temporary file. */
41 switch (pid = fork()) {
42 case 0:
43 /* child */
44 execlp(editor, editor, filename, (void *)NULL);
45 warn("could not execute editor: %s", editor);
46 cleanup(filename);
47 case -1:
48 warn("could not fork");
49 cleanup(filename);
52 /* parent */
53 /* Wait for editor to exit. */
54 if (waitpid(pid, &status, 0) == -1) {
55 warn("waitpid");
56 cleanup(filename);
59 /* Check that editor terminated normally. */
60 if (!WIFEXITED(status)) {
61 warn("%s terminated abnormally", editor);
62 cleanup(filename);
67 * Parse edit command. Returns 0 on success, -1 on error.
69 int
70 eparse(const char *cmd, const char *left, const char *right)
72 FILE *file;
73 size_t nread, nwritten;
74 int fd;
75 char *filename;
76 char buf[BUFSIZ], *text;
78 /* Skip whitespace. */
79 while (isspace((int)(*cmd)))
80 ++cmd;
82 text = NULL;
83 switch (*cmd) {
84 case '\0':
85 /* Edit empty file. */
86 break;
88 case 'b':
89 /* Both strings. */
90 if (left == NULL)
91 goto RIGHT;
92 if (right == NULL)
93 goto LEFT;
95 /* Neither column is blank, so print both. */
96 if (asprintf(&text, "%s\n%s\n", left, right) == -1)
97 err(2, "could not allocate memory");
98 break;
100 case 'l':
101 LEFT:
102 /* Skip if there is no left column. */
103 if (left == NULL)
104 break;
106 if (asprintf(&text, "%s\n", left) == -1)
107 err(2, "could not allocate memory");
109 break;
111 case 'r':
112 RIGHT:
113 /* Skip if there is no right column. */
114 if (right == NULL)
115 break;
117 if (asprintf(&text, "%s\n", right) == -1)
118 err(2, "could not allocate memory");
120 break;
122 default:
123 return (-1);
126 /* Create temp file. */
127 if (asprintf(&filename, "%s/sdiff.XXXXXXXXXX", tmpdir) == -1)
128 err(2, "asprintf");
129 if ((fd = mkstemp(filename)) == -1)
130 err(2, "mkstemp");
131 if (text != NULL) {
132 size_t len;
134 len = strlen(text);
135 if ((size_t)write(fd, text, len) != len) {
136 warn("error writing to temp file");
137 cleanup(filename);
140 close(fd);
142 /* text is no longer used. */
143 free(text);
145 /* Edit temp file. */
146 edit(filename);
148 /* Open temporary file. */
149 if (!(file = fopen(filename, "r"))) {
150 warn("could not open edited file: %s", filename);
151 cleanup(filename);
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);
165 * If we have nothing to read, break out of loop
166 * instead of writing nothing.
168 if (!nread)
169 break;
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);
179 /* We've reached the end of the temporary file, so remove it. */
180 if (unlink(filename))
181 warn("could not delete: %s", filename);
182 fclose(file);
184 free(filename);
186 return (0);