qmail-queue.c
changeset 0 068428edee47
equal deleted inserted replaced
-1:000000000000 0:068428edee47
       
     1 #include <sys/types.h>
       
     2 #include <sys/stat.h>
       
     3 #include "readwrite.h"
       
     4 #include "sig.h"
       
     5 #include "exit.h"
       
     6 #include "open.h"
       
     7 #include "seek.h"
       
     8 #include "fmt.h"
       
     9 #include "alloc.h"
       
    10 #include "substdio.h"
       
    11 #include "datetime.h"
       
    12 #include "now.h"
       
    13 #include "triggerpull.h"
       
    14 #include "extra.h"
       
    15 #include "auto_qmail.h"
       
    16 #include "auto_uids.h"
       
    17 #include "date822fmt.h"
       
    18 #include "fmtqfn.h"
       
    19 
       
    20 #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
       
    21 #define ADDR 1003
       
    22 
       
    23 char inbuf[2048];
       
    24 struct substdio ssin;
       
    25 char outbuf[256];
       
    26 struct substdio ssout;
       
    27 
       
    28 datetime_sec starttime;
       
    29 struct datetime dt;
       
    30 unsigned long mypid;
       
    31 unsigned long uid;
       
    32 char *pidfn;
       
    33 struct stat pidst;
       
    34 unsigned long messnum;
       
    35 char *messfn;
       
    36 char *todofn;
       
    37 char *intdfn;
       
    38 int messfd;
       
    39 int intdfd;
       
    40 int flagmademess = 0;
       
    41 int flagmadeintd = 0;
       
    42 
       
    43 void cleanup()
       
    44 {
       
    45  if (flagmadeintd)
       
    46   {
       
    47    seek_trunc(intdfd,0);
       
    48    if (unlink(intdfn) == -1) return;
       
    49   }
       
    50  if (flagmademess)
       
    51   {
       
    52    seek_trunc(messfd,0);
       
    53    if (unlink(messfn) == -1) return;
       
    54   }
       
    55 }
       
    56 
       
    57 void die(e) int e; { _exit(e); }
       
    58 void die_write() { cleanup(); die(53); }
       
    59 void die_read() { cleanup(); die(54); }
       
    60 void sigalrm() { /* thou shalt not clean up here */ die(52); }
       
    61 void sigbug() { die(81); }
       
    62 
       
    63 unsigned int receivedlen;
       
    64 char *received;
       
    65 /* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */
       
    66 
       
    67 static unsigned int receivedfmt(s)
       
    68 char *s;
       
    69 {
       
    70  unsigned int i;
       
    71  unsigned int len;
       
    72  len = 0;
       
    73  i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i;
       
    74  i = fmt_ulong(s,mypid); len += i; if (s) s += i;
       
    75  i = fmt_str(s," invoked "); len += i; if (s) s += i;
       
    76  if (uid == auto_uida)
       
    77   { i = fmt_str(s,"by alias"); len += i; if (s) s += i; }
       
    78  else if (uid == auto_uidd)
       
    79   { i = fmt_str(s,"from network"); len += i; if (s) s += i; }
       
    80  else if (uid == auto_uids)
       
    81   { i = fmt_str(s,"for bounce"); len += i; if (s) s += i; }
       
    82  else
       
    83   {
       
    84    i = fmt_str(s,"by uid "); len += i; if (s) s += i;
       
    85    i = fmt_ulong(s,uid); len += i; if (s) s += i;
       
    86   }
       
    87  i = fmt_str(s,"); "); len += i; if (s) s += i;
       
    88  i = date822fmt(s,&dt); len += i; if (s) s += i;
       
    89  return len;
       
    90 }
       
    91 
       
    92 void received_setup()
       
    93 {
       
    94  receivedlen = receivedfmt((char *) 0);
       
    95  received = alloc(receivedlen + 1);
       
    96  if (!received) die(51);
       
    97  receivedfmt(received);
       
    98 }
       
    99 
       
   100 unsigned int pidfmt(s,seq)
       
   101 char *s;
       
   102 unsigned long seq;
       
   103 {
       
   104  unsigned int i;
       
   105  unsigned int len;
       
   106 
       
   107  len = 0;
       
   108  i = fmt_str(s,"pid/"); len += i; if (s) s += i;
       
   109  i = fmt_ulong(s,mypid); len += i; if (s) s += i;
       
   110  i = fmt_str(s,"."); len += i; if (s) s += i;
       
   111  i = fmt_ulong(s,starttime); len += i; if (s) s += i;
       
   112  i = fmt_str(s,"."); len += i; if (s) s += i;
       
   113  i = fmt_ulong(s,seq); len += i; if (s) s += i;
       
   114  ++len; if (s) *s++ = 0;
       
   115 
       
   116  return len;
       
   117 }
       
   118 
       
   119 char *fnnum(dirslash,flagsplit)
       
   120 char *dirslash;
       
   121 int flagsplit;
       
   122 {
       
   123  char *s;
       
   124 
       
   125  s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit));
       
   126  if (!s) die(51);
       
   127  fmtqfn(s,dirslash,messnum,flagsplit);
       
   128  return s;
       
   129 }
       
   130 
       
   131 void pidopen()
       
   132 {
       
   133  unsigned int len;
       
   134  unsigned long seq;
       
   135 
       
   136  seq = 1;
       
   137  len = pidfmt((char *) 0,seq);
       
   138  pidfn = alloc(len);
       
   139  if (!pidfn) die(51);
       
   140 
       
   141  for (seq = 1;seq < 10;++seq)
       
   142   {
       
   143    if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
       
   144    pidfmt(pidfn,seq);
       
   145    messfd = open_excl(pidfn);
       
   146    if (messfd != -1) return;
       
   147   }
       
   148 
       
   149  die(63);
       
   150 }
       
   151 
       
   152 char tmp[FMT_ULONG];
       
   153 
       
   154 void main()
       
   155 {
       
   156  unsigned int len;
       
   157  char ch;
       
   158 
       
   159  sig_blocknone();
       
   160  umask(033);
       
   161  if (chdir(auto_qmail) == -1) die(61);
       
   162  if (chdir("queue") == -1) die(62);
       
   163 
       
   164  mypid = getpid();
       
   165  uid = getuid();
       
   166  starttime = now();
       
   167  datetime_tai(&dt,starttime);
       
   168 
       
   169  received_setup();
       
   170 
       
   171  sig_pipeignore();
       
   172  sig_miscignore();
       
   173  sig_alarmcatch(sigalrm);
       
   174  sig_bugcatch(sigbug);
       
   175 
       
   176  alarm(DEATH);
       
   177 
       
   178  pidopen();
       
   179  if (fstat(messfd,&pidst) == -1) die(63);
       
   180 
       
   181  messnum = pidst.st_ino;
       
   182  messfn = fnnum("mess/",1);
       
   183  todofn = fnnum("todo/",0);
       
   184  intdfn = fnnum("intd/",0);
       
   185 
       
   186  if (link(pidfn,messfn) == -1) die(64);
       
   187  if (unlink(pidfn) == -1) die(63);
       
   188  flagmademess = 1;
       
   189 
       
   190  substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
       
   191  substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
       
   192 
       
   193  if (substdio_bput(&ssout,received,receivedlen) == -1) die_write();
       
   194 
       
   195  switch(substdio_copy(&ssout,&ssin))
       
   196   {
       
   197    case -2: die_read();
       
   198    case -3: die_write();
       
   199   }
       
   200 
       
   201  if (substdio_flush(&ssout) == -1) die_write();
       
   202  if (fsync(messfd) == -1) die_write();
       
   203 
       
   204  intdfd = open_excl(intdfn);
       
   205  if (intdfd == -1) die(65);
       
   206  flagmadeintd = 1;
       
   207 
       
   208  substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf));
       
   209  substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf));
       
   210 
       
   211  if (substdio_bput(&ssout,"u",1) == -1) die_write();
       
   212  if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,uid)) == -1) die_write();
       
   213  if (substdio_bput(&ssout,"",1) == -1) die_write();
       
   214 
       
   215  if (substdio_bput(&ssout,"p",1) == -1) die_write();
       
   216  if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,mypid)) == -1) die_write();
       
   217  if (substdio_bput(&ssout,"",1) == -1) die_write();
       
   218 
       
   219  if (substdio_get(&ssin,&ch,1) < 1) die_read();
       
   220  if (ch != 'F') die(91);
       
   221  if (substdio_bput(&ssout,&ch,1) == -1) die_write();
       
   222  for (len = 0;len < ADDR;++len)
       
   223   {
       
   224    if (substdio_get(&ssin,&ch,1) < 1) die_read();
       
   225    if (substdio_put(&ssout,&ch,1) == -1) die_write();
       
   226    if (!ch) break;
       
   227   }
       
   228  if (len >= ADDR) die(11);
       
   229 
       
   230  if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
       
   231 
       
   232  for (;;)
       
   233   {
       
   234    if (substdio_get(&ssin,&ch,1) < 1) die_read();
       
   235    if (!ch) break;
       
   236    if (ch != 'T') die(91);
       
   237    if (substdio_bput(&ssout,&ch,1) == -1) die_write();
       
   238    for (len = 0;len < ADDR;++len)
       
   239     {
       
   240      if (substdio_get(&ssin,&ch,1) < 1) die_read();
       
   241      if (substdio_bput(&ssout,&ch,1) == -1) die_write();
       
   242      if (!ch) break;
       
   243     }
       
   244    if (len >= ADDR) die(11);
       
   245   }
       
   246 
       
   247  if (substdio_flush(&ssout) == -1) die_write();
       
   248  if (fsync(intdfd) == -1) die_write();
       
   249 
       
   250  if (link(intdfn,todofn) == -1) die(66);
       
   251 
       
   252  triggerpull();
       
   253  die(0);
       
   254 }