masqmail-0.2

view src/masqmail.c @ 91:3e7136221104

correct masqmail path in rmail script; remove docs on uninstall on install the correct path to the masqmail executable gets inserted into the rmail script now. now documentation, examples, and the templates are removed on uninstall. Empty directories are the only thing that may remain if one installs masqmail into an unusual path.
author meillo@marmaro.de
date Mon, 21 Jun 2010 09:40:16 +0200
parents 085d6cd44462
children b76080154aec
line source
1 /* MasqMail
2 Copyright (C) 1999-2001 Oliver Kurth
3 Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
20 #include <stdio.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/time.h>
28 #include <netinet/in.h>
29 #include <netdb.h>
30 #include <syslog.h>
31 #include <signal.h>
33 #include <glib.h>
35 #include "masqmail.h"
37 /* mutually exclusive modes. Note that there is neither a 'get' mode
38 nor a 'queue daemon' mode. These, as well as the distinction beween
39 the two (non exclusive) daemon (queue and listen) modes are handled
40 by flags.*/
41 typedef enum _mta_mode {
42 MODE_ACCEPT = 0, /* accept message on stdin */
43 MODE_DAEMON, /* run as daemon */
44 MODE_RUNQUEUE, /* single queue run, online or offline */
45 MODE_GET_DAEMON, /* run as get (retrieve) daemon */
46 MODE_SMTP, /* accept SMTP on stdin */
47 MODE_LIST, /* list queue */
48 MODE_MCMD, /* do queue manipulation */
49 MODE_VERSION, /* show version */
50 MODE_BI, /* fake ;-) */
51 MODE_NONE /* to prevent default MODE_ACCEPT */
52 } mta_mode;
54 char *pidfile = NULL;
55 volatile int sigterm_in_progress = 0;
57 static void
58 sigterm_handler(int sig)
59 {
60 if (sigterm_in_progress)
61 raise(sig);
62 sigterm_in_progress = 1;
64 if (pidfile) {
65 uid_t uid;
66 uid = seteuid(0);
67 if (unlink(pidfile) != 0)
68 logwrite(LOG_WARNING, "could not delete pid file %s: %s\n", pidfile, strerror(errno));
69 seteuid(uid); /* we exit anyway after this, just to be sure */
70 }
72 signal(sig, SIG_DFL);
73 raise(sig);
74 }
76 #ifdef ENABLE_IDENT /* so far used for that only */
77 static gboolean
78 is_in_netlist(gchar * host, GList * netlist)
79 {
80 guint hostip = inet_addr(host);
81 struct in_addr addr;
83 addr.s_addr = hostip;
84 if (addr.s_addr != INADDR_NONE) {
85 GList *node;
86 foreach(netlist, node) {
87 struct in_addr *net = (struct in_addr *) (node->data);
88 if ((addr.s_addr & net->s_addr) == net->s_addr)
89 return TRUE;
90 }
91 }
92 return FALSE;
93 }
94 #endif
96 gchar*
97 get_optarg(char *argv[], gint argc, gint * argp, gint * pos)
98 {
99 if (argv[*argp][*pos])
100 return &(argv[*argp][*pos]);
101 else {
102 if (*argp + 1 < argc) {
103 if (argv[(*argp) + 1][0] != '-') {
104 (*argp)++;
105 *pos = 0;
106 return &(argv[*argp][*pos]);
107 }
108 }
109 }
110 return NULL;
111 }
113 gchar*
114 get_progname(gchar * arg0)
115 {
116 gchar *p = arg0 + strlen(arg0) - 1;
117 while (p > arg0) {
118 if (*p == '/')
119 return p + 1;
120 p--;
121 }
122 return p;
123 }
125 gboolean
126 write_pidfile(gchar * name)
127 {
128 FILE *fptr;
130 if ((fptr = fopen(name, "wt"))) {
131 fprintf(fptr, "%d\n", getpid());
132 fclose(fptr);
133 pidfile = strdup(name);
134 return TRUE;
135 }
136 logwrite(LOG_WARNING, "could not write pid file: %s\n", strerror(errno));
137 return FALSE;
138 }
140 static void
141 mode_daemon(gboolean do_listen, gint queue_interval, char *argv[])
142 {
143 guint pid;
145 /* daemon */
146 if (!conf.run_as_user) {
147 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) {
148 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER);
149 exit(EXIT_FAILURE);
150 }
151 }
153 /* reparent to init only if init is not already the parent */
154 if (getppid() != 1) {
155 if ((pid = fork()) > 0) {
156 exit(EXIT_SUCCESS);
157 } else if (pid < 0) {
158 logwrite(LOG_ALERT, "could not fork!");
159 exit(EXIT_FAILURE);
160 }
161 }
163 signal(SIGTERM, sigterm_handler);
164 write_pidfile(PIDFILEDIR "/masqmail.pid");
166 conf.do_verbose = FALSE;
168 /* closing and reopening the log ensures that it is open afterwards
169 because it is possible that the log is assigned to fd 1 and gets
170 thus closes by fclose(stdout). Similar for the debugfile.
171 */
172 logclose();
173 fclose(stdin);
174 fclose(stdout);
175 fclose(stderr);
176 logopen();
178 listen_port(do_listen ? conf.listen_addresses : NULL, queue_interval, argv);
179 }
181 #ifdef ENABLE_POP3
182 static void
183 mode_get_daemon(gint get_interval, char *argv[])
184 {
185 guint pid;
187 /* daemon */
188 if (!conf.run_as_user) {
189 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) {
190 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER);
191 exit(EXIT_FAILURE);
192 }
193 }
195 /* reparent to init only if init is not already the parent */
196 if (getppid() != 1) {
197 if ((pid = fork()) > 0) {
198 exit(EXIT_SUCCESS);
199 } else if (pid < 0) {
200 logwrite(LOG_ALERT, "could not fork!");
201 exit(EXIT_FAILURE);
202 }
203 }
205 signal(SIGTERM, sigterm_handler);
206 write_pidfile(PIDFILEDIR "/masqmail-get.pid");
208 conf.do_verbose = FALSE;
210 /* closing and reopening the log ensures that it is open afterwards
211 because it is possible that the log is assigned to fd 1 and gets
212 thus closes by fclose(stdout). Similar for the debugfile.
213 */
214 logclose();
215 fclose(stdin);
216 fclose(stdout);
217 fclose(stderr);
218 logopen();
220 get_daemon(get_interval, argv);
221 }
222 #endif
224 #ifdef ENABLE_SMTP_SERVER
225 static void
226 mode_smtp()
227 {
228 /* accept smtp message on stdin */
229 /* write responses to stderr. */
231 struct sockaddr_in saddr;
232 gchar *peername = NULL;
233 int dummy = sizeof(saddr);
235 conf.do_verbose = FALSE;
237 if (!conf.run_as_user) {
238 seteuid(conf.orig_uid);
239 setegid(conf.orig_gid);
240 }
242 DEBUG(5) debugf("accepting smtp message on stdin\n");
244 if (getpeername(0, (struct sockaddr *) (&saddr), &dummy) == 0) {
245 peername = g_strdup(inet_ntoa(saddr.sin_addr));
246 } else if (errno != ENOTSOCK)
247 exit(EXIT_FAILURE);
249 smtp_in(stdin, stderr, peername, NULL);
250 }
251 #endif
253 static void
254 mode_accept(address * return_path, gchar * full_sender_name, guint accept_flags, char **addresses, int addr_cnt)
255 {
256 /* accept message on stdin */
257 accept_error err;
258 message *msg = create_message();
259 gint i;
261 if (return_path && !is_privileged_user(conf.orig_uid)) {
262 fprintf(stderr, "must be in root, %s or in group %s for setting return path.\n", DEF_MAIL_USER, DEF_MAIL_GROUP);
263 exit(EXIT_FAILURE);
264 }
266 if (!conf.run_as_user) {
267 seteuid(conf.orig_uid);
268 setegid(conf.orig_gid);
269 }
271 DEBUG(5) debugf("accepting message on stdin\n");
273 msg->received_prot = PROT_LOCAL;
274 for (i = 0; i < addr_cnt; i++) {
275 if (addresses[i][0] != '|')
276 msg->rcpt_list = g_list_append(msg->rcpt_list, create_address_qualified(addresses[i], TRUE, conf.host_name));
277 else {
278 logwrite(LOG_ALERT, "no pipe allowed as recipient address: %s\n", addresses[i]);
279 exit(EXIT_FAILURE);
280 }
281 }
283 /* -f option */
284 msg->return_path = return_path;
286 /* -F option */
287 msg->full_sender_name = full_sender_name;
289 if ((err = accept_message(stdin, msg, accept_flags)) == AERR_OK) {
290 if (spool_write(msg, TRUE)) {
291 pid_t pid;
292 logwrite(LOG_NOTICE, "%s <= %s with %s\n", msg->uid, addr_string(msg->return_path), prot_names[PROT_LOCAL]);
294 if (!conf.do_queue) {
295 if ((pid = fork()) == 0) {
296 conf.do_verbose = FALSE;
297 fclose(stdin);
298 fclose(stdout);
299 fclose(stderr);
300 if (deliver(msg)) {
301 exit(EXIT_SUCCESS);
302 } else
303 exit(EXIT_FAILURE);
304 } else if (pid < 0) {
305 logwrite(LOG_ALERT, "could not fork for delivery, id = %s", msg->uid);
306 }
307 }
308 } else {
309 fprintf(stderr, "Could not write spool file\n");
310 exit(EXIT_FAILURE);
311 }
312 } else {
313 switch (err) {
314 case AERR_EOF:
315 fprintf(stderr, "unexpected EOF.\n");
316 exit(EXIT_FAILURE);
317 case AERR_NORCPT:
318 fprintf(stderr, "no recipients.\n");
319 exit(EXIT_FAILURE);
320 default:
321 /* should never happen: */
322 fprintf(stderr, "Unknown error (%d)\r\n", err);
323 exit(EXIT_FAILURE);
324 }
325 exit(EXIT_FAILURE);
326 }
327 }
329 int
330 main(int argc, char *argv[])
331 {
332 /* cmd line flags */
333 gchar *conf_file = CONF_FILE;
334 gint arg = 1;
335 gboolean do_get = FALSE;
336 gboolean do_get_online = FALSE;
338 gboolean do_listen = FALSE;
339 gboolean do_runq = FALSE;
340 gboolean do_runq_online = FALSE;
342 gboolean do_queue = FALSE;
344 gboolean do_verbose = FALSE;
345 gint debug_level = -1;
347 mta_mode mta_mode = MODE_ACCEPT;
349 gint queue_interval = 0;
350 gint get_interval = 0;
351 gboolean opt_t = FALSE;
352 gboolean opt_i = FALSE;
353 gboolean opt_odb = FALSE;
354 gboolean opt_oem = FALSE;
355 gboolean exit_failure = FALSE;
357 gchar *M_cmd = NULL;
359 gint exit_code = EXIT_SUCCESS;
360 gchar *route_name = NULL;
361 gchar *get_name = NULL;
362 gchar *progname;
363 gchar *f_address = NULL;
364 gchar *full_sender_name = NULL;
365 address *return_path = NULL; /* may be changed by -f option */
367 progname = get_progname(argv[0]);
369 if (strcmp(progname, "mailq") == 0) {
370 mta_mode = MODE_LIST;
371 } else if (strcmp(progname, "mailrm") == 0) {
372 mta_mode = MODE_MCMD;
373 M_cmd = "rm";
374 } else if (strcmp(progname, "runq") == 0) {
375 mta_mode = MODE_RUNQUEUE;
376 do_runq = TRUE;
377 } else if (strcmp(progname, "rmail") == 0) {
378 /* the `rmail' alias should probably be removed now
379 that we have the rmail script. But let's keep it
380 for some while for compatibility. 2010-06-19 */
381 mta_mode = MODE_ACCEPT;
382 opt_i = TRUE;
383 } else if (strcmp(progname, "smtpd") == 0 || strcmp(progname, "in.smtpd") == 0) {
384 mta_mode = MODE_SMTP;
385 }
387 /* parse cmd line */
388 while (arg < argc) {
389 gint pos = 0;
390 if ((argv[arg][pos] == '-') && (argv[arg][pos + 1] != '-')) {
391 pos++;
392 switch (argv[arg][pos++]) {
393 case 'b':
394 switch (argv[arg][pos++]) {
395 case 'd':
396 do_listen = TRUE;
397 mta_mode = MODE_DAEMON;
398 break;
399 case 'i':
400 /* ignored */
401 mta_mode = MODE_BI;
402 break;
403 case 's':
404 mta_mode = MODE_SMTP;
405 break;
406 case 'p':
407 mta_mode = MODE_LIST;
408 break;
409 case 'V':
410 mta_mode = MODE_VERSION;
411 break;
412 default:
413 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]);
414 exit(EXIT_FAILURE);
415 }
416 break;
417 case 'B':
418 /* we ignore this and throw the argument away */
419 get_optarg(argv, argc, &arg, &pos);
420 break;
421 case 'C':
422 if (!(conf_file = get_optarg(argv, argc, &arg, &pos))) {
423 fprintf(stderr, "-C requires a filename as argument.\n");
424 exit(EXIT_FAILURE);
425 }
426 break;
427 case 'F':
428 {
429 full_sender_name = get_optarg(argv, argc, &arg, &pos);
430 if (!full_sender_name) {
431 fprintf(stderr, "-F requires a name as an argument\n");
432 exit(EXIT_FAILURE);
433 }
434 }
435 break;
436 case 'd':
437 if (getuid() == 0) {
438 char *lvl = get_optarg(argv, argc, &arg, &pos);
439 if (lvl)
440 debug_level = atoi(lvl);
441 else {
442 fprintf(stderr, "-d requires a number as an argument.\n");
443 exit(EXIT_FAILURE);
444 }
445 } else {
446 fprintf(stderr, "only root may set the debug level.\n");
447 exit(EXIT_FAILURE);
448 }
449 break;
450 case 'f':
451 /* set return path */
452 {
453 gchar *address;
454 address = get_optarg(argv, argc, &arg, &pos);
455 if (address) {
456 f_address = g_strdup(address);
457 } else {
458 fprintf(stderr, "-f requires an address as an argument\n");
459 exit(EXIT_FAILURE);
460 }
461 }
462 break;
463 case 'g':
464 do_get = TRUE;
465 if (!mta_mode)
466 mta_mode = MODE_NONE; /* to prevent default MODE_ACCEPT */
467 if (argv[arg][pos] == 'o') {
468 pos++;
469 do_get_online = TRUE;
470 /* can be NULL, then we use online detection method */
471 route_name = get_optarg(argv, argc, &arg, &pos);
473 if (route_name != NULL) {
474 if (isdigit(route_name[0])) {
475 get_interval = time_interval(route_name, &pos);
476 route_name = get_optarg(argv, argc, &arg, &pos);
477 mta_mode = MODE_GET_DAEMON;
478 do_get = FALSE;
479 }
480 }
481 } else {
482 if ((optarg = get_optarg(argv, argc, &arg, &pos))) {
483 get_name = get_optarg(argv, argc, &arg, &pos);
484 }
485 }
486 break;
487 case 'i':
488 if (argv[arg][pos] == 0) {
489 opt_i = TRUE;
490 exit_failure = FALSE; /* may override -oem */
491 } else {
492 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]);
493 exit(EXIT_FAILURE);
494 }
495 break;
496 case 'M':
497 {
498 mta_mode = MODE_MCMD;
499 M_cmd = g_strdup(&(argv[arg][pos]));
500 }
501 break;
502 case 'o':
503 switch (argv[arg][pos++]) {
504 case 'e':
505 if (argv[arg][pos++] == 'm') /* -oem */
506 if (!opt_i)
507 exit_failure = TRUE;
508 opt_oem = TRUE;
509 break;
510 case 'd':
511 if (argv[arg][pos] == 'b') /* -odb */
512 opt_odb = TRUE;
513 else if (argv[arg][pos] == 'q') /* -odq */
514 do_queue = TRUE;
515 break;
516 case 'i':
517 opt_i = TRUE;
518 exit_failure = FALSE; /* may override -oem */
519 break;
520 }
521 break;
523 case 'q':
524 {
525 gchar *optarg;
527 do_runq = TRUE;
528 mta_mode = MODE_RUNQUEUE;
529 if (argv[arg][pos] == 'o') {
530 pos++;
531 do_runq = FALSE;
532 do_runq_online = TRUE;
533 /* can be NULL, then we use online detection method */
534 route_name = get_optarg(argv, argc, &arg, &pos);
535 } else
536 if ((optarg = get_optarg(argv, argc, &arg, &pos))) {
537 mta_mode = MODE_DAEMON;
538 queue_interval = time_interval(optarg, &pos);
539 }
540 }
541 break;
542 case 't':
543 if (argv[arg][pos] == 0) {
544 opt_t = TRUE;
545 } else {
546 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]);
547 exit(EXIT_FAILURE);
548 }
549 break;
550 case 'v':
551 do_verbose = TRUE;
552 break;
553 default:
554 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]);
555 exit(EXIT_FAILURE);
556 }
557 } else {
558 if (argv[arg][pos + 1] == '-') {
559 if (argv[arg][pos + 2] != '\0') {
560 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]);
561 exit(EXIT_FAILURE);
562 }
563 arg++;
564 }
565 break;
566 }
567 arg++;
568 }
570 if (mta_mode == MODE_VERSION) {
571 gchar *with_resolver = "";
572 gchar *with_smtp_server = "";
573 gchar *with_pop3 = "";
574 gchar *with_auth = "";
575 gchar *with_maildir = "";
576 gchar *with_ident = "";
577 gchar *with_mserver = "";
579 #ifdef ENABLE_RESOLVER
580 with_resolver = " +resolver";
581 #endif
582 #ifdef ENABLE_SMTP_SERVER
583 with_smtp_server = " +smtp-server";
584 #endif
585 #ifdef ENABLE_POP3
586 with_pop3 = " +pop3";
587 #endif
588 #ifdef ENABLE_AUTH
589 with_auth = " +auth";
590 #endif
591 #ifdef ENABLE_MAILDIR
592 with_maildir = " +maildir";
593 #endif
594 #ifdef ENABLE_IDENT
595 with_ident = " +ident";
596 #endif
597 #ifdef ENABLE_MSERVER
598 with_mserver = " +mserver";
599 #endif
601 printf("%s %s%s%s%s%s%s%s%s\n", PACKAGE, VERSION, with_resolver, with_smtp_server,
602 with_pop3, with_auth, with_maildir, with_ident, with_mserver);
604 exit(EXIT_SUCCESS);
605 }
607 /* initialize random generator */
608 srand(time(NULL));
609 /* ignore SIGPIPE signal */
610 signal(SIGPIPE, SIG_IGN);
612 /* close all possibly open file descriptors, except std{in,out,err} */
613 {
614 int i, max_fd = sysconf(_SC_OPEN_MAX);
616 if (max_fd <= 0)
617 max_fd = 64;
618 for (i = 3; i < max_fd; i++)
619 close(i);
620 }
622 init_conf();
624 /* if we are not privileged, and the config file was changed we
625 implicetely set the the run_as_user flag and give up all
626 privileges.
628 So it is possible for a user to run his own daemon without
629 breaking security.
630 */
631 if (strcmp(conf_file, CONF_FILE) != 0) {
632 if (conf.orig_uid != 0) {
633 conf.run_as_user = TRUE;
634 seteuid(conf.orig_uid);
635 setegid(conf.orig_gid);
636 setuid(conf.orig_uid);
637 setgid(conf.orig_gid);
638 }
639 }
641 read_conf(conf_file);
643 if (do_queue)
644 conf.do_queue = TRUE;
645 if (do_verbose)
646 conf.do_verbose = TRUE;
647 if (debug_level >= 0) /* if >= 0, it was given by argument */
648 conf.debug_level = debug_level;
650 /* It appears that changing to / ensures that we are never in
651 a directory which we cannot access. This situation could be
652 possible after changing identity.
653 Maybe we should only change to / if we not run as user, to
654 allow relative paths for log files in test setups for
655 instance.
656 */
657 chdir("/");
659 if (!conf.run_as_user) {
660 if (setgid(0) != 0) {
661 fprintf(stderr, "could not set gid to 0. Is the setuid bit set? : %s\n", strerror(errno));
662 exit(EXIT_FAILURE);
663 }
664 if (setuid(0) != 0) {
665 fprintf(stderr, "could not gain root privileges. Is the setuid bit set? : %s\n", strerror(errno));
666 exit(EXIT_FAILURE);
667 }
668 }
670 if (!logopen()) {
671 fprintf(stderr, "could not open log file\n");
672 exit(EXIT_FAILURE);
673 }
675 DEBUG(1) debugf("masqmail %s starting\n", VERSION);
677 DEBUG(5) {
678 gchar **str = argv;
679 debugf("args: \n");
680 while (*str) {
681 debugf("%s \n", *str);
682 str++;
683 }
684 }
685 DEBUG(5) debugf("queue_interval = %d\n", queue_interval);
687 if (f_address) {
688 return_path = create_address_qualified(f_address, TRUE, conf.host_name);
689 g_free(f_address);
690 if (!return_path) {
691 fprintf(stderr, "invalid RFC821 address: %s\n", f_address);
692 exit(EXIT_FAILURE);
693 }
694 }
696 if (do_get) {
697 #ifdef ENABLE_POP3
698 if ((mta_mode == MODE_NONE) || (mta_mode == MODE_RUNQUEUE)) {
699 set_identity(conf.orig_uid, "getting mail");
700 if (do_get_online) {
701 if (route_name != NULL) {
702 conf.online_detect = g_strdup("argument");
703 set_online_name(route_name);
704 }
705 get_online();
706 } else {
707 if (get_name)
708 get_from_name(get_name);
709 else
710 get_all();
711 }
712 } else {
713 logwrite(LOG_ALERT, "get (-g) only allowed alone or together with queue run (-q)\n");
714 }
715 #else
716 fprintf(stderr, "get (pop) support not compiled in\n");
717 #endif
718 }
720 switch (mta_mode) {
721 case MODE_DAEMON:
722 mode_daemon(do_listen, queue_interval, argv);
723 break;
724 case MODE_RUNQUEUE:
725 {
726 /* queue runs */
727 set_identity(conf.orig_uid, "queue run");
729 if (do_runq)
730 exit_code = queue_run() ? EXIT_SUCCESS : EXIT_FAILURE;
732 if (do_runq_online) {
733 if (route_name != NULL) {
734 conf.online_detect = g_strdup("argument");
735 set_online_name(route_name);
736 }
737 exit_code =
738 queue_run_online() ? EXIT_SUCCESS : EXIT_FAILURE;
739 }
740 }
741 break;
742 case MODE_GET_DAEMON:
743 #ifdef ENABLE_POP3
744 if (route_name != NULL) {
745 conf.online_detect = g_strdup("argument");
746 set_online_name(route_name);
747 }
748 mode_get_daemon(get_interval, argv);
749 #endif
750 break;
752 case MODE_SMTP:
753 #ifdef ENABLE_SMTP_SERVER
754 mode_smtp();
755 #else
756 fprintf(stderr, "smtp server support not compiled in\n");
757 #endif
758 break;
760 case MODE_LIST:
761 queue_list();
762 break;
764 case MODE_BI:
765 exit(EXIT_SUCCESS);
766 break; /* well... */
768 case MODE_MCMD:
769 if (strcmp(M_cmd, "rm") == 0) {
770 gboolean ok = FALSE;
772 set_euidgid(conf.mail_uid, conf.mail_gid, NULL, NULL);
774 if (is_privileged_user(conf.orig_uid)) {
775 for (; arg < argc; arg++) {
776 if (queue_delete(argv[arg]))
777 ok = TRUE;
778 }
779 } else {
780 struct passwd *pw = getpwuid(conf.orig_uid);
781 if (pw) {
782 for (; arg < argc; arg++) {
783 message *msg = msg_spool_read(argv[arg], FALSE);
784 #ifdef ENABLE_IDENT
785 if (((msg->received_host == NULL) && (msg->received_prot == PROT_LOCAL))
786 || is_in_netlist(msg->received_host, conf.ident_trusted_nets)) {
787 #else
788 if ((msg->received_host == NULL) && (msg->received_prot == PROT_LOCAL)) {
789 #endif
790 if (msg->ident) {
791 if (strcmp(pw->pw_name, msg->ident) == 0) {
792 if (queue_delete(argv[arg]))
793 ok = TRUE;
794 } else {
795 fprintf(stderr, "you do not own message id %s\n", argv[arg]);
796 }
797 } else
798 fprintf(stderr, "message %s does not have an ident.\n", argv[arg]);
799 } else {
800 fprintf(stderr, "message %s was not received locally or from a trusted network.\n", argv[arg]);
801 }
802 }
803 } else {
804 fprintf(stderr, "could not find a passwd entry for uid %d: %s\n", conf.orig_uid, strerror(errno));
805 }
806 }
807 exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
808 } else {
809 fprintf(stderr, "unknown command %s\n", M_cmd);
810 exit(EXIT_FAILURE);
811 }
812 break;
814 case MODE_ACCEPT:
815 {
816 guint accept_flags = (opt_t ? ACC_DEL_RCPTS | ACC_DEL_BCC | ACC_RCPT_FROM_HEAD : ACC_HEAD_FROM_RCPT)
817 | (opt_i ? ACC_NODOT_TERM : ACC_NODOT_RELAX);
818 mode_accept(return_path, full_sender_name, accept_flags, &(argv[arg]), argc - arg);
819 exit(exit_failure ? EXIT_FAILURE : EXIT_SUCCESS);
820 }
821 break;
822 case MODE_NONE:
823 break;
824 default:
825 fprintf(stderr, "unknown mode: %d\n", mta_mode);
826 break;
827 }
829 logclose();
831 exit(exit_code);
832 }