Back to index

courier  0.68.2
courier.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2007 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "courier.h"
00007 #include      "localstatedir.h"
00008 #include      "datadir.h"
00009 #include      "comctlfile.h"
00010 #include      "comparseqid.h"
00011 #include      "comqueuename.h"
00012 #include      "comtrack.h"
00013 #include      <sys/types.h>
00014 #include      <string.h>
00015 #include      <signal.h>
00016 #include      <stdlib.h>
00017 #if    HAVE_UNISTD_H
00018 #include      <unistd.h>
00019 #endif
00020 #if    HAVE_FCNTL_H
00021 #include      <fcntl.h>
00022 #endif
00023 #if    HAVE_SYS_IOCTL_H
00024 #include      <sys/ioctl.h>
00025 #endif
00026 #if    HAVE_SYS_STAT_H
00027 #include      <sys/stat.h>
00028 #endif
00029 #include      "waitlib/waitlib.h"
00030 #include      "liblock/config.h"
00031 #include      "liblock/liblock.h"
00032 #include      "numlib/numlib.h"
00033 
00034 void courier_clear_all();
00035 void courier_show_all();
00036 
00037 int main(int argc, char **argv)
00038 {
00039        if (argc > 1 && strcmp(argv[1], "--version") == 0)
00040        {
00041               printf("%s\n", COURIER_COPYRIGHT);
00042               exit(0);
00043        }
00044 
00045        if (chdir(courierdir()))
00046        {
00047               perror("chdir");
00048               return (1);
00049        }
00050        if (argc < 2) return (0);
00051 
00052        if (strcmp(argv[1], "stop") == 0)
00053        {
00054        int    fd;
00055 
00056               trigger(TRIGGER_STOP);
00057 
00058               /* Wait until the exclusive lock goes away: */
00059 
00060               signal(SIGHUP, SIG_DFL);
00061               if ((fd=open(TMPDIR "/courierd.lock", O_RDWR|O_CREAT, 0600))
00062                      < 0)   clog_msg_errno();
00063 
00064               alarm(15);    /* But abort after 15 seconds. */
00065 
00066               ll_lock_ex(fd);
00067               return (0);
00068        }
00069 
00070        if (strcmp(argv[1], "restart") == 0)
00071        {
00072               trigger(TRIGGER_RESTART);
00073               return (0);
00074        }
00075 
00076        if (strcmp(argv[1], "flush") == 0)
00077        {
00078        ino_t  n;
00079        struct ctlfile       ctf;
00080 
00081               if (getuid())
00082               {
00083               /*
00084               ** We'll fail trying to open the pipe anyway, but let's
00085               ** give a meaningful error message now.
00086               */
00087                      fprintf(stderr,
00088               "courier flush can be executed only by the superuser.\n");
00089                      exit(1);
00090               }
00091 
00092               if (argc < 3)
00093               {
00094                      trigger(TRIGGER_FLUSH);     /* Everything */
00095                      exit(0);
00096               }
00097 
00098               if (comparseqid(argv[2], &n) == 0 &&
00099                      ctlfile_openi(n, &ctf, 1) == 0)
00100               {
00101               int c=ctlfile_searchfirst(&ctf, COMCTLFILE_MSGID);
00102 
00103                      if (c >= 0 && strcmp(ctf.lines[c]+1, argv[2]) == 0)
00104                      {
00105                      char   *s=courier_malloc(sizeof(TRIGGER_FLUSHMSG)+1+
00106                             strlen(argv[2]));
00107 
00108                             strcat(strcat(strcpy(s, TRIGGER_FLUSHMSG),
00109                                    argv[2]), "\n");
00110                             trigger(s);
00111                             ctlfile_close(&ctf);
00112                             return (0);
00113                      }
00114                      ctlfile_close(&ctf);
00115               }
00116               fprintf(stderr, "No such message.\n");
00117               exit(1);
00118               return (1);
00119        }
00120 
00121        /* Might as well... */
00122 
00123        if (strcmp(argv[1], "start") == 0)
00124        {
00125        pid_t  p;
00126        int    waitstat;
00127        char   dummy;
00128 
00129        /*
00130        ** Ok, courierd will close file descriptor 3 when it starts, so we
00131        ** put a pipe on there, and wait for it to close.
00132        */
00133        int    pipefd[2];
00134 
00135               close(3);
00136               if (open("/dev/null", O_RDONLY) != 3 || pipe(pipefd))
00137               {
00138                      fprintf(stderr, "Cannot open pipe\n");
00139                      exit(1);
00140               }
00141 
00142               if (getuid())
00143               {
00144               /*
00145               ** We'll fail trying to execute courierd anyway, but let's
00146               ** give a meaningful error message now.
00147               */
00148                      fprintf(stderr, "courier start can be executed only by the superuser.\n");
00149                      return (1);
00150               }
00151               signal(SIGCHLD, SIG_DFL);
00152               while ((p=fork()) == -1)
00153               {
00154                      perror("fork");
00155                      sleep(10);
00156               }
00157               if (p == 0)
00158               {
00159                      dup2(pipefd[1], 3);
00160                      close(pipefd[1]);
00161                      close(pipefd[0]);
00162                      while ((p=fork()) == -1)
00163                      {
00164                             perror("fork");
00165                             sleep(10);
00166                      }
00167                      if (p == 0)
00168                      {
00169                             /*
00170                             ** stdin from the bitbucket.  stdout to
00171                             ** /dev/null, or the bitbucket.
00172                             */
00173 
00174                             signal(SIGHUP, SIG_IGN);
00175                             close(0);
00176                             open("/dev/null", O_RDWR);
00177                             dup2(0, 1);
00178                             dup2(0, 2);
00179                      /* See if we can disconnect from the terminal */
00180 
00181 #ifdef TIOCNOTTY
00182                             {
00183                             int fd=open("/dev/tty", O_RDWR);
00184 
00185                                    if (fd >= 0)
00186                                    {
00187                                           ioctl(fd, TIOCNOTTY, 0);
00188                                           close(fd);
00189                                    }
00190                             }
00191 #endif
00192                      /* Remove any process groups */
00193 
00194 #if    HAVE_SETPGRP
00195 #if    SETPGRP_VOID
00196                             setpgrp();
00197 #else
00198                             setpgrp(0, 0);
00199 #endif
00200 #endif
00201                             execl( DATADIR "/courierctl.start",
00202                                    "courierctl.start", (char *)0);
00203                             perror("exec");
00204                             _exit(1);
00205                      }
00206                      _exit(0);
00207               }
00208               close(pipefd[1]);
00209               while (wait(&waitstat) != p)
00210                      ;
00211               if (read(pipefd[0], &dummy, 1) < 0)
00212                      ; /* ignore */
00213               close(pipefd[0]);
00214               close(3);
00215               return (0);
00216        }
00217 
00218        if (strcmp(argv[1], "clear") == 0 && argc > 2)
00219        {
00220               libmail_changeuidgid(MAILUID, MAILGID);
00221 
00222               if (strcmp(argv[2], "all") == 0)
00223               {
00224                      courier_clear_all();
00225               }
00226               else
00227               {
00228                      track_save(argv[2], TRACK_ADDRACCEPTED);
00229                      printf("%s cleared.\n", argv[2]);
00230               }
00231               return (0);
00232        }
00233 
00234        if (argc > 2 && strcmp(argv[1], "show") == 0 &&
00235            strcmp(argv[2], "all") == 0)
00236        {
00237               libmail_changeuidgid(MAILUID, MAILGID);
00238               courier_show_all();
00239        }
00240 
00241        return (0);
00242 }