dma.c (6cec9cad762b6476313fb1f8e931a1647822db6b) dma.c (e56bad4a94aff7e3e43200568b211de872a52aea)
1/*
1/*
2 * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
3 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 *
5 * This code is derived from software contributed to The DragonFly Project
5 * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
6 * by Simon Schubert <2@0x2c.org>.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright

--- 228 unchanged lines hidden (view full) ---

242go_background(struct queue *queue)
243{
244 struct sigaction sa;
245 struct qitem *it;
246 pid_t pid;
247
248 if (daemonize && daemon(0, 0) != 0) {
249 syslog(LOG_ERR, "can not daemonize: %m");
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright

--- 228 unchanged lines hidden (view full) ---

243go_background(struct queue *queue)
244{
245 struct sigaction sa;
246 struct qitem *it;
247 pid_t pid;
248
249 if (daemonize && daemon(0, 0) != 0) {
250 syslog(LOG_ERR, "can not daemonize: %m");
250 exit(1);
251 exit(EX_OSERR);
251 }
252 daemonize = 0;
253
254 bzero(&sa, sizeof(sa));
255 sa.sa_handler = SIG_IGN;
256 sigaction(SIGCHLD, &sa, NULL);
257
258 LIST_FOREACH(it, &queue->queue, next) {
259 /* No need to fork for the last dest */
260 if (LIST_NEXT(it, next) == NULL)
261 goto retit;
262
263 pid = fork();
264 switch (pid) {
265 case -1:
266 syslog(LOG_ERR, "can not fork: %m");
252 }
253 daemonize = 0;
254
255 bzero(&sa, sizeof(sa));
256 sa.sa_handler = SIG_IGN;
257 sigaction(SIGCHLD, &sa, NULL);
258
259 LIST_FOREACH(it, &queue->queue, next) {
260 /* No need to fork for the last dest */
261 if (LIST_NEXT(it, next) == NULL)
262 goto retit;
263
264 pid = fork();
265 switch (pid) {
266 case -1:
267 syslog(LOG_ERR, "can not fork: %m");
267 exit(1);
268 exit(EX_OSERR);
268 break;
269
270 case 0:
271 /*
272 * Child:
273 *
274 * return and deliver mail
275 */

--- 5 unchanged lines hidden (view full) ---

281 * to flush the queue.
282 */
283 setlogident("%s", it->queueid);
284 switch (acquirespool(it)) {
285 case 0:
286 break;
287 case 1:
288 if (doqueue)
269 break;
270
271 case 0:
272 /*
273 * Child:
274 *
275 * return and deliver mail
276 */

--- 5 unchanged lines hidden (view full) ---

282 * to flush the queue.
283 */
284 setlogident("%s", it->queueid);
285 switch (acquirespool(it)) {
286 case 0:
287 break;
288 case 1:
289 if (doqueue)
289 exit(0);
290 exit(EX_OK);
290 syslog(LOG_WARNING, "could not lock queue file");
291 syslog(LOG_WARNING, "could not lock queue file");
291 exit(1);
292 exit(EX_SOFTWARE);
292 default:
293 default:
293 exit(1);
294 exit(EX_SOFTWARE);
294 }
295 dropspool(queue, it);
296 return (it);
297
298 default:
299 /*
300 * Parent:
301 *
302 * fork next child
303 */
304 break;
305 }
306 }
307
308 syslog(LOG_CRIT, "reached dead code");
295 }
296 dropspool(queue, it);
297 return (it);
298
299 default:
300 /*
301 * Parent:
302 *
303 * fork next child
304 */
305 break;
306 }
307 }
308
309 syslog(LOG_CRIT, "reached dead code");
309 exit(1);
310 exit(EX_SOFTWARE);
310}
311
312static void
313deliver(struct qitem *it)
314{
315 int error;
316 unsigned int backoff = MIN_RETRY, slept;
317 struct timeval now;

--- 8 unchanged lines hidden (view full) ---

326 error = deliver_remote(it);
327 else
328 error = deliver_local(it);
329
330 switch (error) {
331 case 0:
332 delqueue(it);
333 syslog(LOG_INFO, "delivery successful");
311}
312
313static void
314deliver(struct qitem *it)
315{
316 int error;
317 unsigned int backoff = MIN_RETRY, slept;
318 struct timeval now;

--- 8 unchanged lines hidden (view full) ---

327 error = deliver_remote(it);
328 else
329 error = deliver_local(it);
330
331 switch (error) {
332 case 0:
333 delqueue(it);
334 syslog(LOG_INFO, "delivery successful");
334 exit(0);
335 exit(EX_OK);
335
336 case 1:
337 if (stat(it->queuefn, &st) != 0) {
338 syslog(LOG_ERR, "lost queue file `%s'", it->queuefn);
336
337 case 1:
338 if (stat(it->queuefn, &st) != 0) {
339 syslog(LOG_ERR, "lost queue file `%s'", it->queuefn);
339 exit(1);
340 exit(EX_SOFTWARE);
340 }
341 if (gettimeofday(&now, NULL) == 0 &&
342 (now.tv_sec - st.st_mtim.tv_sec > MAX_TIMEOUT)) {
343 snprintf(errmsg, sizeof(errmsg),
344 "Could not deliver for the last %d seconds. Giving up.",
345 MAX_TIMEOUT);
346 goto bounce;
347 }

--- 85 unchanged lines hidden (view full) ---

433 */
434 if (geteuid() == 0 || getuid() == 0) {
435 struct passwd *pw;
436
437 errno = 0;
438 pw = getpwnam(DMA_ROOT_USER);
439 if (pw == NULL) {
440 if (errno == 0)
341 }
342 if (gettimeofday(&now, NULL) == 0 &&
343 (now.tv_sec - st.st_mtim.tv_sec > MAX_TIMEOUT)) {
344 snprintf(errmsg, sizeof(errmsg),
345 "Could not deliver for the last %d seconds. Giving up.",
346 MAX_TIMEOUT);
347 goto bounce;
348 }

--- 85 unchanged lines hidden (view full) ---

434 */
435 if (geteuid() == 0 || getuid() == 0) {
436 struct passwd *pw;
437
438 errno = 0;
439 pw = getpwnam(DMA_ROOT_USER);
440 if (pw == NULL) {
441 if (errno == 0)
441 errx(1, "user '%s' not found", DMA_ROOT_USER);
442 errx(EX_CONFIG, "user '%s' not found", DMA_ROOT_USER);
442 else
443 else
443 err(1, "cannot drop root privileges");
444 err(EX_OSERR, "cannot drop root privileges");
444 }
445
446 if (setuid(pw->pw_uid) != 0)
445 }
446
447 if (setuid(pw->pw_uid) != 0)
447 err(1, "cannot drop root privileges");
448 err(EX_OSERR, "cannot drop root privileges");
448
449 if (geteuid() == 0 || getuid() == 0)
449
450 if (geteuid() == 0 || getuid() == 0)
450 errx(1, "cannot drop root privileges");
451 errx(EX_OSERR, "cannot drop root privileges");
451 }
452
453 atexit(deltmp);
454 init_random();
455
456 bzero(&queue, sizeof(queue));
457 LIST_INIT(&queue.queue);
458
459 if (strcmp(argv[0], "mailq") == 0) {
460 argv++; argc--;
461 showq = 1;
462 if (argc != 0)
452 }
453
454 atexit(deltmp);
455 init_random();
456
457 bzero(&queue, sizeof(queue));
458 LIST_INIT(&queue.queue);
459
460 if (strcmp(argv[0], "mailq") == 0) {
461 argv++; argc--;
462 showq = 1;
463 if (argc != 0)
463 errx(1, "invalid arguments");
464 errx(EX_USAGE, "invalid arguments");
464 goto skipopts;
465 } else if (strcmp(argv[0], "newaliases") == 0) {
466 logident_base = "dma";
467 setlogident("%s", logident_base);
468
469 if (read_aliases() != 0)
465 goto skipopts;
466 } else if (strcmp(argv[0], "newaliases") == 0) {
467 logident_base = "dma";
468 setlogident("%s", logident_base);
469
470 if (read_aliases() != 0)
470 errx(1, "could not parse aliases file `%s'", config.aliases);
471 exit(0);
471 errx(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases);
472 exit(EX_OK);
472 }
473
474 opterr = 0;
475 while ((ch = getopt(argc, argv, ":A:b:B:C:d:Df:F:h:iL:N:no:O:q:r:R:tUV:vX:")) != -1) {
476 switch (ch) {
477 case 'A':
478 /* -AX is being ignored, except for -A{c,m} */
479 if (optarg[0] == 'c' || optarg[0] == 'm') {

--- 62 unchanged lines hidden (view full) ---

542 if (optopt == 'q') {
543 doqueue = 1;
544 break;
545 }
546 /* FALLTHROUGH */
547
548 default:
549 fprintf(stderr, "invalid argument: `-%c'\n", optopt);
473 }
474
475 opterr = 0;
476 while ((ch = getopt(argc, argv, ":A:b:B:C:d:Df:F:h:iL:N:no:O:q:r:R:tUV:vX:")) != -1) {
477 switch (ch) {
478 case 'A':
479 /* -AX is being ignored, except for -A{c,m} */
480 if (optarg[0] == 'c' || optarg[0] == 'm') {

--- 62 unchanged lines hidden (view full) ---

543 if (optopt == 'q') {
544 doqueue = 1;
545 break;
546 }
547 /* FALLTHROUGH */
548
549 default:
550 fprintf(stderr, "invalid argument: `-%c'\n", optopt);
550 exit(1);
551 exit(EX_USAGE);
551 }
552 }
553 argc -= optind;
554 argv += optind;
555 opterr = 1;
556
557 if (argc != 0 && (showq || doqueue))
552 }
553 }
554 argc -= optind;
555 argv += optind;
556 opterr = 1;
557
558 if (argc != 0 && (showq || doqueue))
558 errx(1, "sending mail and queue operations are mutually exclusive");
559 errx(EX_USAGE, "sending mail and queue operations are mutually exclusive");
559
560 if (showq + doqueue > 1)
560
561 if (showq + doqueue > 1)
561 errx(1, "conflicting queue operations");
562 errx(EX_USAGE, "conflicting queue operations");
562
563skipopts:
564 if (logident_base == NULL)
565 logident_base = "dma";
566 setlogident("%s", logident_base);
567
568 act.sa_handler = sighup_handler;
569 act.sa_flags = 0;
570 sigemptyset(&act.sa_mask);
571 if (sigaction(SIGHUP, &act, NULL) != 0)
572 syslog(LOG_WARNING, "can not set signal handler: %m");
573
574 parse_conf(CONF_PATH "/dma.conf");
575
576 if (config.authpath != NULL)
577 parse_authfile(config.authpath);
578
579 if (showq) {
580 if (load_queue(&queue) < 0)
563
564skipopts:
565 if (logident_base == NULL)
566 logident_base = "dma";
567 setlogident("%s", logident_base);
568
569 act.sa_handler = sighup_handler;
570 act.sa_flags = 0;
571 sigemptyset(&act.sa_mask);
572 if (sigaction(SIGHUP, &act, NULL) != 0)
573 syslog(LOG_WARNING, "can not set signal handler: %m");
574
575 parse_conf(CONF_PATH "/dma.conf");
576
577 if (config.authpath != NULL)
578 parse_authfile(config.authpath);
579
580 if (showq) {
581 if (load_queue(&queue) < 0)
581 errlog(1, "can not load queue");
582 errlog(EX_NOINPUT, "can not load queue");
582 show_queue(&queue);
583 return (0);
584 }
585
586 if (doqueue) {
587 flushqueue_signal();
588 if (load_queue(&queue) < 0)
583 show_queue(&queue);
584 return (0);
585 }
586
587 if (doqueue) {
588 flushqueue_signal();
589 if (load_queue(&queue) < 0)
589 errlog(1, "can not load queue");
590 errlog(EX_NOINPUT, "can not load queue");
590 run_queue(&queue);
591 return (0);
592 }
593
594 if (read_aliases() != 0)
591 run_queue(&queue);
592 return (0);
593 }
594
595 if (read_aliases() != 0)
595 errlog(1, "could not parse aliases file `%s'", config.aliases);
596 errlog(EX_SOFTWARE, "could not parse aliases file `%s'", config.aliases);
596
597 if ((sender = set_from(&queue, sender)) == NULL)
597
598 if ((sender = set_from(&queue, sender)) == NULL)
598 errlog(1, "set_from failed");
599 errlog(EX_SOFTWARE, NULL);
599
600 if (newspoolf(&queue) != 0)
600
601 if (newspoolf(&queue) != 0)
601 errlog(1, "can not create temp file in `%s'", config.spooldir);
602 errlog(EX_CANTCREAT, "can not create temp file in `%s'", config.spooldir);
602
603 setlogident("%s", queue.id);
604
605 for (i = 0; i < argc; i++) {
606 if (add_recp(&queue, argv[i], EXPAND_WILDCARD) != 0)
603
604 setlogident("%s", queue.id);
605
606 for (i = 0; i < argc; i++) {
607 if (add_recp(&queue, argv[i], EXPAND_WILDCARD) != 0)
607 errlogx(1, "invalid recipient `%s'", argv[i]);
608 errlogx(EX_DATAERR, "invalid recipient `%s'", argv[i]);
608 }
609
610 if (LIST_EMPTY(&queue.queue) && !recp_from_header)
609 }
610
611 if (LIST_EMPTY(&queue.queue) && !recp_from_header)
611 errlogx(1, "no recipients");
612 errlogx(EX_NOINPUT, "no recipients");
612
613 if (readmail(&queue, nodot, recp_from_header) != 0)
613
614 if (readmail(&queue, nodot, recp_from_header) != 0)
614 errlog(1, "can not read mail");
615 errlog(EX_NOINPUT, "can not read mail");
615
616 if (LIST_EMPTY(&queue.queue))
616
617 if (LIST_EMPTY(&queue.queue))
617 errlogx(1, "no recipients");
618 errlogx(EX_NOINPUT, "no recipients");
618
619 if (linkspool(&queue) != 0)
619
620 if (linkspool(&queue) != 0)
620 errlog(1, "can not create spools");
621 errlog(EX_CANTCREAT, "can not create spools");
621
622 /* From here on the mail is safe. */
623
624 if (config.features & DEFER || queue_only)
625 return (0);
626
627 run_queue(&queue);
628
629 /* NOTREACHED */
630 return (0);
631}
622
623 /* From here on the mail is safe. */
624
625 if (config.features & DEFER || queue_only)
626 return (0);
627
628 run_queue(&queue);
629
630 /* NOTREACHED */
631 return (0);
632}