nightmaremail

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

qmail-qmqpd.c (3815B)


      1 #include "noreturn.h"
      2 #include "auto_qmail.h"
      3 #include "qmail.h"
      4 #include "received.h"
      5 #include "sig.h"
      6 #include "substdio.h"
      7 #include "readwrite.h"
      8 #include "exit.h"
      9 #include "now.h"
     10 #include "fmt.h"
     11 #include "byte.h"
     12 #include "env.h"
     13 #include "str.h"
     14 #include "netstrings.h"
     15 
     16 void _noreturn_ resources() { _exit(111); }
     17 void _noreturn_ badproto() { _exit(100); }
     18 void _noreturn_ die_wtf() { _exit(100); }
     19 
     20 ssize_t safewrite(int fd, const void *buf, size_t len)
     21 {
     22   ssize_t r;
     23   r = write(fd,buf,len);
     24   if (r == 0 || r == -1) _exit(0);
     25   return r;
     26 }
     27 ssize_t saferead(int fd, void *buf, size_t len)
     28 {
     29   ssize_t r;
     30   r = read(fd,buf,len);
     31   if (r == 0 || r == -1) _exit(0);
     32   return r;
     33 }
     34 
     35 char ssinbuf[512];
     36 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof(ssinbuf));
     37 char ssoutbuf[256];
     38 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof(ssoutbuf));
     39 
     40 unsigned long long bytesleft = 100;
     41 
     42 void getbyte(ch)
     43 char *ch;
     44 {
     45   if (!bytesleft--) _exit(100);
     46   substdio_get(&ssin,ch,1);
     47 }
     48 
     49 unsigned long long getlen()
     50 {
     51   unsigned long long len = 0;
     52   switch (ns_getlength(&ssin,&len)) {
     53     case NS_SUCCESS: return len; break;
     54     case NS_TOOMUCH: resources(); break;
     55     case NS_PROTOCOL: badproto(); break;
     56     case NS_INVAL: die_wtf(); break;
     57     case NS_BIOERR: die_wtf(); break;
     58   } 
     59   // we won't reach here.
     60   return len;
     61 #if 0
     62   char ch;
     63 
     64   for (;;) {
     65     getbyte(&ch);
     66     if (ch == ':') return len;
     67     if (len > 200000000) resources();
     68     len = 10 * len + (ch - '0');
     69   }
     70 #endif
     71 }
     72 
     73 void getcomma()
     74 {
     75   switch (ns_getcomma(&ssin)) {
     76     case NS_SUCCESS: break;
     77     case NS_PROTOCOL: badproto(); break;
     78   }
     79 
     80 #if 0
     81   char ch;
     82   getbyte(&ch);
     83   if (ch != ',') _exit(100);
     84 #endif
     85 }
     86 
     87 struct qmail qq;
     88 
     89 void identify()
     90 {
     91   char *remotehost;
     92   char *remoteinfo;
     93   char *remoteip;
     94   char *local;
     95 
     96   remotehost = env_get("TCPREMOTEHOST");
     97   if (!remotehost) remotehost = "unknown";
     98   remoteinfo = env_get("TCPREMOTEINFO");
     99   remoteip = env_get("TCPREMOTEIP");
    100   if (!remoteip) remoteip = "unknown";
    101   local = env_get("TCPLOCALHOST");
    102   if (!local) local = env_get("TCPLOCALIP");
    103   if (!local) local = "unknown";
    104  
    105   received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,NULL);
    106 }
    107 
    108 char buf[1000];
    109 char strnum[FMT_ULONG];
    110 
    111 int getbuf()
    112 {
    113   unsigned long long len;
    114   int i;
    115 
    116   len = getlen();
    117   if (len >= 1000) {
    118     for (i = 0;i < len;++i) getbyte(buf);
    119     getcomma();
    120     buf[0] = 0;
    121     return 0;
    122   }
    123 
    124   for (i = 0;i < len;++i) getbyte(buf + i);
    125   getcomma();
    126   buf[len] = 0;
    127   return byte_chr(buf,len,'\0') == len;
    128 }
    129 
    130 int flagok = 1;
    131 
    132 int
    133 main()
    134 {
    135   char *result;
    136   unsigned long long qp;
    137   unsigned long long len;
    138   char ch;
    139 
    140   sig_pipeignore();
    141   sig_alarmcatch(resources);
    142   alarm(3600);
    143 
    144   bytesleft = getlen();
    145 
    146   len = getlen();
    147 
    148   if (chdir(auto_qmail) == -1) resources();
    149   if (qmail_open(&qq) == -1) resources();
    150   qp = qmail_qp(&qq);
    151   identify();
    152 
    153   while (len > 0) { /* XXX: could speed this up */
    154     getbyte(&ch);
    155     --len;
    156     qmail_put(&qq,&ch,1);
    157   }
    158   getcomma();
    159 
    160   if (getbuf())
    161     qmail_from(&qq,buf);
    162   else {
    163     qmail_from(&qq,"");
    164     qmail_fail(&qq);
    165     flagok = 0;
    166   }
    167 
    168   while (bytesleft)
    169     if (getbuf())
    170       qmail_to(&qq,buf);
    171     else {
    172       qmail_fail(&qq);
    173       flagok = 0;
    174     }
    175 
    176   bytesleft = 1;
    177   getcomma();
    178 
    179   result = qmail_close(&qq);
    180 
    181   if (!*result) {
    182     len = fmt_str(buf,"Kok ");
    183     len += fmt_ulong(buf + len,(unsigned long) now());
    184     len += fmt_str(buf + len," qp ");
    185     len += fmt_ulong(buf + len,qp);
    186     buf[len] = 0;
    187     result = buf;
    188   }
    189 
    190   if (!flagok)
    191     result = "Dsorry, I can't accept addresses like that (#5.1.3)";
    192 
    193   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
    194   substdio_puts(&ssout,":");
    195   substdio_puts(&ssout,result);
    196   substdio_puts(&ssout,",");
    197   substdio_flush(&ssout);
    198   _exit(0);
    199 }