split out the child runner. trunk
authorchristos <christos@NetBSD.org>
Sun, 04 Feb 2018 03:37:59 +0000
branchtrunk
changeset 274958 0551fb0455d4
parent 274957 24b437595f28
child 274959 26ac044dbe9b
split out the child runner.
external/bsd/cron/dist/do_command.c
--- a/external/bsd/cron/dist/do_command.c	Sun Feb 04 03:19:51 2018 +0000
+++ b/external/bsd/cron/dist/do_command.c	Sun Feb 04 03:37:59 2018 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: do_command.c,v 1.11 2017/09/28 02:32:51 christos Exp $	*/
+/*	$NetBSD: do_command.c,v 1.12 2018/02/04 03:37:59 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.11 2017/09/28 02:32:51 christos Exp $");
+__RCSID("$NetBSD: do_command.c,v 1.12 2018/02/04 03:37:59 christos Exp $");
 #endif
 #endif
 
@@ -272,101 +272,15 @@
 
 extern char **environ;
 static int
-child_process(entry *e) {
-	int stdin_pipe[2], stdout_pipe[2];
-	char * volatile input_data;
-	char *homedir, *usernm, * volatile mailto;
-	struct sigaction sact;
-	char **envp = e->envp;
-	int retval = OK_EXIT;
-
-	Debug(DPROC, ("[%ld] child_process('%s')\n", (long)getpid(), e->cmd));
-
-	setproctitle("running job");
-
-	/* discover some useful and important environment settings
-	 */
-	usernm = e->pwd->pw_name;
-	mailto = env_get("MAILTO", envp);
-
-	memset(&sact, 0, sizeof(sact));
-	sigemptyset(&sact.sa_mask);
-	sact.sa_flags = 0;
-#ifdef SA_RESTART
-	sact.sa_flags |= SA_RESTART;
-#endif
-	sact.sa_handler = sigchld_handler;
-	(void) sigaction(SIGCHLD, &sact, NULL);
+exec_user_command(entry *e, char **envp, char *usernm, int *stdin_pipe,
+    int *stdout_pipe)
+{
+	char *homedir;
+	char * volatile *ep = envp;
 
-	/* create some pipes to talk to our future child
-	 */
-	if (pipe(stdin_pipe) == -1) 	/* child's stdin */
-		log_it("CRON", getpid(), "error", "create child stdin pipe");
-	if (pipe(stdout_pipe) == -1)	/* child's stdout */
-		log_it("CRON", getpid(), "error", "create child stdout pipe");
-	
-	/* since we are a forked process, we can diddle the command string
-	 * we were passed -- nobody else is going to use it again, right?
-	 *
-	 * if a % is present in the command, previous characters are the
-	 * command, and subsequent characters are the additional input to
-	 * the command.  An escaped % will have the escape character stripped
-	 * from it.  Subsequent %'s will be transformed into newlines,
-	 * but that happens later.
-	 */
-	/*local*/{
-		int escaped = FALSE;
-		int ch;
-		char *p;
-
-		/* translation:
-		 *	\% -> %
-		 *	%  -> end of command, following is command input.
-		 *	\x -> \x	for all x != %
-		 */
-		input_data = p = e->cmd;
-		while ((ch = *input_data++) != '\0') {
- 			if (escaped) {
-				if (ch != '%')
-					*p++ = '\\';
-			} else {
-				if (ch == '%') {
-					break;
-				}
-			}
-
-			if (!(escaped = (ch == '\\'))) {
-				*p++ = (char)ch;
-			}
-		}
-		if (ch == '\0') {
-			/* move pointer back, so that code below
-			 * won't think we encountered % sequence */
-			input_data--;
-		}
-		if (escaped)
-			*p++ = '\\';
-
-		*p = '\0';
-	}
-
-#ifdef USE_PAM
-	if (!cron_pam_start(usernm))
-		return ERROR_EXIT;
-
-	if (!(envp = cron_pam_getenvlist(envp))) {
-		retval = ERROR_EXIT;
-		goto child_process_end;
-	}
-#endif
-
-	/* fork again, this time so we can exec the user's command.
-	 */
 	switch (vfork()) {
 	case -1:
-		retval = ERROR_EXIT;
-		goto child_process_end;
-		/*NOTREACHED*/
+		return -1;
 	case 0:
 		Debug(DPROC, ("[%ld] grandchild process vfork()'ed\n",
 			      (long)getpid()));
@@ -456,7 +370,7 @@
 			 */
 			if (env_get("PATH", envp) == NULL && environ != NULL) {
 				if ((p = getenv("PATH")) != NULL)
-					envp = env_set(envp, p);
+					ep = env_set(envp, p);
 			}
 		}
 #else
@@ -489,7 +403,7 @@
 		}
 		/* we aren't root after this... */
 #endif /* LOGIN_CAP */
-		homedir = env_get("HOME", envp);
+		homedir = env_get("HOME", __UNVOLATILE(ep));
 		if (chdir(homedir) != 0) {
 			syslog(LOG_ERR, "chdir(%s) $HOME failed for %s: %m",
 			    homedir, e->pwd->pw_name);
@@ -511,7 +425,7 @@
 		 * Exec the command.
 		 */
 		{
-			char	*shell = env_get("SHELL", envp);
+			char	*shell = env_get("SHELL", __UNVOLATILE(ep));
 
 # if DEBUGGING
 			if (DebugFlags & DTEST) {
@@ -526,11 +440,109 @@
 			warn("execl: couldn't exec `%s'", shell);
 			_exit(ERROR_EXIT);
 		}
-		break;
+		return 0;
 	default:
 		/* parent process */
-		break;
+		return 0;
 	}
+}
+
+static int
+child_process(entry *e) {
+	int stdin_pipe[2], stdout_pipe[2];
+	char * volatile input_data;
+	char *usernm, * volatile mailto;
+	struct sigaction sact;
+	char **envp = e->envp;
+	int retval = OK_EXIT;
+
+	Debug(DPROC, ("[%ld] child_process('%s')\n", (long)getpid(), e->cmd));
+
+	setproctitle("running job");
+
+	/* discover some useful and important environment settings
+	 */
+	usernm = e->pwd->pw_name;
+	mailto = env_get("MAILTO", envp);
+
+	memset(&sact, 0, sizeof(sact));
+	sigemptyset(&sact.sa_mask);
+	sact.sa_flags = 0;
+#ifdef SA_RESTART
+	sact.sa_flags |= SA_RESTART;
+#endif
+	sact.sa_handler = sigchld_handler;
+	(void) sigaction(SIGCHLD, &sact, NULL);
+
+	/* create some pipes to talk to our future child
+	 */
+	if (pipe(stdin_pipe) == -1) 	/* child's stdin */
+		log_it("CRON", getpid(), "error", "create child stdin pipe");
+	if (pipe(stdout_pipe) == -1)	/* child's stdout */
+		log_it("CRON", getpid(), "error", "create child stdout pipe");
+	
+	/* since we are a forked process, we can diddle the command string
+	 * we were passed -- nobody else is going to use it again, right?
+	 *
+	 * if a % is present in the command, previous characters are the
+	 * command, and subsequent characters are the additional input to
+	 * the command.  An escaped % will have the escape character stripped
+	 * from it.  Subsequent %'s will be transformed into newlines,
+	 * but that happens later.
+	 */
+	/*local*/{
+		int escaped = FALSE;
+		int ch;
+		char *p;
+
+		/* translation:
+		 *	\% -> %
+		 *	%  -> end of command, following is command input.
+		 *	\x -> \x	for all x != %
+		 */
+		input_data = p = e->cmd;
+		while ((ch = *input_data++) != '\0') {
+ 			if (escaped) {
+				if (ch != '%')
+					*p++ = '\\';
+			} else {
+				if (ch == '%') {
+					break;
+				}
+			}
+
+			if (!(escaped = (ch == '\\'))) {
+				*p++ = (char)ch;
+			}
+		}
+		if (ch == '\0') {
+			/* move pointer back, so that code below
+			 * won't think we encountered % sequence */
+			input_data--;
+		}
+		if (escaped)
+			*p++ = '\\';
+
+		*p = '\0';
+	}
+
+#ifdef USE_PAM
+	if (!cron_pam_start(usernm))
+		return ERROR_EXIT;
+
+	if (!(envp = cron_pam_getenvlist(envp))) {
+		retval = ERROR_EXIT;
+		goto child_process_end;
+	}
+#endif
+
+	/* fork again, this time so we can exec the user's command.
+	 */
+	if (exec_user_command(e, envp, usernm, stdin_pipe, stdout_pipe) == -1) {
+		retval = ERROR_EXIT;
+		goto child_process_end;
+	}
+
 
 	/* middle process, child of original cron, parent of process running
 	 * the user's command.