Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/cron/cron/do_command.c
Show First 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
int stdin_pipe[2], stdout_pipe[2]; | int stdin_pipe[2], stdout_pipe[2]; | ||||
register char *input_data; | register char *input_data; | ||||
char *usernm, *mailto, *mailfrom; | char *usernm, *mailto, *mailfrom; | ||||
PID_T jobpid, stdinjob, mailpid; | PID_T jobpid, stdinjob, mailpid; | ||||
register FILE *mail; | register FILE *mail; | ||||
register int bytes = 1; | register int bytes = 1; | ||||
int status = 0; | int status = 0; | ||||
const char *homedir = NULL; | |||||
# if defined(LOGIN_CAP) | # if defined(LOGIN_CAP) | ||||
struct passwd *pwd; | struct passwd *pwd; | ||||
login_cap_t *lc; | login_cap_t *lc; | ||||
# endif | # endif | ||||
Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd)) | Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd)) | ||||
/* mark ourselves as different to PS command watchers by upshifting | /* mark ourselves as different to PS command watchers by upshifting | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | |||||
# if defined(LOGIN_CAP) | # if defined(LOGIN_CAP) | ||||
/* Set user's entire context, but note that PATH will | /* Set user's entire context, but note that PATH will | ||||
* be overridden later | * be overridden later | ||||
*/ | */ | ||||
if ((pwd = getpwnam(usernm)) == NULL) | if ((pwd = getpwnam(usernm)) == NULL) | ||||
pwd = getpwuid(e->uid); | pwd = getpwuid(e->uid); | ||||
lc = NULL; | lc = NULL; | ||||
if (pwd != NULL) { | if (pwd != NULL) { | ||||
if (pwd->pw_dir != NULL | |||||
&& pwd->pw_dir[0] != '\0') { | |||||
kevans: The style around here is so odd, but I did confirm this lined up with the prevailing wrapping... | |||||
homedir = strdup(pwd->pw_dir); | |||||
Done Inline Actions...here. Should it be done also in the !LOGIN_CAP case? sigsys_gmail.com: ...here. Should it be done also in the !LOGIN_CAP case? | |||||
Done Inline ActionsGood catch. Looks like the simplest fix is to put it back in entry.c in the !LOGIN_CAP case. andrew_tao173.riddles.org.uk: Good catch. Looks like the simplest fix is to put it back in entry.c in the !LOGIN_CAP case. | |||||
if (homedir == NULL) { | |||||
warn("strdup"); | |||||
_exit(ERROR_EXIT); | |||||
} | |||||
} | |||||
pwd->pw_gid = e->gid; | pwd->pw_gid = e->gid; | ||||
if (e->class != NULL) | if (e->class != NULL) | ||||
lc = login_getclass(e->class); | lc = login_getclass(e->class); | ||||
} | } | ||||
if (pwd && | if (pwd && | ||||
setusercontext(lc, pwd, e->uid, | setusercontext(lc, pwd, e->uid, | ||||
LOGIN_SETALL) == 0) | LOGIN_SETALL) == 0) | ||||
(void) endpwent(); | (void) endpwent(); | ||||
Show All 27 Lines | # endif | ||||
_exit(ERROR_EXIT); | _exit(ERROR_EXIT); | ||||
} | } | ||||
/* we aren't root after this..*/ | /* we aren't root after this..*/ | ||||
#if defined(LOGIN_CAP) | #if defined(LOGIN_CAP) | ||||
} | } | ||||
if (lc != NULL) | if (lc != NULL) | ||||
login_close(lc); | login_close(lc); | ||||
#endif | #endif | ||||
chdir(env_get("HOME", e->envp)); | |||||
/* exec the command. | /* For compatibility, we chdir to the value of HOME if it was | ||||
* specified explicitly in the crontab file, but not if it was | |||||
* set in the environment by some other mechanism. We chdir to | |||||
* the homedir given by the pw entry otherwise. | |||||
* | |||||
* If !LOGIN_CAP, then HOME is always set in e->envp. | |||||
* | |||||
* XXX: probably should also consult PAM. | |||||
*/ | */ | ||||
{ | { | ||||
char *new_home = env_get("HOME", e->envp); | |||||
if (new_home != NULL && new_home[0] != '\0') | |||||
chdir(new_home); | |||||
else if (homedir != NULL) | |||||
chdir(homedir); | |||||
else | |||||
chdir("/"); | |||||
} | |||||
/* exec the command. Note that SHELL is not respected from | |||||
* either login.conf or pw_shell, only an explicit setting | |||||
* in the crontab. (default of _PATH_BSHELL is supplied when | |||||
* setting up the entry) | |||||
*/ | |||||
{ | |||||
char *shell = env_get("SHELL", e->envp); | char *shell = env_get("SHELL", e->envp); | ||||
char **p; | char **p; | ||||
/* Apply the environment from the entry, overriding existing | /* Apply the environment from the entry, overriding | ||||
* values (this will always set PATH, LOGNAME, etc.) putenv | * existing values (this will always set LOGNAME and | ||||
* should not fail unless malloc does. | * SHELL). putenv should not fail unless malloc does. | ||||
*/ | */ | ||||
for (p = e->envp; *p; ++p) { | for (p = e->envp; *p; ++p) { | ||||
if (putenv(*p) != 0) { | if (putenv(*p) != 0) { | ||||
warn("putenv"); | warn("putenv"); | ||||
_exit(ERROR_EXIT); | _exit(ERROR_EXIT); | ||||
} | } | ||||
} | |||||
/* HOME in login.conf overrides pw, and HOME in the | |||||
* crontab overrides both. So set pw's value only if | |||||
* nothing was already set (overwrite==0). | |||||
*/ | |||||
if (homedir != NULL | |||||
&& setenv("HOME", homedir, 0) < 0) { | |||||
warn("setenv(HOME)"); | |||||
_exit(ERROR_EXIT); | |||||
} | |||||
/* PATH in login.conf is respected, but the crontab | |||||
* overrides; set a default value only if nothing | |||||
* already set. | |||||
*/ | |||||
if (setenv("PATH", _PATH_DEFPATH, 0) < 0) { | |||||
warn("setenv(PATH)"); | |||||
_exit(ERROR_EXIT); | |||||
} | } | ||||
# if DEBUGGING | # if DEBUGGING | ||||
if (DebugFlags & DTEST) { | if (DebugFlags & DTEST) { | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"debug DTEST is on, not exec'ing command.\n"); | "debug DTEST is on, not exec'ing command.\n"); | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"\tcmd='%s' shell='%s'\n", e->cmd, shell); | "\tcmd='%s' shell='%s'\n", e->cmd, shell); | ||||
▲ Show 20 Lines • Show All 277 Lines • Show Last 20 Lines |
The style around here is so odd, but I did confirm this lined up with the prevailing wrapping...