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

Reply via email to