diff options
author | Ray Lai <ray@cvs.openbsd.org> | 2007-04-25 05:02:18 +0000 |
---|---|---|
committer | Ray Lai <ray@cvs.openbsd.org> | 2007-04-25 05:02:18 +0000 |
commit | 89e8e2d7a2184b77bdd0ea82f683bd24c3529eaa (patch) | |
tree | 56be4b250142620bd340f6ba99e29fc875812225 | |
parent | fd8c824bfbe05401573954c37f2df9d4c04d60da (diff) |
Copy signal-safe edit function from sendbug.
OK millert@, threatened by deraadt@.
-rw-r--r-- | usr.bin/sdiff/edit.c | 97 |
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"))) { |