Commit | Line | Data |
---|---|---|
81b7d258 EA |
1 | # include "sendmail.h" |
2 | # include <sys/stat.h> | |
ccd1d833 | 3 | # include <ndir.h> |
aba51985 | 4 | # include <signal.h> |
81b7d258 EA |
5 | # include <errno.h> |
6 | ||
884a20cb | 7 | # ifndef QUEUE |
96476cab | 8 | SCCSID(@(#)queue.c 3.35 %G% (no queueing)); |
884a20cb EA |
9 | # else QUEUE |
10 | ||
96476cab | 11 | SCCSID(@(#)queue.c 3.35 %G%); |
81b7d258 EA |
12 | |
13 | /* | |
14 | ** QUEUEUP -- queue a message up for future transmission. | |
15 | ** | |
16 | ** The queued message should already be in the correct place. | |
17 | ** This routine just outputs the control file as appropriate. | |
18 | ** | |
19 | ** Parameters: | |
dd1fe05b | 20 | ** e -- the envelope to queue up. |
d0bd03ce EA |
21 | ** queueall -- if TRUE, queue all addresses, rather than |
22 | ** just those with the QQUEUEUP flag set. | |
81b7d258 EA |
23 | ** |
24 | ** Returns: | |
25 | ** none. | |
26 | ** | |
27 | ** Side Effects: | |
28 | ** The current request (only unsatisfied addresses) | |
29 | ** are saved in a control file. | |
30 | */ | |
31 | ||
d0bd03ce | 32 | queueup(e, queueall) |
dd1fe05b | 33 | register ENVELOPE *e; |
d0bd03ce | 34 | bool queueall; |
81b7d258 | 35 | { |
2cce0c26 EA |
36 | char *tf; |
37 | char *qf; | |
9416f3a0 | 38 | char buf[MAXLINE]; |
2cce0c26 | 39 | register FILE *tfp; |
81b7d258 | 40 | register HDR *h; |
d4f42161 | 41 | register ADDRESS *q; |
808ac89b | 42 | register int i; |
81b7d258 | 43 | |
9ccf54c4 EA |
44 | /* |
45 | ** Create control file. | |
46 | */ | |
81b7d258 | 47 | |
2cce0c26 EA |
48 | tf = newstr(queuename(e, 't')); |
49 | tfp = fopen(tf, "w"); | |
50 | if (tfp == NULL) | |
81b7d258 | 51 | { |
2cce0c26 | 52 | syserr("queueup: cannot create temp file %s", tf); |
81b7d258 EA |
53 | return; |
54 | } | |
2cce0c26 | 55 | (void) chmod(tf, 0600); |
81b7d258 EA |
56 | |
57 | # ifdef DEBUG | |
9678c96d | 58 | if (tTd(40, 1)) |
2cce0c26 | 59 | printf("queueing in %s\n", tf); |
81b7d258 EA |
60 | # endif DEBUG |
61 | ||
dd1fe05b EA |
62 | /* |
63 | ** If there is no data file yet, create one. | |
64 | */ | |
65 | ||
66 | if (e->e_df == NULL) | |
67 | { | |
68 | register FILE *dfp; | |
69 | ||
2cce0c26 | 70 | e->e_df = newstr(queuename(e, 'd')); |
dd1fe05b EA |
71 | dfp = fopen(e->e_df, "w"); |
72 | if (dfp == NULL) | |
73 | { | |
74 | syserr("queueup: cannot create %s", e->e_df); | |
2cce0c26 | 75 | (void) fclose(tfp); |
dd1fe05b EA |
76 | return; |
77 | } | |
c3eff282 | 78 | (void) chmod(e->e_df, 0600); |
dd1fe05b | 79 | (*e->e_putbody)(dfp, Mailer[1], FALSE); |
f9566d23 | 80 | (void) fclose(dfp); |
dd1fe05b EA |
81 | } |
82 | ||
81b7d258 EA |
83 | /* |
84 | ** Output future work requests. | |
85 | */ | |
86 | ||
87 | /* output name of data file */ | |
2cce0c26 | 88 | fprintf(tfp, "D%s\n", e->e_df); |
81b7d258 EA |
89 | |
90 | /* output name of sender */ | |
2cce0c26 | 91 | fprintf(tfp, "S%s\n", e->e_from.q_paddr); |
81b7d258 | 92 | |
96476cab EA |
93 | /* output creation time */ |
94 | fprintf(tfp, "T%ld\n", e->e_ctime); | |
81b7d258 | 95 | |
aba51985 | 96 | /* output message priority */ |
2cce0c26 | 97 | fprintf(tfp, "P%ld\n", e->e_msgpriority); |
dd1fe05b EA |
98 | |
99 | /* output message class */ | |
2cce0c26 | 100 | fprintf(tfp, "C%d\n", e->e_class); |
aba51985 | 101 | |
808ac89b | 102 | /* output macro definitions */ |
9416f3a0 | 103 | /* I don't think this is needed any more..... |
808ac89b EA |
104 | for (i = 0; i < 128; i++) |
105 | { | |
dd1fe05b | 106 | register char *p = e->e_macro[i]; |
808ac89b EA |
107 | |
108 | if (p != NULL && i != (int) 'b') | |
2cce0c26 | 109 | fprintf(tfp, "M%c%s\n", i, p); |
808ac89b | 110 | } |
9416f3a0 | 111 | ..... */ |
808ac89b | 112 | |
81b7d258 | 113 | /* output list of recipient addresses */ |
dd1fe05b | 114 | for (q = e->e_sendqueue; q != NULL; q = q->q_next) |
81b7d258 | 115 | { |
9ccf54c4 | 116 | # ifdef DEBUG |
9678c96d | 117 | if (tTd(40, 1)) |
9ccf54c4 EA |
118 | { |
119 | printf("queueing "); | |
120 | printaddr(q, FALSE); | |
121 | } | |
122 | # endif DEBUG | |
9416f3a0 EA |
123 | if (queueall ? !bitset(QDONTSEND, q->q_flags) : |
124 | bitset(QQUEUEUP, q->q_flags)) | |
2cce0c26 | 125 | fprintf(tfp, "R%s\n", q->q_paddr); |
81b7d258 EA |
126 | } |
127 | ||
128 | /* output headers for this message */ | |
9416f3a0 | 129 | define('g', "$f"); |
dd1fe05b | 130 | for (h = e->e_header; h != NULL; h = h->h_link) |
81b7d258 EA |
131 | { |
132 | if (h->h_value == NULL || h->h_value[0] == '\0') | |
133 | continue; | |
2cce0c26 | 134 | fprintf(tfp, "H"); |
81b7d258 | 135 | if (h->h_mflags != 0 && bitset(H_CHECK|H_ACHECK, h->h_flags)) |
2cce0c26 EA |
136 | mfdecode(h->h_mflags, tfp); |
137 | fprintf(tfp, "%s: ", h->h_field); | |
9416f3a0 EA |
138 | if (bitset(H_DEFAULT, h->h_flags)) |
139 | { | |
140 | (void) expand(h->h_value, buf, &buf[sizeof buf], e); | |
2cce0c26 | 141 | fprintf(tfp, "%s\n", buf); |
9416f3a0 EA |
142 | } |
143 | else | |
2cce0c26 | 144 | fprintf(tfp, "%s\n", h->h_value); |
81b7d258 EA |
145 | } |
146 | ||
147 | /* | |
148 | ** Clean up. | |
149 | */ | |
150 | ||
2cce0c26 EA |
151 | (void) fclose(tfp); |
152 | qf = queuename(e, 'q'); | |
153 | (void) unlink(qf); | |
154 | if (link(tf, qf) < 0) | |
155 | syserr("cannot link(%s, %s), df=%s", tf, qf, e->e_df); | |
dd1fe05b | 156 | else |
2cce0c26 EA |
157 | (void) unlink(tf); |
158 | e->e_qf = NULL; | |
1a13ccd8 | 159 | |
9678c96d EA |
160 | # ifdef LOG |
161 | /* save log info */ | |
162 | if (LogLevel > 9) | |
2cce0c26 | 163 | syslog(LOG_INFO, "%s queueup: qf=%s, df=%s\n", e->e_id, qf, e->e_df); |
9678c96d EA |
164 | # endif LOG |
165 | ||
1a13ccd8 EA |
166 | /* disconnect this temp file from the job */ |
167 | e->e_df = NULL; | |
81b7d258 EA |
168 | } |
169 | \f/* | |
170 | ** RUNQUEUE -- run the jobs in the queue. | |
171 | ** | |
172 | ** Gets the stuff out of the queue in some presumably logical | |
173 | ** order and processes them. | |
174 | ** | |
175 | ** Parameters: | |
176 | ** none. | |
177 | ** | |
178 | ** Returns: | |
179 | ** none. | |
180 | ** | |
181 | ** Side Effects: | |
182 | ** runs things in the mail queue. | |
183 | */ | |
184 | ||
2cf55cb7 EA |
185 | bool ReorderQueue; /* if set, reorder the send queue */ |
186 | int QueuePid; /* pid of child running queue */ | |
aba51985 | 187 | |
2cf55cb7 EA |
188 | runqueue(forkflag) |
189 | bool forkflag; | |
81b7d258 | 190 | { |
aba51985 | 191 | extern reordersig(); |
81b7d258 | 192 | |
b6dffdf5 EA |
193 | /* |
194 | ** See if we want to go off and do other useful work. | |
195 | */ | |
2cf55cb7 EA |
196 | |
197 | if (forkflag) | |
198 | { | |
199 | QueuePid = dofork(); | |
200 | if (QueuePid > 0) | |
201 | { | |
202 | /* parent */ | |
c4442979 EA |
203 | if (QueueIntvl != 0) |
204 | setevent(QueueIntvl, reordersig, TRUE); | |
2cf55cb7 EA |
205 | return; |
206 | } | |
b6dffdf5 | 207 | } |
81b7d258 | 208 | |
b6dffdf5 EA |
209 | /* |
210 | ** Start making passes through the queue. | |
211 | ** First, read and sort the entire queue. | |
212 | ** Then, process the work in that order. | |
213 | ** But if you take too long, start over. | |
214 | ** There is a race condition at the end -- we could get | |
215 | ** a reorder signal after finishing the queue. | |
216 | ** In this case we will hang for one more queue | |
217 | ** interval -- clearly a botch, but rare and | |
218 | ** relatively innocuous. | |
219 | */ | |
81b7d258 | 220 | |
b6dffdf5 EA |
221 | for (;;) |
222 | { | |
223 | /* order the existing work requests */ | |
224 | orderq(); | |
c4442979 EA |
225 | |
226 | /* arrange to reorder later */ | |
aba51985 | 227 | ReorderQueue = FALSE; |
c4442979 EA |
228 | if (QueueIntvl != 0) |
229 | setevent(QueueIntvl, reordersig, FALSE); | |
aba51985 | 230 | |
b6dffdf5 | 231 | /* process them once at a time */ |
aba51985 EA |
232 | while (WorkQ != NULL) |
233 | { | |
234 | WORK *w = WorkQ; | |
235 | ||
236 | WorkQ = WorkQ->w_next; | |
237 | dowork(w); | |
238 | free(w->w_name); | |
239 | free((char *) w); | |
240 | if (ReorderQueue) | |
241 | break; | |
242 | } | |
243 | ||
b6dffdf5 | 244 | /* if we are just doing one pass, then we are done */ |
aba51985 | 245 | if (QueueIntvl == 0) |
c4442979 | 246 | finis(); |
b6dffdf5 EA |
247 | |
248 | /* wait for work -- note (harmless) race condition here */ | |
c4442979 EA |
249 | while (!ReorderQueue) |
250 | { | |
251 | if (forkflag) | |
252 | finis(); | |
b6dffdf5 | 253 | pause(); |
c4442979 | 254 | } |
81b7d258 EA |
255 | } |
256 | } | |
257 | \f/* | |
c4442979 | 258 | ** REORDERSIG -- catch the reorder signal and tell sendmail to reorder queue. |
aba51985 EA |
259 | ** |
260 | ** Parameters: | |
c4442979 EA |
261 | ** parent -- if set, called from parent (i.e., not |
262 | ** really doing the work). | |
aba51985 EA |
263 | ** |
264 | ** Returns: | |
265 | ** none. | |
266 | ** | |
267 | ** Side Effects: | |
268 | ** sets the "reorder work queue" flag. | |
269 | */ | |
270 | ||
c4442979 EA |
271 | reordersig(parent) |
272 | bool parent; | |
aba51985 | 273 | { |
c4442979 | 274 | if (!parent) |
2cf55cb7 EA |
275 | { |
276 | /* we are in a child doing queueing */ | |
277 | ReorderQueue = TRUE; | |
278 | } | |
279 | else | |
280 | { | |
c4442979 EA |
281 | /* |
282 | ** In parent. If the child still exists, we want | |
283 | ** to do nothing. If the child is gone, we will | |
284 | ** start up a new one. | |
285 | ** If the child exists, it is responsible for | |
286 | ** doing a queue reorder. | |
287 | ** This code really sucks. | |
288 | */ | |
289 | ||
2cf55cb7 EA |
290 | if (kill(QueuePid, SIGALRM) < 0) |
291 | { | |
292 | /* no child -- get zombie & start new one */ | |
293 | static int st; | |
294 | ||
62fff4f9 | 295 | (void) wait(&st); |
c4442979 | 296 | runqueue(TRUE); |
2cf55cb7 EA |
297 | } |
298 | } | |
299 | ||
300 | /* | |
301 | ** Arrange to get this signal again. | |
302 | */ | |
303 | ||
c4442979 | 304 | setevent(QueueIntvl, reordersig, parent); |
aba51985 EA |
305 | } |
306 | \f/* | |
81b7d258 EA |
307 | ** ORDERQ -- order the work queue. |
308 | ** | |
309 | ** Parameters: | |
310 | ** none. | |
311 | ** | |
312 | ** Returns: | |
313 | ** none. | |
314 | ** | |
315 | ** Side Effects: | |
316 | ** Sets WorkQ to the queue of available work, in order. | |
317 | */ | |
318 | ||
319 | # define WLSIZE 120 /* max size of worklist per sort */ | |
320 | ||
321 | orderq() | |
322 | { | |
ccd1d833 | 323 | register struct direct *d; |
81b7d258 EA |
324 | register WORK *w; |
325 | register WORK **wp; /* parent of w */ | |
ccd1d833 | 326 | DIR *f; |
81b7d258 | 327 | register int i; |
81b7d258 EA |
328 | WORK wlist[WLSIZE]; |
329 | int wn = 0; | |
330 | extern workcmpf(); | |
331 | extern char *QueueDir; | |
332 | ||
333 | /* clear out old WorkQ */ | |
334 | for (w = WorkQ; w != NULL; ) | |
335 | { | |
336 | register WORK *nw = w->w_next; | |
337 | ||
338 | WorkQ = nw; | |
339 | free(w->w_name); | |
340 | free((char *) w); | |
341 | w = nw; | |
342 | } | |
343 | ||
344 | /* open the queue directory */ | |
ccd1d833 | 345 | f = opendir(QueueDir); |
81b7d258 EA |
346 | if (f == NULL) |
347 | { | |
348 | syserr("orderq: cannot open %s", QueueDir); | |
349 | return; | |
350 | } | |
351 | ||
352 | /* | |
353 | ** Read the work directory. | |
354 | */ | |
355 | ||
ccd1d833 | 356 | while (wn < WLSIZE && (d = readdir(f)) != NULL) |
81b7d258 EA |
357 | { |
358 | char cbuf[MAXNAME]; | |
359 | char lbuf[MAXNAME]; | |
360 | FILE *cf; | |
361 | register char *p; | |
362 | ||
363 | /* is this an interesting entry? */ | |
2cce0c26 | 364 | if (d->d_name[0] != 'q' || d->d_name[1] != 'f') |
81b7d258 EA |
365 | continue; |
366 | ||
367 | /* yes -- find the control file location */ | |
f9566d23 EA |
368 | (void) strcpy(cbuf, QueueDir); |
369 | (void) strcat(cbuf, "/"); | |
81b7d258 | 370 | p = &cbuf[strlen(cbuf)]; |
f9566d23 | 371 | (void) strcpy(p, d->d_name); |
81b7d258 EA |
372 | |
373 | /* open control file */ | |
374 | cf = fopen(cbuf, "r"); | |
375 | if (cf == NULL) | |
376 | { | |
91f69adf EA |
377 | /* this may be some random person sending hir msgs */ |
378 | /* syserr("orderq: cannot open %s", cbuf); */ | |
379 | errno = 0; | |
81b7d258 EA |
380 | continue; |
381 | } | |
9ccf54c4 | 382 | wlist[wn].w_name = newstr(cbuf); |
81b7d258 EA |
383 | |
384 | /* extract useful information */ | |
81b7d258 EA |
385 | while (fgets(lbuf, sizeof lbuf, cf) != NULL) |
386 | { | |
387 | fixcrlf(lbuf, TRUE); | |
388 | ||
389 | switch (lbuf[0]) | |
390 | { | |
81b7d258 | 391 | case 'P': /* message priority */ |
9ccf54c4 | 392 | (void) sscanf(&lbuf[1], "%ld", &wlist[wn].w_pri); |
81b7d258 EA |
393 | break; |
394 | } | |
395 | } | |
396 | wn++; | |
397 | (void) fclose(cf); | |
398 | } | |
ccd1d833 | 399 | (void) closedir(f); |
81b7d258 EA |
400 | |
401 | /* | |
402 | ** Sort the work directory. | |
403 | */ | |
404 | ||
405 | qsort(wlist, wn, sizeof *wlist, workcmpf); | |
406 | ||
407 | /* | |
408 | ** Convert the work list into canonical form. | |
409 | */ | |
410 | ||
411 | wp = &WorkQ; | |
412 | for (i = 0; i < wn; i++) | |
413 | { | |
414 | w = (WORK *) xalloc(sizeof *w); | |
415 | w->w_name = wlist[i].w_name; | |
81b7d258 EA |
416 | w->w_pri = wlist[i].w_pri; |
417 | w->w_next = NULL; | |
418 | *wp = w; | |
419 | wp = &w->w_next; | |
420 | } | |
421 | ||
422 | # ifdef DEBUG | |
9678c96d | 423 | if (tTd(40, 1)) |
81b7d258 EA |
424 | { |
425 | for (w = WorkQ; w != NULL; w = w->w_next) | |
9ccf54c4 | 426 | printf("%32s: pri=%ld\n", w->w_name, w->w_pri); |
81b7d258 EA |
427 | } |
428 | # endif DEBUG | |
429 | } | |
430 | \f/* | |
9678c96d | 431 | ** WORKCMPF -- compare function for ordering work. |
81b7d258 EA |
432 | ** |
433 | ** Parameters: | |
434 | ** a -- the first argument. | |
435 | ** b -- the second argument. | |
436 | ** | |
437 | ** Returns: | |
438 | ** -1 if a < b | |
439 | ** 0 if a == b | |
440 | ** 1 if a > b | |
441 | ** | |
442 | ** Side Effects: | |
443 | ** none. | |
444 | */ | |
445 | ||
446 | # define PRIFACT 1800 /* bytes each priority point is worth */ | |
447 | ||
448 | workcmpf(a, b) | |
9ccf54c4 EA |
449 | register WORK *a; |
450 | register WORK *b; | |
81b7d258 | 451 | { |
9ccf54c4 | 452 | if (a->w_pri == b->w_pri) |
81b7d258 | 453 | return (0); |
9ccf54c4 | 454 | else if (a->w_pri > b->w_pri) |
81b7d258 EA |
455 | return (1); |
456 | else | |
457 | return (-1); | |
458 | } | |
459 | \f/* | |
460 | ** DOWORK -- do a work request. | |
461 | ** | |
462 | ** Parameters: | |
463 | ** w -- the work request to be satisfied. | |
464 | ** | |
465 | ** Returns: | |
466 | ** none. | |
467 | ** | |
468 | ** Side Effects: | |
469 | ** The work request is satisfied if possible. | |
470 | */ | |
471 | ||
472 | dowork(w) | |
473 | register WORK *w; | |
474 | { | |
475 | register int i; | |
476 | auto int xstat; | |
477 | ||
478 | # ifdef DEBUG | |
9678c96d | 479 | if (tTd(40, 1)) |
9ccf54c4 | 480 | printf("dowork: %s pri %ld\n", w->w_name, w->w_pri); |
81b7d258 EA |
481 | # endif DEBUG |
482 | ||
483 | /* | |
484 | ** Fork for work. | |
485 | */ | |
486 | ||
487 | i = fork(); | |
488 | if (i < 0) | |
489 | { | |
490 | syserr("dowork: cannot fork"); | |
491 | return; | |
492 | } | |
493 | ||
494 | if (i == 0) | |
495 | { | |
dd1fe05b EA |
496 | char buf[MAXNAME]; |
497 | ||
81b7d258 EA |
498 | /* |
499 | ** CHILD | |
dd1fe05b | 500 | ** Change the name of the control file to avoid |
68f0b54c EA |
501 | ** duplicate deliveries. Then run the file |
502 | ** as though we had just read it. | |
503 | ** We save an idea of the temporary name so we | |
504 | ** can recover on interrupt. | |
81b7d258 EA |
505 | */ |
506 | ||
9416f3a0 | 507 | /* set basic modes, etc. */ |
37eaaadb | 508 | (void) alarm(0); |
16671f5a | 509 | FatalErrors = FALSE; |
81b7d258 | 510 | QueueRun = TRUE; |
1ff06f70 | 511 | MailBack = TRUE; |
2cce0c26 EA |
512 | CurEnv->e_qf = w->w_name; |
513 | CurEnv->e_id = &w->w_name[strlen(QueueDir) + 3]; | |
9416f3a0 EA |
514 | |
515 | /* don't use the headers from sendmail.cf... */ | |
516 | CurEnv->e_header = NULL; | |
517 | chompheader("from: $q", TRUE); | |
518 | ||
519 | /* create the link to the control file during processing */ | |
2cce0c26 | 520 | if (link(w->w_name, queuename(CurEnv, 'l')) < 0) |
dd1fe05b | 521 | { |
2cce0c26 | 522 | /* being processed by another queuer */ |
dd1fe05b EA |
523 | exit(EX_OK); |
524 | } | |
dd1fe05b EA |
525 | |
526 | /* create ourselves a transcript file */ | |
aba51985 | 527 | openxscrpt(); |
dd1fe05b EA |
528 | |
529 | /* do basic system initialization */ | |
81b7d258 | 530 | initsys(); |
dd1fe05b EA |
531 | |
532 | /* read the queue control file */ | |
2cce0c26 | 533 | readqf(CurEnv->e_qf); |
dd6ec29b | 534 | eatheader(); |
dd1fe05b EA |
535 | |
536 | /* do the delivery */ | |
a5a315e5 EA |
537 | if (!FatalErrors) |
538 | sendall(CurEnv, FALSE); | |
dd1fe05b EA |
539 | |
540 | /* if still not sent, perhaps we should time out.... */ | |
aba51985 | 541 | # ifdef DEBUG |
9678c96d | 542 | if (tTd(40, 3)) |
96476cab EA |
543 | printf("CurTime=%ld, TimeOut=%ld\n", CurTime, |
544 | CurEnv->e_ctime + TimeOut); | |
aba51985 | 545 | # endif DEBUG |
96476cab | 546 | if (CurEnv->e_queueup && CurTime > CurEnv->e_ctime + TimeOut) |
aba51985 | 547 | timeout(w); |
dd1fe05b | 548 | |
dd1fe05b | 549 | /* finish up and exit */ |
81b7d258 EA |
550 | finis(); |
551 | } | |
552 | ||
553 | /* | |
554 | ** Parent -- pick up results. | |
555 | */ | |
556 | ||
557 | errno = 0; | |
558 | while ((i = wait(&xstat)) > 0 && errno != EINTR) | |
559 | { | |
560 | if (errno == EINTR) | |
561 | { | |
562 | errno = 0; | |
563 | } | |
564 | } | |
565 | } | |
566 | \f/* | |
567 | ** READQF -- read queue file and set up environment. | |
568 | ** | |
569 | ** Parameters: | |
570 | ** cf -- name of queue control file. | |
571 | ** | |
572 | ** Returns: | |
573 | ** none. | |
574 | ** | |
575 | ** Side Effects: | |
576 | ** cf is read and created as the current job, as though | |
577 | ** we had been invoked by argument. | |
578 | */ | |
579 | ||
580 | readqf(cf) | |
581 | char *cf; | |
582 | { | |
583 | register FILE *f; | |
6a86d693 | 584 | char buf[MAXFIELD]; |
d08bed81 EA |
585 | register char *p; |
586 | register int i; | |
abae7b2d | 587 | extern ADDRESS *sendto(); |
81b7d258 EA |
588 | |
589 | /* | |
590 | ** Open the file created by queueup. | |
591 | */ | |
592 | ||
593 | f = fopen(cf, "r"); | |
594 | if (f == NULL) | |
595 | { | |
596 | syserr("readqf: no cf file %s", cf); | |
597 | return; | |
598 | } | |
599 | ||
600 | /* | |
601 | ** Read and process the file. | |
602 | */ | |
603 | ||
37eaaadb EA |
604 | if (Verbose) |
605 | printf("\nRunning %s\n", cf); | |
6a86d693 | 606 | while (fgetfolded(buf, sizeof buf, f) != NULL) |
81b7d258 | 607 | { |
81b7d258 EA |
608 | switch (buf[0]) |
609 | { | |
610 | case 'R': /* specify recipient */ | |
abae7b2d | 611 | (void) sendto(&buf[1], 1, (ADDRESS *) NULL, 0); |
81b7d258 EA |
612 | break; |
613 | ||
614 | case 'H': /* header */ | |
615 | (void) chompheader(&buf[1], FALSE); | |
616 | break; | |
617 | ||
618 | case 'S': /* sender */ | |
aba51985 | 619 | setsender(newstr(&buf[1])); |
81b7d258 EA |
620 | break; |
621 | ||
622 | case 'D': /* data file name */ | |
1ff06f70 EA |
623 | CurEnv->e_df = newstr(&buf[1]); |
624 | TempFile = fopen(CurEnv->e_df, "r"); | |
81b7d258 | 625 | if (TempFile == NULL) |
1ff06f70 | 626 | syserr("readqf: cannot open %s", CurEnv->e_df); |
81b7d258 EA |
627 | break; |
628 | ||
96476cab EA |
629 | case 'T': /* init time */ |
630 | (void) sscanf(&buf[1], "%ld", &CurEnv->e_ctime); | |
81b7d258 EA |
631 | break; |
632 | ||
aba51985 | 633 | case 'P': /* message priority */ |
2654b031 | 634 | (void) sscanf(&buf[1], "%ld", &CurEnv->e_msgpriority); |
9ccf54c4 EA |
635 | |
636 | /* make sure that big things get sent eventually */ | |
2654b031 | 637 | CurEnv->e_msgpriority -= WKTIMEFACT; |
aba51985 EA |
638 | break; |
639 | ||
dd1fe05b EA |
640 | case 'C': /* message class */ |
641 | (void) sscanf(&buf[1], "%hd", &CurEnv->e_class); | |
642 | break; | |
643 | ||
808ac89b EA |
644 | case 'M': /* define macro */ |
645 | define(buf[1], newstr(&buf[2])); | |
646 | break; | |
647 | ||
81b7d258 EA |
648 | default: |
649 | syserr("readqf(%s): bad line \"%s\"", cf, buf); | |
650 | break; | |
651 | } | |
652 | } | |
653 | } | |
654 | \f/* | |
655 | ** TIMEOUT -- process timeout on queue file. | |
656 | ** | |
657 | ** Parameters: | |
658 | ** w -- pointer to work request that timed out. | |
659 | ** | |
660 | ** Returns: | |
661 | ** none. | |
662 | ** | |
663 | ** Side Effects: | |
664 | ** Returns a message to the sender saying that this | |
665 | ** message has timed out. | |
666 | */ | |
667 | ||
668 | timeout(w) | |
669 | register WORK *w; | |
670 | { | |
42c2dff8 | 671 | char buf[MAXLINE]; |
96476cab | 672 | extern char *pintvl(); |
42c2dff8 | 673 | |
aba51985 | 674 | # ifdef DEBUG |
9678c96d | 675 | if (tTd(40, 3)) |
aba51985 EA |
676 | printf("timeout(%s)\n", w->w_name); |
677 | # endif DEBUG | |
1ff06f70 | 678 | message(Arpa_Info, "Message has timed out"); |
aba51985 EA |
679 | |
680 | /* return message to sender */ | |
96476cab | 681 | (void) sprintf(buf, "Cannot send mail for %s", pintvl(TimeOut, FALSE)); |
42c2dff8 | 682 | (void) returntosender(buf, &CurEnv->e_from, TRUE); |
aba51985 EA |
683 | |
684 | /* arrange to remove files from queue */ | |
96476cab | 685 | CurEnv->e_dontqueue = TRUE; |
81b7d258 | 686 | } |
884a20cb EA |
687 | |
688 | # endif QUEUE |