crond: implement "SHELL=prog" in crontab. Export LOGNAME as POSIX wants
function old new delta fork_job 343 456 +113 load_crontab 688 777 +89 crond_main 1456 1434 -22 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 202/-22) Total: 180 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
d5929d602e
commit
43b8a1cc38
@ -104,6 +104,7 @@ typedef struct CronLine {
|
|||||||
int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */
|
int cl_empty_mail_size; /* size of mail header only, 0 if no mailfile */
|
||||||
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;
|
||||||
/* 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 */
|
||||||
@ -135,6 +136,8 @@ struct globals {
|
|||||||
#if SETENV_LEAKS
|
#if SETENV_LEAKS
|
||||||
char *env_var_user;
|
char *env_var_user;
|
||||||
char *env_var_home;
|
char *env_var_home;
|
||||||
|
char *env_var_shell;
|
||||||
|
char *env_var_logname;
|
||||||
#endif
|
#endif
|
||||||
} FIX_ALIASING;
|
} FIX_ALIASING;
|
||||||
#define G (*(struct globals*)&bb_common_bufsiz1)
|
#define G (*(struct globals*)&bb_common_bufsiz1)
|
||||||
@ -397,6 +400,7 @@ static void load_crontab(const char *fileName)
|
|||||||
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
|
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
|
||||||
char *mailTo = NULL;
|
char *mailTo = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
char *shell = NULL;
|
||||||
|
|
||||||
delete_cronfile(fileName);
|
delete_cronfile(fileName);
|
||||||
|
|
||||||
@ -441,7 +445,12 @@ static void load_crontab(const char *fileName)
|
|||||||
#endif /* otherwise just ignore such lines */
|
#endif /* otherwise just ignore such lines */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//TODO: handle SHELL=, HOME= too? "man crontab" says:
|
if (0 == strncmp(tokens[0], "SHELL=", 6)) {
|
||||||
|
free(shell);
|
||||||
|
shell = xstrdup(&tokens[0][6]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//TODO: handle HOME= too? "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
|
||||||
@ -453,6 +462,7 @@ static void load_crontab(const char *fileName)
|
|||||||
//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 and SHELL may be overridden by settings
|
||||||
//in the crontab; LOGNAME may not.
|
//in the crontab; LOGNAME may not.
|
||||||
|
|
||||||
/* check if a minimum of tokens is specified */
|
/* check if a minimum of tokens is specified */
|
||||||
if (n < 6)
|
if (n < 6)
|
||||||
continue;
|
continue;
|
||||||
@ -472,9 +482,9 @@ static void load_crontab(const char *fileName)
|
|||||||
/* copy mailto (can be NULL) */
|
/* copy mailto (can be NULL) */
|
||||||
line->cl_mailto = xstrdup(mailTo);
|
line->cl_mailto = xstrdup(mailTo);
|
||||||
#endif
|
#endif
|
||||||
|
line->cl_shell = xstrdup(shell);
|
||||||
/* copy command */
|
/* copy command */
|
||||||
line->cl_cmd = xstrdup(tokens[5]);
|
line->cl_cmd = xstrdup(tokens[5]);
|
||||||
log5(" command:%s", tokens[5]);
|
|
||||||
pline = &line->cl_next;
|
pline = &line->cl_next;
|
||||||
//bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
|
//bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
|
||||||
}
|
}
|
||||||
@ -484,6 +494,10 @@ static void load_crontab(const char *fileName)
|
|||||||
G.cron_files = file;
|
G.cron_files = file;
|
||||||
}
|
}
|
||||||
config_close(parser);
|
config_close(parser);
|
||||||
|
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
|
||||||
|
free(mailTo);
|
||||||
|
#endif
|
||||||
|
free(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_cron_update_file(void)
|
static void process_cron_update_file(void)
|
||||||
@ -555,19 +569,22 @@ static void safe_setenv(char **pvar_val, const char *var, const char *val)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void set_env_vars(struct passwd *pas)
|
static void set_env_vars(struct passwd *pas, const char *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_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);
|
||||||
/* if we want to set user's shell instead: */
|
safe_setenv(&G.env_var_shell, "SHELL", shell);
|
||||||
/*safe_setenv(G.env_var_shell, "SHELL", pas->pw_shell);*/
|
|
||||||
#else
|
#else
|
||||||
|
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);
|
||||||
#endif
|
#endif
|
||||||
/* currently, we use constant one: */
|
|
||||||
/*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void change_user(struct passwd *pas)
|
static void change_user(struct passwd *pas)
|
||||||
@ -584,12 +601,11 @@ static void change_user(struct passwd *pas)
|
|||||||
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
|
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
|
||||||
|
|
||||||
static pid_t
|
static pid_t
|
||||||
fork_job(const char *user, int mailFd,
|
fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail)
|
||||||
const char *prog,
|
{
|
||||||
const char *shell_cmd /* if NULL, we run sendmail */
|
|
||||||
) {
|
|
||||||
smallint sv_logmode;
|
|
||||||
struct passwd *pas;
|
struct passwd *pas;
|
||||||
|
const char *shell, *prog;
|
||||||
|
smallint sv_logmode;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
/* prepare things before vfork */
|
/* prepare things before vfork */
|
||||||
@ -598,7 +614,11 @@ fork_job(const char *user, int mailFd,
|
|||||||
bb_error_msg("can't get uid for %s", user);
|
bb_error_msg("can't get uid for %s", user);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
set_env_vars(pas);
|
|
||||||
|
shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL;
|
||||||
|
prog = run_sendmail ? SENDMAIL : shell;
|
||||||
|
|
||||||
|
set_env_vars(pas, shell);
|
||||||
|
|
||||||
sv_logmode = logmode;
|
sv_logmode = logmode;
|
||||||
pid = vfork();
|
pid = vfork();
|
||||||
@ -608,12 +628,15 @@ fork_job(const char *user, int mailFd,
|
|||||||
change_user(pas);
|
change_user(pas);
|
||||||
log5("child running %s", prog);
|
log5("child running %s", prog);
|
||||||
if (mailFd >= 0) {
|
if (mailFd >= 0) {
|
||||||
xmove_fd(mailFd, shell_cmd ? 1 : 0);
|
xmove_fd(mailFd, run_sendmail ? 0 : 1);
|
||||||
dup2(1, 2);
|
dup2(1, 2);
|
||||||
}
|
}
|
||||||
/* crond 3.0pl1-100 puts tasks in separate process groups */
|
/* crond 3.0pl1-100 puts tasks in separate process groups */
|
||||||
bb_setpgrp();
|
bb_setpgrp();
|
||||||
execlp(prog, prog, (shell_cmd ? "-c" : SENDMAIL_ARGS), shell_cmd, (char *) NULL);
|
if (!run_sendmail)
|
||||||
|
execlp(prog, prog, "-c", line->cl_cmd, (char *) NULL);
|
||||||
|
else
|
||||||
|
execlp(prog, prog, SENDMAIL_ARGS, (char *) NULL);
|
||||||
/*
|
/*
|
||||||
* I want this error message on stderr too,
|
* I want this error message on stderr too,
|
||||||
* even if other messages go only to syslog:
|
* even if other messages go only to syslog:
|
||||||
@ -662,7 +685,7 @@ static void start_one_job(const char *user, CronLine *line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line->cl_pid = fork_job(user, mailFd, DEFAULT_SHELL, line->cl_cmd);
|
line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 0);
|
||||||
if (mailFd >= 0) {
|
if (mailFd >= 0) {
|
||||||
if (line->cl_pid <= 0) {
|
if (line->cl_pid <= 0) {
|
||||||
unlink(mailFile);
|
unlink(mailFile);
|
||||||
@ -718,13 +741,14 @@ static void process_finished_job(const char *user, CronLine *line)
|
|||||||
}
|
}
|
||||||
line->cl_empty_mail_size = 0;
|
line->cl_empty_mail_size = 0;
|
||||||
/* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */
|
/* if (line->cl_mailto) - always true if cl_empty_mail_size was nonzero */
|
||||||
line->cl_pid = fork_job(user, mailFd, SENDMAIL, NULL);
|
line->cl_pid = fork_job(user, mailFd, line, /*sendmail?*/ 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */
|
#else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */
|
||||||
|
|
||||||
static void start_one_job(const char *user, CronLine *line)
|
static void start_one_job(const char *user, CronLine *line)
|
||||||
{
|
{
|
||||||
|
const char *shell;
|
||||||
struct passwd *pas;
|
struct passwd *pas;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
@ -735,7 +759,8 @@ static void start_one_job(const char *user, CronLine *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare things before vfork */
|
/* Prepare things before vfork */
|
||||||
set_env_vars(pas);
|
shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL;
|
||||||
|
set_env_vars(pas, shell);
|
||||||
|
|
||||||
/* Fork as the user in question and run program */
|
/* Fork as the user in question and run program */
|
||||||
pid = vfork();
|
pid = vfork();
|
||||||
@ -743,11 +768,11 @@ static void start_one_job(const char *user, CronLine *line)
|
|||||||
/* CHILD */
|
/* CHILD */
|
||||||
/* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
|
/* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
|
||||||
change_user(pas);
|
change_user(pas);
|
||||||
log5("child running %s", DEFAULT_SHELL);
|
log5("child running %s", shell);
|
||||||
/* crond 3.0pl1-100 puts tasks in separate process groups */
|
/* crond 3.0pl1-100 puts tasks in separate process groups */
|
||||||
bb_setpgrp();
|
bb_setpgrp();
|
||||||
execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL);
|
execl(shell, shell, "-c", line->cl_cmd, (char *) NULL);
|
||||||
bb_error_msg_and_die("can't execute '%s' for user %s", DEFAULT_SHELL, user);
|
bb_error_msg_and_die("can't execute '%s' for user %s", shell, user);
|
||||||
}
|
}
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
bb_perror_msg("vfork");
|
bb_perror_msg("vfork");
|
||||||
@ -916,11 +941,10 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
logmode = LOGMODE_SYSLOG;
|
logmode = LOGMODE_SYSLOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
reopen_logfile_to_stderr();
|
|
||||||
|
|
||||||
xchdir(G.crontab_dir_name);
|
|
||||||
//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
|
//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
|
||||||
xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
|
|
||||||
|
reopen_logfile_to_stderr();
|
||||||
|
xchdir(G.crontab_dir_name);
|
||||||
log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
|
log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
|
||||||
rescan_crontab_dir();
|
rescan_crontab_dir();
|
||||||
write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");
|
write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");
|
||||||
|
Loading…
Reference in New Issue
Block a user