Module Name: src Committed By: christos Date: Thu Jun 14 22:04:28 UTC 2018
Modified Files: src/external/bsd/cron/dist: do_command.c entry.c funcs.h popen.c structs.h Log Message: Add -n (don't send mail if command exited normally) option. From OpenBSD via Job Snidjers. To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/external/bsd/cron/dist/do_command.c cvs rdiff -u -r1.7 -r1.8 src/external/bsd/cron/dist/entry.c cvs rdiff -u -r1.5 -r1.6 src/external/bsd/cron/dist/funcs.h \ src/external/bsd/cron/dist/popen.c cvs rdiff -u -r1.2 -r1.3 src/external/bsd/cron/dist/structs.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/cron/dist/do_command.c diff -u src/external/bsd/cron/dist/do_command.c:1.12 src/external/bsd/cron/dist/do_command.c:1.13 --- src/external/bsd/cron/dist/do_command.c:1.12 Sat Feb 3 22:37:59 2018 +++ src/external/bsd/cron/dist/do_command.c Thu Jun 14 18:04:28 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: do_command.c,v 1.12 2018/02/04 03:37:59 christos Exp $ */ +/* $NetBSD: do_command.c,v 1.13 2018/06/14 22:04:28 christos Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved @@ -25,7 +25,7 @@ #if 0 static char rcsid[] = "Id: do_command.c,v 1.9 2004/01/23 18:56:42 vixie Exp"; #else -__RCSID("$NetBSD: do_command.c,v 1.12 2018/02/04 03:37:59 christos Exp $"); +__RCSID("$NetBSD: do_command.c,v 1.13 2018/06/14 22:04:28 christos Exp $"); #endif #endif @@ -50,7 +50,9 @@ do_command(entry *e, user *u) { * vfork() is unsuitable, since we have much to do, and the parent * needs to be able to run off and fork other processes. */ - switch (fork()) { + + pid_t jobpid; + switch (jobpid = fork()) { case -1: log_it("CRON", getpid(), "error", "can't fork"); break; @@ -144,7 +146,7 @@ write_data(char *volatile input_data, in static int read_data(entry *e, const char *mailto, const char *usernm, char **envp, - int *stdout_pipe) + int *stdout_pipe, pid_t jobpid) { FILE *in = fdopen(stdout_pipe[READ_PIPE], "r"); FILE *mail = NULL; @@ -241,14 +243,43 @@ read_data(entry *e, const char *mailto, */ if (mailto) { - Debug(DPROC, ("[%ld] closing pipe to mail\n", (long)getpid())); - /* Note: the pclose will probably see - * the termination of the grandchild - * in addition to the mail process, since - * it (the grandchild) is likely to exit - * after closing its stdout. - */ - status = cron_pclose(mail); + if (e->flags & MAIL_WHEN_ERR) { + int jstatus = -1; + if (jobpid <= 0) + log_it("CRON", getpid(), "error", + "no job pid"); + else { + while (waitpid(jobpid, &jstatus, WNOHANG) == -1) + if (errno != EINTR) { + log_it("CRON", getpid(), + "error", "no job pid"); + break; + } + } + /* If everything went well, and -n was set, _and_ we + * have mail, we won't be mailing... so shoot the + * messenger! + */ + if (WIFEXITED(jstatus) && WEXITSTATUS(jstatus) == 0) { + Debug(DPROC, ("[%ld] aborting pipe to mail\n", + (long)getpid())); + status = cron_pabort(mail); + mailto = NULL; + } + } + + if (mailto) { + Debug(DPROC, ("[%ld] closing pipe to mail\n", + (long)getpid())); + /* Note: the pclose will probably see + * the termination of the grandchild + * in addition to the mail process, since + * it (the grandchild) is likely to exit + * after closing its stdout. + */ + status = cron_pclose(mail); + mail = NULL; + } (void) signal(SIGCHLD, oldchld); } @@ -273,15 +304,16 @@ out: extern char **environ; static int exec_user_command(entry *e, char **envp, char *usernm, int *stdin_pipe, - int *stdout_pipe) + int *stdout_pipe, pid_t *jobpid) { char *homedir; - char * volatile *ep = envp; + char * volatile *ep; - switch (vfork()) { + switch (*jobpid = vfork()) { case -1: return -1; case 0: + ep = envp; Debug(DPROC, ("[%ld] grandchild process vfork()'ed\n", (long)getpid())); @@ -455,6 +487,7 @@ child_process(entry *e) { struct sigaction sact; char **envp = e->envp; int retval = OK_EXIT; + pid_t jobpid = 0; Debug(DPROC, ("[%ld] child_process('%s')\n", (long)getpid(), e->cmd)); @@ -538,7 +571,8 @@ child_process(entry *e) { /* fork again, this time so we can exec the user's command. */ - if (exec_user_command(e, envp, usernm, stdin_pipe, stdout_pipe) == -1) { + if (exec_user_command(e, envp, usernm, stdin_pipe, stdout_pipe, + &jobpid) == -1) { retval = ERROR_EXIT; goto child_process_end; } @@ -595,7 +629,7 @@ child_process(entry *e) { Debug(DPROC, ("[%ld] child reading output from grandchild\n", (long)getpid())); - retval = read_data(e, mailto, usernm, envp, stdout_pipe); + retval = read_data(e, mailto, usernm, envp, stdout_pipe, jobpid); if (retval) goto child_process_end; Index: src/external/bsd/cron/dist/entry.c diff -u src/external/bsd/cron/dist/entry.c:1.7 src/external/bsd/cron/dist/entry.c:1.8 --- src/external/bsd/cron/dist/entry.c:1.7 Fri Nov 20 18:43:52 2015 +++ src/external/bsd/cron/dist/entry.c Thu Jun 14 18:04:28 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: entry.c,v 1.7 2015/11/20 23:43:52 christos Exp $ */ +/* $NetBSD: entry.c,v 1.8 2018/06/14 22:04:28 christos Exp $ */ /* * Copyright 1988,1990,1993,1994 by Paul Vixie @@ -26,7 +26,7 @@ #if 0 static char rcsid[] = "Id: entry.c,v 1.17 2004/01/23 18:56:42 vixie Exp"; #else -__RCSID("$NetBSD: entry.c,v 1.7 2015/11/20 23:43:52 christos Exp $"); +__RCSID("$NetBSD: entry.c,v 1.8 2018/06/14 22:04:28 christos Exp $"); #endif #endif @@ -342,16 +342,34 @@ load_entry(FILE *file, void (*error_func /* If the first character of the command is '-' it is a cron option. */ - while ((ch = get_char(file)) == '-') { + ch = get_char(file); + while (ch == '-') { switch (ch = get_char(file)) { + case 'n': + /* only allow the user to set the option once */ + if ((e->flags & MAIL_WHEN_ERR) == MAIL_WHEN_ERR) { + ecode = e_option; + goto eof; + } + e->flags |= MAIL_WHEN_ERR; + break; case 'q': + /* only allow the user to set the option once */ + if ((e->flags & DONT_LOG) == DONT_LOG) { + ecode = e_option; + goto eof; + } e->flags |= DONT_LOG; - Skip_Nonblanks(ch, file); break; default: ecode = e_option; goto eof; } + ch = get_char(file); + if (ch != '\t' && ch != ' ') { + ecode = e_option; + goto eof; + } Skip_Blanks(ch, file); if (ch == EOF || ch == '\n') { ecode = e_cmd; Index: src/external/bsd/cron/dist/funcs.h diff -u src/external/bsd/cron/dist/funcs.h:1.5 src/external/bsd/cron/dist/funcs.h:1.6 --- src/external/bsd/cron/dist/funcs.h:1.5 Thu Aug 17 04:53:00 2017 +++ src/external/bsd/cron/dist/funcs.h Thu Jun 14 18:04:28 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: funcs.h,v 1.5 2017/08/17 08:53:00 christos Exp $ */ +/* $NetBSD: funcs.h,v 1.6 2018/06/14 22:04:28 christos Exp $ */ /* * Id: funcs.h,v 1.9 2004/01/23 18:56:42 vixie Exp @@ -55,6 +55,7 @@ int job_runqueue(void), get_string(char *, int, FILE *, const char *), load_env(char *, FILE *), cron_pclose(FILE *), + cron_pabort(FILE *), glue_strings(char *, size_t, const char *, const char *, char), strcmp_until(const char *, const char *, char), strdtb(char *); Index: src/external/bsd/cron/dist/popen.c diff -u src/external/bsd/cron/dist/popen.c:1.5 src/external/bsd/cron/dist/popen.c:1.6 --- src/external/bsd/cron/dist/popen.c:1.5 Fri Jun 9 13:36:30 2017 +++ src/external/bsd/cron/dist/popen.c Thu Jun 14 18:04:28 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: popen.c,v 1.5 2017/06/09 17:36:30 christos Exp $ */ +/* $NetBSD: popen.c,v 1.6 2018/06/14 22:04:28 christos Exp $ */ /* * Copyright (c) 1988, 1993, 1994 @@ -44,7 +44,7 @@ static sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94"; static char rcsid[] = "Id: popen.c,v 1.6 2003/02/16 04:40:01 vixie Exp"; #else -__RCSID("$NetBSD: popen.c,v 1.5 2017/06/09 17:36:30 christos Exp $"); +__RCSID("$NetBSD: popen.c,v 1.6 2018/06/14 22:04:28 christos Exp $"); #endif #endif /* not lint */ @@ -163,8 +163,8 @@ cron_popen(char *program, const char *ty return (iop); } -int -cron_pclose(FILE *iop) { +static int +cron_finalize(FILE *iop, int sig) { int fdes; PID_T pid; WAIT_T status; @@ -176,7 +176,13 @@ cron_pclose(FILE *iop) { */ if (pids == 0 || pids[fdes = fileno(iop)] == 0) return (-1); - (void)fclose(iop); + + if (sig) { + if (kill(pids[fdes], sig) == -1) + return -1; + } else { + (void)fclose(iop); + } (void)sigemptyset(&sset); (void)sigaddset(&sset, SIGINT); (void)sigaddset(&sset, SIGQUIT); @@ -185,11 +191,24 @@ cron_pclose(FILE *iop) { while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR) continue; (void)sigprocmask(SIG_SETMASK, &osset, NULL); + if (sig) + (void)fclose(iop); pids[fdes] = 0; if (pid < 0) - return (pid); + return pid; if (WIFEXITED(status)) - return (WEXITSTATUS(status)); + return WEXITSTATUS(status); else return WTERMSIG(status); } + +int +cron_pclose(FILE *iop) { + return cron_finalize(iop, 0); +} + +int +cron_pabort(FILE *iop) { + int e = cron_finalize(iop, SIGKILL); + return e == SIGKILL ? 0 : e; +} Index: src/external/bsd/cron/dist/structs.h diff -u src/external/bsd/cron/dist/structs.h:1.2 src/external/bsd/cron/dist/structs.h:1.3 --- src/external/bsd/cron/dist/structs.h:1.2 Thu May 6 14:53:17 2010 +++ src/external/bsd/cron/dist/structs.h Thu Jun 14 18:04:28 2018 @@ -1,5 +1,3 @@ -/* $NetBSD: structs.h,v 1.2 2010/05/06 18:53:17 christos Exp $ */ - /* * Id: structs.h,v 1.7 2004/01/23 18:56:43 vixie Exp */ @@ -38,6 +36,7 @@ typedef struct _entry { #define DOW_STAR 0x08 #define WHEN_REBOOT 0x10 #define DONT_LOG 0x20 +#define MAIL_WHEN_ERR 0x40 } entry; /* the crontab database will be a list of the