crond: implement support for setting PATH in crontab files
It's very inconvenient for a cron user not to be able to set a "personal" PATH for their cron jobs, as is possible with other crons function old new delta load_crontab 868 942 +74 .rodata 104878 104884 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 80/0) Total: 80 bytes Signed-off-by: Paul Fox <pgf@foxharp.boston.ma.us> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -125,6 +125,7 @@ typedef struct CronLine { | |||||||
| 	char *cl_mailto;                /* whom to mail results, may be NULL */ | 	char *cl_mailto;                /* whom to mail results, may be NULL */ | ||||||
| #endif | #endif | ||||||
| 	char *cl_shell; | 	char *cl_shell; | ||||||
|  | 	char *cl_path; | ||||||
| 	/* ordered by size, not in natural order. makes code smaller: */ | 	/* ordered by size, not in natural order. makes code smaller: */ | ||||||
| 	char cl_Dow[7];                 /* 0-6, beginning sunday */ | 	char cl_Dow[7];                 /* 0-6, beginning sunday */ | ||||||
| 	char cl_Mons[12];               /* 0-11 */ | 	char cl_Mons[12];               /* 0-11 */ | ||||||
| @@ -421,6 +422,7 @@ static void load_crontab(const char *fileName) | |||||||
| 	char *mailTo = NULL; | 	char *mailTo = NULL; | ||||||
| #endif | #endif | ||||||
| 	char *shell = NULL; | 	char *shell = NULL; | ||||||
|  | 	char *path = NULL; | ||||||
|  |  | ||||||
| 	delete_cronfile(fileName); | 	delete_cronfile(fileName); | ||||||
|  |  | ||||||
| @@ -470,7 +472,12 @@ static void load_crontab(const char *fileName) | |||||||
| 				shell = xstrdup(&tokens[0][6]); | 				shell = xstrdup(&tokens[0][6]); | ||||||
| 				continue; | 				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 | //name = value | ||||||
| // | // | ||||||
| //where the spaces around the equal-sign (=) are optional, and any subsequent | //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. | //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 | //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 | //line of the crontab's owner.  HOME, SHELL, and PATH may be overridden by | ||||||
| //in the crontab; LOGNAME may not. | //settings in the crontab; LOGNAME may not. | ||||||
|  |  | ||||||
| #if ENABLE_FEATURE_CROND_SPECIAL_TIMES | #if ENABLE_FEATURE_CROND_SPECIAL_TIMES | ||||||
| 			if (tokens[0][0] == '@') { | 			if (tokens[0][0] == '@') { | ||||||
| @@ -567,6 +574,7 @@ static void load_crontab(const char *fileName) | |||||||
| 			line->cl_mailto = xstrdup(mailTo); | 			line->cl_mailto = xstrdup(mailTo); | ||||||
| #endif | #endif | ||||||
| 			line->cl_shell = xstrdup(shell); | 			line->cl_shell = xstrdup(shell); | ||||||
|  | 			line->cl_path = xstrdup(path); | ||||||
| 			/* copy command */ | 			/* copy command */ | ||||||
| 			line->cl_cmd = xstrdup(tokens[5]); | 			line->cl_cmd = xstrdup(tokens[5]); | ||||||
| 			pline = &line->cl_next; | 			pline = &line->cl_next; | ||||||
| @@ -653,21 +661,22 @@ static void safe_setenv(char **pvar_val, const char *var, const char *val) | |||||||
| } | } | ||||||
| #endif | #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. | 	/* POSIX requires crond to set up at least HOME, LOGNAME, PATH, SHELL. | ||||||
| 	 * We assume crond inherited suitable PATH. |  | ||||||
| 	 */ | 	 */ | ||||||
| #if SETENV_LEAKS | #if SETENV_LEAKS | ||||||
| 	safe_setenv(&G.env_var_logname, "LOGNAME", pas->pw_name); | 	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_user, "USER", pas->pw_name); | ||||||
| 	safe_setenv(&G.env_var_home, "HOME", pas->pw_dir); | 	safe_setenv(&G.env_var_home, "HOME", pas->pw_dir); | ||||||
| 	safe_setenv(&G.env_var_shell, "SHELL", shell); | 	safe_setenv(&G.env_var_shell, "SHELL", shell); | ||||||
|  | 	if (path) safe_setenv(&G.env_var_shell, "PATH", path); | ||||||
| #else | #else | ||||||
| 	xsetenv("LOGNAME", pas->pw_name); | 	xsetenv("LOGNAME", pas->pw_name); | ||||||
| 	xsetenv("USER", pas->pw_name); | 	xsetenv("USER", pas->pw_name); | ||||||
| 	xsetenv("HOME", pas->pw_dir); | 	xsetenv("HOME", pas->pw_dir); | ||||||
| 	xsetenv("SHELL", shell); | 	xsetenv("SHELL", shell); | ||||||
|  | 	if (path) xsetenv("PATH", path); | ||||||
| #endif | #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; | 	shell = line->cl_shell ? line->cl_shell : G.default_shell; | ||||||
| 	prog = run_sendmail ? SENDMAIL : 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; | 	sv_logmode = logmode; | ||||||
| 	pid = vfork(); | 	pid = vfork(); | ||||||
| @@ -845,7 +854,7 @@ static pid_t start_one_job(const char *user, CronLine *line) | |||||||
|  |  | ||||||
| 	/* Prepare things before vfork */ | 	/* Prepare things before vfork */ | ||||||
| 	shell = line->cl_shell ? line->cl_shell : G.default_shell; | 	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 */ | 	/* Fork as the user in question and run program */ | ||||||
| 	pid = vfork(); | 	pid = vfork(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user