10 #include "auto_qmail.h"
11 #include "readwrite.h"
15 void badproto() { _exit(100); }
16 void resources() { _exit(111); }
18 int safewrite(fd,buf,len) int fd; char *buf; int len;
21 r = write(fd,buf,len);
27 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
29 int saferead(fd,buf,len) int fd; char *buf; int len;
32 substdio_flush(&ssout);
39 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
41 unsigned long getlen()
43 unsigned long len = 0;
46 substdio_get(&ssin,&ch,1);
47 if (ch == ':') return len;
48 if (len > 200000000) resources();
49 len = 10 * len + (ch - '0');
56 substdio_get(&ssin,&ch,1);
57 if (ch != ',') badproto();
60 unsigned int databytes = 0;
61 unsigned int bytestooverflow = 0;
72 stralloc failure = {0};
92 sig_alarmcatch(resources);
95 if (chdir(auto_qmail) == -1) resources();
97 if (control_init() == -1) resources();
98 if (rcpthosts_init() == -1) resources();
99 relayclient = env_get("RELAYCLIENT");
100 relayclientlen = relayclient ? str_len(relayclient) : 0;
102 if (control_readint(&databytes,"control/databytes") == -1) resources();
103 x = env_get("DATABYTES");
104 if (x) { scan_ulong(x,&u); databytes = u; }
105 if (!(databytes + 1)) --databytes;
107 remotehost = env_get("TCPREMOTEHOST");
108 if (!remotehost) remotehost = "unknown";
109 remoteinfo = env_get("TCPREMOTEINFO");
110 remoteip = env_get("TCPREMOTEIP");
111 if (!remoteip) remoteip = "unknown";
112 local = env_get("TCPLOCALHOST");
113 if (!local) local = env_get("TCPLOCALIP");
114 if (!local) local = "unknown";
117 if (!stralloc_copys(&failure,"")) resources();
121 if (len == 0) badproto();
123 if (databytes) bytestooverflow = databytes + 1;
124 if (qmail_open(&qq) == -1) resources();
127 substdio_get(&ssin,&ch,1);
129 if (ch == 10) flagdos = 0;
130 else if (ch == 13) flagdos = 1;
133 received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0);
135 /* XXX: check for loops? only if len is big? */
139 substdio_get(&ssin,&ch,1);
141 while ((ch == 13) && len) {
142 substdio_get(&ssin,&ch,1);
145 if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq);
146 qmail_put(&qq,"\015",1);
148 if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq);
149 qmail_put(&qq,&ch,1);
153 if (len > databytes) {
157 while (len > 0) { /* XXX: could speed this up, obviously */
158 substdio_get(&ssin,&ch,1);
160 qmail_put(&qq,&ch,1);
170 for (i = 0;i < len;++i)
171 substdio_get(&ssin,&ch,1);
174 for (i = 0;i < len;++i) {
175 substdio_get(&ssin,buf + i,1);
176 if (!buf[i]) flagsenderok = 0;
184 if (!flagsenderok) qmail_fail(&qq);
188 if (!stralloc_append(&failure,"")) resources();
192 if (!biglen) badproto();
193 substdio_get(&ssin,&ch,1);
195 if (ch == ':') break;
196 if (len > 200000000) resources();
197 len = 10 * len + (ch - '0');
199 if (len >= biglen) badproto();
200 if (len + relayclientlen >= 1000) {
201 failure.s[failure.len - 1] = 'L';
202 for (i = 0;i < len;++i)
203 substdio_get(&ssin,&ch,1);
206 for (i = 0;i < len;++i) {
207 substdio_get(&ssin,buf + i,1);
208 if (!buf[i]) failure.s[failure.len - 1] = 'N';
213 str_copy(buf + len,relayclient);
215 switch(rcpthosts(buf,len)) {
216 case -1: resources();
217 case 0: failure.s[failure.len - 1] = 'D';
220 if (!failure.s[failure.len - 1]) {
230 if (!flagbother) qmail_fail(&qq);
231 result = qmail_close(&qq);
232 if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)";
233 if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
236 len = str_len(result);
240 len += fmt_str(buf2 + len,"Kok ");
241 len += fmt_ulong(buf2 + len,(unsigned long) now());
242 len += fmt_str(buf2 + len," qp ");
243 len += fmt_ulong(buf2 + len,qp);
248 len = fmt_ulong(buf,len);
250 len += fmt_str(buf + len,result);
253 for (i = 0;i < failure.len;++i)
254 switch(failure.s[i]) {
256 substdio_put(&ssout,buf,len);
259 substdio_puts(&ssout,"66:Dsorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),");
262 substdio_puts(&ssout,"46:Dsorry, I can't handle that recipient (#5.1.3),");
266 /* ssout will be flushed when we read from the network again */