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