Implemented biff notification.
Showing
1 changed file
with
130 additions
and
57 deletions
... | @@ -19,7 +19,7 @@ | ... | @@ -19,7 +19,7 @@ |
19 | 19 | ||
20 | int debug_level; | 20 | int debug_level; |
21 | int multiple_delivery; | 21 | int multiple_delivery; |
22 | int bounce_quota; | 22 | int ex_quota_tempfail; |
23 | int exit_code = EX_OK; | 23 | int exit_code = EX_OK; |
24 | uid_t uid; | 24 | uid_t uid; |
25 | char *maildir = MU_PATH_MAILDIR; | 25 | char *maildir = MU_PATH_MAILDIR; |
... | @@ -27,6 +27,7 @@ char *quotadbname = NULL; | ... | @@ -27,6 +27,7 @@ char *quotadbname = NULL; |
27 | int lock_timeout = 300; | 27 | int lock_timeout = 300; |
28 | 28 | ||
29 | #define MAXFD 64 | 29 | #define MAXFD 64 |
30 | #define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE) | ||
30 | 31 | ||
31 | static void print_help (void); | 32 | static void print_help (void); |
32 | static void print_license (void); | 33 | static void print_license (void); |
... | @@ -37,15 +38,17 @@ FILE *make_tmp (const char *from, char **tempfile); | ... | @@ -37,15 +38,17 @@ FILE *make_tmp (const char *from, char **tempfile); |
37 | void deliver (FILE *fp, char *name); | 38 | void deliver (FILE *fp, char *name); |
38 | void guess_retval (int ec); | 39 | void guess_retval (int ec); |
39 | void mailer_err (char *fmt, ...); | 40 | void mailer_err (char *fmt, ...); |
41 | void notify_biff (mailbox_t mbox, char *name, size_t size); | ||
40 | 42 | ||
41 | char short_opts[] = "hf:Llm:q:r:s:x::v"; | 43 | char short_opts[] = "hf:Llm:q:r:s:x::vW;"; |
42 | 44 | ||
43 | static struct option long_opts[] = { | 45 | static struct option long_opts[] = { |
46 | { "ex-multiple-delivery-success", no_argument, &multiple_delivery, 1 }, | ||
47 | { "ex-quota-tempfail", no_argument, &ex_quota_tempfail, 1 }, | ||
44 | { "from", required_argument, 0, 'f' }, | 48 | { "from", required_argument, 0, 'f' }, |
45 | { "help", no_argument, 0, 'h' }, | 49 | { "help", no_argument, 0, 'h' }, |
46 | { "license", no_argument, 0, 'L' }, | 50 | { "license", no_argument, 0, 'L' }, |
47 | { "maildir", required_argument, 0, 'm' }, | 51 | { "maildir", required_argument, 0, 'm' }, |
48 | { "multiple-delivery", no_argument, 0, 'M' }, | ||
49 | { "quota-db", required_argument, 0, 'q' }, | 52 | { "quota-db", required_argument, 0, 'q' }, |
50 | { "source", required_argument, 0, 's' }, | 53 | { "source", required_argument, 0, 's' }, |
51 | { "timeout", required_argument, 0, 't' }, | 54 | { "timeout", required_argument, 0, 't' }, |
... | @@ -62,8 +65,8 @@ main (int argc, char *argv[]) | ... | @@ -62,8 +65,8 @@ main (int argc, char *argv[]) |
62 | FILE *fp; | 65 | FILE *fp; |
63 | char *from = NULL; | 66 | char *from = NULL; |
64 | char *progfile_pattern = NULL; | 67 | char *progfile_pattern = NULL; |
65 | struct mda_data mda_data; | 68 | char *tempfile = NULL; |
66 | 69 | ||
67 | /* Preparative work: close inherited fds, force a reasonable umask | 70 | /* Preparative work: close inherited fds, force a reasonable umask |
68 | and prepare a logging. */ | 71 | and prepare a logging. */ |
69 | close_fds (); | 72 | close_fds (); |
... | @@ -76,6 +79,8 @@ main (int argc, char *argv[]) | ... | @@ -76,6 +79,8 @@ main (int argc, char *argv[]) |
76 | while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != EOF) | 79 | while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != EOF) |
77 | switch (c) | 80 | switch (c) |
78 | { | 81 | { |
82 | case 0: /* option already handled */ | ||
83 | break; | ||
79 | case 'r': | 84 | case 'r': |
80 | case 'f': | 85 | case 'f': |
81 | if (from != NULL) | 86 | if (from != NULL) |
... | @@ -98,10 +103,6 @@ main (int argc, char *argv[]) | ... | @@ -98,10 +103,6 @@ main (int argc, char *argv[]) |
98 | maildir = optarg; | 103 | maildir = optarg; |
99 | break; | 104 | break; |
100 | 105 | ||
101 | case 'M': | ||
102 | multiple_delivery++; | ||
103 | break; | ||
104 | |||
105 | #ifdef USE_DBM | 106 | #ifdef USE_DBM |
106 | case 'q': | 107 | case 'q': |
107 | quotadbname = optarg; | 108 | quotadbname = optarg; |
... | @@ -120,9 +121,21 @@ main (int argc, char *argv[]) | ... | @@ -120,9 +121,21 @@ main (int argc, char *argv[]) |
120 | 121 | ||
121 | case 'x': | 122 | case 'x': |
122 | if (optarg) | 123 | if (optarg) |
123 | debug_level = strtoul (optarg, NULL, 0); | 124 | { |
125 | #ifdef WITH_GUILE | ||
126 | if (strcmp (optarg, "guile") == 0) | ||
127 | debug_guile = 1; | ||
128 | else | ||
129 | #endif | ||
130 | debug_level = strtoul (optarg, NULL, 0); | ||
131 | } | ||
124 | else | 132 | else |
125 | debug_level = 9; | 133 | { |
134 | debug_level = 9; | ||
135 | #ifdef WITH_GUILE | ||
136 | debug_guile = 1; | ||
137 | #endif | ||
138 | } | ||
126 | break; | 139 | break; |
127 | 140 | ||
128 | case 'v': | 141 | case 'v': |
... | @@ -146,18 +159,6 @@ main (int argc, char *argv[]) | ... | @@ -146,18 +159,6 @@ main (int argc, char *argv[]) |
146 | return 1; | 159 | return 1; |
147 | } | 160 | } |
148 | 161 | ||
149 | if (!from) | ||
150 | { | ||
151 | struct passwd *pw = getpwuid (uid); | ||
152 | if (pw) | ||
153 | from = pw->pw_name; | ||
154 | else | ||
155 | { | ||
156 | mu_error ("From unknown"); | ||
157 | return 1; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | #ifdef HAVE_MYSQL | 162 | #ifdef HAVE_MYSQL |
162 | mu_register_getpwnam (getMpwnam); | 163 | mu_register_getpwnam (getMpwnam); |
163 | #endif | 164 | #endif |
... | @@ -172,22 +173,26 @@ main (int argc, char *argv[]) | ... | @@ -172,22 +173,26 @@ main (int argc, char *argv[]) |
172 | list_append (bookie, smtp_record); | 173 | list_append (bookie, smtp_record); |
173 | } | 174 | } |
174 | 175 | ||
175 | memset (&mda_data, 0, sizeof mda_data); | 176 | fp = make_tmp (from, &tempfile); |
176 | fp = make_tmp (from, &mda_data.tempfile); | ||
177 | 177 | ||
178 | if (multiple_delivery) | 178 | if (multiple_delivery) |
179 | multiple_delivery = argc > 1; | 179 | multiple_delivery = argc > 1; |
180 | 180 | ||
181 | #ifdef WITH_GUILE | 181 | #ifdef WITH_GUILE |
182 | mda_data.fp = fp; | ||
183 | mda_data.argv = argv; | ||
184 | mda_data.progfile_pattern = progfile_pattern; | ||
185 | |||
186 | if (progfile_pattern) | 182 | if (progfile_pattern) |
187 | return prog_mda (&mda_data); | 183 | { |
184 | struct mda_data mda_data; | ||
185 | |||
186 | memset (&mda_data, 0, sizeof mda_data); | ||
187 | mda_data.fp = fp; | ||
188 | mda_data.argv = argv; | ||
189 | mda_data.progfile_pattern = progfile_pattern; | ||
190 | mda_data.tempfile = tempfile; | ||
191 | return prog_mda (&mda_data); | ||
192 | } | ||
188 | #endif | 193 | #endif |
189 | 194 | ||
190 | unlink (mda_data.tempfile); | 195 | unlink (tempfile); |
191 | for (; *argv; argv++) | 196 | for (; *argv; argv++) |
192 | mda (fp, *argv, NULL); | 197 | mda (fp, *argv, NULL); |
193 | return exit_code; | 198 | return exit_code; |
... | @@ -280,7 +285,7 @@ mda (FILE *fp, char *username, mailbox_t mbox) | ... | @@ -280,7 +285,7 @@ mda (FILE *fp, char *username, mailbox_t mbox) |
280 | if (attribute_is_deleted (attr)) | 285 | if (attribute_is_deleted (attr)) |
281 | return EX_OK; | 286 | return EX_OK; |
282 | } | 287 | } |
283 | 288 | ||
284 | deliver (fp, username); | 289 | deliver (fp, username); |
285 | 290 | ||
286 | if (multiple_delivery) | 291 | if (multiple_delivery) |
... | @@ -332,31 +337,53 @@ make_tmp (const char *from, char **tempfile) | ... | @@ -332,31 +337,53 @@ make_tmp (const char *from, char **tempfile) |
332 | FILE *fp; | 337 | FILE *fp; |
333 | char *buf = NULL; | 338 | char *buf = NULL; |
334 | size_t n = 0; | 339 | size_t n = 0; |
340 | int line; | ||
335 | 341 | ||
336 | if (fd == -1 || (fp = fdopen(fd, "w+")) == NULL) | 342 | if (fd == -1 || (fp = fdopen (fd, "w+")) == NULL) |
337 | { | 343 | { |
338 | mailer_err("unable to open temporary file"); | 344 | mailer_err ("unable to open temporary file"); |
339 | exit (exit_code); | 345 | exit (exit_code); |
340 | } | 346 | } |
341 | |||
342 | time (&t); | ||
343 | fprintf (fp, "From %s %s", from, ctime (&t)); | ||
344 | 347 | ||
345 | while (getline(&buf, &n, stdin) > 0) { | 348 | line = 0; |
346 | if (!memcmp(buf, "From ", 5)) | 349 | while (getline (&buf, &n, stdin) > 0) { |
347 | fputc('>', fp); | 350 | line++; |
351 | if (line == 1) | ||
352 | { | ||
353 | if (memcmp (buf, "From ", 5)) | ||
354 | { | ||
355 | if (!from) | ||
356 | { | ||
357 | struct passwd *pw = getpwuid (uid); | ||
358 | if (pw) | ||
359 | from = pw->pw_name; | ||
360 | } | ||
361 | if (from) | ||
362 | { | ||
363 | time (&t); | ||
364 | fprintf (fp, "From %s %s", from, ctime (&t)); | ||
365 | } | ||
366 | else | ||
367 | { | ||
368 | mailer_err ("Can't determine sender address"); | ||
369 | exit (EX_UNAVAILABLE); | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | else if (!memcmp (buf, "From ", 5)) | ||
374 | fputc ('>', fp); | ||
348 | if (fputs (buf, fp) == EOF) | 375 | if (fputs (buf, fp) == EOF) |
349 | { | 376 | { |
350 | mailer_err ("temporary file write error"); | 377 | mailer_err ("temporary file write error"); |
351 | fclose(fp); | 378 | fclose (fp); |
352 | return NULL; | 379 | return NULL; |
353 | } | 380 | } |
354 | } | 381 | } |
355 | 382 | ||
356 | if (buf && strchr(buf, '\n') == NULL) | 383 | if (buf && strchr (buf, '\n') == NULL) |
357 | putc('\n', fp); | 384 | putc ('\n', fp); |
358 | 385 | ||
359 | putc('\n', fp); | 386 | putc ('\n', fp); |
360 | free (buf); | 387 | free (buf); |
361 | 388 | ||
362 | return fp; | 389 | return fp; |
... | @@ -459,7 +486,7 @@ deliver (FILE *fp, char *name) | ... | @@ -459,7 +486,7 @@ deliver (FILE *fp, char *name) |
459 | { | 486 | { |
460 | case MQUOTA_EXCEEDED: | 487 | case MQUOTA_EXCEEDED: |
461 | mailer_err ("%s: mailbox quota exceeded for this recipient", name); | 488 | mailer_err ("%s: mailbox quota exceeded for this recipient", name); |
462 | exit_code = EX_UNAVAILABLE; | 489 | exit_code = EX_QUOTA(); |
463 | failed++; | 490 | failed++; |
464 | break; | 491 | break; |
465 | case MQUOTA_UNLIMITED: | 492 | case MQUOTA_UNLIMITED: |
... | @@ -475,7 +502,7 @@ deliver (FILE *fp, char *name) | ... | @@ -475,7 +502,7 @@ deliver (FILE *fp, char *name) |
475 | { | 502 | { |
476 | mailer_err ("%s: message would exceed maximum mailbox size for this recipient", | 503 | mailer_err ("%s: message would exceed maximum mailbox size for this recipient", |
477 | name); | 504 | name); |
478 | exit_code = EX_UNAVAILABLE; | 505 | exit_code = EX_QUOTA(); |
479 | failed++; | 506 | failed++; |
480 | } | 507 | } |
481 | break; | 508 | break; |
... | @@ -503,15 +530,51 @@ deliver (FILE *fp, char *name) | ... | @@ -503,15 +530,51 @@ deliver (FILE *fp, char *name) |
503 | free (buf); | 530 | free (buf); |
504 | switch_user_id (0); | 531 | switch_user_id (0); |
505 | } | 532 | } |
506 | 533 | ||
534 | if (!failed) | ||
535 | notify_biff (mbox, name, size); | ||
536 | |||
507 | locker_unlock (lock); | 537 | locker_unlock (lock); |
508 | /* FIXME: Flush the data */ | 538 | |
509 | mailbox_close (mbox); | 539 | mailbox_close (mbox); |
510 | mailbox_destroy (&mbox); | 540 | mailbox_destroy (&mbox); |
511 | #if 0 /*FIXME*/ | 541 | } |
512 | if (!failed) | 542 | |
513 | notify_biff (name, size); | 543 | void |
514 | #endif | 544 | notify_biff (mailbox_t mbox, char *name, size_t size) |
545 | { | ||
546 | static int fd = -1; | ||
547 | url_t url = NULL; | ||
548 | char *buf = NULL; | ||
549 | static struct sockaddr_in inaddr; | ||
550 | |||
551 | if (fd == -1) | ||
552 | { | ||
553 | struct servent *sp; | ||
554 | |||
555 | if ((sp = getservbyname ("biff", "udp")) == NULL) | ||
556 | return; | ||
557 | |||
558 | inaddr.sin_family = AF_INET; | ||
559 | inaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | ||
560 | inaddr.sin_port = sp->s_port; | ||
561 | |||
562 | fd = socket (AF_INET, SOCK_DGRAM, 0); | ||
563 | if (fd < 0) | ||
564 | fd = -2; /* Mark failed initialization */ | ||
565 | } | ||
566 | |||
567 | if (fd < 0) | ||
568 | return; | ||
569 | |||
570 | mailbox_get_url (mbox, &url); | ||
571 | asprintf (&buf, "%s@%ld:%s", name, size, url_to_string (url)); | ||
572 | if (buf) | ||
573 | { | ||
574 | sendto (fd, buf, strlen (buf), 0, (struct sockaddr *)&inaddr, | ||
575 | sizeof inaddr); | ||
576 | free (buf); | ||
577 | } | ||
515 | } | 578 | } |
516 | 579 | ||
517 | void | 580 | void |
... | @@ -531,9 +594,6 @@ int temp_errors[] = { | ... | @@ -531,9 +594,6 @@ int temp_errors[] = { |
531 | #ifdef EAGAIN | 594 | #ifdef EAGAIN |
532 | EAGAIN, /* Try again */ | 595 | EAGAIN, /* Try again */ |
533 | #endif | 596 | #endif |
534 | #ifdef EDQUOT | ||
535 | EDQUOT, /* Disk quota esceeded */ | ||
536 | #endif | ||
537 | #ifdef EBUSY | 597 | #ifdef EBUSY |
538 | EBUSY, /* Device or resource busy */ | 598 | EBUSY, /* Device or resource busy */ |
539 | #endif | 599 | #endif |
... | @@ -613,6 +673,14 @@ guess_retval (int ec) | ... | @@ -613,6 +673,14 @@ guess_retval (int ec) |
613 | /* Temporary failures override hard errors. */ | 673 | /* Temporary failures override hard errors. */ |
614 | if (exit_code == EX_TEMPFAIL) | 674 | if (exit_code == EX_TEMPFAIL) |
615 | return; | 675 | return; |
676 | #ifdef EDQUOT | ||
677 | if (ec == EDQUOT) | ||
678 | { | ||
679 | exit_code = EX_QUOTA(); | ||
680 | return; | ||
681 | } | ||
682 | #endif | ||
683 | |||
616 | for (i = 0; i < sizeof (temp_errors)/sizeof (temp_errors[0]); i++) | 684 | for (i = 0; i < sizeof (temp_errors)/sizeof (temp_errors[0]); i++) |
617 | if (temp_errors[i] == ec) | 685 | if (temp_errors[i] == ec) |
618 | { | 686 | { |
... | @@ -632,8 +700,6 @@ static char help_message[] = | ... | @@ -632,8 +700,6 @@ static char help_message[] = |
632 | " -h, --help Display this help and exit\n" | 700 | " -h, --help Display this help and exit\n" |
633 | " -L, --license Display GNU General Public License\n" | 701 | " -L, --license Display GNU General Public License\n" |
634 | " -m, --maildir PATH Specify path to mailspool directory\n" | 702 | " -m, --maildir PATH Specify path to mailspool directory\n" |
635 | " -M, --multiple-delivery Don't return errors when delivering to multiple\n" | ||
636 | " recipients\n" | ||
637 | #ifdef USE_DBM | 703 | #ifdef USE_DBM |
638 | " -q, --quota-db FILE Specify path to quota database.\n" | 704 | " -q, --quota-db FILE Specify path to quota database.\n" |
639 | #endif | 705 | #endif |
... | @@ -641,8 +707,15 @@ static char help_message[] = | ... | @@ -641,8 +707,15 @@ static char help_message[] = |
641 | " -s, --source PATTERN Set name pattern for user-defined mail filters.\n" | 707 | " -s, --source PATTERN Set name pattern for user-defined mail filters.\n" |
642 | #endif | 708 | #endif |
643 | " -t, --timeout NUMBER Set timeout for acquiring the lockfile\n" | 709 | " -t, --timeout NUMBER Set timeout for acquiring the lockfile\n" |
710 | #ifdef WITH_GUILE | ||
711 | " -x, --debug guile Start with guile debugging evaluator and backtraces\n" | ||
712 | #endif | ||
644 | " -x, --debug NUMBER Set debugging level\n" | 713 | " -x, --debug NUMBER Set debugging level\n" |
645 | " -v, --version Display program version and exit.\n" | 714 | " -v, --version Display program version and exit.\n" |
715 | " --ex-multiple-delivery-success Don't return errors when delivering to\n" | ||
716 | " multiple recipients\n" | ||
717 | " --ex-quota-tempfail Return temporary failure if disk or mailbox quota\n" | ||
718 | " is exceeded\n" | ||
646 | "\nReport bugs to bug-mailutils@gnu.org\n"; | 719 | "\nReport bugs to bug-mailutils@gnu.org\n"; |
647 | 720 | ||
648 | printf ("%s", help_message); | 721 | printf ("%s", help_message); | ... | ... |
-
Please register or sign in to post a comment