diff options
Diffstat (limited to 'usr.sbin/edquota/edquota.c')
-rw-r--r-- | usr.sbin/edquota/edquota.c | 100 |
1 files changed, 52 insertions, 48 deletions
diff --git a/usr.sbin/edquota/edquota.c b/usr.sbin/edquota/edquota.c index be3f981b3f1..cb04b0c067a 100644 --- a/usr.sbin/edquota/edquota.c +++ b/usr.sbin/edquota/edquota.c @@ -38,7 +38,7 @@ static char copyright[] = #ifndef lint /*static char sccsid[] = "from: @(#)edquota.c 8.1 (Berkeley) 6/6/93";*/ -static char *rcsid = "$Id: edquota.c,v 1.46 2007/08/06 19:16:07 sobrado Exp $"; +static char *rcsid = "$Id: edquota.c,v 1.47 2007/08/31 23:14:21 ray Exp $"; #endif /* not lint */ /* @@ -81,7 +81,7 @@ int getentry(char *, int, u_int *); struct quotause * getprivs(u_int, int); void putprivs(long, int, struct quotause *); -int editit(char *); +int editit(const char *); int writeprivs(struct quotause *, int, char *, int); int readprivs(struct quotause *, int); int writetimes(struct quotause *, int, int); @@ -162,7 +162,11 @@ main(int argc, char *argv[]) unlink(tmpfil); exit(1); } - if (editit(tmpfil) && readtimes(protoprivs, tmpfd)) + if (editit(tmpfil) == -1) { + unlink(tmpfil); + err(1, "error starting editor"); + } + if (readtimes(protoprivs, tmpfd)) putprivs(0, quotatype, protoprivs); freeprivs(protoprivs); unlink(tmpfil); @@ -174,7 +178,11 @@ main(int argc, char *argv[]) curprivs = getprivs(id, quotatype); if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) continue; - if (editit(tmpfil) && readprivs(curprivs, tmpfd)) + if (editit(tmpfil) == -1) { + warn("error starting editor"); + continue; + } + if (readprivs(curprivs, tmpfd)) putprivs(id, quotatype, curprivs); freeprivs(curprivs); } @@ -344,62 +352,58 @@ putprivs(long id, int quotatype, struct quotause *quplist) } /* - * Take a list of privileges and get it edited. + * Execute an editor on the specified pathname, which is interpreted + * from the shell. This means flags may be included. + * + * Returns -1 on error, or the exit value on success. */ int -editit(char *tmpfile) +editit(const char *pathname) { - pid_t pid, xpid; - char *argp[] = {"sh", "-c", NULL, NULL}; - char *ed, *p; - sigset_t mask, omask; - int stat; - - if ((ed = getenv("EDITOR")) == (char *)0) + char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p; + sig_t sighup, sigint, sigquit; + pid_t pid; + int saved_errno, 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, tmpfile) == -1) - return (0); + if (asprintf(&p, "%s %s", ed, pathname) == -1) + return (-1); argp[2] = p; - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGQUIT); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_SETMASK, &mask, &omask); - top: - if ((pid = fork()) < 0) { - 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); - } + sighup = signal(SIGHUP, SIG_IGN); + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + if ((pid = fork()) == -1) + goto fail; if (pid == 0) { - sigprocmask(SIG_SETMASK, &omask, NULL); - setgid(getgid()); - setuid(getuid()); execv(_PATH_BSHELL, argp); _exit(127); } + while (waitpid(pid, &st, 0) == -1) + if (errno != EINTR) + goto fail; free(p); - for (;;) { - xpid = waitpid(pid, (int *)&stat, WUNTRACED); - if (WIFSTOPPED(stat)) - raise(WSTOPSIG(stat)); - else if (WIFEXITED(stat)) - break; + (void)signal(SIGHUP, sighup); + (void)signal(SIGINT, sigint); + (void)signal(SIGQUIT, sigquit); + if (!WIFEXITED(st)) { + errno = EINTR; + return (-1); } - sigprocmask(SIG_SETMASK, &omask, NULL); - if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) - return(0); - return(1); + return (WEXITSTATUS(st)); + + fail: + saved_errno = errno; + (void)signal(SIGHUP, sighup); + (void)signal(SIGINT, sigint); + (void)signal(SIGQUIT, sigquit); + free(p); + errno = saved_errno; + return (-1); } /* |