Commit 3dc97482 3dc974822b70bec356ef67234667a85033260e1b by Sergey Poznyakoff

Added to repository

1 parent d81db5ae
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include <mu_scm.h>
19
20 static void _scheme_main (void *closure, int argc, char **argv);
21
22 void
23 mu_process_mailbox (int argc, char *argv[], guimb_param_t *param)
24 {
25 scm_boot_guile (argc, argv, _scheme_main, param);
26 }
27
28 SCM _current_mailbox;
29 SCM _user_name;
30
31 static SCM
32 catch_body (void *closure)
33 {
34 guimb_param_t *param = closure;
35 return param->catch_body (param->data, param->mbox);
36 }
37
38 void
39 _scheme_main (void *closure, int argc, char **argv)
40 {
41 guimb_param_t *param = closure;
42 SCM *scm_loc;
43
44 if (param->debug_guile)
45 {
46 SCM_DEVAL_P = 1;
47 SCM_BACKTRACE_P = 1;
48 SCM_RECORD_POSITIONS_P = 1;
49 SCM_RESET_DEBUG_MODE;
50 }
51
52 /* Initialize scheme library */
53 mu_scm_init ();
54
55 /* Provide basic primitives */
56 #include <mu_guimb.x>
57
58 _current_mailbox = mu_scm_mailbox_create (param->mbox);
59 scm_loc = SCM_CDRLOC (scm_sysintern ("current-mailbox", SCM_EOL));
60 *scm_loc = _current_mailbox;
61
62 _user_name = param->user_name ?
63 scm_makfrom0str (param->user_name) : SCM_BOOL_F;
64 scm_loc = SCM_CDRLOC (scm_sysintern ("user-name", SCM_EOL));
65 *scm_loc = _user_name;
66
67 if (param->init)
68 param->init (param->data);
69
70 do {
71 scm_internal_lazy_catch (SCM_BOOL_T,
72 catch_body, closure,
73 param->catch_handler, param->data);
74 } while (param->next && param->next (param->data, param->mbox));
75
76 if (param->exit)
77 exit (param->exit (param->data, param->mbox));
78
79 exit (0);
80 }
1 AUTOMAKE_OPTIONS = ../lib/ansi2knr
2 INCLUDES =-I$(srcdir) -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir)/libmu_scm
3
4 libexec_PROGRAMS = mail.local
5 mail_local_SOURCES = main.c mailquota.c script.c mail.local.h
6
7 mail_local_LDADD = @LIBMU_SCM@ ../mailbox/libmailbox.la ../lib/libmailutils.a @GUILE_LIBS@
8
9 install-exec-hook:
10 for i in $(libexec_PROGRAMS); do\
11 chown root:mail $(libexecdir)/$$i;\
12 chmod 4755 $(libexecdir)/$$i;\
13 done
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #if defined(HAVE_CONFIG_H)
19 # include <config.h>
20 #endif
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <syslog.h>
27 #include <pwd.h>
28 #include <grp.h>
29 #include <stdarg.h>
30 #include <sys/stat.h>
31 #include <sysexits.h>
32 #include "getopt.h"
33
34 #ifdef HAVE_STRINGS_H
35 # include <strings.h>
36 #endif
37
38 #include <mailutils/mailbox.h>
39 #include <mailutils/message.h>
40 #include <mailutils/error.h>
41 #include <mailutils/registrar.h>
42 #include <mailutils/stream.h>
43 #include <mailutils/mutil.h>
44 #include <mu_dbm.h>
45
46 /* Debug */
47 extern int debug_level;
48 #define dbg() if (debug_level) debug
49
50 /* mailquota settings */
51 #define MQUOTA_OK 0
52 #define MQUOTA_EXCEEDED 1
53 #define MQUOTA_UNLIMITED 2
54
55 struct mda_data
56 {
57 FILE *fp;
58 char *progfile;
59 char *progfile_pattern;
60 char **argv;
61 char *tempfile;
62 };
63
64 extern char *quotadbname;
65 extern int exit_code;
66
67 extern void setgroupquota (char *str);
68 extern int check_quota (char *name, size_t size, size_t *rest);
69
70 int mda (FILE *fp, char *username, mailbox_t mbox);
71 char *make_progfile_name (char *pattern, char *username);
72
73 #ifdef WITH_GUILE
74 int prog_mda (struct mda_data *data);
75 #endif
76
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include <mail.local.h>
19
20 #ifdef USE_DBM
21
22 #define DEFRETVAL MQUOTA_UNLIMITED
23
24 size_t groupquota = 5*1024*1024UL;
25 static int get_size (char *, size_t *, char **);
26
27 int
28 get_size (char *str, size_t *size, char **endp)
29 {
30 size_t s;
31
32 s = strtol (str, &str, 0);
33 switch (*str)
34 {
35 case 0:
36 break;
37 case 'k':
38 case 'K':
39 s *= 1024;
40 break;
41 case 'm':
42 case 'M':
43 s *= 1024*1024;
44 break;
45 default:
46 *endp = str;
47 return -1;
48 }
49 *size = s;
50 return 0;
51 }
52
53 int
54 check_quota (char *name, size_t size, size_t *rest)
55 {
56 DBM_FILE db;
57 DBM_DATUM named, contentd;
58 size_t quota;
59 char buffer[64];
60 int unlimited = 0;
61 int rc;
62
63 if (!quotadbname || mu_dbm_open (quotadbname, &db, MU_STREAM_READ, 0600))
64 return DEFRETVAL;
65
66 memset (&named, 0, sizeof named);
67 MU_DATUM_PTR (named) = name;
68 MU_DATUM_SIZE (named) = strlen (name);
69 rc = mu_dbm_fetch (db, named, &contentd);
70 if (rc || !MU_DATUM_PTR (contentd))
71 {
72 /* User not in database, try default quota */
73 memset (&named, 0, sizeof named);
74 MU_DATUM_PTR (named) = "DEFAULT";
75 MU_DATUM_SIZE (named) = strlen ("DEFAULT");
76 rc = mu_dbm_fetch (db, named, &contentd);
77 if (rc)
78 {
79 //mu_error("can't fetch data: %s", strerror (rc));
80 return DEFRETVAL;
81 }
82 if (!MU_DATUM_PTR (contentd))
83 return DEFRETVAL;
84 }
85
86 if (strncasecmp("none",
87 MU_DATUM_PTR (contentd),
88 MU_DATUM_SIZE (contentd)) == 0)
89 unlimited = 1;
90 else if (MU_DATUM_SIZE (contentd) > sizeof(buffer)-1)
91 {
92 mu_error ("mailbox quota for `%s' is too big: %d digits",
93 name, MU_DATUM_SIZE (contentd));
94 quota = groupquota;
95 }
96 else
97 {
98 char *p;
99
100 strncpy(buffer, MU_DATUM_PTR (contentd), MU_DATUM_SIZE (contentd));
101 buffer[MU_DATUM_SIZE (contentd)] = 0;
102 quota = strtoul (buffer, &p, 0);
103 if (get_size (buffer, &quota, &p))
104 {
105 mu_error ("bogus mailbox quota for `%s' (near `%s')", name, p);
106 quota = groupquota;
107 }
108 }
109
110 mu_dbm_close (db);
111 if (unlimited)
112 return MQUOTA_UNLIMITED;
113 else if (quota < size) /* Mailbox full */
114 return MQUOTA_EXCEEDED;
115
116 if (rest)
117 *rest = quota - size;
118
119 return MQUOTA_OK;
120 }
121
122 #endif
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include <mail.local.h>
19
20 int debug_level;
21 int multiple_delivery;
22 int bounce_quota;
23 int exit_code = EX_OK;
24 uid_t uid;
25 char *maildir = MU_PATH_MAILDIR;
26 char *quotadbname = NULL;
27 int lock_timeout = 300;
28
29 #define MAXFD 64
30
31 static void print_help (void);
32 static void print_license (void);
33 static void print_version (void);
34 void close_fds ();
35 int switch_user_id (uid_t uid);
36 FILE *make_tmp (const char *from, char **tempfile);
37 void deliver (FILE *fp, char *name);
38 void guess_retval (int ec);
39 void mailer_err (char *fmt, ...);
40
41 char short_opts[] = "hf:Llm:q:r:s:x::v";
42
43 static struct option long_opts[] = {
44 { "from", required_argument, 0, 'f' },
45 { "help", no_argument, 0, 'h' },
46 { "license", no_argument, 0, 'L' },
47 { "maildir", required_argument, 0, 'm' },
48 { "multiple-delivery", no_argument, 0, 'M' },
49 { "quota-db", required_argument, 0, 'q' },
50 { "source", required_argument, 0, 's' },
51 { "timeout", required_argument, 0, 't' },
52 { "debug", optional_argument, 0, 'x' },
53 { "version", no_argument, 0, 'v' },
54 { 0, 0, 0, 0 }
55 };
56
57
58 int
59 main (int argc, char *argv[])
60 {
61 int c;
62 FILE *fp;
63 char *from = NULL;
64 char *progfile_pattern = NULL;
65 struct mda_data mda_data;
66
67 /* Preparative work: close inherited fds, force a reasonable umask
68 and prepare a logging. */
69 close_fds ();
70 umask (0077);
71
72 openlog ("mail.local", LOG_PID, LOG_FACILITY);
73 mu_error_set_print (mu_syslog_error_printer);
74
75 uid = getuid ();
76 while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != EOF)
77 switch (c)
78 {
79 case 'r':
80 case 'f':
81 if (from != NULL)
82 {
83 mu_error ("multiple --from options");
84 return 1;
85 }
86 from = optarg;
87 break;
88
89 case 'h':
90 print_help ();
91 break;
92
93 case 'L':
94 print_license ();
95 break;
96
97 case 'm':
98 maildir = optarg;
99 break;
100
101 case 'M':
102 multiple_delivery++;
103 break;
104
105 #ifdef USE_DBM
106 case 'q':
107 quotadbname = optarg;
108 break;
109 #endif
110
111 #ifdef WITH_GUILE
112 case 's':
113 progfile_pattern = optarg;
114 break;
115 #endif
116
117 case 't':
118 lock_timeout = strtoul (optarg, NULL, 0);
119 break;
120
121 case 'x':
122 if (optarg)
123 debug_level = strtoul (optarg, NULL, 0);
124 else
125 debug_level = 9;
126 break;
127
128 case 'v':
129 print_version ();
130 break;
131
132 default:
133 return 1;
134 }
135
136 argc -= optind;
137 argv += optind;
138
139 if (!argc)
140 print_help ();
141
142 maildir = mu_normalize_maildir (maildir);
143 if (!maildir)
144 {
145 mu_error ("Badly formed maildir: %s", maildir);
146 return 1;
147 }
148
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 mu_register_getpwnam (getMpwnam);
163 #endif
164 /* Register local mbox formats. */
165 {
166 list_t bookie;
167 registrar_get_list (&bookie);
168 list_append (bookie, mbox_record);
169 list_append (bookie, path_record);
170 /* Possible supported mailers. */
171 list_append (bookie, sendmail_record);
172 list_append (bookie, smtp_record);
173 }
174
175 memset (&mda_data, 0, sizeof mda_data);
176 fp = make_tmp (from, &mda_data.tempfile);
177
178 if (multiple_delivery)
179 multiple_delivery = argc > 1;
180
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)
187 return prog_mda (&mda_data);
188 #endif
189
190 unlink (mda_data.tempfile);
191 for (; *argv; argv++)
192 mda (fp, *argv, NULL);
193 return exit_code;
194 }
195
196 char *
197 make_progfile_name (char *pattern, char *username)
198 {
199 char *homedir = NULL;
200 char *p, *q, *startp;
201 char *progfile;
202 int len = 0;
203
204 for (p = pattern; *p; p++)
205 {
206 if (*p == '%')
207 switch (*++p)
208 {
209 case 'u':
210 len += strlen (username);
211 break;
212 case 'h':
213 if (!homedir)
214 {
215 struct passwd *pwd = getpwnam (username);
216 if (!pwd)
217 return NULL;
218 homedir = pwd->pw_dir;
219 }
220 len += strlen (homedir);
221 break;
222 case '%':
223 len++;
224 break;
225 default:
226 len += 2;
227 }
228 else
229 len++;
230 }
231
232 progfile = malloc (len + 1);
233 if (!progfile)
234 return NULL;
235
236 startp = pattern;
237 q = progfile;
238 while (*startp && (p = strchr (startp, '%')) != NULL)
239 {
240 memcpy (q, startp, p - startp);
241 q += p - startp;
242 switch (*++p)
243 {
244 case 'u':
245 strcpy (q, username);
246 q += strlen (username);
247 break;
248 case 'h':
249 strcpy (q, homedir);
250 q += strlen (homedir);
251 break;
252 case '%':
253 *q++ = '%';
254 break;
255 default:
256 *q++ = '%';
257 *q++ = *p;
258 }
259 startp = p + 1;
260 }
261 if (*startp)
262 {
263 strcpy (q, startp);
264 q += strlen (startp);
265 }
266 *q = 0;
267 return progfile;
268 }
269
270 int
271 mda (FILE *fp, char *username, mailbox_t mbox)
272 {
273 if (mbox)
274 {
275 message_t mesg = NULL;
276 attribute_t attr = NULL;
277
278 mailbox_get_message (mbox, 1, &mesg);
279 message_get_attribute (mesg, &attr);
280 if (attribute_is_deleted (attr))
281 return EX_OK;
282 }
283
284 deliver (fp, username);
285
286 if (multiple_delivery)
287 exit_code = EX_OK;
288
289 return exit_code;
290 }
291
292 void
293 close_fds ()
294 {
295 int i;
296 long fdlimit = MAXFD;
297
298 #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
299 fdlimit = sysconf (_SC_OPEN_MAX);
300 #elif defined (HAVE_GETDTABLESIZE)
301 fdlimit = getdtablesize ();
302 #endif
303
304 for (i = 3; i < fdlimit; i++)
305 close (i);
306 }
307
308 int
309 switch_user_id (uid_t uid)
310 {
311 int rc;
312 #if defined(HAVE_SETREUID)
313 rc = setreuid (0, uid);
314 #elif defined(HAVE_SETRESUID)
315 rc = setresuid (-1, uid, -1);
316 #elif defined(HAVE_SETEUID)
317 rc = seteuid (uid);
318 #else
319 # error "No way to reset user privileges?"
320 #endif
321 if (rc < 0)
322 mailer_err ("setreuid(0, %d): %s (r=%d, e=%d)",
323 uid, strerror (errno), getuid (), geteuid ());
324 return rc;
325 }
326
327 FILE *
328 make_tmp (const char *from, char **tempfile)
329 {
330 time_t t;
331 int fd = mu_tempfile (NULL, tempfile);
332 FILE *fp;
333 char *buf = NULL;
334 size_t n = 0;
335
336 if (fd == -1 || (fp = fdopen(fd, "w+")) == NULL)
337 {
338 mailer_err("unable to open temporary file");
339 exit (exit_code);
340 }
341
342 time (&t);
343 fprintf (fp, "From %s %s", from, ctime (&t));
344
345 while (getline(&buf, &n, stdin) > 0) {
346 if (!memcmp(buf, "From ", 5))
347 fputc('>', fp);
348 if (fputs (buf, fp) == EOF)
349 {
350 mailer_err ("temporary file write error");
351 fclose(fp);
352 return NULL;
353 }
354 }
355
356 if (buf && strchr(buf, '\n') == NULL)
357 putc('\n', fp);
358
359 putc('\n', fp);
360 free (buf);
361
362 return fp;
363 }
364
365 void
366 deliver (FILE *fp, char *name)
367 {
368 mailbox_t mbox;
369 char *path;
370 url_t url = NULL;
371 size_t n = 0;
372 locker_t lock;
373 int timeout;
374 struct stat sb;
375 struct passwd *pw;
376 int status;
377 stream_t stream;
378 size_t size;
379 int failed = 0;
380
381 pw = mu_getpwnam (name);
382 if (!pw)
383 {
384 mailer_err ("%s: no such user", name);
385 exit_code = EX_UNAVAILABLE;
386 return;
387 }
388
389 path = malloc (strlen (maildir) + strlen (name) + 1);
390 if (!path)
391 {
392 mailer_err ("Out of memory");
393 return;
394 }
395 sprintf (path, "%s%s", maildir, name);
396
397 if ((status = mailbox_create (&mbox, path)) != 0)
398 {
399 mailer_err ("can't open mailbox %s: %s", path, strerror (status));
400 free (path);
401 return;
402 }
403
404 free (path);
405
406 mailbox_get_url (mbox, &url);
407 path = (char*) url_to_string (url);
408
409 /* Actually open the mailbox. Switch to the user's euid to make
410 sure the maildrop file will have right privileges, in case it
411 will be created */
412 if (switch_user_id (pw->pw_uid))
413 return;
414 status = mailbox_open (mbox, MU_STREAM_RDWR|MU_STREAM_CREAT);
415 if (switch_user_id (0))
416 return;
417 if (status != 0)
418 {
419 mailer_err ("can't open mailbox %s: %s", path, strerror (status));
420 mailbox_destroy (&mbox);
421 return;
422 }
423
424 mailbox_get_locker (mbox, &lock);
425
426 timeout = lock_timeout;
427 while ((status = locker_lock (lock, MU_LOCKER_WRLOCK)))
428 {
429 if (timeout-- <= 0)
430 break;
431 sleep (1);
432 }
433
434 if (status)
435 {
436 mailer_err ("cannot lock mailbox '%s': %s", path, strerror (status));
437 mailbox_destroy (&mbox);
438 return;
439 }
440
441 if ((status = mailbox_get_stream (mbox, &stream)))
442 {
443 mailer_err ("can't get stream for mailbox %s: %s",
444 path, strerror (status));
445 mailbox_destroy (&mbox);
446 return;
447 }
448
449 if ((status = stream_size (stream, (off_t *) &size)))
450 {
451 mailer_err ("can't get stream size (mailbox %s): %s",
452 path, strerror (status));
453 mailbox_destroy (&mbox);
454 return;
455 }
456
457 #if defined(USE_DBM)
458 switch (check_quota (name, size, &n))
459 {
460 case MQUOTA_EXCEEDED:
461 mailer_err ("%s: mailbox quota exceeded for this recipient", name);
462 exit_code = EX_UNAVAILABLE;
463 failed++;
464 break;
465 case MQUOTA_UNLIMITED:
466 break;
467 default:
468 if (fstat (fileno (fp), &sb))
469 {
470 mailer_err ("cannot stat tempfile: %s", strerror (errno));
471 exit_code = EX_UNAVAILABLE;
472 failed++;
473 }
474 else if (sb.st_size > n)
475 {
476 mailer_err ("%s: message would exceed maximum mailbox size for this recipient",
477 name);
478 exit_code = EX_UNAVAILABLE;
479 failed++;
480 }
481 break;
482 }
483 #endif
484
485 if (!failed && switch_user_id (pw->pw_uid) == 0)
486 {
487 off_t off = size;
488 size_t nwr;
489 char *buf = NULL;
490
491 n = 0;
492 status = 0;
493 fseek (fp, 0, SEEK_SET);
494 while (getline(&buf, &n, fp) > 0) {
495 status = stream_write (stream, buf, strlen (buf), off, &nwr);
496 if (status)
497 {
498 mailer_err ("error writing to mailbox: %s", strerror (status));
499 break;
500 }
501 off += nwr;
502 }
503 free (buf);
504 switch_user_id (0);
505 }
506
507 locker_unlock (lock);
508 /* FIXME: Flush the data */
509 mailbox_close (mbox);
510 mailbox_destroy (&mbox);
511 #if 0 /*FIXME*/
512 if (!failed)
513 notify_biff (name, size);
514 #endif
515 }
516
517 void
518 mailer_err (char *fmt, ...)
519 {
520 va_list ap;
521
522 guess_retval (errno);
523 va_start (ap, fmt);
524 vfprintf (stderr, fmt, ap);
525 fprintf (stderr, "\n");
526 mu_verror (fmt, ap);
527 va_end (ap);
528 }
529
530 int temp_errors[] = {
531 #ifdef EAGAIN
532 EAGAIN, /* Try again */
533 #endif
534 #ifdef EDQUOT
535 EDQUOT, /* Disk quota esceeded */
536 #endif
537 #ifdef EBUSY
538 EBUSY, /* Device or resource busy */
539 #endif
540 #ifdef EPROCLIM
541 EPROCLIM, /* Too many processes */
542 #endif
543 #ifdef EUSERS
544 EUSERS, /* Too many users */
545 #endif
546 #ifdef ECONNABORTED
547 ECONNABORTED, /* Software caused connection abort */
548 #endif
549 #ifdef ECONNREFUSED
550 ECONNREFUSED, /* Connection refused */
551 #endif
552 #ifdef ECONNRESET
553 ECONNRESET, /* Connection reset by peer */
554 #endif
555 #ifdef EDEADLK
556 EDEADLK, /* Resource deadlock would occur */
557 #endif
558 #ifdef EDEADLOCK
559 EDEADLOCK, /* Resource deadlock would occur */
560 #endif
561 #ifdef EFBIG
562 EFBIG, /* File too large */
563 #endif
564 #ifdef EHOSTDOWN
565 EHOSTDOWN, /* Host is down */
566 #endif
567 #ifdef EHOSTUNREACH
568 EHOSTUNREACH, /* No route to host */
569 #endif
570 #ifdef EMFILE
571 EMFILE, /* Too many open files */
572 #endif
573 #ifdef ENETDOWN
574 ENETDOWN, /* Network is down */
575 #endif
576 #ifdef ENETUNREACH
577 ENETUNREACH, /* Network is unreachable */
578 #endif
579 #ifdef ENETRESET
580 ENETRESET, /* Network dropped connection because of reset */
581 #endif
582 #ifdef ENFILE
583 ENFILE, /* File table overflow */
584 #endif
585 #ifdef ENOBUFS
586 ENOBUFS, /* No buffer space available */
587 #endif
588 #ifdef ENOMEM
589 ENOMEM, /* Out of memory */
590 #endif
591 #ifdef ENOSPC
592 ENOSPC, /* No space left on device */
593 #endif
594 #ifdef EROFS
595 EROFS, /* Read-only file system */
596 #endif
597 #ifdef ESTALE
598 ESTALE, /* Stale NFS file handle */
599 #endif
600 #ifdef ETIMEDOUT
601 ETIMEDOUT, /* Connection timed out */
602 #endif
603 #ifdef EWOULDBLOCK
604 EWOULDBLOCK, /* Operation would block */
605 #endif
606 };
607
608
609 void
610 guess_retval (int ec)
611 {
612 int i;
613 /* Temporary failures override hard errors. */
614 if (exit_code == EX_TEMPFAIL)
615 return;
616 for (i = 0; i < sizeof (temp_errors)/sizeof (temp_errors[0]); i++)
617 if (temp_errors[i] == ec)
618 {
619 exit_code = EX_TEMPFAIL;
620 return;
621 }
622 exit_code = EX_UNAVAILABLE;
623 }
624
625 void
626 print_help ()
627 {
628 static char help_message[] =
629 "Usage: mail.local [OPTIONS] recipient [recipient...]\n"
630 "Options are:\n"
631 " -f, --from ADDR Specify the sender's name\n"
632 " -h, --help Display this help and exit\n"
633 " -L, --license Display GNU General Public License\n"
634 " -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
638 " -q, --quota-db FILE Specify path to quota database.\n"
639 #endif
640 #ifdef WITH_GUILE
641 " -s, --source PATTERN Set name pattern for user-defined mail filters.\n"
642 #endif
643 " -t, --timeout NUMBER Set timeout for acquiring the lockfile\n"
644 " -x, --debug NUMBER Set debugging level\n"
645 " -v, --version Display program version and exit.\n"
646 "\nReport bugs to bug-mailutils@gnu.org\n";
647
648 printf ("%s", help_message);
649 exit (0);
650 }
651
652 void
653 print_license ()
654 {
655 static char license_text[] =
656 " This program is free software; you can redistribute it and/or modify\n"
657 " it under the terms of the GNU General Public License as published by\n"
658 " the Free Software Foundation; either version 2, or (at your option)\n"
659 " any later version.\n"
660 "\n"
661 " This program is distributed in the hope that it will be useful,\n"
662 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
663 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
664 " GNU General Public License for more details.\n"
665 "\n"
666 " You should have received a copy of the GNU General Public License\n"
667 " along with this program; if not, write to the Free Software\n"
668 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n";
669 printf ("%s", license_text);
670 exit (0);
671 }
672
673 void
674 print_version ()
675 {
676 printf ("mail.local ("PACKAGE " " VERSION ")\n");
677 exit (0);
678 }
679
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include <mail.local.h>
19
20 #ifdef WITH_GUILE
21 #include <mu_scm.h>
22
23 SCM mda_catch_body (void *data, mailbox_t mbox);
24 SCM mda_catch_handler (void *unused, SCM tag, SCM throw_args);
25 int mda_next (void *data, mailbox_t mbox);
26 int mda_exit (void *data, mailbox_t mbox);
27 int mda_init (void *data);
28
29 int
30 prog_mda (struct mda_data *data)
31 {
32 char *x_argv[2];
33 guimb_param_t param;
34 mailbox_t mbox;
35
36 x_argv[0] = "mail.local";
37 x_argv[1] = NULL;
38
39 fflush (data->fp);
40 if (mailbox_create (&mbox, data->tempfile)
41 || mailbox_open (mbox, MU_STREAM_RDWR) != 0)
42 {
43 mailer_err ("can't open temporary storage");
44 return EX_UNAVAILABLE;
45 }
46
47 unlink (data->tempfile);
48
49 param.debug_guile = 1 /*FIXME*/;
50 param.mbox = mbox;
51 param.user_name = NULL;
52 param.init = mda_init;
53 param.catch_body = mda_catch_body;
54 param.catch_handler = mda_catch_handler;
55 param.next = mda_next;
56 param.exit = mda_exit;
57 param.data = data;
58
59 mu_process_mailbox (1, x_argv, &param);
60 return EX_UNAVAILABLE;
61 }
62
63 int
64 mda_init (void *data)
65 {
66 struct mda_data *md = data;
67 md->progfile = make_progfile_name (md->progfile_pattern, md->argv[0]);
68 return 0;
69 }
70
71 SCM
72 mda_catch_body (void *data, mailbox_t mbox)
73 {
74 struct mda_data *md = data;
75
76 if (access (md->progfile, R_OK))
77 {
78 syslog (LOG_ERR, "access to %s failed: %m", md->progfile);
79 }
80 else
81 scm_primitive_load (scm_makfrom0str (md->progfile));
82 mda (md->fp, md->argv[0], mbox);
83 return SCM_BOOL_F;
84 }
85
86 SCM
87 mda_catch_handler (void *data, SCM tag, SCM throw_args)
88 {
89 exit_code = EX_TEMPFAIL;
90 return scm_handle_by_message_noexit ("mail.local", tag, throw_args);
91 }
92
93 int
94 mda_next (void *data, mailbox_t mbox)
95 {
96 struct mda_data *md = data;
97 message_t mesg = NULL;
98 attribute_t attr = NULL;
99
100 md->argv++;
101 if (*md->argv == NULL)
102 return 0;
103 if (md->progfile)
104 free (md->progfile);
105 md->progfile = make_progfile_name (md->progfile_pattern, *md->argv);
106
107 mailbox_get_message (mbox, 1, &mesg);
108 message_get_attribute (mesg, &attr);
109 attribute_unset_deleted (attr);
110
111 return md->progfile != NULL;
112 }
113
114 int
115 mda_exit (void *data, mailbox_t mbox)
116 {
117 return exit_code;
118 }
119
120 #endif