nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

qmail.c (4892B)


      1 #include "qmail.h"
      2 
      3 #include "substdio.h"
      4 //#include "stralloc.h"
      5 #include "readwrite.h"
      6 #include "wait.h"
      7 #include "exit.h"
      8 #include "fork.h"
      9 #include "fd.h"
     10 #include "auto_qmail.h"
     11 #include "env.h"
     12 #include "fmt.h"
     13 
     14 static char *binqqargs[2] = { 0, 0 } ;
     15 
     16 static void setup_qqargs()
     17 {
     18   if(!binqqargs[0])
     19     binqqargs[0] = env_get("QMAILQUEUE");
     20   if(!binqqargs[0])
     21     binqqargs[0] = "bin/qmail-queue";
     22 }
     23 
     24 int qmail_open(qq)
     25 struct qmail *qq;
     26 {
     27   int pim[2];
     28   int pie[2];
     29   int pierr[2];
     30 
     31   setup_qqargs();
     32 
     33   if (pipe(pim) == -1) return -1;
     34   if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
     35   if (pipe(pierr) == -1) {
     36     close(pim[0]); close(pim[1]);
     37     close(pie[0]); close(pie[1]);
     38     return -1;
     39   }
     40  
     41   switch(qq->pid = fork()) {
     42     case -1:
     43       close(pim[0]); close(pim[1]);
     44       close(pie[0]); close(pie[1]);
     45       close(pierr[0]); close(pierr[1]);
     46       return -1;
     47     case 0:
     48       close(pim[1]);
     49       close(pie[1]);
     50       close(pierr[0]); /* we want to receive data */
     51       if (fd_move(0,pim[0]) == -1) _exit(120);
     52       if (fd_move(1,pie[0]) == -1) _exit(120);
     53       if (fd_move(6,pierr[1]) == -1) _exit(120);
     54       if (chdir(auto_qmail) == -1) _exit(61);
     55       execv(*binqqargs,binqqargs);
     56       _exit(120);
     57   }
     58 
     59   qq->fdm = pim[1]; close(pim[0]);
     60   qq->fde = pie[1]; close(pie[0]);
     61   qq->fderr = pierr[0]; close(pierr[1]);
     62   substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf));
     63   qq->flagerr = 0;
     64   return 0;
     65 }
     66 
     67 unsigned long qmail_qp(qq) struct qmail *qq;
     68 {
     69   return qq->pid;
     70 }
     71 
     72 void qmail_fail(qq) struct qmail *qq;
     73 {
     74   qq->flagerr = 1;
     75 }
     76 
     77 void qmail_put(struct qmail *qq, char *s, size_t len)
     78 {
     79   if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1;
     80 }
     81 
     82 void qmail_from(qq,s) struct qmail *qq; char *s;
     83 {
     84   if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
     85   close(qq->fdm);
     86   substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf));
     87   qmail_put(qq,"F",1);
     88   qmail_puts(qq,s);
     89   qmail_put(qq,"",1);
     90 }
     91 
     92 void qmail_to(qq,s) struct qmail *qq; char *s;
     93 {
     94   qmail_put(qq,"T",1);
     95   qmail_puts(qq,s);
     96   qmail_put(qq,"",1);
     97 }
     98 
     99 static size_t qmail_errstr(struct qmail *qq, char *s) {
    100   size_t len = 0;
    101   substdio_fdbuf(&qq->ss,read,qq->fderr,qq->buf,sizeof(qq->buf));
    102   while (substdio_get(&qq->ss,s+len,1) > 0 && len < 255) {
    103     len++;
    104   }
    105   s[len] = '\0';
    106   return len;
    107 }
    108 
    109 char *qmail_close(qq)
    110 struct qmail *qq;
    111 {
    112   int wstat;
    113   int exitcode;
    114   static char errstr[256];
    115   size_t errlen;
    116   char excode[10];
    117 
    118   qmail_put(qq,"",1);
    119   if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
    120   close(qq->fde);
    121   errlen = qmail_errstr(qq, errstr);
    122   close(qq->fderr);
    123 
    124   if (wait_pid(&wstat,qq->pid) != qq->pid)
    125     return "Z4.3.0 qq waitpid surprise";
    126   if (wait_crashed(wstat))
    127     return "Z4.3.0 qq crashed";
    128   exitcode = wait_exitcode(wstat);
    129 
    130   switch(exitcode) {
    131     case 115: /* compatibility */
    132     case 11: return "D5.1.3 envelope address too long for qq";
    133     case 31: return "D5.3.0 mail server permanently rejected message";
    134     case 51: return "Z4.3.0 qq out of memory";
    135     case 52: return "Z4.3.0 qq timeout";
    136     case 53: return "Z4.3.0 qq write error or disk full";
    137     case 0: if (!qq->flagerr) return ""; /* fall through */
    138     case 54: return "Z4.3.0 qq read error";
    139     case 55: return "Z4.3.0 qq unable to read configuration";
    140     case 56: return "Z4.3.0 qq trouble making network connection";
    141     case 61: return "Z4.3.0 qq trouble in home directory";
    142     case 63:
    143     case 64:
    144     case 65:
    145     case 66:
    146     case 62: return "Z4.3.0 qq trouble creating files in queue";
    147     case 71: return "Z4.3.0 mail server temporarily rejected message";
    148     case 72: return "Z4.4.1 connection to mail server timed out";
    149     case 73: return "Z4.4.1 connection to mail server rejected";
    150     case 74: return "Z4.4.2 communication with mail server failed";
    151     case 91: /* fall through */
    152     case 81: return "Z4.3.0 qq internal bug";
    153     case 120: return "Z4.3.0 unable to exec qq";
    154     default:
    155       if (exitcode == 82 && errlen > 2)
    156         return errstr;
    157       if ((exitcode >= 11) && (exitcode <= 40))
    158         return "D5.3.0 qq permanent problem";
    159 #if 0 // change this to zero when done please
    160       if (!stralloc_copys(&exitstr, "Z4.3.0 qq temporary problem: exited with code ")) return "Z4.3.0 temporary problem + memory allocation failure";
    161       excode[fmt_ulong(excode, exitcode)] = 0;
    162       if (!stralloc_cats(&exitstr, excode)) return "Z4.3.0 temporary problem + memory allocation failure";
    163       if (errlen > 2) {
    164         if (!stralloc_cats(&exitstr, " and errstr of")) return "Z4.3.0 temporary problem + memory allocation failure";
    165         if (!stralloc_cats(&exitstr, errstr)) return "Z4.3.0 temporary problem + memory allocation failure";
    166       }
    167       stralloc_0(&exitstr);
    168       return exitstr.s; // dangling pointer
    169 #else
    170       return "Z4.3.0 qq temporary problem";
    171 #endif
    172   }
    173 }