diff options
-rw-r--r-- | miscutils/crond.c | 59 | ||||
-rw-r--r-- | networking/sendmail.c | 28 |
2 files changed, 67 insertions, 20 deletions
diff --git a/miscutils/crond.c b/miscutils/crond.c index ba9cf3581..98dd22d9d 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
@@ -33,7 +33,11 @@ | |||
33 | #define SENDMAIL "sendmail" | 33 | #define SENDMAIL "sendmail" |
34 | #endif | 34 | #endif |
35 | #ifndef SENDMAIL_ARGS | 35 | #ifndef SENDMAIL_ARGS |
36 | #define SENDMAIL_ARGS "-ti", "oem" | 36 | # if ENABLE_SENDMAIL |
37 | # define SENDMAIL_ARGS "localhost", line->cl_MailTo | ||
38 | # else | ||
39 | # define SENDMAIL_ARGS "-ti", "oem" | ||
40 | # endif | ||
37 | #endif | 41 | #endif |
38 | #ifndef CRONUPDATE | 42 | #ifndef CRONUPDATE |
39 | #define CRONUPDATE "cron.update" | 43 | #define CRONUPDATE "cron.update" |
@@ -59,6 +63,7 @@ typedef struct CronLine { | |||
59 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | 63 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
60 | int cl_MailPos; /* 'empty file' size */ | 64 | int cl_MailPos; /* 'empty file' size */ |
61 | smallint cl_MailFlag; /* running pid is for mail */ | 65 | smallint cl_MailFlag; /* running pid is for mail */ |
66 | char *cl_MailTo; /* whom to mail results */ | ||
62 | #endif | 67 | #endif |
63 | /* ordered by size, not in natural order. makes code smaller: */ | 68 | /* ordered by size, not in natural order. makes code smaller: */ |
64 | char cl_Dow[7]; /* 0-6, beginning sunday */ | 69 | char cl_Dow[7]; /* 0-6, beginning sunday */ |
@@ -449,6 +454,9 @@ static void SynchronizeFile(const char *fileName) | |||
449 | int maxEntries; | 454 | int maxEntries; |
450 | int maxLines; | 455 | int maxLines; |
451 | char buf[1024]; | 456 | char buf[1024]; |
457 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | ||
458 | char *mailTo = NULL; | ||
459 | #endif | ||
452 | 460 | ||
453 | if (!fileName) | 461 | if (!fileName) |
454 | return; | 462 | return; |
@@ -485,6 +493,14 @@ static void SynchronizeFile(const char *fileName) | |||
485 | if (DebugOpt) { | 493 | if (DebugOpt) { |
486 | crondlog(LVL5 "user:%s entry:%s", fileName, buf); | 494 | crondlog(LVL5 "user:%s entry:%s", fileName, buf); |
487 | } | 495 | } |
496 | /* check if line is setting MAILTO= */ | ||
497 | if (0 == strncmp("MAILTO=", buf, 7)) { | ||
498 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | ||
499 | free(mailTo); | ||
500 | mailTo = (buf[7]) ? xstrdup(buf+7) : NULL; | ||
501 | #endif /* otherwise just ignore such lines */ | ||
502 | continue; | ||
503 | } | ||
488 | *pline = line = xzalloc(sizeof(CronLine)); | 504 | *pline = line = xzalloc(sizeof(CronLine)); |
489 | /* parse date ranges */ | 505 | /* parse date ranges */ |
490 | ptr = ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, buf); | 506 | ptr = ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, buf); |
@@ -498,10 +514,14 @@ static void SynchronizeFile(const char *fileName) | |||
498 | continue; | 514 | continue; |
499 | } | 515 | } |
500 | /* | 516 | /* |
501 | * fix days and dow - if one is not * and the other | 517 | * fix days and dow - if one is not "*" and the other |
502 | * is *, the other is set to 0, and vise-versa | 518 | * is "*", the other is set to 0, and vise-versa |
503 | */ | 519 | */ |
504 | FixDayDow(line); | 520 | FixDayDow(line); |
521 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | ||
522 | /* copy mailto (can be NULL) */ | ||
523 | line->cl_MailTo = xstrdup(mailTo); | ||
524 | #endif | ||
505 | /* copy command */ | 525 | /* copy command */ |
506 | line->cl_Shell = xstrdup(ptr); | 526 | line->cl_Shell = xstrdup(ptr); |
507 | if (DebugOpt) { | 527 | if (DebugOpt) { |
@@ -515,7 +535,7 @@ static void SynchronizeFile(const char *fileName) | |||
515 | FileBase = file; | 535 | FileBase = file; |
516 | 536 | ||
517 | if (maxLines == 0 || maxEntries == 0) { | 537 | if (maxLines == 0 || maxEntries == 0) { |
518 | crondlog(WARN9 "maximum number of lines reached for user %s", fileName); | 538 | crondlog(WARN9 "user %s: too many lines", fileName); |
519 | } | 539 | } |
520 | } | 540 | } |
521 | fclose(fi); | 541 | fclose(fi); |
@@ -567,7 +587,7 @@ static void SynchronizeDir(void) | |||
567 | 587 | ||
568 | if (!dir) | 588 | if (!dir) |
569 | crondlog(DIE9 "can't chdir(%s)", "."); /* exits */ | 589 | crondlog(DIE9 "can't chdir(%s)", "."); /* exits */ |
570 | while ((den = readdir(dir))) { | 590 | while ((den = readdir(dir)) != NULL) { |
571 | if (strchr(den->d_name, '.') != NULL) { | 591 | if (strchr(den->d_name, '.') != NULL) { |
572 | continue; | 592 | continue; |
573 | } | 593 | } |
@@ -811,23 +831,25 @@ ForkJob(const char *user, CronLine *line, int mailFd, | |||
811 | static void RunJob(const char *user, CronLine *line) | 831 | static void RunJob(const char *user, CronLine *line) |
812 | { | 832 | { |
813 | char mailFile[128]; | 833 | char mailFile[128]; |
814 | int mailFd; | 834 | int mailFd = -1; |
815 | 835 | ||
816 | line->cl_Pid = 0; | 836 | line->cl_Pid = 0; |
817 | line->cl_MailFlag = 0; | 837 | line->cl_MailFlag = 0; |
818 | 838 | ||
819 | /* open mail file - owner root so nobody can screw with it. */ | 839 | if (line->cl_MailTo) { |
820 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid()); | 840 | /* open mail file - owner root so nobody can screw with it. */ |
821 | mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600); | 841 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid()); |
842 | mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600); | ||
822 | 843 | ||
823 | if (mailFd >= 0) { | 844 | if (mailFd >= 0) { |
824 | line->cl_MailFlag = 1; | 845 | line->cl_MailFlag = 1; |
825 | fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user, | 846 | fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user, |
826 | line->cl_Shell); | 847 | line->cl_Shell); |
827 | line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR); | 848 | line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR); |
828 | } else { | 849 | } else { |
829 | crondlog(ERR20 "cannot create mail file %s for user %s, " | 850 | crondlog(ERR20 "cannot create mail file %s for user %s, " |
830 | "discarding output", mailFile, user); | 851 | "discarding output", mailFile, user); |
852 | } | ||
831 | } | 853 | } |
832 | 854 | ||
833 | ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile); | 855 | ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile); |
@@ -877,7 +899,8 @@ static void EndJob(const char *user, CronLine *line) | |||
877 | close(mailFd); | 899 | close(mailFd); |
878 | return; | 900 | return; |
879 | } | 901 | } |
880 | ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL); | 902 | if (line->cl_MailTo) |
903 | ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL); | ||
881 | } | 904 | } |
882 | 905 | ||
883 | #else /* crond without sendmail */ | 906 | #else /* crond without sendmail */ |
diff --git a/networking/sendmail.c b/networking/sendmail.c index 973d712b9..242bb0eaf 100644 --- a/networking/sendmail.c +++ b/networking/sendmail.c | |||
@@ -273,6 +273,7 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
273 | 273 | ||
274 | OPTS_c = 1 << 6, // sendmail: assumed charset | 274 | OPTS_c = 1 << 6, // sendmail: assumed charset |
275 | OPTS_t = 1 << 7, // sendmail: recipient(s) | 275 | OPTS_t = 1 << 7, // sendmail: recipient(s) |
276 | OPTS_i = 1 << 8, // sendmail: ignore lone dots in message body (implied) | ||
276 | }; | 277 | }; |
277 | 278 | ||
278 | const char *options; | 279 | const char *options; |
@@ -288,8 +289,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
288 | // SENDMAIL | 289 | // SENDMAIL |
289 | // save initial stdin (body or attachements can be piped!) | 290 | // save initial stdin (body or attachements can be piped!) |
290 | xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO); | 291 | xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO); |
291 | opt_complementary = "-2:w+:t:t::"; // count(-t) > 0 | 292 | opt_complementary = "-2:w+:t::"; |
292 | options = "w:U:P:X" "ns:c:t:"; | 293 | options = "w:U:P:X" "ns:c:t:i"; |
293 | } else { | 294 | } else { |
294 | // FETCHMAIL | 295 | // FETCHMAIL |
295 | opt_after_connect = NULL; | 296 | opt_after_connect = NULL; |
@@ -346,6 +347,29 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
346 | // get the sender | 347 | // get the sender |
347 | opt_from = sane(*argv++); | 348 | opt_from = sane(*argv++); |
348 | 349 | ||
350 | // if no recipients _and_ no body files specified -> enter all-included mode | ||
351 | // i.e. scan stdin for To: and Subject: lines ... | ||
352 | // ... and then use the rest of stdin as message body | ||
353 | if (!opt_recipients && !*argv) { | ||
354 | // fetch recipients and (optionally) subject | ||
355 | char *s; | ||
356 | while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) { | ||
357 | if (0 == strncmp("To: ", s, 4)) { | ||
358 | llist_add_to_end(&opt_recipients, s+4); | ||
359 | } else if (0 == strncmp("Subject: ", s, 9)) { | ||
360 | opt_subject = s+9; | ||
361 | opts |= OPTS_s; | ||
362 | } else { | ||
363 | char first = s[0]; | ||
364 | free(s); | ||
365 | if (!first) | ||
366 | break; // empty line | ||
367 | } | ||
368 | } | ||
369 | // order to read body from stdin | ||
370 | *--argv = (char *)"-"; | ||
371 | } | ||
372 | |||
349 | // introduce to server | 373 | // introduce to server |
350 | // we should start with modern EHLO | 374 | // we should start with modern EHLO |
351 | if (250 != smtp_checkp("EHLO %s", opt_from, -1)) { | 375 | if (250 != smtp_checkp("EHLO %s", opt_from, -1)) { |