Lines 41-46
static const char rcsid[] =
Link Here
|
41 |
static void child_process(entry *, user *), |
41 |
static void child_process(entry *, user *), |
42 |
do_univ(user *); |
42 |
do_univ(user *); |
43 |
|
43 |
|
|
|
44 |
static WAIT_T wait_on_child(PID_T, char *); |
44 |
|
45 |
|
45 |
void |
46 |
void |
46 |
do_command(e, u) |
47 |
do_command(e, u) |
Lines 94-100
child_process(e, u)
Link Here
|
94 |
int stdin_pipe[2], stdout_pipe[2]; |
95 |
int stdin_pipe[2], stdout_pipe[2]; |
95 |
register char *input_data; |
96 |
register char *input_data; |
96 |
char *usernm, *mailto, *mailfrom; |
97 |
char *usernm, *mailto, *mailfrom; |
97 |
int children = 0; |
98 |
PID_T jobpid, stdinjob, mailpid; |
|
|
99 |
|
100 |
register FILE *mail; |
101 |
register int bytes = 1; |
102 |
int status = 0; |
103 |
|
98 |
# if defined(LOGIN_CAP) |
104 |
# if defined(LOGIN_CAP) |
99 |
struct passwd *pwd; |
105 |
struct passwd *pwd; |
100 |
login_cap_t *lc; |
106 |
login_cap_t *lc; |
Lines 216-222
child_process(e, u)
Link Here
|
216 |
|
222 |
|
217 |
/* fork again, this time so we can exec the user's command. |
223 |
/* fork again, this time so we can exec the user's command. |
218 |
*/ |
224 |
*/ |
219 |
switch (vfork()) { |
225 |
|
|
|
226 |
switch (jobpid = vfork()) { |
220 |
case -1: |
227 |
case -1: |
221 |
log_it("CRON",getpid(),"error","can't vfork"); |
228 |
log_it("CRON",getpid(),"error","can't vfork"); |
222 |
exit(ERROR_EXIT); |
229 |
exit(ERROR_EXIT); |
Lines 237-243
child_process(e, u)
Link Here
|
237 |
* the actual user command shell was going to get and the |
244 |
* the actual user command shell was going to get and the |
238 |
* PID is part of the log message. |
245 |
* PID is part of the log message. |
239 |
*/ |
246 |
*/ |
240 |
/*local*/{ |
247 |
if ((e->flags & DONT_LOG) == 0) { |
241 |
char *x = mkprints((u_char *)e->cmd, strlen(e->cmd)); |
248 |
char *x = mkprints((u_char *)e->cmd, strlen(e->cmd)); |
242 |
|
249 |
|
243 |
log_it(usernm, getpid(), "CMD", x); |
250 |
log_it(usernm, getpid(), "CMD", x); |
Lines 359-366
child_process(e, u)
Link Here
|
359 |
break; |
366 |
break; |
360 |
} |
367 |
} |
361 |
|
368 |
|
362 |
children++; |
|
|
363 |
|
364 |
/* middle process, child of original cron, parent of process running |
369 |
/* middle process, child of original cron, parent of process running |
365 |
* the user's command. |
370 |
* the user's command. |
366 |
*/ |
371 |
*/ |
Lines 384-390
child_process(e, u)
Link Here
|
384 |
* we would block here. thus we must fork again. |
389 |
* we would block here. thus we must fork again. |
385 |
*/ |
390 |
*/ |
386 |
|
391 |
|
387 |
if (*input_data && fork() == 0) { |
392 |
stdinjob = 0; |
|
|
393 |
|
394 |
if (*input_data && (stdinjob = fork()) == 0) { |
388 |
register FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w"); |
395 |
register FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w"); |
389 |
register int need_newline = FALSE; |
396 |
register int need_newline = FALSE; |
390 |
register int escaped = FALSE; |
397 |
register int escaped = FALSE; |
Lines 440-447
child_process(e, u)
Link Here
|
440 |
*/ |
447 |
*/ |
441 |
close(stdin_pipe[WRITE_PIPE]); |
448 |
close(stdin_pipe[WRITE_PIPE]); |
442 |
|
449 |
|
443 |
children++; |
|
|
444 |
|
445 |
/* |
450 |
/* |
446 |
* read output from the grandchild. it's stderr has been redirected to |
451 |
* read output from the grandchild. it's stderr has been redirected to |
447 |
* it's stdout, which has been redirected to our pipe. if there is any |
452 |
* it's stdout, which has been redirected to our pipe. if there is any |
Lines 462-471
child_process(e, u)
Link Here
|
462 |
|
467 |
|
463 |
ch = getc(in); |
468 |
ch = getc(in); |
464 |
if (ch != EOF) { |
469 |
if (ch != EOF) { |
465 |
register FILE *mail; |
|
|
466 |
register int bytes = 1; |
467 |
int status = 0; |
468 |
|
469 |
Debug(DPROC|DEXT, |
470 |
Debug(DPROC|DEXT, |
470 |
("[%d] got data (%x:%c) from grandchild\n", |
471 |
("[%d] got data (%x:%c) from grandchild\n", |
471 |
getpid(), ch, ch)) |
472 |
getpid(), ch, ch)) |
Lines 500-506
child_process(e, u)
Link Here
|
500 |
hostname[sizeof(hostname) - 1] = '\0'; |
501 |
hostname[sizeof(hostname) - 1] = '\0'; |
501 |
(void) snprintf(mailcmd, sizeof(mailcmd), |
502 |
(void) snprintf(mailcmd, sizeof(mailcmd), |
502 |
MAILARGS, MAILCMD); |
503 |
MAILARGS, MAILCMD); |
503 |
if (!(mail = cron_popen(mailcmd, "w", e))) { |
504 |
if (!(mail = cron_popen(mailcmd, "w", e, &mailpid))) { |
504 |
warn("%s", MAILCMD); |
505 |
warn("%s", MAILCMD); |
505 |
(void) _exit(ERROR_EXIT); |
506 |
(void) _exit(ERROR_EXIT); |
506 |
} |
507 |
} |
Lines 538-565
child_process(e, u)
Link Here
|
538 |
if (mailto) |
539 |
if (mailto) |
539 |
putc(ch, mail); |
540 |
putc(ch, mail); |
540 |
} |
541 |
} |
|
|
542 |
} /*if data from grandchild*/ |
541 |
|
543 |
|
542 |
/* only close pipe if we opened it -- i.e., we're |
544 |
Debug(DPROC, ("[%d] got EOF from grandchild\n", getpid())) |
543 |
* mailing... |
545 |
|
544 |
*/ |
546 |
fclose(in); /* also closes stdout_pipe[READ_PIPE] */ |
|
|
547 |
} |
548 |
|
549 |
/* wait for children to die. |
550 |
*/ |
551 |
if (jobpid > 0) { |
552 |
WAIT_T waiter; |
553 |
|
554 |
waiter = wait_on_child(jobpid, "grandchild command job"); |
555 |
|
556 |
/* If everything went well, and -n was set, _and_ we have mail, |
557 |
* we won't be mailing... so shoot the messenger! |
558 |
*/ |
559 |
if (WIFEXITED(waiter) && WEXITSTATUS(waiter) == 0 |
560 |
&& (e->flags & MAIL_WHEN_ERR) == MAIL_WHEN_ERR |
561 |
&& mailto) { |
562 |
Debug(DPROC, ("[%d] %s executed successful, mail suppressed\n", |
563 |
getpid(), "grandchild command job")) |
564 |
kill(mailpid, SIGKILL); |
565 |
(void)fclose(mail); |
566 |
mailto = NULL; |
567 |
} |
545 |
|
568 |
|
546 |
if (mailto) { |
569 |
|
547 |
Debug(DPROC, ("[%d] closing pipe to mail\n", |
570 |
/* only close pipe if we opened it -- i.e., we're |
548 |
getpid())) |
571 |
* mailing... |
549 |
/* Note: the pclose will probably see |
572 |
*/ |
550 |
* the termination of the grandchild |
573 |
|
551 |
* in addition to the mail process, since |
574 |
if (mailto) { |
552 |
* it (the grandchild) is likely to exit |
575 |
Debug(DPROC, ("[%d] closing pipe to mail\n", |
553 |
* after closing its stdout. |
576 |
getpid())) |
554 |
*/ |
577 |
/* Note: the pclose will probably see |
555 |
status = cron_pclose(mail); |
578 |
* the termination of the grandchild |
556 |
} |
579 |
* in addition to the mail process, since |
|
|
580 |
* it (the grandchild) is likely to exit |
581 |
* after closing its stdout. |
582 |
*/ |
583 |
status = cron_pclose(mail); |
557 |
|
584 |
|
558 |
/* if there was output and we could not mail it, |
585 |
/* if there was output and we could not mail it, |
559 |
* log the facts so the poor user can figure out |
586 |
* log the facts so the poor user can figure out |
560 |
* what's going on. |
587 |
* what's going on. |
561 |
*/ |
588 |
*/ |
562 |
if (mailto && status) { |
589 |
if (status) { |
563 |
char buf[MAX_TEMPSTR]; |
590 |
char buf[MAX_TEMPSTR]; |
564 |
|
591 |
|
565 |
snprintf(buf, sizeof(buf), |
592 |
snprintf(buf, sizeof(buf), |
Lines 568-602
child_process(e, u)
Link Here
|
568 |
status); |
595 |
status); |
569 |
log_it(usernm, getpid(), "MAIL", buf); |
596 |
log_it(usernm, getpid(), "MAIL", buf); |
570 |
} |
597 |
} |
|
|
598 |
} |
599 |
} |
571 |
|
600 |
|
572 |
} /*if data from grandchild*/ |
601 |
if (stdinjob > 0) |
|
|
602 |
wait_on_child(stdinjob, "grandchild stdinjob"); |
603 |
} |
573 |
|
604 |
|
574 |
Debug(DPROC, ("[%d] got EOF from grandchild\n", getpid())) |
605 |
static WAIT_T |
|
|
606 |
wait_on_child(PID_T childpid, char *name) { |
607 |
WAIT_T waiter; |
608 |
PID_T pid; |
575 |
|
609 |
|
576 |
fclose(in); /* also closes stdout_pipe[READ_PIPE] */ |
610 |
Debug(DPROC, ("[%d] waiting for %s (%d) to finish\n", |
577 |
} |
611 |
getpid(), name, childpid)) |
578 |
|
612 |
|
579 |
/* wait for children to die. |
613 |
#ifdef POSIX |
580 |
*/ |
614 |
while ((pid = waitpid(childpid, &waiter, 0)) < 0 && errno == EINTR) |
581 |
for (; children > 0; children--) |
615 |
#else |
582 |
{ |
616 |
while ((pid = wait4(childpid, &waiter, 0, NULL)) < 0 && errno == EINTR) |
583 |
WAIT_T waiter; |
617 |
#endif |
584 |
PID_T pid; |
618 |
; |
585 |
|
619 |
|
586 |
Debug(DPROC, ("[%d] waiting for grandchild #%d to finish\n", |
620 |
if (pid < OK) |
587 |
getpid(), children)) |
621 |
return waiter; |
588 |
pid = wait(&waiter); |
622 |
|
589 |
if (pid < OK) { |
623 |
Debug(DPROC, ("[%d] %s (%d) finished, status=%04x", |
590 |
Debug(DPROC, ("[%d] no more grandchildren--mail written?\n", |
624 |
getpid(), name, pid, WEXITSTATUS(waiter))) |
591 |
getpid())) |
625 |
if (WIFSIGNALED(waiter) && WCOREDUMP(waiter)) |
592 |
break; |
626 |
Debug(DPROC, (", dumped core")) |
593 |
} |
627 |
Debug(DPROC, ("\n")) |
594 |
Debug(DPROC, ("[%d] grandchild #%d finished, status=%04x", |
628 |
|
595 |
getpid(), pid, WEXITSTATUS(waiter))) |
629 |
return waiter; |
596 |
if (WIFSIGNALED(waiter) && WCOREDUMP(waiter)) |
|
|
597 |
Debug(DPROC, (", dumped core")) |
598 |
Debug(DPROC, ("\n")) |
599 |
} |
600 |
} |
630 |
} |
601 |
|
631 |
|
602 |
|
632 |
|