debian/rules: Use `git' potty wrapper.
[qmail] / qmail-queue.c
CommitLineData
2117e02e
MW
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
23char inbuf[2048];
24struct substdio ssin;
25char outbuf[256];
26struct substdio ssout;
27
28datetime_sec starttime;
29struct datetime dt;
30unsigned long mypid;
31unsigned long uid;
32char *pidfn;
33struct stat pidst;
34unsigned long messnum;
35char *messfn;
36char *todofn;
37char *intdfn;
38int messfd;
39int intdfd;
40int flagmademess = 0;
41int flagmadeintd = 0;
42
43void 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
57void die(e) int e; { _exit(e); }
212b6f5d
MW
58void die_write() { cleanup(); die(53); }
59void die_read() { cleanup(); die(54); }
60void sigalrm() { /* thou shalt not clean up here */ die(52); }
61void sigbug() { die(81); }
2117e02e
MW
62
63unsigned int receivedlen;
64char *received;
65/* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */
66
67static unsigned int receivedfmt(s)
68char *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
92void received_setup()
93{
94 receivedlen = receivedfmt((char *) 0);
95 received = alloc(receivedlen + 1);
212b6f5d 96 if (!received) die(51);
2117e02e
MW
97 receivedfmt(received);
98}
99
100unsigned int pidfmt(s,seq)
101char *s;
102unsigned 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(dirslash,flagsplit)
120char *dirslash;
121int flagsplit;
122{
123 char *s;
124
125 s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit));
212b6f5d 126 if (!s) die(51);
2117e02e
MW
127 fmtqfn(s,dirslash,messnum,flagsplit);
128 return s;
129}
130
131void pidopen()
132{
133 unsigned int len;
134 unsigned long seq;
135
136 seq = 1;
137 len = pidfmt((char *) 0,seq);
138 pidfn = alloc(len);
212b6f5d 139 if (!pidfn) die(51);
2117e02e
MW
140
141 for (seq = 1;seq < 10;++seq)
142 {
212b6f5d 143 if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
2117e02e
MW
144 pidfmt(pidfn,seq);
145 messfd = open_excl(pidfn);
146 if (messfd != -1) return;
147 }
148
212b6f5d 149 die(63);
2117e02e
MW
150}
151
152char tmp[FMT_ULONG];
153
154void main()
155{
156 unsigned int len;
157 char ch;
158
159 sig_blocknone();
160 umask(033);
212b6f5d
MW
161 if (chdir(auto_qmail) == -1) die(61);
162 if (chdir("queue") == -1) die(62);
2117e02e
MW
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();
212b6f5d 179 if (fstat(messfd,&pidst) == -1) die(63);
2117e02e
MW
180
181 messnum = pidst.st_ino;
182 messfn = fnnum("mess/",1);
183 todofn = fnnum("todo/",0);
184 intdfn = fnnum("intd/",0);
185
212b6f5d
MW
186 if (link(pidfn,messfn) == -1) die(64);
187 if (unlink(pidfn) == -1) die(63);
2117e02e
MW
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);
212b6f5d 205 if (intdfd == -1) die(65);
2117e02e
MW
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();
212b6f5d 220 if (ch != 'F') die(91);
2117e02e
MW
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 }
212b6f5d 228 if (len >= ADDR) die(11);
2117e02e
MW
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;
212b6f5d 236 if (ch != 'T') die(91);
2117e02e
MW
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 }
212b6f5d 244 if (len >= ADDR) die(11);
2117e02e
MW
245 }
246
247 if (substdio_flush(&ssout) == -1) die_write();
248 if (fsync(intdfd) == -1) die_write();
249
212b6f5d 250 if (link(intdfn,todofn) == -1) die(66);
2117e02e
MW
251
252 triggerpull();
253 die(0);
254}