/* $Id: deliver.c,v 1.8 2005/12/09 06:52:12 dm Exp $ */ /* * * Copyright (C) 2004 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "local.h" #include #include "getopt_long.h" char *progname; int truncfd = -1; off_t truncpos; char *deleteme; static int opt_copy; static int opt_norewind; static char *tmp_path; static struct stat tmp_sb; static void cleanup (void) { struct stat sb; if (truncfd >= 0) ftruncate (truncfd, truncpos); if (tmp_path && !lstat (tmp_path, &sb) && tmp_sb.st_dev == sb.st_dev && tmp_sb.st_ino == sb.st_ino) unlink (tmp_path); tmp_path = NULL; if (deleteme) unlink (deleteme); if (!opt_norewind) lseek (0, 0, SEEK_SET); } static void catch (int sig) { exit (EX_TEMPFAIL); } static void deliver (char **dv, int dc) { int rfd; off_t pos = -1; if (!opt_norewind) lseek (0, 0, SEEK_SET); if (opt_copy || nocopymsg (stdin) < 0) { int wfd; initfile (&tmp_path, &wfd, &rfd, &tmp_sb); copymsg (wfd, stdin); close (wfd); } else { rfd = 0; pos = lseek (rfd, 0, SEEK_CUR); if (pos == -1) { perror ("lseek"); exit (EX_OSERR); } } for (; dc-- > 0; dv++) { int res; if (!*dv) continue; if ((*dv)[strlen (*dv) - 1] == '/') res = deliver_maildir (*dv, rfd, pos == -1); else res = deliver_mbox (*dv, rfd, pos == -1); if (res) exit (res); if (dc > 0 && pos != -1 && lseek (rfd, pos, SEEK_CUR) == -1) { perror ("re-lseek"); exit (EX_OSERR); } } } static void usage (void) __attribute__ ((noreturn)); static void usage (void) { fprintf (stderr, "usage: %s [--umask[=val]] mailbox [mailbox ...]\n", progname); exit (EX_USAGE); } int main (int argc, char **argv) { struct option o[] = { { "version", no_argument, NULL, 'v' }, { "umask", optional_argument, NULL, 'U' }, { "copy", no_argument, NULL, 'C' }, { "norewind", no_argument, NULL, 'N' }, { "fcntl", no_argument, NULL, 'P' }, { NULL, 0, NULL, 0 } }; int opt_umask = 077; int c; progname = strrchr (argv[0], '/'); if (progname) progname++; else progname = argv[0]; while ((c = getopt_long (argc, argv, "+", o, NULL)) != -1) switch (c) { case 'v': version (progname, 1); exit (0); break; case 'C': opt_copy = 1; break; case 'N': opt_norewind = 1; break; case 'P': opt_fcntl = 1; break; case 'U': opt_umask = -1; if (optarg) { opt_umask = strtol (optarg, NULL, 0); if (opt_umask & ~0777) usage (); } break; default: usage (); break; } if (optind >= argc) usage (); opt_from = getenv ("SENDER"); atexit (cleanup); signal (SIGHUP, catch); signal (SIGINT, catch); signal (SIGTERM, catch); if (opt_umask != -1) umask (opt_umask); deliver (argv + optind, argc - optind); return 0; }