From 7466dbd684879cbe8d034f388f0c7da703e00c31 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 5 Feb 2020 04:35:54 +0000 Subject: [PATCH] cron(8): set the environment variables of the user and/or login class Prior to processing environment variable set in the crontab file as those should be of higher precedent, pull in the user or login class environment. This is another supporting feature for allowing one to configure system-wide settings that may affect both regular cron jobs as well as services. This is the final part of D21481. Submitted by: Andrew Gierth --- usr.sbin/cron/cron/do_command.c | 27 +++++++++++++++++++++------ usr.sbin/cron/crontab/crontab.5 | 12 ++++++++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/usr.sbin/cron/cron/do_command.c b/usr.sbin/cron/cron/do_command.c index 4a9a49e6c8a..375f55caf7c 100644 --- a/usr.sbin/cron/cron/do_command.c +++ b/usr.sbin/cron/cron/do_command.c @@ -43,6 +43,8 @@ static void child_process(entry *, user *), static WAIT_T wait_on_child(PID_T, const char *); +extern char *environ; + void do_command(e, u) entry *e; @@ -285,9 +287,11 @@ child_process(e, u) */ do_univ(u); + environ = NULL; + # if defined(LOGIN_CAP) - /* Set user's entire context, but skip the environment - * as cron provides a separate interface for this + /* Set user's entire context, but note that PATH will + * be overridden later */ if ((pwd = getpwnam(usernm)) == NULL) pwd = getpwuid(e->uid); @@ -299,7 +303,7 @@ child_process(e, u) } if (pwd && setusercontext(lc, pwd, e->uid, - LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETENV)) == 0) + LOGIN_SETALL) == 0) (void) endpwent(); else { /* fall back to the old method */ @@ -342,6 +346,18 @@ child_process(e, u) */ { char *shell = env_get("SHELL", e->envp); + char **p; + + /* Apply the environment from the entry, overriding existing + * values (this will always set PATH, LOGNAME, etc.) putenv + * should not fail unless malloc does. + */ + for (p = e->envp; *p; ++p) { + if (putenv(*p) != 0) { + warn("putenv"); + _exit(ERROR_EXIT); + } + } # if DEBUGGING if (DebugFlags & DTEST) { @@ -352,9 +368,8 @@ child_process(e, u) _exit(OK_EXIT); } # endif /*DEBUGGING*/ - execle(shell, shell, "-c", e->cmd, (char *)NULL, - e->envp); - warn("execle: couldn't exec `%s'", shell); + execl(shell, shell, "-c", e->cmd, (char *)NULL); + warn("execl: couldn't exec `%s'", shell); _exit(ERROR_EXIT); } break; diff --git a/usr.sbin/cron/crontab/crontab.5 b/usr.sbin/cron/crontab/crontab.5 index 9943adfaf35..adc2b2b5ae9 100644 --- a/usr.sbin/cron/crontab/crontab.5 +++ b/usr.sbin/cron/crontab/crontab.5 @@ -17,7 +17,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 24, 2019 +.Dd January 19, 2020 .Dt CRONTAB 5 .Os .Sh NAME @@ -82,10 +82,18 @@ and are set from the .Pa /etc/passwd line of the crontab's owner. +In addition, the environment variables of the +user's login class, with the exception of +.Ev PATH , +will be set from +.Pa /etc/login.conf.db +and +.Pa ~/.login_conf . .Ev HOME , .Ev PATH and -.Ev SHELL +.Ev SHELL , +and any variables set from the login class, may be overridden by settings in the crontab; .Ev LOGNAME may not.