diff --git a/miscutils/crond.c b/miscutils/crond.c index 1965af656..bd43c6b68 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -125,6 +125,7 @@ typedef struct CronLine { char *cl_mailto; /* whom to mail results, may be NULL */ #endif char *cl_shell; + char *cl_path; /* ordered by size, not in natural order. makes code smaller: */ char cl_Dow[7]; /* 0-6, beginning sunday */ char cl_Mons[12]; /* 0-11 */ @@ -421,6 +422,7 @@ static void load_crontab(const char *fileName) char *mailTo = NULL; #endif char *shell = NULL; + char *path = NULL; delete_cronfile(fileName); @@ -470,7 +472,12 @@ static void load_crontab(const char *fileName) shell = xstrdup(&tokens[0][6]); continue; } -//TODO: handle HOME= too? "man crontab" says: + if (is_prefixed_with(tokens[0], "PATH=")) { + free(path); + path = xstrdup(&tokens[0][5]); + continue; + } +//TODO: handle HOME= too? Better yet, handle arbitrary ENVVARs? "man crontab" says: //name = value // //where the spaces around the equal-sign (=) are optional, and any subsequent @@ -480,8 +487,8 @@ static void load_crontab(const char *fileName) // //Several environment variables are set up automatically by the cron(8) daemon. //SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd -//line of the crontab's owner. HOME and SHELL may be overridden by settings -//in the crontab; LOGNAME may not. +//line of the crontab's owner. HOME, SHELL, and PATH may be overridden by +//settings in the crontab; LOGNAME may not. #if ENABLE_FEATURE_CROND_SPECIAL_TIMES if (tokens[0][0] == '@') { @@ -567,6 +574,7 @@ static void load_crontab(const char *fileName) line->cl_mailto = xstrdup(mailTo); #endif line->cl_shell = xstrdup(shell); + line->cl_path = xstrdup(path); /* copy command */ line->cl_cmd = xstrdup(tokens[5]); pline = &line->cl_next; @@ -653,21 +661,22 @@ static void safe_setenv(char **pvar_val, const char *var, const char *val) } #endif -static void set_env_vars(struct passwd *pas, const char *shell) +static void set_env_vars(struct passwd *pas, const char *shell, const char *path) { /* POSIX requires crond to set up at least HOME, LOGNAME, PATH, SHELL. - * We assume crond inherited suitable PATH. */ #if SETENV_LEAKS safe_setenv(&G.env_var_logname, "LOGNAME", pas->pw_name); safe_setenv(&G.env_var_user, "USER", pas->pw_name); safe_setenv(&G.env_var_home, "HOME", pas->pw_dir); safe_setenv(&G.env_var_shell, "SHELL", shell); + if (path) safe_setenv(&G.env_var_shell, "PATH", path); #else xsetenv("LOGNAME", pas->pw_name); xsetenv("USER", pas->pw_name); xsetenv("HOME", pas->pw_dir); xsetenv("SHELL", shell); + if (path) xsetenv("PATH", path); #endif } @@ -701,7 +710,7 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail) shell = line->cl_shell ? line->cl_shell : G.default_shell; prog = run_sendmail ? SENDMAIL : shell; - set_env_vars(pas, shell); + set_env_vars(pas, shell, NULL); /* don't use crontab's PATH for sendmail */ sv_logmode = logmode; pid = vfork(); @@ -845,7 +854,7 @@ static pid_t start_one_job(const char *user, CronLine *line) /* Prepare things before vfork */ shell = line->cl_shell ? line->cl_shell : G.default_shell; - set_env_vars(pas, shell); + set_env_vars(pas, shell, line->cl_path); /* Fork as the user in question and run program */ pid = vfork();