diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-03-23 17:18:08 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-03-23 17:18:08 +0000 |
commit | 4833e2b31e1a10f7f8f48e78673c2241a50af813 (patch) | |
tree | 677a22d1b7d45d47299ff49139fbd3245340851b /usr.bin/sendbug/sendbug.c | |
parent | bc68e87d50e67a0d16927f88232ac3b56d4dd6d5 (diff) |
correct signal handling and process waiting for the editor spawning
code, so that signals in the editor are handled right. written by ray
after he started looking at other code that does this better
Diffstat (limited to 'usr.bin/sendbug/sendbug.c')
-rw-r--r-- | usr.bin/sendbug/sendbug.c | 81 |
1 files changed, 63 insertions, 18 deletions
diff --git a/usr.bin/sendbug/sendbug.c b/usr.bin/sendbug/sendbug.c index a5a5550316c..d0af34cc752 100644 --- a/usr.bin/sendbug/sendbug.c +++ b/usr.bin/sendbug/sendbug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sendbug.c,v 1.14 2007/03/23 15:46:40 deraadt Exp $ */ +/* $OpenBSD: sendbug.c,v 1.15 2007/03/23 17:18:07 deraadt Exp $ */ /* * Written by Ray Lai <ray@cyth.net>. @@ -19,6 +19,7 @@ #include <limits.h> #include <paths.h> #include <pwd.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -26,6 +27,7 @@ #include "atomicio.h" +int editit(char *); void init(void); int prompt(void); int send_file(const char *, int dst); @@ -60,8 +62,8 @@ cleanup() int main(int argc, char *argv[]) { - const char *editor, *tmpdir; - char *argp[] = {"sh", "-c", NULL, NULL}, *pr_form; + const char *tmpdir; + char *pr_form; int ch, c, fd, ret = 1; struct stat sb; time_t mtime; @@ -135,21 +137,7 @@ main(int argc, char *argv[]) mtime = sb.st_mtime; edit: - if ((editor = getenv("EDITOR")) == NULL) - editor = "vi"; - switch (fork()) { - case -1: - err(1, "fork"); - case 0: - wantcleanup = 0; - if (asprintf(&argp[2], "%s %s", editor, tmppath) == -1) - err(1, "asprintf"); - execv(_PATH_BSHELL, argp); - err(1, "execv"); - default: - wait(NULL); - break; - } + editit(tmppath); if (stat(tmppath, &sb) == -1) { err(1, "stat"); @@ -180,6 +168,63 @@ quit: return (ret); } +int +editit(char *tmpfile) +{ + pid_t pid, xpid; + char *argp[] = {"sh", "-c", NULL, NULL}; + char *ed, *p; + int stat; + + if ((ed = getenv("EDITOR")) == (char *)0) + ed = _PATH_VI; + if (asprintf(&p, "%s %s", ed, tmpfile) == -1) + return (0); + argp[2] = p; + + top: + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + if ((pid = fork()) < 0) { + (void)signal(SIGHUP, SIG_DFL); + (void)signal(SIGINT, SIG_DFL); + (void)signal(SIGQUIT, SIG_DFL); + if (errno == EPROCLIM) { + warnx("you have too many processes"); + free(p); + return(0); + } + if (errno == EAGAIN) { + sleep(1); + goto top; + } + perror("fork"); + free(p); + return(0); + } + if (pid == 0) { + (void)signal(SIGHUP, SIG_DFL); + (void)signal(SIGINT, SIG_DFL); + (void)signal(SIGQUIT, SIG_DFL); + execv(_PATH_BSHELL, argp); + _exit(127); + } + free(p); + for (;;) { + xpid = waitpid(pid, (int *)&stat, WUNTRACED); + if (WIFSTOPPED(stat)) + raise(WSTOPSIG(stat)); + else if (WIFEXITED(stat)) + break; + } + (void)signal(SIGHUP, SIG_DFL); + (void)signal(SIGINT, SIG_DFL); + (void)signal(SIGQUIT, SIG_DFL); + if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) + return(0); + return(1); +} int prompt(void) |