debian/rules: Use `git' potty wrapper.
[qmail] / qmail-queue.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include "readwrite.h"
4 #include "sig.h"
5 #include "exit.h"
6 #include "open.h"
7 #include "seek.h"
8 #include "fmt.h"
9 #include "alloc.h"
10 #include "substdio.h"
11 #include "datetime.h"
12 #include "now.h"
13 #include "triggerpull.h"
14 #include "extra.h"
15 #include "auto_qmail.h"
16 #include "auto_uids.h"
17 #include "date822fmt.h"
18 #include "fmtqfn.h"
19
20 #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
21 #define ADDR 1003
22
23 char inbuf[2048];
24 struct substdio ssin;
25 char outbuf[256];
26 struct substdio ssout;
27
28 datetime_sec starttime;
29 struct datetime dt;
30 unsigned long mypid;
31 unsigned long uid;
32 char *pidfn;
33 struct stat pidst;
34 unsigned long messnum;
35 char *messfn;
36 char *todofn;
37 char *intdfn;
38 int messfd;
39 int intdfd;
40 int flagmademess = 0;
41 int flagmadeintd = 0;
42
43 void cleanup()
44 {
45 if (flagmadeintd)
46 {
47 seek_trunc(intdfd,0);
48 if (unlink(intdfn) == -1) return;
49 }
50 if (flagmademess)
51 {
52 seek_trunc(messfd,0);
53 if (unlink(messfn) == -1) return;
54 }
55 }
56
57 void die(e) int e; { _exit(e); }
58 void die_write() { cleanup(); die(53); }
59 void die_read() { cleanup(); die(54); }
60 void sigalrm() { /* thou shalt not clean up here */ die(52); }
61 void sigbug() { die(81); }
62
63 unsigned int receivedlen;
64 char *received;
65 /* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */
66
67 static unsigned int receivedfmt(s)
68 char *s;
69 {
70 unsigned int i;
71 unsigned int len;
72 len = 0;
73 i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i;
74 i = fmt_ulong(s,mypid); len += i; if (s) s += i;
75 i = fmt_str(s," invoked "); len += i; if (s) s += i;
76 if (uid == auto_uida)
77 { i = fmt_str(s,"by alias"); len += i; if (s) s += i; }
78 else if (uid == auto_uidd)
79 { i = fmt_str(s,"from network"); len += i; if (s) s += i; }
80 else if (uid == auto_uids)
81 { i = fmt_str(s,"for bounce"); len += i; if (s) s += i; }
82 else
83 {
84 i = fmt_str(s,"by uid "); len += i; if (s) s += i;
85 i = fmt_ulong(s,uid); len += i; if (s) s += i;
86 }
87 i = fmt_str(s,"); "); len += i; if (s) s += i;
88 i = date822fmt(s,&dt); len += i; if (s) s += i;
89 return len;
90 }
91
92 void received_setup()
93 {
94 receivedlen = receivedfmt((char *) 0);
95 received = alloc(receivedlen + 1);
96 if (!received) die(51);
97 receivedfmt(received);
98 }
99
100 unsigned int pidfmt(s,seq)
101 char *s;
102 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
119 char *fnnum(dirslash,flagsplit)
120 char *dirslash;
121 int flagsplit;
122 {
123 char *s;
124
125 s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit));
126 if (!s) die(51);
127 fmtqfn(s,dirslash,messnum,flagsplit);
128 return s;
129 }
130
131 void pidopen()
132 {
133 unsigned int len;
134 unsigned long seq;
135
136 seq = 1;
137 len = pidfmt((char *) 0,seq);
138 pidfn = alloc(len);
139 if (!pidfn) die(51);
140
141 for (seq = 1;seq < 10;++seq)
142 {
143 if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
144 pidfmt(pidfn,seq);
145 messfd = open_excl(pidfn);
146 if (messfd != -1) return;
147 }
148
149 die(63);
150 }
151
152 char tmp[FMT_ULONG];
153
154 void main()
155 {
156 unsigned int len;
157 char ch;
158
159 sig_blocknone();
160 umask(033);
161 if (chdir(auto_qmail) == -1) die(61);
162 if (chdir("queue") == -1) die(62);
163
164 mypid = getpid();
165 uid = getuid();
166 starttime = now();
167 datetime_tai(&dt,starttime);
168
169 received_setup();
170
171 sig_pipeignore();
172 sig_miscignore();
173 sig_alarmcatch(sigalrm);
174 sig_bugcatch(sigbug);
175
176 alarm(DEATH);
177
178 pidopen();
179 if (fstat(messfd,&pidst) == -1) die(63);
180
181 messnum = pidst.st_ino;
182 messfn = fnnum("mess/",1);
183 todofn = fnnum("todo/",0);
184 intdfn = fnnum("intd/",0);
185
186 if (link(pidfn,messfn) == -1) die(64);
187 if (unlink(pidfn) == -1) die(63);
188 flagmademess = 1;
189
190 substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
191 substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
192
193 if (substdio_bput(&ssout,received,receivedlen) == -1) die_write();
194
195 switch(substdio_copy(&ssout,&ssin))
196 {
197 case -2: die_read();
198 case -3: die_write();
199 }
200
201 if (substdio_flush(&ssout) == -1) die_write();
202 if (fsync(messfd) == -1) die_write();
203
204 intdfd = open_excl(intdfn);
205 if (intdfd == -1) die(65);
206 flagmadeintd = 1;
207
208 substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf));
209 substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf));
210
211 if (substdio_bput(&ssout,"u",1) == -1) die_write();
212 if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,uid)) == -1) die_write();
213 if (substdio_bput(&ssout,"",1) == -1) die_write();
214
215 if (substdio_bput(&ssout,"p",1) == -1) die_write();
216 if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,mypid)) == -1) die_write();
217 if (substdio_bput(&ssout,"",1) == -1) die_write();
218
219 if (substdio_get(&ssin,&ch,1) < 1) die_read();
220 if (ch != 'F') die(91);
221 if (substdio_bput(&ssout,&ch,1) == -1) die_write();
222 for (len = 0;len < ADDR;++len)
223 {
224 if (substdio_get(&ssin,&ch,1) < 1) die_read();
225 if (substdio_put(&ssout,&ch,1) == -1) die_write();
226 if (!ch) break;
227 }
228 if (len >= ADDR) die(11);
229
230 if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
231
232 for (;;)
233 {
234 if (substdio_get(&ssin,&ch,1) < 1) die_read();
235 if (!ch) break;
236 if (ch != 'T') die(91);
237 if (substdio_bput(&ssout,&ch,1) == -1) die_write();
238 for (len = 0;len < ADDR;++len)
239 {
240 if (substdio_get(&ssin,&ch,1) < 1) die_read();
241 if (substdio_bput(&ssout,&ch,1) == -1) die_write();
242 if (!ch) break;
243 }
244 if (len >= ADDR) die(11);
245 }
246
247 if (substdio_flush(&ssout) == -1) die_write();
248 if (fsync(intdfd) == -1) die_write();
249
250 if (link(intdfn,todofn) == -1) die(66);
251
252 triggerpull();
253 die(0);
254 }