masqmail

view src/masqmail.c @ 421:f37384470855

Changed lockdir to /var/lock/masqmail; Create lockdir and piddir on startup. Moved the lockdir out of the spool dir. (When /var/lock is a ramdisk we do well to have the lock files there.) Added the new configure option --with-lockdir to change that location. Nontheless, if we run_as_user, then lock files are always stored in the spool dir directly. Instead of installing the lockdir and piddir at installation time, we create them on startup time now if they are missing. This is necessary if lockdir or piddir are a tmpfs.
author markus schnalke <meillo@marmaro.de>
date Wed, 30 May 2012 09:38:38 +0200
parents d209b4846f2b
children a19e47ebbb33
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 1999-2001 Oliver Kurth
4 ** Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
21 #include <stdio.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <netinet/in.h>
30 #include <netdb.h>
31 #include <syslog.h>
32 #include <signal.h>
34 #include <glib.h>
36 #include "masqmail.h"
38 /*
39 ** mutually exclusive modes. Note that there is no 'queue daemon' mode.
40 ** It, as well as the distinction beween the two (non exclusive) daemon
41 ** (queue and listen) modes, is handled by flags.
42 */
43 enum mta_mode {
44 MODE_NONE = 0, /* to check if a mode was set */
45 MODE_ACCEPT, /* accept message on stdin (fallback mode) */
46 MODE_DAEMON, /* run as daemon */
47 MODE_RUNQUEUE, /* single queue run, online or offline */
48 MODE_SMTP, /* accept SMTP on stdin */
49 MODE_LIST, /* list queue */
50 MODE_MCMD, /* do queue manipulation */
51 MODE_VERSION, /* show version */
52 MODE_BI, /* fake ;-) */
53 };
54 enum mta_mode mta_mode = MODE_NONE;
56 char *pidfile = NULL;
57 volatile int sigterm_in_progress = 0;
59 static void
60 sigterm_handler(int sig)
61 {
62 if (sigterm_in_progress)
63 raise(sig);
64 sigterm_in_progress = 1;
66 if (pidfile) {
67 uid_t uid = geteuid();
68 if (seteuid(0) != 0) {
69 logwrite(LOG_ALERT, "sigterm_handler: could not set "
70 "euid to %d: %s\n",
71 0, strerror(errno));
72 }
73 if (unlink(pidfile) != 0)
74 logwrite(LOG_WARNING,
75 "could not delete pid file %s: %s\n",
76 pidfile, strerror(errno));
77 seteuid(uid); /* we exit anyway after this, just to be sure */
78 }
80 signal(sig, SIG_DFL);
81 raise(sig);
82 }
84 /*
85 ** argv: the original argv
86 ** argp: number of arg (may get modified!)
87 ** cp: pointing to the char after the option
88 ** e.g. `-d 6' `-d6'
89 ** ^ ^
90 */
91 gchar*
92 get_optarg(char *argv[], gint *argp, char *cp)
93 {
94 if (*cp) {
95 /* this kind: -xval */
96 return cp;
97 }
98 cp = argv[*argp+1];
99 if (cp && (*cp != '-')) {
100 /* this kind: -x val */
101 (*argp)++;
102 return cp;
103 }
104 return NULL;
105 }
107 /*
108 ** Create any missing directory in pathname `dir'. (Like `mkdir -p'.)
109 ** The code is taken from nmh.
110 */
111 gboolean
112 makedir_rec(char *dir, int perms)
113 {
114 char path[PATH_MAX];
115 char *cp, *c;
116 int had_an_error = 0;
118 c = strncpy(path, dir, sizeof(path));
120 while (!had_an_error && (c = strchr(c+1, '/'))) {
121 *c = '\0';
122 /* Create an outer directory. */
123 if (mkdir(path, perms) == -1 && errno != EEXIST) {
124 fprintf(stderr, "unable to create `%s': %s\n",
125 path, strerror(errno));
126 had_an_error = 1;
127 }
128 *c = '/';
129 }
131 /*
132 ** Create the innermost nested subdirectory of the
133 ** path we're being asked to create.
134 */
135 if (!had_an_error && mkdir(dir, perms)==-1 && errno != EEXIST) {
136 fprintf(stderr, "unable to create `%s': %s\n",
137 dir, strerror(errno));
138 had_an_error = 1;
139 }
141 return (had_an_error) ? 0 : 1;
142 }
144 gboolean
145 write_pidfile(gchar *name)
146 {
147 FILE *fptr;
149 if ((fptr = fopen(name, "wt"))) {
150 fprintf(fptr, "%d\n", getpid());
151 fclose(fptr);
152 pidfile = strdup(name);
153 return TRUE;
154 }
155 logwrite(LOG_WARNING, "could not write pid file: %s\n",
156 strerror(errno));
157 return FALSE;
158 }
160 /* on -bd or if -q has an argument */
161 static void
162 mode_daemon(gboolean do_listen, gint queue_interval, char *argv[])
163 {
164 guint pid;
166 /* daemon */
167 if (!conf.run_as_user) {
168 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) {
169 fprintf(stderr, "must be root or %s for daemon.\n",
170 DEF_MAIL_USER);
171 exit(1);
172 }
173 }
175 /* reparent to init only if init is not already the parent */
176 if (getppid() != 1) {
177 if ((pid = fork()) > 0) {
178 exit(0);
179 } else if (pid < 0) {
180 logwrite(LOG_ALERT, "could not fork!\n");
181 exit(1);
182 }
183 }
185 signal(SIGTERM, sigterm_handler);
186 makedir_rec(PID_DIR, 0755);
187 write_pidfile(PID_DIR "/masqmail.pid");
189 conf.do_verbose = FALSE;
191 /*
192 ** closing and reopening the log ensures that it is open afterwards
193 ** because it is possible that the log is assigned to fd 1 and gets
194 ** thus closes by fclose(stdout). Similar for the debugfile.
195 */
196 logclose();
197 fclose(stdin);
198 fclose(stdout);
199 fclose(stderr);
200 logopen();
202 logwrite(LOG_NOTICE, "%s %s daemon starting\n", PACKAGE, VERSION);
203 listen_port(do_listen ? conf.listen_addresses : NULL,
204 queue_interval, argv);
205 }
207 /* -bs or called as smtpd or in.smtpd */
208 static void
209 mode_smtp()
210 {
211 /* accept smtp message on stdin */
212 /* write responses to stderr. */
214 struct sockaddr_in saddr;
215 gchar *peername = NULL;
216 int dummy = sizeof(saddr);
218 conf.do_verbose = FALSE;
220 if (!conf.run_as_user) {
221 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL);
222 }
224 DEBUG(5) debugf("accepting smtp message on stdin\n");
226 if (getpeername(0, (struct sockaddr *) (&saddr), &dummy) == 0) {
227 peername = g_strdup(inet_ntoa(saddr.sin_addr));
228 } else if (errno != ENOTSOCK)
229 exit(1);
231 smtp_in(stdin, stderr, peername, NULL);
232 }
234 /* default mode if address args or -t is specified, or called as rmail */
235 static void
236 mode_accept(address *return_path, gchar *full_sender_name, guint accept_flags,
237 char **addresses, int addr_cnt)
238 {
239 /* accept message on stdin */
240 accept_error err;
241 message *msg = create_message();
242 gint i;
243 pid_t pid;
245 if (return_path && !is_privileged_user(conf.orig_uid)) {
246 fprintf(stderr, "must be root, %s or in group %s for "
247 "setting return path.\n",
248 DEF_MAIL_USER, DEF_MAIL_GROUP);
249 exit(1);
250 }
252 if (!conf.run_as_user) {
253 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL);
254 }
256 DEBUG(5) debugf("accepting message on stdin\n");
258 msg->received_prot = PROT_LOCAL;
260 /* warn if -t option and cmdline addr args */
261 if (addr_cnt && (accept_flags & ACC_RCPT_FROM_HEAD)) {
262 logwrite(LOG_ALERT, "command line address arguments are "
263 "now *added* to the mail header\\\n");
264 logwrite(LOG_ALERT, " recipient addresses (instead of "
265 "substracted) when -t is given.\\\n");
266 logwrite(LOG_ALERT, " this changed with version 0.3.1\n");
267 }
269 for (i = 0; i < addr_cnt; i++) {
270 if (addresses[i][0] == '|') {
271 logwrite(LOG_ALERT, "no pipe allowed as recipient "
272 "address: %s\n", addresses[i]);
273 /* should we better ignore this one addr? */
274 exit(1);
275 }
276 msg->rcpt_list = g_list_append(msg->rcpt_list,
277 create_address_qualified(addresses[i],
278 TRUE, conf.host_name));
279 }
281 /* -f option */
282 msg->return_path = return_path;
284 /* -F option */
285 msg->full_sender_name = full_sender_name;
287 err = accept_message(stdin, msg, accept_flags);
289 switch (err) {
290 case AERR_OK:
291 /* to continue; all other cases exit */
292 break;
293 case AERR_EOF:
294 fprintf(stderr, "unexpected EOF.\n");
295 exit(1);
296 case AERR_NORCPT:
297 fprintf(stderr, "no recipients.\n");
298 exit(1);
299 case AERR_SIZE:
300 fprintf(stderr, "max message size exceeded.\n");
301 exit(1);
302 default:
303 /* should never happen: */
304 fprintf(stderr, "Unknown error (%d)\r\n", err);
305 exit(1);
306 }
308 if (!spool_write(msg, TRUE)) {
309 fprintf(stderr, "Could not write spool file\n");
310 exit(1);
311 }
313 /* here the mail is queued and thus in our responsibility */
314 logwrite(LOG_NOTICE, "%s <= %s with %s\n", msg->uid,
315 addr_string(msg->return_path), prot_names[PROT_LOCAL]);
317 if (conf.do_queue) {
318 /* we're finished as we only need to queue it */
319 return;
320 }
322 /* deliver at once */
323 if ((pid = fork()) < 0) {
324 logwrite(LOG_ALERT, "could not fork for delivery, id = %s\n",
325 msg->uid);
326 } else if (pid == 0) {
327 conf.do_verbose = FALSE;
328 fclose(stdin);
329 fclose(stdout);
330 fclose(stderr);
331 if (deliver(msg)) {
332 exit(0);
333 } else {
334 /*
335 ** TODO: Should we really fail here? Because the
336 ** mail is queued already. If we fail the client
337 ** might submit it again. If at-once-delivery
338 ** is seen as an additional best-effort service,
339 ** then we should still exit successful here.
340 */
341 exit(1);
342 }
343 }
344 }
346 /*
347 ** if -Mrm is given
348 **
349 ** currently only the `rm' command is supported
350 ** until this changes, we don't need any facility for further commands
351 ** return success if at least one message had been deleted
352 */
353 static int
354 manipulate_queue(char *cmd, char *id[])
355 {
356 gboolean ok = FALSE;
358 if (strcmp(cmd, "rm") != 0) {
359 fprintf(stderr, "unknown command %s\n", cmd);
360 return FALSE;
361 }
363 set_euidgid(conf.mail_uid, conf.mail_gid, NULL, NULL);
365 /* privileged users may delete any mail */
366 if (is_privileged_user(conf.orig_uid)) {
367 for (; *id; id++) {
368 fprintf(stderr, "id: %s\n", *id);
369 if (queue_delete(*id)) {
370 ok = TRUE;
371 }
372 }
373 return ok;
374 }
376 struct passwd *pw = getpwuid(conf.orig_uid);
377 if (!pw) {
378 fprintf(stderr, "could not find a passwd entry for "
379 "uid %d: %s\n",
380 conf.orig_uid, strerror(errno));
381 return FALSE;
382 }
384 /* non-privileged users may only delete their own messages */
385 for (; *id; id++) {
386 message *msg = msg_spool_read(*id);
388 fprintf(stderr, "id: %s\n", *id);
390 if (!msg->ident) {
391 fprintf(stderr, "message %s does not have an ident\n",
392 *id);
393 continue;
394 }
395 if (strcmp(pw->pw_name, msg->ident) != 0) {
396 fprintf(stderr, "you do not own message id %s\n", *id);
397 continue;
398 }
400 if (msg->received_host || (msg->received_prot != PROT_LOCAL)) {
401 fprintf(stderr, "message %s was not received "
402 "locally\n", *id);
403 continue;
404 }
406 ok = queue_delete(*id);
407 }
408 return ok;
409 }
411 /* -qo, -q (without argument), or called as runq */
412 static int
413 run_queue(gboolean do_runq, gboolean do_runq_online, char *route_name)
414 {
415 int ret;
417 /* queue runs */
418 set_identity(conf.orig_uid, "queue run");
420 if (do_runq) {
421 ret = queue_run();
422 }
424 if (do_runq_online) {
425 if (route_name) {
426 conf.online_query = g_strdup_printf("/bin/echo %s",
427 route_name);
428 }
429 /*
430 ** TODO: change behavior of `-qo without argument'?
431 ** Because that behavior is included in -q.
432 */
433 ret = queue_run_online();
434 }
435 return ret;
436 }
438 /* -bV or default mode if neither addr arg nor -t */
439 static void
440 mode_version(void)
441 {
442 gchar *with_resolver = "";
443 gchar *with_auth = "";
445 #ifdef ENABLE_RESOLVER
446 with_resolver = " +resolver";
447 #endif
448 #ifdef ENABLE_AUTH
449 with_auth = " +auth";
450 #endif
452 printf("%s %s%s%s\n", PACKAGE, VERSION, with_resolver, with_auth);
453 }
455 void
456 set_mode(enum mta_mode mode)
457 {
458 if (mta_mode && mta_mode!=mode) {
459 fprintf(stderr, "operation mode was already specified "
460 "(%d vs. %d)\n", mta_mode, mode);
461 exit(1);
462 }
464 mta_mode = mode;
465 return;
466 }
468 int
469 main(int argc, char *argv[])
470 {
471 gchar *progname;
472 char *opt;
473 gint arg;
475 gboolean do_listen = FALSE;
476 gboolean do_runq = FALSE;
477 gboolean do_runq_online = FALSE;
478 gboolean do_queue = FALSE;
479 gint queue_interval = 0;
480 gchar *M_cmd = NULL;
481 gboolean opt_t = FALSE;
482 gboolean opt_i = FALSE;
483 gchar *conf_file = CONF_FILE;
484 gchar *route_name = NULL;
485 gchar *f_address = NULL;
486 address *return_path = NULL; /* may be changed by -f option */
487 gchar *full_sender_name = NULL;
488 gboolean do_verbose = FALSE;
489 gint debug_level = -1;
491 /* strip the path part */
492 progname = strrchr(argv[0], '/');
493 progname = (progname) ? progname+1 : argv[0];
495 if (strcmp(progname, "mailq") == 0) {
496 mta_mode = MODE_LIST;
497 } else if (strcmp(progname, "mailrm") == 0) {
498 mta_mode = MODE_MCMD;
499 M_cmd = "rm";
500 } else if (strcmp(progname, "newaliases") == 0) {
501 mta_mode = MODE_BI;
502 } else if (strcmp(progname, "rmail") == 0) {
503 /*
504 ** the `rmail' alias should probably be removed now
505 ** that we have the rmail script. But let's keep it
506 ** for some while for compatibility. 2010-06-19
507 */
508 mta_mode = MODE_ACCEPT;
509 opt_i = TRUE;
510 } else if (strcmp(progname, "runq") == 0) {
511 mta_mode = MODE_RUNQUEUE;
512 do_runq = TRUE;
513 } else if (strcmp(progname, "smtpd") == 0
514 || strcmp(progname, "in.smtpd") == 0) {
515 mta_mode = MODE_SMTP;
516 }
518 /* parse cmd line */
519 for (arg=1; arg<argc && argv[arg][0]=='-'; arg++) {
520 opt = argv[arg] + 1; /* points to the char after the dash */
522 if (strcmp(opt, "-") == 0) {
523 /* everything after `--' are address arguments */
524 arg++;
525 break;
527 } else if (strcmp(opt, "bm") == 0) {
528 set_mode(MODE_ACCEPT);
530 } else if (strcmp(opt, "bd") == 0) {
531 set_mode(MODE_DAEMON);
532 do_listen = TRUE;
534 } else if (strcmp(opt, "bi") == 0) {
535 set_mode(MODE_BI);
537 } else if (strcmp(opt, "bs") == 0) {
538 set_mode(MODE_SMTP);
540 } else if (strcmp(opt, "bp") == 0) {
541 set_mode(MODE_LIST);
543 } else if (strcmp(opt, "bV") == 0) {
544 set_mode(MODE_VERSION);
546 } else if (strncmp(opt, "B", 1) == 0) {
547 /* we ignore this and throw the argument away */
548 get_optarg(argv, &arg, opt+1);
550 } else if (strncmp(opt, "C", 1) == 0) {
551 conf_file = get_optarg(argv, &arg, opt+1);
552 if (!conf_file) {
553 fprintf(stderr, "-C requires filename arg.\n");
554 exit(1);
555 }
557 } else if (strncmp(opt, "d", 1) == 0) {
558 if (getuid() != 0) {
559 fprintf(stderr, "only root may set the "
560 "debug level.\n");
561 exit(1);
562 }
563 char *lvl = get_optarg(argv, &arg, opt+1);
564 if (!lvl) {
565 fprintf(stderr, "-d requires number arg.\n");
566 exit(1);
567 }
568 debug_level = atoi(lvl);
570 } else if (strncmp(opt, "f", 1) == 0) {
571 /* set return path */
572 gchar *address = get_optarg(argv, &arg, opt+1);
573 if (!address) {
574 fprintf(stderr, "-f requires address arg.\n");
575 exit(1);
576 }
577 f_address = g_strdup(address);
579 } else if (strncmp(opt, "F", 1) == 0) {
580 full_sender_name = get_optarg(argv, &arg, opt+1);
581 if (!full_sender_name) {
582 fprintf(stderr, "-F requires name arg.\n");
583 exit(1);
584 }
586 } else if (strcmp(opt, "i") == 0) {
587 opt_i = TRUE;
589 } else if (strcmp(opt, "m") == 0) {
590 /* ignore -m (me too) switch (see man page) */
592 } else if (strcmp(opt, "Mrm") == 0) {
593 set_mode(MODE_MCMD);
594 M_cmd = "rm";
596 } else if (strcmp(opt, "odq") == 0) {
597 do_queue = TRUE;
599 } else if (strcmp(opt, "oi") == 0) {
600 opt_i = TRUE;
602 } else if (strncmp(opt, "o", 1) == 0) {
603 /* ignore all other -oXXX options */
605 } else if (strncmp(opt, "qo", 2) == 0) {
606 /* must be before the `q' check */
607 set_mode(MODE_RUNQUEUE);
608 do_runq_online = TRUE;
609 /* can be NULL, then we use online detection method */
610 /* TODO: behavior might change if it is NULL */
611 route_name = get_optarg(argv, &arg, opt+2);
612 if (!route_name) {
613 fprintf(stderr, "Please do not use -qo "
614 "without argument anymore; "
615 "use -q instead.\n");
616 fprintf(stderr, "The behavior for -qo without "
617 "argument is likely to "
618 "change.\n");
619 }
621 } else if (strncmp(opt, "q", 1) == 0) {
622 /* must be after the `qo' check */
623 gchar *optarg;
625 optarg = get_optarg(argv, &arg, opt+1);
626 if (optarg) {
627 /* do regular queue runs */
628 set_mode(MODE_DAEMON);
629 queue_interval = time_interval(optarg);
630 } else {
631 /* do a single queue run */
632 set_mode(MODE_RUNQUEUE);
633 do_runq = TRUE;
634 }
636 } else if (strcmp(opt, "t") == 0) {
637 opt_t = TRUE;
639 } else if (strcmp(opt, "v") == 0) {
640 do_verbose = TRUE;
642 } else {
643 fprintf(stderr, "unrecognized option `-%s'\n", opt);
644 exit(1);
645 }
646 }
648 if (!mta_mode && arg==argc && !opt_t) {
649 /*
650 ** In this case no rcpts can be found, thus no mail
651 ** can be sent, thus masqmail will always fail. We
652 ** rather do something better instead. This covers
653 ** also the case of calling masqmail without args.
654 */
655 mode_version();
656 exit(0);
657 }
659 if (mta_mode == MODE_VERSION) {
660 mode_version();
661 exit(0);
662 }
664 if (!mta_mode) {
665 mta_mode = MODE_ACCEPT;
666 }
668 /* initialize random generator */
669 srand(time(NULL));
670 /* ignore SIGPIPE signal */
671 signal(SIGPIPE, SIG_IGN);
673 /* close all possibly open file descriptors, except std{in,out,err} */
674 {
675 int i, max_fd = sysconf(_SC_OPEN_MAX);
677 if (max_fd <= 0) {
678 max_fd = 64;
679 }
680 for (i=3; i<max_fd; i++) {
681 close(i);
682 }
683 }
685 init_conf();
687 /*
688 ** if we are not privileged, and the config file was changed we
689 ** implicetely set the the run_as_user flag and give up all
690 ** privileges.
691 **
692 ** So it is possible for a user to run his own daemon without
693 ** breaking security.
694 */
695 if ((strcmp(conf_file, CONF_FILE) != 0) && (conf.orig_uid != 0)) {
696 logwrite(LOG_NOTICE, "Changing to run_as_user.\n");
697 conf.run_as_user = TRUE;
698 set_euidgid(conf.orig_uid, conf.orig_gid, NULL, NULL);
699 if (setgid(conf.orig_gid)) {
700 logwrite(LOG_ALERT, "could not set gid to %d: %s\n",
701 conf.orig_gid, strerror(errno));
702 exit(1);
703 }
704 if (setuid(conf.orig_uid)) {
705 logwrite(LOG_ALERT, "could not set uid to %d: %s\n",
706 conf.orig_uid, strerror(errno));
707 exit(1);
708 }
709 }
711 conf.log_dir = LOG_DIR;
712 conf.debug_level = debug_level; /* for debuggin during read_conf() */
713 /* FIXME: fails if we run as user */
714 logopen();
715 if (!read_conf(conf_file)) {
716 logwrite(LOG_ALERT, "SHUTTING DOWN due to problems reading "
717 "config\n");
718 exit(5);
719 }
720 logclose();
722 if (do_queue) {
723 conf.do_queue = TRUE;
724 }
725 if (do_verbose) {
726 conf.do_verbose = TRUE;
727 }
728 if (debug_level >= 0) { /* if >= 0, it was given by argument */
729 conf.debug_level = debug_level;
730 }
732 /*
733 ** It appears that changing to / ensures that we are never in
734 ** a directory which we cannot access. This situation could be
735 ** possible after changing identity.
736 ** Maybe we should only change to / if we not run as user, to
737 ** allow relative paths for log files in test setups for
738 ** instance.
739 */
740 chdir("/");
742 if (!conf.run_as_user) {
743 if (setgid(0) != 0) {
744 fprintf(stderr, "could not set gid to 0. "
745 "Is the setuid bit set? : %s\n",
746 strerror(errno));
747 exit(1);
748 }
749 if (setuid(0) != 0) {
750 fprintf(stderr, "could not gain root privileges. "
751 "Is the setuid bit set? : %s\n",
752 strerror(errno));
753 exit(1);
754 }
755 }
757 if (conf.run_as_user) {
758 logwrite(LOG_NOTICE, "Using spool directory `%s' for "
759 "lock files.\n", conf.spool_dir);
760 conf.lock_dir = conf.spool_dir;
761 } else {
762 int olduid, oldgid;
764 set_euidgid(conf.mail_uid, conf.mail_gid, &olduid, &oldgid);
765 makedir_rec(conf.lock_dir, 0775);
766 set_euidgid(olduid, oldgid, NULL, NULL);
767 }
769 if (!logopen()) {
770 fprintf(stderr, "could not open log file\n");
771 exit(1);
772 }
774 DEBUG(1) debugf("----STARTING---- masqmail %s\n", VERSION);
776 DEBUG(5) {
777 gchar **str = argv;
778 debugf("args: \n");
779 while (*str) {
780 debugf("%s \n", *str);
781 str++;
782 }
783 }
784 DEBUG(5) debugf("queue_interval = %d\n", queue_interval);
786 if (f_address) {
787 return_path = create_address_qualified(f_address, TRUE,
788 conf.host_name);
789 g_free(f_address);
790 if (!return_path) {
791 fprintf(stderr, "invalid RFC821 address: %s\n",
792 f_address);
793 exit(1);
794 }
795 }
797 switch (mta_mode) {
798 case MODE_DAEMON:
799 mode_daemon(do_listen, queue_interval, argv);
800 break;
802 case MODE_RUNQUEUE:
803 exit(run_queue(do_runq, do_runq_online, route_name) ? 0 : 1);
804 break;
806 case MODE_SMTP:
807 mode_smtp();
808 break;
810 case MODE_LIST:
811 queue_list();
812 break;
814 case MODE_BI:
815 exit(0);
816 break; /* well... */
818 case MODE_MCMD:
819 exit(manipulate_queue(M_cmd, &argv[arg]) ? 0 : 1);
820 break;
822 case MODE_ACCEPT:
823 {
824 guint accept_flags = 0;
825 accept_flags |= (opt_t ? ACC_RCPT_FROM_HEAD : 0);
826 accept_flags |= (opt_i ?
827 ACC_DOT_IGNORE : ACC_NODOT_RELAX);
828 mode_accept(return_path, full_sender_name,
829 accept_flags, argv + arg, argc - arg);
830 exit(0);
831 }
832 break;
834 default:
835 fprintf(stderr, "unknown mode: %d\n", mta_mode);
836 break;
837 }
839 logclose();
841 exit(0);
842 }