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 }