nightmaremail

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

nmail-qmqpd.c (5834B)


      1 #include <unistd.h>
      2 #include <stdio.h>
      3 //#define dprintf(x, ...)
      4 #include "noreturn.h"
      5 #include "auto_qmail.h"
      6 #include "qmail.h"
      7 #include "received.h"
      8 #include "sig.h"
      9 #include "substdio.h"
     10 #include "readwrite.h"
     11 #include "exit.h"
     12 #include "now.h"
     13 #include "fmt.h"
     14 #include "byte.h"
     15 #include "env.h"
     16 #include "str.h"
     17 #include "netstrings.h"
     18 
     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 buf[1000];
     36 char strnum[FMT_ULONG];
     37 
     38 char ssinbuf[512];
     39 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof(ssinbuf));
     40 char ssoutbuf[256];
     41 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof(ssoutbuf));
     42 
     43 void _noreturn_ resources() {
     44   char *result = "DOut of resources";
     45 
     46   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
     47   substdio_puts(&ssout,":");
     48   substdio_puts(&ssout,result);
     49   substdio_puts(&ssout,",");
     50   substdio_flush(&ssout);
     51 _exit(111); }
     52 void _noreturn_ badproto() {
     53   char *result = "DBad protocol";
     54 
     55   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
     56   substdio_puts(&ssout,":");
     57   substdio_puts(&ssout,result);
     58   substdio_puts(&ssout,",");
     59   substdio_flush(&ssout);
     60 _exit(100); }
     61 void _noreturn_ bytesout() {
     62   char *result = "DBytes Out";
     63 
     64   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
     65   substdio_puts(&ssout,":");
     66   substdio_puts(&ssout,result);
     67   substdio_puts(&ssout,",");
     68   substdio_flush(&ssout);
     69 _exit(100); }
     70 void _noreturn_ badcomma() {
     71   char *result = "DBad comma";
     72 
     73   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
     74   substdio_puts(&ssout,":");
     75   substdio_puts(&ssout,result);
     76   substdio_puts(&ssout,",");
     77   substdio_flush(&ssout);
     78 _exit(100); }
     79 void _noreturn_ die_wtf() {
     80   char *result = "DWTF?";
     81 
     82   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
     83   substdio_puts(&ssout,":");
     84   substdio_puts(&ssout,result);
     85   substdio_puts(&ssout,",");
     86   substdio_flush(&ssout);
     87 _exit(100); }
     88 
     89 unsigned long long bytesleft = 100;
     90 
     91 void getbyte(ch)
     92 char *ch;
     93 {
     94   if (!bytesleft--) bytesout();
     95   substdio_get(&ssin,ch,1);
     96 }
     97 
     98 int getlen_times_called = 0;
     99 
    100 unsigned long long getlen()
    101 {
    102   unsigned long long len = 0;
    103   dprintf(2, "getlen has been called %d times\n", getlen_times_called++);
    104   switch (ns_getlength(&ssin,&len)) {
    105     case NS_SUCCESS: return len; break;
    106     case NS_TOOMUCH: resources(); break;
    107     case NS_PROTOCOL: badproto(); break;
    108     case NS_INVAL: die_wtf(); break;
    109     case NS_BIOERR: die_wtf(); break;
    110   }
    111   // we won't reach here.
    112   return len;
    113 #if 0
    114   char ch;
    115 
    116   for (;;) {
    117     getbyte(&ch);
    118     if (ch == ':') return len;
    119     if (len > 200000000) resources();
    120     len = 10 * len + (ch - '0');
    121   }
    122 #endif
    123 }
    124 
    125 void getcomma()
    126 {
    127   switch (ns_getcomma(&ssin,&bytesleft)) {
    128     case NS_SUCCESS: break;
    129     case NS_BYTES: bytesout(); break;
    130     case NS_PROTOCOL: badcomma(); break;
    131   }
    132 
    133 #if 0
    134   char ch;
    135   getbyte(&ch);
    136   if (ch != ',') _exit(100);
    137 #endif
    138 }
    139 
    140 struct qmail qq;
    141 
    142 void identify()
    143 {
    144   char *remotehost;
    145   char *remoteinfo;
    146   char *remoteip;
    147   char *local;
    148 
    149   remotehost = env_get("TCPREMOTEHOST");
    150   if (!remotehost) remotehost = "unknown";
    151   remoteinfo = env_get("TCPREMOTEINFO");
    152   remoteip = env_get("TCPREMOTEIP");
    153   if (!remoteip) remoteip = "unknown";
    154   local = env_get("TCPLOCALHOST");
    155   if (!local) local = env_get("TCPLOCALIP");
    156   if (!local) local = "unknown";
    157  
    158   received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,NULL);
    159 }
    160 
    161 int getbuf()
    162 {
    163   unsigned long long len;
    164   int i;
    165 
    166   len = getlen();
    167   if (len >= 1000) {
    168     for (i = 0;i < len;++i) getbyte(buf);
    169     getcomma();
    170     buf[0] = 0;
    171     return 0;
    172   }
    173 
    174   for (i = 0;i < len;++i) getbyte(buf + i);
    175   getcomma();
    176   buf[len] = 0;
    177   return byte_chr(buf,len,'\0') == len;
    178 }
    179 
    180 int flagok = 1;
    181 
    182 int
    183 main()
    184 {
    185   char *result;
    186   unsigned long long qp;
    187   unsigned long long len, gb;
    188   char ch;
    189 
    190   sig_pipeignore();
    191   sig_alarmcatch(resources);
    192   alarm(3600);
    193   dprintf(2, "%s\n", "stopwatch set: die in 3600 s");
    194 
    195   bytesleft = getlen();
    196 
    197   len = getlen();
    198   dprintf(2, "bytesleft %llu len %llu\n", bytesleft, len);
    199 
    200   if (chdir(auto_qmail) == -1) resources();
    201   if (qmail_open(&qq) == -1) resources();
    202   qp = qmail_qp(&qq);
    203   identify();
    204 
    205   while (len > 0) { /* XXX: could speed this up */
    206     getbyte(&ch);
    207     --len;
    208     qmail_put(&qq,&ch,1);
    209   }
    210   getcomma();
    211 
    212   dprintf(2, "pre-from bytesleft %llu len %llu\n", bytesleft, len);
    213 
    214   if (getbuf()) {
    215     dprintf(2, "from bytesleft %llu len %llu\n", bytesleft, len);
    216     qmail_from(&qq,buf);
    217   } else {
    218     qmail_from(&qq,"");
    219     qmail_fail(&qq);
    220     flagok = 0;
    221     dprintf(2, "dying due to failed getbuf for from\n");
    222   }
    223 
    224   while (bytesleft)
    225     if (getbuf()) {
    226       dprintf(2, "to bytesleft %llu len %llu\n", bytesleft, len);
    227       qmail_to(&qq,buf);
    228     } else {
    229       dprintf(2, "to bytesleft %llu len %llu\n", bytesleft, len);
    230       dprintf(2, "dying due to failed getbuf for to\n");
    231       qmail_fail(&qq);
    232       flagok = 0;
    233     }
    234 
    235   bytesleft = 1;
    236   getcomma();
    237   dprintf(2, "bytesleft %llu len %llu\n", bytesleft, len);
    238 
    239   result = qmail_close(&qq);
    240 
    241   if (!*result) {
    242     len = fmt_str(buf,"Kok ");
    243     len += fmt_ulong(buf + len,(unsigned long) now());
    244     len += fmt_str(buf + len," qp ");
    245     len += fmt_ulong(buf + len,qp);
    246     buf[len] = 0;
    247     result = buf;
    248   }
    249 
    250   if (!flagok)
    251     result = "Dsorry, I can't accept addresses like that (#5.1.3)";
    252 
    253   substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result)));
    254   substdio_puts(&ssout,":");
    255   substdio_puts(&ssout,result);
    256   substdio_puts(&ssout,",");
    257   substdio_flush(&ssout);
    258   _exit(0);
    259 }