1 /* Copyright 1988,1990,1993,1994 by Paul Vixie
6 * Copyright (c) 1997 by Internet Software Consortium
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
13 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
14 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
18 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 #if !defined(lint) && !defined(LINT)
23 static const char rcsid[] =
24 "$Id: do_command.c,v 1.3 1998/08/14 00:32:39 vixie Exp $";
28 #if defined(LOGIN_CAP)
29 # include <login_cap.h>
32 # include <security/pam_appl.h>
33 # include <security/openpam.h>
36 static void child_process(entry *, user *);
37 static WAIT_T wait_on_child(PID_T, const char *);
42 do_command(entry *e, user *u)
46 Debug(DPROC, ("[%d] do_command(%s, (%s,%d,%d))\n",
47 getpid(), e->cmd, u->name, e->uid, e->gid))
49 /* fork to become asynchronous -- parent process is done immediately,
50 * and continues to run the normal cron code, which means return to
51 * tick(). the child and grandchild don't leave this function, alive.
53 switch ((pid = fork())) {
55 log_it("CRON", getpid(), "error", "can't fork");
56 if (e->flags & INTERVAL)
57 e->lastexit = time(NULL);
63 Debug(DPROC, ("[%d] child process done, exiting\n", getpid()))
68 Debug(DPROC, ("[%d] main process forked child #%d, "
69 "returning to work\n", getpid(), pid))
70 if (e->flags & INTERVAL) {
76 Debug(DPROC, ("[%d] main process returning to work\n", getpid()))
81 child_process(entry *e, user *u)
83 int stdin_pipe[2], stdout_pipe[2];
85 const char *usernm, *mailto, *mailfrom;
86 PID_T jobpid, stdinjob, mailpid;
90 const char *homedir = NULL;
91 # if defined(LOGIN_CAP)
96 Debug(DPROC, ("[%d] child_process('%s')\n", getpid(), e->cmd))
98 /* mark ourselves as different to PS command watchers by upshifting
99 * our program name. This has no effect on some kernels.
101 setproctitle("running job");
103 /* discover some useful and important environment settings
105 usernm = env_get("LOGNAME", e->envp);
106 mailto = env_get("MAILTO", e->envp);
107 mailfrom = env_get("MAILFROM", e->envp);
110 /* use PAM to see if the user's account is available,
111 * i.e., not locked or expired or whatever. skip this
112 * for system tasks from /etc/crontab -- they can run
115 if (strcmp(u->name, SYS_NAME)) { /* not equal */
116 pam_handle_t *pamh = NULL;
118 struct pam_conv pamc = {
119 .conv = openpam_nullconv,
123 Debug(DPROC, ("[%d] checking account with PAM\n", getpid()))
125 /* u->name keeps crontab owner name while LOGNAME is the name
126 * of user to run command on behalf of. they should be the
127 * same for a task from a per-user crontab.
129 if (strcmp(u->name, usernm)) {
130 log_it(usernm, getpid(), "username ambiguity", u->name);
134 pam_err = pam_start("cron", usernm, &pamc, &pamh);
135 if (pam_err != PAM_SUCCESS) {
136 log_it("CRON", getpid(), "error", "can't start PAM");
140 pam_err = pam_acct_mgmt(pamh, PAM_SILENT);
141 /* Expired password shouldn't prevent the job from running. */
142 if (pam_err != PAM_SUCCESS && pam_err != PAM_NEW_AUTHTOK_REQD) {
143 log_it(usernm, getpid(), "USER", "account unavailable");
147 pam_end(pamh, pam_err);
151 /* our parent is watching for our death by catching SIGCHLD. we
152 * do not care to watch for our children's deaths this way -- we
153 * use wait() explicitly. so we have to disable the signal (which
154 * was inherited from the parent).
156 (void) signal(SIGCHLD, SIG_DFL);
158 /* create some pipes to talk to our future child
160 if (pipe(stdin_pipe) != 0 || pipe(stdout_pipe) != 0) {
161 log_it("CRON", getpid(), "error", "can't pipe");
165 /* since we are a forked process, we can diddle the command string
166 * we were passed -- nobody else is going to use it again, right?
168 * if a % is present in the command, previous characters are the
169 * command, and subsequent characters are the additional input to
170 * the command. Subsequent %'s will be transformed into newlines,
171 * but that happens later.
173 * If there are escaped %'s, remove the escape character.
180 for (input_data = p = e->cmd;
181 (ch = *input_data) != '\0';
186 if (ch == '%' || ch == '\\')
196 *input_data++ = '\0';
203 /* fork again, this time so we can exec the user's command.
205 switch (jobpid = fork()) {
207 log_it("CRON", getpid(), "error", "can't fork");
211 Debug(DPROC, ("[%d] grandchild process fork()'ed\n",
214 if (e->uid == ROOT_UID)
218 sleep(random() % Jitter);
221 /* write a log message. we've waited this long to do it
222 * because it was not until now that we knew the PID that
223 * the actual user command shell was going to get and the
224 * PID is part of the log message.
226 if ((e->flags & DONT_LOG) == 0) {
227 char *x = mkprints((u_char *)e->cmd, strlen(e->cmd));
229 log_it(usernm, getpid(), "CMD", x);
233 /* that's the last thing we'll log. close the log files.
239 /* get new pgrp, void tty, etc.
243 /* close the pipe ends that we won't use. this doesn't affect
244 * the parent, who has to read and write them; it keeps the
245 * kernel from recording us as a potential client TWICE --
246 * which would keep it from sending SIGPIPE in otherwise
247 * appropriate circumstances.
249 close(stdin_pipe[WRITE_PIPE]);
250 close(stdout_pipe[READ_PIPE]);
252 /* grandchild process. make std{in,out} be the ends of
253 * pipes opened by our daddy; make stderr go to stdout.
255 close(STDIN); dup2(stdin_pipe[READ_PIPE], STDIN);
256 close(STDOUT); dup2(stdout_pipe[WRITE_PIPE], STDOUT);
257 close(STDERR); dup2(STDOUT, STDERR);
259 /* close the pipes we just dup'ed. The resources will remain.
261 close(stdin_pipe[READ_PIPE]);
262 close(stdout_pipe[WRITE_PIPE]);
266 # if defined(LOGIN_CAP)
267 /* Set user's entire context, but note that PATH will
268 * be overridden later
270 if ((pwd = getpwnam(usernm)) == NULL)
271 pwd = getpwuid(e->uid);
274 if (pwd->pw_dir != NULL
275 && pwd->pw_dir[0] != '\0') {
276 homedir = strdup(pwd->pw_dir);
277 if (homedir == NULL) {
282 pwd->pw_gid = e->gid;
283 if (e->class != NULL)
284 lc = login_getclass(e->class);
287 setusercontext(lc, pwd, e->uid,
291 /* fall back to the old method */
294 /* set our directory, uid and gid. Set gid first,
295 * since once we set uid, we've lost root privileges.
297 if (setgid(e->gid) != 0) {
298 log_it(usernm, getpid(),
299 "error", "setgid failed");
302 if (initgroups(usernm, e->gid) != 0) {
303 log_it(usernm, getpid(),
304 "error", "initgroups failed");
307 if (setlogin(usernm) != 0) {
308 log_it(usernm, getpid(),
309 "error", "setlogin failed");
312 if (setuid(e->uid) != 0) {
313 log_it(usernm, getpid(),
314 "error", "setuid failed");
317 /* we aren't root after this..*/
318 #if defined(LOGIN_CAP)
324 /* For compatibility, we chdir to the value of HOME if it was
325 * specified explicitly in the crontab file, but not if it was
326 * set in the environment by some other mechanism. We chdir to
327 * the homedir given by the pw entry otherwise.
329 * If !LOGIN_CAP, then HOME is always set in e->envp.
331 * XXX: probably should also consult PAM.
334 char *new_home = env_get("HOME", e->envp);
335 if (new_home != NULL && new_home[0] != '\0')
337 else if (homedir != NULL)
343 /* exec the command. Note that SHELL is not respected from
344 * either login.conf or pw_shell, only an explicit setting
345 * in the crontab. (default of _PATH_BSHELL is supplied when
346 * setting up the entry)
349 char *shell = env_get("SHELL", e->envp);
352 /* Apply the environment from the entry, overriding
353 * existing values (this will always set LOGNAME and
354 * SHELL). putenv should not fail unless malloc does.
356 for (p = e->envp; *p; ++p) {
357 if (putenv(*p) != 0) {
363 /* HOME in login.conf overrides pw, and HOME in the
364 * crontab overrides both. So set pw's value only if
365 * nothing was already set (overwrite==0).
368 && setenv("HOME", homedir, 0) < 0) {
369 warn("setenv(HOME)");
373 /* PATH in login.conf is respected, but the crontab
374 * overrides; set a default value only if nothing
377 if (setenv("PATH", _PATH_DEFPATH, 0) < 0) {
378 warn("setenv(PATH)");
383 if (DebugFlags & DTEST) {
385 "debug DTEST is on, not exec'ing command.\n");
387 "\tcmd='%s' shell='%s'\n", e->cmd, shell);
390 # endif /*DEBUGGING*/
391 execl(shell, shell, "-c", e->cmd, (char *)NULL);
392 warn("execl: couldn't exec `%s'", shell);
401 /* middle process, child of original cron, parent of process running
402 * the user's command.
405 Debug(DPROC, ("[%d] child continues, closing pipes\n", getpid()))
407 /* close the ends of the pipe that will only be referenced in the
408 * grandchild process...
410 close(stdin_pipe[READ_PIPE]);
411 close(stdout_pipe[WRITE_PIPE]);
414 * write, to the pipe connected to child's stdin, any input specified
415 * after a % in the crontab entry. while we copy, convert any
416 * additional %'s to newlines. when done, if some characters were
417 * written and the last one wasn't a newline, write a newline.
419 * Note that if the input data won't fit into one pipe buffer (2K
420 * or 4K on most BSD systems), and the child doesn't read its stdin,
421 * we would block here. thus we must fork again.
424 if (*input_data && (stdinjob = fork()) == 0) {
425 FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w");
426 int need_newline = FALSE;
431 warn("fdopen failed in child2");
435 Debug(DPROC, ("[%d] child2 sending data to grandchild\n", getpid()))
437 /* close the pipe we don't use, since we inherited it and
438 * are part of its reference count now.
440 close(stdout_pipe[READ_PIPE]);
445 * \x -> \x for all x != %
447 while ((ch = *input_data++) != '\0') {
456 if (!(escaped = (ch == '\\'))) {
458 need_newline = (ch != '\n');
466 /* close the pipe, causing an EOF condition. fclose causes
467 * stdin_pipe[WRITE_PIPE] to be closed, too.
471 Debug(DPROC, ("[%d] child2 done sending to grandchild\n", getpid()))
475 /* close the pipe to the grandkiddie's stdin, since its wicked uncle
476 * ernie back there has it open and will close it when he's done.
478 close(stdin_pipe[WRITE_PIPE]);
481 * read output from the grandchild. it's stderr has been redirected to
482 * it's stdout, which has been redirected to our pipe. if there is any
483 * output, we'll be mailing it to the user whose crontab this is...
484 * when the grandchild exits, we'll get EOF.
487 Debug(DPROC, ("[%d] child reading output from grandchild\n", getpid()))
490 FILE *in = fdopen(stdout_pipe[READ_PIPE], "r");
494 warn("fdopen failed in child");
503 ("[%d] got data (%x:%c) from grandchild\n",
506 /* get name of recipient. this is MAILTO if set to a
507 * valid local username; USER otherwise.
509 if (mailto == NULL) {
510 /* MAILTO not present, set to USER,
511 * unless globally overridden.
518 if (mailto && *mailto == '\0')
521 /* if we are supposed to be mailing, MAILTO will
522 * be non-NULL. only in this case should we set
523 * up the mail command and subjects and stuff...
528 char mailcmd[MAX_COMMAND];
529 char hostname[MAXHOSTNAMELEN];
531 if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
533 hostname[sizeof(hostname) - 1] = '\0';
534 if (snprintf(mailcmd, sizeof(mailcmd), MAILFMT,
535 MAILARG) >= sizeof(mailcmd)) {
536 warnx("mail command too long");
537 (void) _exit(ERROR_EXIT);
539 if (!(mail = cron_popen(mailcmd, "w", e, &mailpid))) {
541 (void) _exit(ERROR_EXIT);
543 if (mailfrom == NULL || *mailfrom == '\0')
544 fprintf(mail, "From: Cron Daemon <%s@%s>\n",
547 fprintf(mail, "From: Cron Daemon <%s>\n",
549 fprintf(mail, "To: %s\n", mailto);
550 fprintf(mail, "Subject: Cron <%s@%s> %s\n",
551 usernm, first_word(hostname, "."),
554 fprintf(mail, "Date: %s\n",
555 arpadate(&TargetTime));
557 for (env = e->envp; *env; env++)
558 fprintf(mail, "X-Cron-Env: <%s>\n",
562 /* this was the first char from the pipe
567 /* we have to read the input pipe no matter whether
568 * we mail or not, but obviously we only write to
569 * mail pipe if we ARE mailing.
572 while (EOF != (ch = getc(in))) {
578 /*if data from grandchild*/
580 Debug(DPROC, ("[%d] got EOF from grandchild\n", getpid()))
582 /* also closes stdout_pipe[READ_PIPE] */
586 /* wait for children to die.
591 waiter = wait_on_child(jobpid, "grandchild command job");
593 /* If everything went well, and -n was set, _and_ we have mail,
594 * we won't be mailing... so shoot the messenger!
596 if (WIFEXITED(waiter) && WEXITSTATUS(waiter) == 0
597 && (e->flags & MAIL_WHEN_ERR) == MAIL_WHEN_ERR
599 Debug(DPROC, ("[%d] %s executed successfully, mail suppressed\n",
600 getpid(), "grandchild command job"))
601 kill(mailpid, SIGKILL);
606 /* only close pipe if we opened it -- i.e., we're
611 Debug(DPROC, ("[%d] closing pipe to mail\n",
613 /* Note: the pclose will probably see
614 * the termination of the grandchild
615 * in addition to the mail process, since
616 * it (the grandchild) is likely to exit
617 * after closing its stdout.
619 status = cron_pclose(mail);
621 /* if there was output and we could not mail it,
622 * log the facts so the poor user can figure out
626 char buf[MAX_TEMPSTR];
628 snprintf(buf, sizeof(buf),
629 "mailed %d byte%s of output but got status 0x%04x\n",
630 bytes, (bytes==1)?"":"s",
632 log_it(usernm, getpid(), "MAIL", buf);
637 if (*input_data && stdinjob > 0)
638 wait_on_child(stdinjob, "grandchild stdinjob");
642 wait_on_child(PID_T childpid, const char *name)
647 Debug(DPROC, ("[%d] waiting for %s (%d) to finish\n",
648 getpid(), name, childpid))
651 while ((pid = waitpid(childpid, &waiter, 0)) < 0 && errno == EINTR)
653 while ((pid = wait4(childpid, &waiter, 0, NULL)) < 0 && errno == EINTR)
660 Debug(DPROC, ("[%d] %s (%d) finished, status=%04x",
661 getpid(), name, pid, WEXITSTATUS(waiter)))
662 if (WIFSIGNALED(waiter) && WCOREDUMP(waiter))
663 Debug(DPROC, (", dumped core"))