From 00195b8c5b8c78d52bf1d13f495857381a5b34a1 Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Wed, 26 Apr 2023 12:16:42 +0200 Subject: [PATCH 1/6] Add support for INHERIT_OUTPUTS env variable --- anacron/runjob.c | 127 +++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 58 deletions(-) diff --git a/anacron/runjob.c b/anacron/runjob.c index 04d6904..102062b 100644 --- a/anacron/runjob.c +++ b/anacron/runjob.c @@ -163,15 +163,19 @@ setup_env(const job_rec *jr) } static void -run_job(const job_rec *jr) +run_job(const job_rec *jr, int inherit_outputs) /* This is called to start the job, after the fork */ { - /* setup stdout and stderr */ - xclose(1); - xclose(2); - if (dup2(jr->output_fd, 1) != 1 || dup2(jr->output_fd, 2) != 2) - die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ - in_background = 0; /* now, errors will be mailed to the user */ + /* If outputs are not inherited from the parent, pipe outputs to temp file */ + if (!inherit_outputs) { + /* setup stdout and stderr */ + xclose(1); + xclose(2); + if (dup2(jr->output_fd, 1) != 1 || dup2(jr->output_fd, 2) != 2) + die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ + in_background = 0; /* now, errors will be mailed to the user */ + } + if (chdir("/")) die_e("Can't chdir to '/'"); if (sigprocmask(SIG_SETMASK, &old_sigmask, NULL)) @@ -291,6 +295,7 @@ launch_job(job_rec *jr) char *mailfrom; char mailto_expanded[MAX_EMAILSTR]; char mailfrom_expanded[MAX_EMAILSTR]; + int inherit_outputs; /* get hostname */ if (gethostname(hostname, 512)) { @@ -299,69 +304,75 @@ launch_job(job_rec *jr) setup_env(jr); - /* Get the destination email address if set, or current user otherwise */ - mailto = getenv("MAILTO"); - if (mailto == NULL) { - mailto = username(); - } - else { - if (expand_envvar(mailto, mailto_expanded, sizeof(mailto_expanded))) { - mailto = mailto_expanded; + inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL; + + /* Set up email functionality if outputs should *not* be inherited */ + if (!inherit_outputs) { + /* Get the destination email address if set, or current user otherwise */ + mailto = getenv("MAILTO"); + if (mailto == NULL) { + mailto = username(); } else { - complain("The environment variable 'MAILTO' could not be expanded. The non-expanded value will be used."); - } - } + if (expand_envvar(mailto, mailto_expanded, sizeof(mailto_expanded))) { + mailto = mailto_expanded; + } + else { + complain("The environment variable 'MAILTO' could not be expanded. The non-expanded value will be used."); + } + } - /* Get the source email address if set, or current user otherwise */ - mailfrom = getenv("MAILFROM"); - if (mailfrom == NULL) { - mailfrom = username(); - } - else { - if (expand_envvar(mailfrom, mailfrom_expanded, sizeof(mailfrom_expanded))) { - mailfrom = mailfrom_expanded; + /* Get the source email address if set, or current user otherwise */ + mailfrom = getenv("MAILFROM"); + if (mailfrom == NULL) { + mailfrom = username(); } else { - complain("The environment variable 'MAILFROM' could not be expanded. The non-expanded value will be used."); - } - } + if (expand_envvar(mailfrom, mailfrom_expanded, sizeof(mailfrom_expanded))) { + mailfrom = mailfrom_expanded; + } + else { + complain("The environment variable 'MAILFROM' could not be expanded. The non-expanded value will be used."); + } + } - /* create temporary file for stdout and stderr of the job */ - temp_file(jr); fd = jr->output_fd; - /* write mail header */ - xwrite(fd, "From: "); - xwrite(fd, "Anacron <"); - xwrite(fd, mailfrom); - xwrite(fd, ">\n"); - xwrite(fd, "To: "); - xwrite(fd, mailto); - xwrite(fd, "\n"); - xwrite(fd, "MIME-Version: 1.0\n"); - xwrite(fd, "Content-Type: text/plain; charset=\""); - xwrite(fd, nl_langinfo(CODESET)); - xwrite(fd, "\"\n"); - xwrite(fd, "Content-Transfer-Encoding: 8bit\n"); - xwrite(fd, "Subject: Anacron job '"); - xwrite(fd, jr->ident); - xwrite(fd, "' on "); - xwrite(fd, hostname); - xwrite(fd, "\n\n"); - - if (*mailto == '\0') - jr->mailto = NULL; - else - /* ugly but works without strdup() */ - jr->mailto = mailto; - - jr->mail_header_size = file_size(fd); + /* create temporary file for stdout and stderr of the job */ + temp_file(jr); fd = jr->output_fd; + /* write mail header */ + xwrite(fd, "From: "); + xwrite(fd, "Anacron <"); + xwrite(fd, mailfrom); + xwrite(fd, ">\n"); + xwrite(fd, "To: "); + xwrite(fd, mailto); + xwrite(fd, "\n"); + xwrite(fd, "MIME-Version: 1.0\n"); + xwrite(fd, "Content-Type: text/plain; charset=\""); + xwrite(fd, nl_langinfo(CODESET)); + xwrite(fd, "\"\n"); + xwrite(fd, "Content-Transfer-Encoding: 8bit\n"); + xwrite(fd, "Subject: Anacron job '"); + xwrite(fd, jr->ident); + xwrite(fd, "' on "); + xwrite(fd, hostname); + xwrite(fd, "\n\n"); + + if (*mailto == '\0') + jr->mailto = NULL; + else + /* ugly but works without strdup() */ + jr->mailto = mailto; + + jr->mail_header_size = file_size(fd); + + } pid = xfork(); if (pid == 0) { /* child */ in_background = 1; - run_job(jr); + run_job(jr, inherit_outputs); /* execution never gets here */ } /* parent */ From 9ed69f3d03a904a925ff5ab895b27f44ffaf0670 Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Wed, 26 Apr 2023 12:52:47 +0200 Subject: [PATCH 2/6] Make inherit_outputs field part of job_rec struct --- anacron/global.h | 1 + anacron/runjob.c | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/anacron/global.h b/anacron/global.h index 1856854..8b28d4f 100644 --- a/anacron/global.h +++ b/anacron/global.h @@ -62,6 +62,7 @@ struct job_rec1 { char *ident; char *command; char *mailto; + int inherit_outputs; int tab_line; int arg_num; diff --git a/anacron/runjob.c b/anacron/runjob.c index 102062b..62cb433 100644 --- a/anacron/runjob.c +++ b/anacron/runjob.c @@ -163,11 +163,11 @@ setup_env(const job_rec *jr) } static void -run_job(const job_rec *jr, int inherit_outputs) +run_job(const job_rec *jr) /* This is called to start the job, after the fork */ { /* If outputs are not inherited from the parent, pipe outputs to temp file */ - if (!inherit_outputs) { + if (!jr->inherit_outputs) { /* setup stdout and stderr */ xclose(1); xclose(2); @@ -295,7 +295,6 @@ launch_job(job_rec *jr) char *mailfrom; char mailto_expanded[MAX_EMAILSTR]; char mailfrom_expanded[MAX_EMAILSTR]; - int inherit_outputs; /* get hostname */ if (gethostname(hostname, 512)) { @@ -304,10 +303,10 @@ launch_job(job_rec *jr) setup_env(jr); - inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL; + jr->inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL; /* Set up email functionality if outputs should *not* be inherited */ - if (!inherit_outputs) { + if (!jr->inherit_outputs) { /* Get the destination email address if set, or current user otherwise */ mailto = getenv("MAILTO"); if (mailto == NULL) { @@ -364,7 +363,6 @@ launch_job(job_rec *jr) jr->mailto = mailto; jr->mail_header_size = file_size(fd); - } pid = xfork(); @@ -372,7 +370,7 @@ launch_job(job_rec *jr) { /* child */ in_background = 1; - run_job(jr, inherit_outputs); + run_job(jr); /* execution never gets here */ } /* parent */ @@ -390,7 +388,7 @@ tend_job(job_rec *jr, int status) update_timestamp(jr); unlock(jr); - if (file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1; + if (!jr->inherit_outputs && file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1; else mail_output = 0; m = mail_output ? " (produced output)" : ""; @@ -408,8 +406,11 @@ tend_job(job_rec *jr, int status) jr->job_pid = 0; running_jobs--; if (mail_output) launch_mailer(jr); - xclose(jr->output_fd); - xclose(jr->input_fd); + /* output_fd and input_fd are only set if outputs are not inherited */ + if (!jr->inherit_outputs) { + xclose(jr->output_fd); + xclose(jr->input_fd); + } } void From fe05d65d703e2ecaafe45db4fa083804889368c5 Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Wed, 26 Apr 2023 13:00:53 +0200 Subject: [PATCH 3/6] Add check if inherit outputs is empty --- anacron/runjob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/anacron/runjob.c b/anacron/runjob.c index 62cb433..9b72651 100644 --- a/anacron/runjob.c +++ b/anacron/runjob.c @@ -303,7 +303,7 @@ launch_job(job_rec *jr) setup_env(jr); - jr->inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL; + jr->inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL && *getenv("INHERIT_OUTPUTS"); /* Set up email functionality if outputs should *not* be inherited */ if (!jr->inherit_outputs) { From 5063a3ef84571878029526c9d24ac85f5cffa40a Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Wed, 26 Apr 2023 13:15:10 +0200 Subject: [PATCH 4/6] Document changes --- anacron/runjob.c | 1 + man/anacrontab.5 | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/anacron/runjob.c b/anacron/runjob.c index 9b72651..5322424 100644 --- a/anacron/runjob.c +++ b/anacron/runjob.c @@ -303,6 +303,7 @@ launch_job(job_rec *jr) setup_env(jr); + /* Outputs are inherited if INHERIT_OUTPUTS is defined and non-empty */ jr->inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL && *getenv("INHERIT_OUTPUTS"); /* Set up email functionality if outputs should *not* be inherited */ diff --git a/man/anacrontab.5 b/man/anacrontab.5 index 507cfd8..f26ca3c 100644 --- a/man/anacrontab.5 +++ b/man/anacrontab.5 @@ -81,6 +81,10 @@ and .I MAILTO variables are expanded, so setting them as in the following example works as expected: MAILFROM=cron-$USER@cron.com ($USER is replaced by the system user) ) .PP +If +.I INHERIT_OUTPUTS +is defined (and non-empty), anacron's output includes the outputs of job processes and the mail functionality is disabled. +.PP .PP Empty lines are either blank lines, line containing white spaces only, or lines with white spaces followed by a '#' followed by an arbitrary From 13c46f5b216418894a4e901d227ecba3bcec4338 Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Wed, 26 Apr 2023 15:51:06 +0200 Subject: [PATCH 5/6] INHERIT_OUTPUTS -> NO_MAIL_OUTPUT --- anacron/global.h | 2 +- anacron/runjob.c | 17 ++++++++--------- man/anacrontab.5 | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/anacron/global.h b/anacron/global.h index 8b28d4f..5a5934c 100644 --- a/anacron/global.h +++ b/anacron/global.h @@ -62,7 +62,7 @@ struct job_rec1 { char *ident; char *command; char *mailto; - int inherit_outputs; + int no_mail_output; int tab_line; int arg_num; diff --git a/anacron/runjob.c b/anacron/runjob.c index 5322424..7457d51 100644 --- a/anacron/runjob.c +++ b/anacron/runjob.c @@ -166,8 +166,8 @@ static void run_job(const job_rec *jr) /* This is called to start the job, after the fork */ { - /* If outputs are not inherited from the parent, pipe outputs to temp file */ - if (!jr->inherit_outputs) { + /* If mail functionality is not disabled, pipe outputs to temp file */ + if (!jr->no_mail_output) { /* setup stdout and stderr */ xclose(1); xclose(2); @@ -303,11 +303,10 @@ launch_job(job_rec *jr) setup_env(jr); - /* Outputs are inherited if INHERIT_OUTPUTS is defined and non-empty */ - jr->inherit_outputs = getenv("INHERIT_OUTPUTS") != NULL && *getenv("INHERIT_OUTPUTS"); + jr->no_mail_output = getenv("NO_MAIL_OUTPUT") != NULL && *getenv("NO_MAIL_OUTPUT"); - /* Set up email functionality if outputs should *not* be inherited */ - if (!jr->inherit_outputs) { + /* Set up email functionality if it isn't disabled */ + if (!jr->no_mail_output) { /* Get the destination email address if set, or current user otherwise */ mailto = getenv("MAILTO"); if (mailto == NULL) { @@ -389,7 +388,7 @@ tend_job(job_rec *jr, int status) update_timestamp(jr); unlock(jr); - if (!jr->inherit_outputs && file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1; + if (!jr->no_mail_output && file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1; else mail_output = 0; m = mail_output ? " (produced output)" : ""; @@ -407,8 +406,8 @@ tend_job(job_rec *jr, int status) jr->job_pid = 0; running_jobs--; if (mail_output) launch_mailer(jr); - /* output_fd and input_fd are only set if outputs are not inherited */ - if (!jr->inherit_outputs) { + /* output_fd and input_fd are only set if mail functionality is enabled */ + if (!jr->no_mail_output) { xclose(jr->output_fd); xclose(jr->input_fd); } diff --git a/man/anacrontab.5 b/man/anacrontab.5 index f26ca3c..9badb57 100644 --- a/man/anacrontab.5 +++ b/man/anacrontab.5 @@ -82,7 +82,7 @@ and variables are expanded, so setting them as in the following example works as expected: MAILFROM=cron-$USER@cron.com ($USER is replaced by the system user) ) .PP If -.I INHERIT_OUTPUTS +.I NO_MAIL_OUTPUT is defined (and non-empty), anacron's output includes the outputs of job processes and the mail functionality is disabled. .PP .PP From 74e32d877ba93b540e449b3ce461b2c991273fe1 Mon Sep 17 00:00:00 2001 From: JohnnyJayJay Date: Thu, 27 Apr 2023 11:32:31 +0200 Subject: [PATCH 6/6] Apply changes suggested in review --- anacron/runjob.c | 10 ++++++---- man/anacrontab.5 | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/anacron/runjob.c b/anacron/runjob.c index 7457d51..050ef20 100644 --- a/anacron/runjob.c +++ b/anacron/runjob.c @@ -172,7 +172,7 @@ run_job(const job_rec *jr) xclose(1); xclose(2); if (dup2(jr->output_fd, 1) != 1 || dup2(jr->output_fd, 2) != 2) - die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ + die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ in_background = 0; /* now, errors will be mailed to the user */ } @@ -295,6 +295,7 @@ launch_job(job_rec *jr) char *mailfrom; char mailto_expanded[MAX_EMAILSTR]; char mailfrom_expanded[MAX_EMAILSTR]; + char *no_mail_output; /* get hostname */ if (gethostname(hostname, 512)) { @@ -303,7 +304,8 @@ launch_job(job_rec *jr) setup_env(jr); - jr->no_mail_output = getenv("NO_MAIL_OUTPUT") != NULL && *getenv("NO_MAIL_OUTPUT"); + no_mail_output = getenv("NO_MAIL_OUTPUT"); + jr->no_mail_output = no_mail_output != NULL && *no_mail_output; /* Set up email functionality if it isn't disabled */ if (!jr->no_mail_output) { @@ -388,8 +390,8 @@ tend_job(job_rec *jr, int status) update_timestamp(jr); unlock(jr); - if (!jr->no_mail_output && file_size(jr->output_fd) > jr->mail_header_size) mail_output = 1; - else mail_output = 0; + + mail_output = !jr->no_mail_output && file_size(jr->output_fd) > jr->mail_header_size; m = mail_output ? " (produced output)" : ""; if (WIFEXITED(status) && WEXITSTATUS(status) == 0) diff --git a/man/anacrontab.5 b/man/anacrontab.5 index 9badb57..f7ca5c0 100644 --- a/man/anacrontab.5 +++ b/man/anacrontab.5 @@ -83,7 +83,7 @@ variables are expanded, so setting them as in the following example works as exp .PP If .I NO_MAIL_OUTPUT -is defined (and non-empty), anacron's output includes the outputs of job processes and the mail functionality is disabled. +is defined (and non-empty), the standard output and error descriptors of job processes are not redirected and e-mailed. .PP .PP Empty lines are either blank lines, line containing white spaces only, or