Back to index

courier  0.68.2
lockmail.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2002-2006 Double Precision, Inc.  See COPYING for
00003 ** distribution information.
00004 */
00005 
00006 #include      "config.h"
00007 #include      "liblock.h"
00008 #include      "mail.h"
00009 #include      <stdio.h>
00010 #include      <stdlib.h>
00011 #include      <string.h>
00012 #include      <unistd.h>
00013 #include      <errno.h>
00014 #include      <signal.h>
00015 #include      <sys/types.h>
00016 #include      <sys/stat.h>
00017 #if HAVE_SYS_WAIT_H
00018 #include <sys/wait.h>
00019 #endif
00020 #ifdef HAVE_FCNTL_H
00021 #include <fcntl.h>
00022 #endif
00023 #ifndef WEXITSTATUS
00024 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
00025 #endif
00026 #ifndef WIFEXITED
00027 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
00028 #endif
00029 
00030 #if HAVE_SYSEXITS_H
00031 #include <sysexits.h>
00032 #endif
00033 
00034 #ifndef EX_TEMPFAIL
00035 #define EX_TEMPFAIL 75
00036 #endif
00037 
00038 
00039 #define NTRIES_DEFAULT      60
00040 #define DELAY 5
00041 
00042 static int sig=0;
00043 
00044 static int catch(int signum)
00045 {
00046        sig=1;
00047        signal(SIGHUP, (RETSIGTYPE (*)(int))catch);
00048        signal(SIGTERM, (RETSIGTYPE (*)(int))catch);
00049        signal(SIGINT, (RETSIGTYPE (*)(int))catch);
00050        return 0;
00051 }
00052 
00053 static int caught()
00054 {
00055        signal(SIGHUP, SIG_DFL);
00056        signal(SIGTERM, SIG_DFL);
00057        signal(SIGINT, SIG_DFL);
00058        return sig;
00059 }
00060 
00061 int main(int argc, char **argv)
00062 {
00063        char **argvec;
00064        int n;
00065        int fd;
00066        pid_t pid, pid2;
00067        int waitstat;
00068        struct ll_mail *p;
00069        int ntries=NTRIES_DEFAULT;
00070        int readonly=0;
00071        int optchar;
00072 
00073        while ((optchar=getopt(argc, argv, "+rt:")) != -1)
00074               switch (optchar) {
00075               case 'r':
00076                      readonly=1;
00077                      break;
00078               case 't':
00079                      ntries=atoi(optarg);
00080                      if (ntries < 0)
00081                      {
00082                             fprintf(stderr, "%s: invalid argument to -t\n",
00083                                    argv[0]);
00084                             exit(EX_TEMPFAIL);
00085                      }
00086                      ntries= (ntries / DELAY) + 1;
00087                      break;
00088               default:
00089                      exit(1);
00090               }
00091 
00092        if (argc - optind < 2)
00093        {
00094               fprintf(stderr, "Usage: %s [-r] [-t time] mailfile program [args]...\n",
00095                      argv[0]);
00096               exit(1);
00097        }
00098 
00099        if ((argvec=malloc(sizeof(char *) * (argc - optind + 1))) == NULL)
00100        {
00101               perror("malloc");
00102               exit (1);
00103        }
00104 
00105        for (n=optind+1; n<argc; n++)
00106               argvec[n-optind - 1]=argv[n];
00107 
00108        argvec[n-optind-1]=NULL;
00109 
00110        /* Create the mail file, if it doesn't exist */
00111 
00112        if ((n=open(argv[optind], O_RDWR|O_CREAT, 0600)) >= 0)
00113               close(n);
00114 
00115        signal(SIGUSR2, SIG_IGN);
00116        signal(SIGCHLD, SIG_DFL);
00117 
00118        p=NULL;
00119 
00120        for (n=0; n<ntries; sleep(DELAY), n++)
00121        {
00122               if (p)
00123                      ll_mail_free(p);
00124 
00125               if ((p=ll_mail_alloc(argv[optind])) == NULL)
00126               {
00127                      perror("malloc");
00128                      exit(1);
00129               }
00130 
00131               signal(SIGHUP, (RETSIGTYPE (*)(int))catch);
00132               signal(SIGTERM, (RETSIGTYPE (*)(int))catch);
00133               signal(SIGINT, (RETSIGTYPE (*)(int))catch);
00134 
00135               if (ll_mail_lock(p) < 0)
00136               {
00137                      if (errno == ENOENT)
00138                             break; /* Mail file gone? */
00139                      if (caught())
00140                             break;
00141                      continue;
00142               }
00143 
00144               if ((fd=ll_mail_open(p)) < 0)
00145               {
00146                      if (!readonly || (fd=ll_mail_open_ro(p)) < 0)
00147                      {
00148                             if (caught())
00149                                    break;
00150                             continue;
00151                      }
00152               }
00153 
00154               if ((pid=fork()) < 0)
00155               {
00156                      perror("fork");
00157                      exit(1);
00158               }
00159 
00160               if (pid == 0)
00161               {
00162                      setgid(getgid());
00163                      setuid(getuid());
00164 
00165                      (void)caught();
00166                      execvp(argvec[0], argvec);
00167 
00168                      perror(argvec[0]);
00169                      exit(1);
00170               }
00171 
00172               while ((pid2=wait(&waitstat)) != pid)
00173                      ;
00174 
00175               ll_mail_free(p);
00176 
00177               if (WIFEXITED(waitstat))
00178                      exit(WEXITSTATUS(waitstat));
00179               exit(EX_TEMPFAIL);
00180        }
00181        if (p)
00182               ll_mail_free(p);
00183        exit(EX_TEMPFAIL);
00184        return (0);
00185 }
00186