masqmail
view src/masqmail.c @ 75:257a9e6d1a8e
fixed correct processing of mails with data lines longer 4096 chars
Mail messages with lines longer than 4096 chars were already read
correctly, i.e. the spool files were correct. This commit fixes the
reading of spool files with long lines.
The old behavior was that the message body was truncated right
before the first line longer 4096 chars. The number comes from
MAX_DATALINE.
author | meillo@marmaro.de |
---|---|
date | Wed, 16 Jun 2010 19:06:34 +0200 |
parents | 9db75b801dc4 |
children | 3b344bf57162 |
line source
1 /* MasqMail
2 Copyright (C) 1999-2001 Oliver Kurth
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 of the License, or
7 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
19 #include <stdio.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #include <netinet/in.h>
28 #include <netdb.h>
29 #include <syslog.h>
30 #include <signal.h>
32 #include <glib.h>
34 #include "masqmail.h"
36 /* mutually exclusive modes. Note that there is neither a 'get' mode
37 nor a 'queue daemon' mode. These, as well as the distinction beween
38 the two (non exclusive) daemon (queue and listen) modes are handled
39 by flags.*/
40 typedef enum _mta_mode {
41 MODE_ACCEPT = 0, /* accept message on stdin */
42 MODE_DAEMON, /* run as daemon */
43 MODE_RUNQUEUE, /* single queue run, online or offline */
44 MODE_GET_DAEMON, /* run as get (retrieve) daemon */
45 MODE_SMTP, /* accept SMTP on stdin */
46 MODE_LIST, /* list queue */
47 MODE_MCMD, /* do queue manipulation */
48 MODE_VERSION, /* show version */
49 MODE_BI, /* fake ;-) */
50 MODE_NONE /* to prevent default MODE_ACCEPT */
51 } mta_mode;
53 char *pidfile = NULL;
54 volatile int sigterm_in_progress = 0;
56 static void
57 sigterm_handler(int sig)
58 {
59 if (sigterm_in_progress)
60 raise(sig);
61 sigterm_in_progress = 1;
63 if (pidfile) {
64 uid_t uid;
65 uid = seteuid(0);
66 if (unlink(pidfile) != 0)
67 logwrite(LOG_WARNING, "could not delete pid file %s: %s\n", pidfile, strerror(errno));
68 seteuid(uid); /* we exit anyway after this, just to be sure */
69 }
71 signal(sig, SIG_DFL);
72 raise(sig);
73 }
75 #ifdef ENABLE_IDENT /* so far used for that only */
76 static gboolean
77 is_in_netlist(gchar * host, GList * netlist)
78 {
79 guint hostip = inet_addr(host);
80 struct in_addr addr;
82 addr.s_addr = hostip;
83 if (addr.s_addr != INADDR_NONE) {
84 GList *node;
85 foreach(netlist, node) {
86 struct in_addr *net = (struct in_addr *) (node->data);
87 if ((addr.s_addr & net->s_addr) == net->s_addr)
88 return TRUE;
89 }
90 }
91 return FALSE;
92 }
93 #endif
95 gchar*
96 get_optarg(char *argv[], gint argc, gint * argp, gint * pos)
97 {
98 if (argv[*argp][*pos])
99 return &(argv[*argp][*pos]);
100 else {
101 if (*argp + 1 < argc) {
102 if (argv[(*argp) + 1][0] != '-') {
103 (*argp)++;
104 *pos = 0;
105 return &(argv[*argp][*pos]);
106 }
107 }
108 }
109 return NULL;
110 }
112 gchar*
113 get_progname(gchar * arg0)
114 {
115 gchar *p = arg0 + strlen(arg0) - 1;
116 while (p > arg0) {
117 if (*p == '/')
118 return p + 1;
119 p--;
120 }
121 return p;
122 }
124 gboolean
125 write_pidfile(gchar * name)
126 {
127 FILE *fptr;
129 if ((fptr = fopen(name, "wt"))) {
130 fprintf(fptr, "%d\n", getpid());
131 fclose(fptr);
132 pidfile = strdup(name);
133 return TRUE;
134 }
135 logwrite(LOG_WARNING, "could not write pid file: %s\n", strerror(errno));
136 return FALSE;
137 }
139 static void
140 mode_daemon(gboolean do_listen, gint queue_interval, char *argv[])
141 {
142 guint pid;
144 /* daemon */
145 if (!conf.run_as_user) {
146 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) {
147 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER);
148 exit(EXIT_FAILURE);
149 }
150 }
152 /* reparent to init only if init is not already the parent */
153 if (getppid() != 1) {
154 if ((pid = fork()) > 0) {
155 exit(EXIT_SUCCESS);
156 } else if (pid < 0) {
157 logwrite(LOG_ALERT, "could not fork!");
158 exit(EXIT_FAILURE);
159 }
160 }
162 signal(SIGTERM, sigterm_handler);
163 write_pidfile(PIDFILEDIR "/masqmail.pid");
165 conf.do_verbose = FALSE;
167 /* closing and reopening the log ensures that it is open afterwards
168 because it is possible that the log is assigned to fd 1 and gets
169 thus closes by fclose(stdout). Similar for the debugfile.
170 */
171 logclose();
172 fclose(stdin);
173 fclose(stdout);
174 fclose(stderr);
175 logopen();
177 listen_port(do_listen ? conf.listen_addresses : NULL, queue_interval, argv);
178 }
180 #ifdef ENABLE_POP3
181 static void
182 mode_get_daemon(gint get_interval, char *argv[])
183 {
184 guint pid;
186 /* daemon */
187 if (!conf.run_as_user) {
188 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) {
189 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER);
190 exit(EXIT_FAILURE);
191 }
192 }
194 /* reparent to init only if init is not already the parent */
195 if (getppid() != 1) {
196 if ((pid = fork()) > 0) {
197 exit(EXIT_SUCCESS);
198 } else if (pid < 0) {
199 logwrite(LOG_ALERT, "could not fork!");
200 exit(EXIT_FAILURE);
201 }
202 }
204 signal(SIGTERM, sigterm_handler);
205 write_pidfile(PIDFILEDIR "/masqmail-get.pid");
207 conf.do_verbose = FALSE;
209 /* closing and reopening the log ensures that it is open afterwards
210 because it is possible that the log is assigned to fd 1 and gets
211 thus closes by fclose(stdout). Similar for the debugfile.
212 */
213 logclose();
214 fclose(stdin);
215 fclose(stdout);
216 fclose(stderr);
217 logopen();
219 get_daemon(get_interval, argv);
220 }
221 #endif
223 #ifdef ENABLE_SMTP_SERVER
224 static void
225 mode_smtp()
226 {
227 /* accept smtp message on stdin */
228 /* write responses to stderr. */
230 struct sockaddr_in saddr;
231 gchar *peername = NULL;
232 int dummy = sizeof(saddr);
234 conf.do_verbose = FALSE;
236 if (!conf.run_as_user) {
237 seteuid(conf.orig_uid);
238 setegid(conf.orig_gid);
239 }
241 DEBUG(5) debugf("accepting smtp message on stdin\n");
243 if (getpeername(0, (struct sockaddr *) (&saddr), &dummy) == 0) {
244 peername = g_strdup(inet_ntoa(saddr.sin_addr));
245 } else if (errno != ENOTSOCK)
246 exit(EXIT_FAILURE);
248 smtp_in(stdin, stderr, peername, NULL);
249 }
250 #endif
252 static void
253 mode_accept(address * return_path, gchar * full_sender_name, guint accept_flags, char **addresses, int addr_cnt)
254 {
255 /* accept message on stdin */
256 accept_error err;
257 message *msg = create_message();
258 gint i;
260 if (return_path != NULL) {
261 if ((conf.orig_uid != 0)
262 && (conf.orig_uid != conf.mail_uid)
263 && (!is_ingroup(conf.orig_uid, conf.mail_gid))) {
264 fprintf(stderr, "must be in root, %s or in group %s for setting return path.\n", DEF_MAIL_USER, DEF_MAIL_GROUP);
265 exit(EXIT_FAILURE);
266 }
267 }
269 if (!conf.run_as_user) {
270 seteuid(conf.orig_uid);
271 setegid(conf.orig_gid);
272 }
274 DEBUG(5) debugf("accepting message on stdin\n");
276 msg->received_prot = PROT_LOCAL;
277 for (i = 0; i < addr_cnt; i++) {
278 if (addresses[i][0] != '|')
279 msg->rcpt_list = g_list_append(msg->rcpt_list, create_address_qualified(addresses[i], TRUE, conf.host_name));
280 else {
281 logwrite(LOG_ALERT, "no pipe allowed as recipient address: %s\n", addresses[i]);
282 exit(EXIT_FAILURE);
283 }
284 }
286 /* -f option */
287 msg->return_path = return_path;
289 /* -F option */
290 msg->full_sender_name = full_sender_name;
292 if ((err = accept_message(stdin, msg, accept_flags)) == AERR_OK) {
293 if (spool_write(msg, TRUE)) {
294 pid_t pid;
295 logwrite(LOG_NOTICE, "%s <= %s with %s\n", msg->uid, addr_string(msg->return_path), prot_names[PROT_LOCAL]);
297 if (!conf.do_queue) {
298 if ((pid = fork()) == 0) {
299 conf.do_verbose = FALSE;
300 fclose(stdin);
301 fclose(stdout);
302 fclose(stderr);
303 if (deliver(msg)) {
304 exit(EXIT_SUCCESS);
305 } else
306 exit(EXIT_FAILURE);
307 } else if (pid < 0) {
308 logwrite(LOG_ALERT, "could not fork for delivery, id = %s", msg->uid);
309 }
310 }
311 } else {
312 fprintf(stderr, "Could not write spool file\n");
313 exit(EXIT_FAILURE);
314 }
315 } else {
316 switch (err) {
317 case AERR_EOF:
318 fprintf(stderr, "unexpected EOF.\n");
319 exit(EXIT_FAILURE);
320 case AERR_NORCPT:
321 fprintf(stderr, "no recipients.\n");
322 exit(EXIT_FAILURE);
323 default:
324 /* should never happen: */
325 fprintf(stderr, "Unknown error (%d)\r\n", err);
326 exit(EXIT_FAILURE);
327 }
328 exit(EXIT_FAILURE);
329 }
330 }
332 int
333 main(int argc, char *argv[])
334 {
335 /* cmd line flags */
336 gchar *conf_file = CONF_FILE;
337 gint arg = 1;
338 gboolean do_get = FALSE;
339 gboolean do_get_online = FALSE;
341 gboolean do_listen = FALSE;
342 gboolean do_runq = FALSE;
343 gboolean do_runq_online = FALSE;
345 gboolean do_queue = FALSE;
347 gboolean do_verbose = FALSE;
348 gint debug_level = -1;
350 mta_mode mta_mode = MODE_ACCEPT;
352 gint queue_interval = 0;
353 gint get_interval = 0;
354 gboolean opt_t = FALSE;
355 gboolean opt_i = FALSE;
356 gboolean opt_odb = FALSE;
357 gboolean opt_oem = FALSE;
358 gboolean exit_failure = FALSE;
360 gchar *M_cmd = NULL;
362 gint exit_code = EXIT_SUCCESS;
363 gchar *route_name = NULL;
364 gchar *get_name = NULL;
365 gchar *progname;
366 gchar *f_address = NULL;
367 gchar *full_sender_name = NULL;
368 address *return_path = NULL; /* may be changed by -f option */
370 progname = get_progname(argv[0]);
372 if (strcmp(progname, "mailq") == 0) {
373 mta_mode = MODE_LIST;
374 } else if (strcmp(progname, "mailrm") == 0) {
375 mta_mode = MODE_MCMD;
376 M_cmd = "rm";
377 } else if (strcmp(progname, "runq") == 0) {
378 mta_mode = MODE_RUNQUEUE;
379 do_runq = TRUE;
380 } else if (strcmp(progname, "rmail") == 0) {
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 }