Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/external/bsd/cron/dist Factor out the read and write data co...
details: https://anonhg.NetBSD.org/src/rev/cf1d67beb675
branches: trunk
changeset: 356429:cf1d67beb675
user: christos <christos%NetBSD.org@localhost>
date: Mon Sep 25 08:30:46 2017 +0000
description:
Factor out the read and write data code from the huge child_process function.
When we create a pipe to read data, restore the sigchld signal handler since
pclose expects to wait for the child (to avoid spurious error reporting later).
diffstat:
external/bsd/cron/dist/do_command.c | 374 +++++++++++++++++++----------------
1 files changed, 199 insertions(+), 175 deletions(-)
diffs (truncated from 411 to 300 lines):
diff -r 59da79de7752 -r cf1d67beb675 external/bsd/cron/dist/do_command.c
--- a/external/bsd/cron/dist/do_command.c Mon Sep 25 04:15:33 2017 +0000
+++ b/external/bsd/cron/dist/do_command.c Mon Sep 25 08:30:46 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: do_command.c,v 1.9 2017/08/17 08:53:00 christos Exp $ */
+/* $NetBSD: do_command.c,v 1.10 2017/09/25 08:30:46 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.9 2017/08/17 08:53:00 christos Exp $");
+__RCSID("$NetBSD: do_command.c,v 1.10 2017/09/25 08:30:46 christos Exp $");
#endif
#endif
@@ -87,6 +87,190 @@
}
}
+static void
+write_data(char *volatile input_data, int *stdin_pipe, int *stdout_pipe)
+{
+ FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w");
+ int need_newline = FALSE;
+ int escaped = FALSE;
+ int ch;
+
+ Debug(DPROC, ("[%ld] child2 sending data to grandchild\n",
+ (long)getpid()));
+
+#ifdef USE_PAM
+ cron_pam_child_close();
+#else
+ log_close();
+#endif
+
+ /* close the pipe we don't use, since we inherited it and
+ * are part of its reference count now.
+ */
+ (void)close(stdout_pipe[READ_PIPE]);
+
+ /* translation:
+ * \% -> %
+ * % -> \n
+ * \x -> \x for all x != %
+ */
+ while ((ch = *input_data++) != '\0') {
+ if (escaped) {
+ if (ch != '%')
+ (void)putc('\\', out);
+ } else {
+ if (ch == '%')
+ ch = '\n';
+ }
+
+ if (!(escaped = (ch == '\\'))) {
+ (void)putc(ch, out);
+ need_newline = (ch != '\n');
+ }
+ }
+ if (escaped)
+ (void)putc('\\', out);
+ if (need_newline)
+ (void)putc('\n', out);
+
+ /* close the pipe, causing an EOF condition. fclose causes
+ * stdin_pipe[WRITE_PIPE] to be closed, too.
+ */
+ (void)fclose(out);
+
+ Debug(DPROC, ("[%ld] child2 done sending to grandchild\n",
+ (long)getpid()));
+}
+
+static int
+read_data(entry *e, const char *mailto, const char *usernm, char **envp,
+ int *stdout_pipe)
+{
+ FILE *in = fdopen(stdout_pipe[READ_PIPE], "r");
+ FILE *mail = NULL;
+ int bytes = 1;
+ int status = 0;
+ int ch = getc(in);
+ int retval = 0;
+ sig_t oldchld = NULL;
+
+ if (ch == EOF)
+ goto out;
+
+ Debug(DPROC|DEXT, ("[%ld] got data (%x:%c) from grandchild\n",
+ (long)getpid(), ch, ch));
+
+ /* get name of recipient. this is MAILTO if set to a
+ * valid local username; USER otherwise.
+ */
+ if (mailto) {
+ /* MAILTO was present in the environment
+ */
+ if (!*mailto) {
+ /* ... but it's empty. set to NULL
+ */
+ mailto = NULL;
+ }
+ } else {
+ /* MAILTO not present, set to USER.
+ */
+ mailto = usernm;
+ }
+
+ /*
+ * Unsafe, disable mailing.
+ */
+ if (!safe_p(usernm, mailto))
+ mailto = NULL;
+
+ /* if we are supposed to be mailing, MAILTO will
+ * be non-NULL. only in this case should we set
+ * up the mail command and subjects and stuff...
+ */
+
+ if (mailto) {
+ char **env;
+ char mailcmd[MAX_COMMAND];
+ char hostname[MAXHOSTNAMELEN + 1];
+
+ (void)gethostname(hostname, MAXHOSTNAMELEN);
+ if (strlens(MAILFMT, MAILARG, NULL) + 1 >= sizeof mailcmd) {
+ log_it(usernm, getpid(), "MAIL", "mailcmd too long");
+ retval = ERROR_EXIT;
+ goto out;
+ }
+ (void)snprintf(mailcmd, sizeof(mailcmd), MAILFMT, MAILARG);
+ oldchld = signal(SIGCHLD, SIG_DFL);
+ if (!(mail = cron_popen(mailcmd, "w", e->pwd))) {
+ log_itx(usernm, getpid(), "MAIL",
+ "cannot run `%s'", mailcmd);
+ (void) signal(SIGCHLD, oldchld);
+ retval = ERROR_EXIT;
+ goto out;
+ }
+ log_itx(usernm, getpid(), "MAIL", "opened pipe `%s'", mailcmd);
+ (void)fprintf(mail, "From: root (Cron Daemon)\n");
+ (void)fprintf(mail, "To: %s\n", mailto);
+ (void)fprintf(mail, "Subject: Cron <%s@%s> %s\n",
+ usernm, hostname, e->cmd);
+ (void)fprintf(mail, "Auto-Submitted: auto-generated\n");
+#ifdef MAIL_DATE
+ (void)fprintf(mail, "Date: %s\n", arpadate(&StartTime));
+#endif /*MAIL_DATE*/
+ for (env = envp; *env; env++)
+ (void)fprintf(mail, "X-Cron-Env: <%s>\n", *env);
+ (void)fprintf(mail, "\n");
+
+ /* this was the first char from the pipe
+ */
+ (void)putc(ch, mail);
+ }
+
+ /* we have to read the input pipe no matter whether
+ * we mail or not, but obviously we only write to
+ * mail pipe if we ARE mailing.
+ */
+
+ while (EOF != (ch = getc(in))) {
+ bytes++;
+ if (mailto)
+ (void)putc(ch, mail);
+ }
+
+ /* only close pipe if we opened it -- i.e., we're
+ * mailing...
+ */
+
+ 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);
+ (void) signal(SIGCHLD, oldchld);
+ }
+
+ /* if there was output and we could not mail it,
+ * log the facts so the poor user can figure out
+ * what's going on.
+ */
+ if (mailto && status) {
+ log_itx(usernm, getpid(), "MAIL",
+ "mailed %d byte%s of output to `%s' but"
+ " got status %#04x", bytes,
+ bytes == 1 ? "" : "s", mailto, status);
+ }
+
+out:
+ Debug(DPROC, ("[%ld] got EOF from grandchild\n", (long)getpid()));
+
+ (void)fclose(in); /* also closes stdout_pipe[READ_PIPE] */
+ return retval;
+}
+
extern char **environ;
static int
child_process(entry *e) {
@@ -372,58 +556,17 @@
* we would block here. thus we must fork again.
*/
- if (*input_data && fork() == 0) {
- FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w");
- int need_newline = FALSE;
- int escaped = FALSE;
- int ch;
-
- Debug(DPROC, ("[%ld] child2 sending data to grandchild\n",
- (long)getpid()));
-
-#ifdef USE_PAM
- cron_pam_child_close();
-#else
- log_close();
-#endif
-
- /* close the pipe we don't use, since we inherited it and
- * are part of its reference count now.
- */
- (void)close(stdout_pipe[READ_PIPE]);
-
- /* translation:
- * \% -> %
- * % -> \n
- * \x -> \x for all x != %
- */
- while ((ch = *input_data++) != '\0') {
- if (escaped) {
- if (ch != '%')
- (void)putc('\\', out);
- } else {
- if (ch == '%')
- ch = '\n';
- }
-
- if (!(escaped = (ch == '\\'))) {
- (void)putc(ch, out);
- need_newline = (ch != '\n');
- }
+ if (*input_data) {
+ switch (fork()) {
+ case 0:
+ write_data(input_data, stdin_pipe, stdout_pipe);
+ exit(EXIT_SUCCESS);
+ case -1:
+ retval = ERROR_EXIT;
+ goto child_process_end;
+ default:
+ break;
}
- if (escaped)
- (void)putc('\\', out);
- if (need_newline)
- (void)putc('\n', out);
-
- /* close the pipe, causing an EOF condition. fclose causes
- * stdin_pipe[WRITE_PIPE] to be closed, too.
- */
- (void)fclose(out);
-
- Debug(DPROC, ("[%ld] child2 done sending to grandchild\n",
- (long)getpid()));
- exit(0);
}
/* close the pipe to the grandkiddie's stdin, since its wicked uncle
@@ -441,129 +584,10 @@
Debug(DPROC, ("[%ld] child reading output from grandchild\n",
(long)getpid()));
- /*local*/{
- FILE *in = fdopen(stdout_pipe[READ_PIPE], "r");
- int ch = getc(in);
-
- if (ch != EOF) {
- FILE *mail = NULL;
- int bytes = 1;
- int status = 0;
-
- Debug(DPROC|DEXT,
- ("[%ld] got data (%x:%c) from grandchild\n",
- (long)getpid(), ch, ch));
-
- /* get name of recipient. this is MAILTO if set to a
- * valid local username; USER otherwise.
- */
- if (mailto) {
- /* MAILTO was present in the environment
Home |
Main Index |
Thread Index |
Old Index