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 */