summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Lai <ray@cvs.openbsd.org>2007-04-25 05:02:18 +0000
committerRay Lai <ray@cvs.openbsd.org>2007-04-25 05:02:18 +0000
commit89e8e2d7a2184b77bdd0ea82f683bd24c3529eaa (patch)
tree56be4b250142620bd340f6ba99e29fc875812225
parentfd8c824bfbe05401573954c37f2df9d4c04d60da (diff)
Copy signal-safe edit function from sendbug.
OK millert@, threatened by deraadt@.
-rw-r--r--usr.bin/sdiff/edit.c97
1 files changed, 62 insertions, 35 deletions
diff --git a/usr.bin/sdiff/edit.c b/usr.bin/sdiff/edit.c
index d82f90cb8f5..e4853c73251 100644
--- a/usr.bin/sdiff/edit.c
+++ b/usr.bin/sdiff/edit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: edit.c,v 1.15 2007/02/26 08:32:00 steven Exp $ */
+/* $OpenBSD: edit.c,v 1.16 2007/04/25 05:02:17 ray Exp $ */
/*
* Written by Raymond Lai <ray@cyth.net>.
@@ -10,6 +10,9 @@
#include <ctype.h>
#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -18,48 +21,66 @@
#include "common.h"
#include "extern.h"
-static void edit(const char *);
+int editit(const char *);
/*
* Takes the name of a file and opens it with an editor.
*/
-static void
-edit(const char *filename)
+int
+editit(const char *pathname)
{
- int status;
+ char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p;
+ sig_t sighup, sigint, sigquit;
pid_t pid;
- const char *editor;
-
- editor = getenv("VISUAL");
- if (editor == NULL)
- editor = getenv("EDITOR");
- if (editor == NULL)
- editor = "vi";
-
- /* Start editor on temporary file. */
- switch (pid = fork()) {
- case 0:
- /* child */
- execlp(editor, editor, filename, (void *)NULL);
- warn("could not execute editor: %s", editor);
- cleanup(filename);
- case -1:
- warn("could not fork");
- cleanup(filename);
+ int st;
+
+ ed = getenv("VISUAL");
+ if (ed == NULL || ed[0] == '\0')
+ ed = getenv("EDITOR");
+ if (ed == NULL || ed[0] == '\0')
+ ed = _PATH_VI;
+ if (asprintf(&p, "%s %s", ed, pathname) == -1)
+ return (-1);
+ argp[2] = p;
+
+ top:
+ sighup = signal(SIGHUP, SIG_IGN);
+ sigint = signal(SIGINT, SIG_IGN);
+ sigquit = signal(SIGQUIT, SIG_IGN);
+ if ((pid = fork()) == -1) {
+ int saved_errno = errno;
+
+ (void)signal(SIGHUP, sighup);
+ (void)signal(SIGINT, sigint);
+ (void)signal(SIGQUIT, sigquit);
+ if (saved_errno == EAGAIN) {
+ sleep(1);
+ goto top;
+ }
+ free(p);
+ errno = saved_errno;
+ return (-1);
}
-
- /* parent */
- /* Wait for editor to exit. */
- if (waitpid(pid, &status, 0) == -1) {
- warn("waitpid");
- cleanup(filename);
+ if (pid == 0) {
+ execv(_PATH_BSHELL, argp);
+ _exit(127);
}
-
- /* Check that editor terminated normally. */
- if (!WIFEXITED(status)) {
- warn("%s terminated abnormally", editor);
- cleanup(filename);
+ free(p);
+ for (;;) {
+ if (waitpid(pid, &st, 0) == -1) {
+ if (errno != EINTR)
+ return (-1);
+ } else
+ break;
+ }
+ (void)signal(SIGHUP, sighup);
+ (void)signal(SIGINT, sigint);
+ (void)signal(SIGQUIT, sigquit);
+ if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
+ errno = ECHILD;
+ return (-1);
}
+ return (0);
}
/*
@@ -144,7 +165,13 @@ RIGHT:
free(text);
/* Edit temp file. */
- edit(filename);
+ if (editit(filename) == -1) {
+ if (errno == ECHILD)
+ warnx("editor terminated abnormally");
+ else
+ warn("error editing %s", filename);
+ cleanup(filename);
+ }
/* Open temporary file. */
if (!(file = fopen(filename, "r"))) {