s/qmail 4.2.29a
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-queue.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <fcntl.h>
5#include "sig.h"
6#include "exit.h"
7#include "open.h"
8#include "seek.h"
9#include "fmt.h"
10#include "alloc.h"
11#include "buffer.h"
12#include "datetime.h"
13#include "now.h"
14#include "triggerpull.h"
15#include "extra.h"
16#include "auto_qmail.h"
17#include "auto_uids.h"
18#include "date822fmt.h"
19#include "fmtqfn.h"
20#include "env.h"
21#include "wait.h"
22#include "scan.h"
23
24#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
25#define ADDR 1003
26
27char inbuf[2048];
28struct buffer bi;
29char outbuf[256];
30struct buffer bo;
31
33struct datetime dt;
34unsigned long mypid;
35unsigned long uid;
36char *pidfn;
37struct stat pidst;
38unsigned long messnum;
39char *messfn;
40char *todofn;
41char *intdfn;
46
47void cleanup()
48{
49 if (flagmadeintd) {
50 seek_trunc(intdfd,0);
51 if (unlink(intdfn) == -1) return;
52 }
53 if (flagmademess) {
54 seek_trunc(messfd,0);
55 if (unlink(messfn) == -1) return;
56 }
57}
58
59void die(int e) { _exit(e); }
60void die_qhpsi() { cleanup(); die(71); }
61void die_write() { cleanup(); die(53); }
62void die_read() { cleanup(); die(54); }
63void sigalrm() { /* thou shalt not clean up here */ die(52); }
64void sigbug() { die(81); }
65
66unsigned int receivedlen;
68/* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */
69
70static unsigned int receivedfmt(char *s)
71{
72 unsigned int i;
73 unsigned int len;
74 len = 0;
75
76 i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i;
77 i = fmt_ulong(s,mypid); len += i; if (s) s += i;
78 i = fmt_str(s," invoked "); len += i; if (s) s += i;
79 if (uid == auto_uida) {
80 i = fmt_str(s,"by alias"); len += i; if (s) s += i;
81 } else if (uid == auto_uidd) {
82 i = fmt_str(s,"from network"); len += i; if (s) s += i;
83 } else if (uid == auto_uids) {
84 i = fmt_str(s,"for bounce"); len += i; if (s) s += i;
85 } else {
86 i = fmt_str(s,"by uid "); len += i; if (s) s += i;
87 i = fmt_ulong(s,uid); len += i; if (s) s += i;
88 }
89 i = fmt_str(s,"); "); len += i; if (s) s += i;
90 i = date822fmt(s,&dt); len += i; if (s) s += i;
91 return len;
92}
93
95{
96 receivedlen = receivedfmt((char *) 0);
97 received = alloc(receivedlen + 1);
98 if (!received) die(51);
99 receivedfmt(received);
100}
101
102unsigned int pidfmt(char *s,unsigned long seq)
103{
104 unsigned int i;
105 unsigned int len;
106
107 len = 0;
108 i = fmt_str(s,"pid/"); len += i; if (s) s += i;
109 i = fmt_ulong(s,mypid); len += i; if (s) s += i;
110 i = fmt_str(s,"."); len += i; if (s) s += i;
111 i = fmt_ulong(s,starttime); len += i; if (s) s += i;
112 i = fmt_str(s,"."); len += i; if (s) s += i;
113 i = fmt_ulong(s,seq); len += i; if (s) s += i;
114 ++len; if (s) *s++ = 0;
115
116 return len;
117}
118
119char *fnnum(char *dirslash,int flagsplit)
120{
121 char *s;
122
123 s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit));
124 if (!s) die(51);
125 fmtqfn(s,dirslash,messnum,flagsplit);
126 return s;
127}
128
129void pidopen(void)
130{
131 unsigned int len;
132 unsigned long seq;
133
134 seq = 1;
135 len = pidfmt((char *) 0,seq);
136 pidfn = alloc(len);
137 if (!pidfn) die(51);
138
139 for (seq = 1; seq < 10; ++seq) {
140 if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
141 pidfmt(pidfn,seq);
142 messfd = open_excl(pidfn);
143 if (messfd != -1) return;
144 }
145
146 die(63);
147}
148
149char *qhpsi;
150
151void qhpsiprog(char *arg)
152{
153 int wstat;
154 int child;
155 char *qhpsiargs[6] = { 0, 0, 0, 0, 0, 0 };
156 char *x;
157 unsigned long u;
158 int childrc;
159 int qhpsirc = 1;
160 unsigned int size;
161 unsigned int qhpsiminsize = 0;
162 unsigned int qhpsimaxsize = 0;
163
164 struct stat st;
165
166 if (stat(messfn,&st) == -1) die(63);
167 size = (unsigned int) st.st_size;
168
169 x = env_get("QHPSIMINSIZE");
170 if (x) { scan_ulong(x,&u); qhpsiminsize = (int) u; }
171 if (qhpsiminsize) if (size < qhpsiminsize) return;
172 x = env_get("QHPSIMAXSIZE");
173 if (x) { scan_ulong(x,&u); qhpsimaxsize = (int) u; }
174 if (qhpsimaxsize) if (size > qhpsimaxsize) return;
175
176 if (*arg) {
177 switch (child = fork()) {
178 case -1:
179 die_qhpsi();
180 case 0:
181 qhpsiargs[0] = arg;
182 qhpsiargs[1] = messfn;
183 qhpsiargs[2] = env_get("QHPSIARG1");
184 if (!qhpsiargs[2]) qhpsiargs[2] = 0;
185 qhpsiargs[3] = env_get("QHPSIARG2");
186 if (!qhpsiargs[3]) qhpsiargs[3] = 0;
187 qhpsiargs[4] = env_get("QHPSIARG3");
188 if (!qhpsiargs[4]) qhpsiargs[4] = 0;
189 x = env_get("QHPSIRC");
190 if (x) { scan_ulong(x,&u); qhpsirc = (int) u; }
191 execvp(*qhpsiargs,qhpsiargs);
192 die_qhpsi();
193 }
194 if (wait_pid(&wstat,child) == -1) die_qhpsi();
195 if (wait_crashed(wstat)) die_qhpsi();
196 childrc = wait_exitcode(wstat);
197 if (childrc == qhpsirc) { cleanup(); die(32); }
198 else if (childrc != 0) die_qhpsi();
199 }
200}
201
202char tmp[FMT_ULONG];
203
204int main()
205{
206 unsigned int len;
207 char ch;
208 int fd;
209
210 sig_blocknone();
211 umask(033);
212 if (chdir(auto_qmail) == -1) die(61);
213 if (chdir("queue") == -1) die(62);
214
215 mypid = getpid();
216 uid = getuid();
217 starttime = now();
219 qhpsi = env_get("QHPSI");
220
222
223 sig_pipeignore();
224 sig_miscignore();
225 sig_alarmcatch(sigalrm);
226 sig_bugcatch(sigbug);
227
228 alarm(DEATH);
229
230 pidopen();
231 if (fstat(messfd,&pidst) == -1) die(63);
232
233 messnum = pidst.st_ino;
234 messfn = fnnum("mess/",1);
235 todofn = fnnum("todo/",1);
236 intdfn = fnnum("intd/",1);
237
238 if (link(pidfn,messfn) == -1) die(64);
239 if (unlink(pidfn) == -1) die(63);
240 flagmademess = 1;
241
242 buffer_init(&bo,write,messfd,outbuf,sizeof(outbuf));
243 buffer_init(&bi,read,0,inbuf,sizeof(inbuf));
244
245 if (buffer_put(&bo,received,receivedlen) == -1) die_write();
246
247 switch (buffer_copy(&bo,&bi)) {
248 case -2: die_read();
249 case -3: die_write();
250 }
251 if (buffer_flush(&bo) == -1) die_write();
252 if (fsync(messfd) == -1) die_write();
253
254 intdfd = open_excl(intdfn);
255 if (intdfd == -1) die(65);
256 flagmadeintd = 1;
257
258 buffer_init(&bo,write,intdfd,outbuf,sizeof(outbuf));
259 buffer_init(&bi,read,1,inbuf,sizeof(inbuf));
260
261 if (buffer_put(&bo,"u",1) == -1) die_write();
262 if (buffer_put(&bo,tmp,fmt_ulong(tmp,uid)) == -1) die_write();
263 if (buffer_put(&bo,"",1) == -1) die_write();
264
265 if (buffer_put(&bo,"p",1) == -1) die_write();
266 if (buffer_put(&bo,tmp,fmt_ulong(tmp,mypid)) == -1) die_write();
267 if (buffer_put(&bo,"",1) == -1) die_write();
268
269 if (buffer_get(&bi,&ch,1) < 1) die_read();
270 if (ch != 'F') die(91);
271 if (buffer_put(&bo,&ch,1) == -1) die_write();
272 for (len = 0; len < ADDR; ++len) {
273 if (buffer_get(&bi,&ch,1) < 1) die_read();
274 if (buffer_put(&bo,&ch,1) == -1) die_write();
275 if (!ch) break;
276 }
277 if (len >= ADDR) die(11);
278
279 if (buffer_put(&bo,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
280
281 for (;;) {
282 if (buffer_get(&bi,&ch,1) < 1) die_read();
283 if (!ch) break;
284 if (ch == 'Q') { qhpsi = 0; break; }
285 if (ch != 'T') die(91);
286 if (buffer_put(&bo,&ch,1) == -1) die_write();
287 for (len = 0; len < ADDR; ++len) {
288 if (buffer_get(&bi,&ch,1) < 1) die_read();
289 if (buffer_put(&bo,&ch,1) == -1) die_write();
290 if (!ch) break;
291 }
292 if (len >= ADDR) die(11);
293 }
294
295 if (qhpsi) qhpsiprog(qhpsi);
296
297 if (buffer_flush(&bo) == -1) die_write();
298 if (fsync(intdfd) == -1) die_write();
299
300 if (link(intdfn,todofn) == -1) die(66);
301 if ((fd = open(todofn,O_RDONLY)) < 0 || fsync(fd) < 0 || close(fd)) die(66);
302
303 triggerpull();
304 die(0);
305}
char auto_qmail[]
int auto_uidd
int auto_uida
int auto_uids
unsigned int date822fmt(char *s, struct datetime *dt)
Definition: date822fmt.c:9
long datetime_sec
Definition: datetime.h:15
void datetime_tai()
void _exit()
#define QUEUE_EXTRA
Definition: extra.h:4
#define QUEUE_EXTRALEN
Definition: extra.h:5
unsigned int fmtqfn(char *s, char *dirslash, unsigned long id, int flagsplit)
Definition: fmtqfn.c:5
datetime_sec now()
Definition: now.c:5
int fd
int
Definition: qmail-mrtg.c:26
void die()
Definition: qmail-pop3d.c:24
unsigned long size
Definition: qmail-qread.c:55
void die_qhpsi()
Definition: qmail-queue.c:60
struct stat pidst
Definition: qmail-queue.c:37
unsigned long messnum
Definition: qmail-queue.c:38
char * qhpsi
Definition: qmail-queue.c:149
char tmp[FMT_ULONG]
Definition: qmail-queue.c:202
unsigned int pidfmt(char *s, unsigned long seq)
Definition: qmail-queue.c:102
int intdfd
Definition: qmail-queue.c:43
void sigalrm()
Definition: qmail-queue.c:63
char * todofn
Definition: qmail-queue.c:40
void cleanup()
Definition: qmail-queue.c:47
datetime_sec starttime
Definition: qmail-queue.c:32
void sigbug()
Definition: qmail-queue.c:64
unsigned long uid
Definition: qmail-queue.c:35
int flagmademess
Definition: qmail-queue.c:44
struct buffer bi
Definition: qmail-queue.c:28
void die_write()
Definition: qmail-queue.c:61
#define DEATH
Definition: qmail-queue.c:24
char * fnnum(char *dirslash, int flagsplit)
Definition: qmail-queue.c:119
char * pidfn
Definition: qmail-queue.c:36
int flagmadeintd
Definition: qmail-queue.c:45
void qhpsiprog(char *arg)
Definition: qmail-queue.c:151
void pidopen(void)
Definition: qmail-queue.c:129
void die_read()
Definition: qmail-queue.c:62
unsigned long mypid
Definition: qmail-queue.c:34
char outbuf[256]
Definition: qmail-queue.c:29
char * messfn
Definition: qmail-queue.c:39
int messfd
Definition: qmail-queue.c:42
struct buffer bo
Definition: qmail-queue.c:30
struct datetime dt
Definition: qmail-queue.c:33
#define ADDR
Definition: qmail-queue.c:25
char inbuf[2048]
Definition: qmail-queue.c:27
char * intdfn
Definition: qmail-queue.c:41
char * received
Definition: qmail-queue.c:67
int main()
Definition: qmail-queue.c:204
void received_setup()
Definition: qmail-queue.c:94
unsigned int receivedlen
Definition: qmail-queue.c:66
void write()
void triggerpull()
Definition: trigger.c:31