Commit | Line | Data |
---|---|---|
b3cbe40f EA |
1 | # include <stdio.h> |
2 | # include <signal.h> | |
3 | # include <ctype.h> | |
4 | # include "dlvrmail.h" | |
5 | # ifdef LOG | |
6 | # include <log.h> | |
7 | # endif LOG | |
8 | ||
916b3375 EA |
9 | static char SccsId[] = "@(#)main.c 1.4 %G%"; |
10 | ||
b3cbe40f EA |
11 | /* |
12 | ** DELIVERMAIL -- Deliver mail to a set of destinations | |
13 | ** | |
14 | ** This is the basic mail router. All user mail programs should | |
15 | ** call this routine to actually deliver mail. Delivermail in | |
16 | ** turn calls a bunch of mail servers that do the real work of | |
17 | ** delivering the mail. | |
18 | ** | |
19 | ** Delivermail is driven by tables defined in config.c. This | |
20 | ** file will be different from system to system, but the rest | |
21 | ** of the code will be the same. This table could be read in, | |
22 | ** but it seemed nicer to have it compiled in, since deliver- | |
23 | ** mail will potentially be exercised a lot. | |
24 | ** | |
25 | ** Usage: | |
26 | ** /etc/delivermail [-f name] [-a] [-q] [-v] [-n] [-m] addr ... | |
27 | ** | |
28 | ** Positional Parameters: | |
29 | ** addr -- the address to deliver the mail to. There | |
30 | ** can be several. | |
31 | ** | |
32 | ** Flags: | |
33 | ** -f name The mail is from "name" -- used for | |
34 | ** the header in local mail, and to | |
35 | ** deliver reports of failures to. | |
36 | ** -r name Same as -f; however, this flag is | |
37 | ** reserved to indicate special processing | |
38 | ** for remote mail delivery as needed | |
39 | ** in the future. So, network servers | |
40 | ** should use -r. | |
41 | ** -a This mail should be in ARPANET std | |
42 | ** format (not used). | |
43 | ** -n Don't do aliasing. This might be used | |
44 | ** when delivering responses, for | |
45 | ** instance. | |
46 | ** -d Run in debug mode. | |
47 | ** -em Mail back a response if there was an | |
48 | ** error in processing. This should be | |
49 | ** used when the origin of this message | |
50 | ** is another machine. | |
51 | ** -ew Write back a response if the user is | |
52 | ** still logged in, otherwise, act like | |
53 | ** -em. | |
54 | ** -eq Don't print any error message (just | |
55 | ** return exit status). | |
56 | ** -ep (default) Print error messages | |
57 | ** normally. | |
3b661a43 EA |
58 | ** -ee Send BerkNet style errors. This |
59 | ** is equivalent to MailBack except | |
60 | ** that it has gives zero return code | |
61 | ** (unless there were errors during | |
62 | ** returning). This used to be | |
63 | ** "EchoBack", but you know how the old | |
64 | ** software bounces. | |
b3cbe40f EA |
65 | ** -m In group expansion, send to the |
66 | ** sender also (stands for the Mail metoo | |
67 | ** option. | |
68 | ** -i Do not terminate mail on a line | |
69 | ** containing just dot. | |
70 | ** -s Save UNIX-like "From" lines on the | |
71 | ** front of messages. | |
72 | ** | |
73 | ** Return Codes: | |
74 | ** As defined in <sysexits.h>. | |
75 | ** | |
76 | ** These codes are actually returned from the auxiliary | |
77 | ** mailers; it is their responsibility to make them | |
78 | ** correct. | |
79 | ** | |
80 | ** Defined Constants: | |
81 | ** none | |
82 | ** | |
83 | ** Compilation Flags: | |
84 | ** BADMAIL -- the mailer used for local mail doesn't | |
85 | ** return the standard set of exit codes. This | |
86 | ** causes the name to be looked up before mail | |
87 | ** is ever sent. | |
88 | ** LOG -- if set, everything is logged. | |
89 | ** MESSAGEID -- if set, the Message-Id field is added | |
90 | ** to the message header if one does not already | |
91 | ** exist. This can be used to delete duplicate | |
92 | ** messages. | |
93 | ** | |
94 | ** Compilation Instructions: | |
95 | ** cc -c -O main.c config.c deliver.c parse.c | |
96 | ** cc -n -s *.o -lS | |
97 | ** chown root a.out | |
98 | ** chmod 755 a.out | |
99 | ** mv a.out delivermail | |
100 | ** | |
101 | ** Requires: | |
102 | ** signal (sys) | |
103 | ** setbuf (sys) | |
104 | ** initlog (libX) | |
105 | ** open (sys) | |
106 | ** lseek (sys) | |
107 | ** close (sys) | |
108 | ** dup (sys) | |
109 | ** printf (sys) | |
110 | ** syserr | |
111 | ** atoi (sys) | |
112 | ** freopen (sys) | |
113 | ** openxscript | |
114 | ** maketemp | |
115 | ** getname | |
116 | ** strcmp (sys) | |
117 | ** getuid (sys) | |
118 | ** parse | |
119 | ** usrerr | |
120 | ** finis | |
121 | ** sendto | |
122 | ** alias | |
123 | ** recipient | |
124 | ** nxtinq | |
125 | ** deliver | |
126 | ** | |
127 | ** Deficiencies: | |
128 | ** It ought to collect together messages that are | |
129 | ** destined for a single host and send these | |
130 | ** to the auxiliary mail server together. | |
131 | ** It should take "user at host" as three separate | |
132 | ** parameters and combine them into one address. | |
133 | ** | |
134 | ** Author: | |
135 | ** Eric Allman, UCB/INGRES | |
136 | ** | |
137 | ** History: | |
138 | ** 12/26/79 -- first written. | |
139 | */ | |
140 | ||
141 | ||
142 | ||
143 | ||
144 | ||
145 | char ArpaFmt; /* mail is expected to be in ARPANET format */ | |
146 | char FromFlag; /* from person is explicitly specified */ | |
147 | char Debug; /* run in debug mode */ | |
148 | char MailBack; /* mail back response on error */ | |
3b661a43 | 149 | char BerkNet; /* called from BerkNet */ |
b3cbe40f EA |
150 | char WriteBack; /* write back response on error */ |
151 | char HasXscrpt; /* if set, the transcript file exists */ | |
152 | char NoAlias; /* don't do aliasing */ | |
153 | char ForceMail; /* mail even if already sent a copy */ | |
154 | char MeToo; /* send to the sender also if in a group expansion */ | |
155 | char SaveFrom; /* save From lines on the front of messages */ | |
156 | char IgnrDot; /* if set, ignore dot when collecting mail */ | |
157 | char Error; /* set if errors */ | |
158 | char SuprErrs; /* supress errors if set */ | |
159 | char InFileName[] = "/tmp/mailtXXXXXX"; | |
160 | char Transcript[] = "/tmp/mailxXXXXXX"; | |
161 | addrq From; /* the from person */ | |
162 | char *To; /* the target person */ | |
163 | char MsgId[MAXNAME]; /* the message-id for this letter */ | |
164 | int HopCount; /* hop count */ | |
165 | int ExitStat; /* the exit status byte */ | |
166 | addrq SendQ; /* queue of people to send to */ | |
167 | addrq AliasQ; /* queue of people who turned out to be aliases */ | |
168 | ||
169 | ||
170 | ||
171 | ||
172 | ||
173 | ||
174 | main(argc, argv) | |
175 | int argc; | |
176 | char **argv; | |
177 | { | |
178 | register char *p; | |
179 | extern char *maketemp(); | |
180 | extern char *getname(); | |
181 | extern int finis(); | |
182 | extern addrq *parse(); | |
183 | register addrq *q; | |
184 | extern char Version[]; | |
185 | extern int errno; | |
186 | char *from; | |
187 | register int i; | |
188 | typedef int (*fnptr)(); | |
189 | ||
190 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) | |
191 | signal(SIGINT, finis); | |
192 | signal(SIGTERM, finis); | |
193 | setbuf(stdout, (char *) NULL); | |
194 | # ifdef LOG | |
195 | initlog("delivermail", 0, LOG_INDEP); | |
196 | # endif LOG | |
197 | # ifdef DEBUG | |
198 | # ifdef DEBUGFILE | |
199 | if ((i = open(DEBUGFILE, 1)) > 0) | |
200 | { | |
201 | lseek(i, 0L, 2); | |
202 | close(1); | |
203 | dup(i); | |
204 | close(i); | |
205 | Debug++; | |
206 | } | |
207 | # endif DEBUGFILE | |
208 | if (Debug) | |
209 | printf("%s\n", Version); | |
210 | # endif | |
211 | errno = 0; | |
212 | from = NULL; | |
213 | ||
214 | /* | |
215 | ** Crack argv. | |
216 | */ | |
217 | ||
218 | while (--argc > 0 && (p = *++argv)[0] == '-') | |
219 | { | |
220 | switch (p[1]) | |
221 | { | |
222 | case 'r': /* obsolete -f flag */ | |
223 | case 'f': /* from address */ | |
224 | p += 2; | |
225 | if (*p == '\0') | |
226 | { | |
227 | p = *++argv; | |
228 | if (--argc <= 0 || *p == '-') | |
229 | { | |
230 | syserr("No \"from\" person"); | |
231 | argc++; | |
232 | argv--; | |
233 | break; | |
234 | } | |
235 | } | |
236 | if (from != NULL) | |
237 | { | |
238 | syserr("More than one \"from\" person"); | |
239 | break; | |
240 | } | |
241 | from = p; | |
242 | break; | |
243 | ||
244 | case 'h': /* hop count */ | |
245 | p += 2; | |
246 | if (*p == '\0') | |
247 | { | |
248 | p = *++argv; | |
249 | if (--argc <= 0 || *p < '0' || *p > '9') | |
250 | { | |
251 | syserr("Bad hop count (%s)", p); | |
252 | argc++; | |
253 | argv--; | |
254 | break; | |
255 | } | |
256 | } | |
257 | HopCount = atoi(p); | |
258 | break; | |
259 | ||
260 | case 'e': /* error message disposition */ | |
261 | switch (p[2]) | |
262 | { | |
263 | case 'p': /* print errors normally */ | |
264 | break; /* (default) */ | |
265 | ||
266 | case 'q': /* be silent about it */ | |
267 | freopen("/dev/null", "w", stdout); | |
268 | break; | |
269 | ||
270 | case 'm': /* mail back */ | |
271 | MailBack++; | |
272 | openxscrpt(); | |
273 | break; | |
274 | ||
3b661a43 EA |
275 | case 'e': /* do berknet error processing */ |
276 | BerkNet++; | |
b3cbe40f EA |
277 | openxscrpt(); |
278 | break; | |
279 | ||
280 | case 'w': /* write back (or mail) */ | |
281 | WriteBack++; | |
282 | openxscrpt(); | |
283 | break; | |
284 | } | |
285 | break; | |
286 | ||
287 | # ifdef DEBUG | |
288 | case 'd': /* debug */ | |
289 | Debug++; | |
290 | break; | |
291 | # endif DEBUG | |
292 | ||
293 | case 'n': /* don't alias */ | |
294 | NoAlias++; | |
295 | break; | |
296 | ||
297 | case 'm': /* send to me too */ | |
298 | MeToo++; | |
299 | break; | |
300 | ||
301 | case 'i': /* don't let dot stop me */ | |
302 | IgnrDot++; | |
303 | break; | |
304 | ||
305 | case 'a': /* arpanet format */ | |
306 | ArpaFmt++; | |
307 | break; | |
308 | ||
309 | case 's': /* save From lines in headers */ | |
310 | SaveFrom++; | |
311 | break; | |
312 | ||
313 | default: | |
314 | /* at Eric Schmidt's suggestion, this will not be an error.... | |
315 | syserr("Unknown flag %s", p); | |
316 | ... seems that upward compatibility will be easier. */ | |
317 | break; | |
318 | } | |
319 | } | |
320 | ||
321 | if (from != NULL && ArpaFmt) | |
322 | syserr("-f and -a are mutually exclusive"); | |
323 | ||
324 | /* | |
325 | ** Get a temp file. | |
326 | */ | |
327 | ||
328 | p = maketemp(); | |
329 | if (from == NULL) | |
330 | from = p; | |
331 | # ifdef DEBUG | |
332 | if (Debug) | |
333 | printf("Message-Id: <%s>\n", MsgId); | |
334 | # endif DEBUG | |
335 | ||
336 | /* | |
337 | ** Figure out who it's coming from. | |
338 | ** If we are root or "network", then allow -f. Otherwise, | |
339 | ** insist that we figure it out ourselves. | |
340 | */ | |
341 | ||
342 | errno = 0; | |
343 | p = getname(); | |
344 | if (p == NULL || p[0] == '\0') | |
345 | { | |
346 | syserr("Who are you? (uid=%d)", getuid()); | |
347 | finis(); | |
348 | } | |
349 | errno = 0; | |
350 | if (from != NULL) | |
351 | { | |
352 | if (strcmp(p, "network") != 0 && getuid() != 0 /* && strcmp(p, From) != 0 */ ) | |
353 | { | |
354 | /* network sends -r regardless (why why why?) */ | |
355 | /* syserr("%s, you cannot use the -f flag", p); */ | |
356 | from = NULL; | |
357 | } | |
358 | } | |
359 | if (from == NULL || from[0] == '\0') | |
360 | from = p; | |
361 | else | |
362 | FromFlag++; | |
363 | SuprErrs = TRUE; | |
364 | if (parse(from, &From, 0) == NULL) | |
365 | { | |
366 | /* too many arpanet hosts generate garbage From addresses .... | |
367 | syserr("Bad from address `%s'", from); | |
368 | .... so we will just ignore this address */ | |
369 | from = p; | |
370 | FromFlag = FALSE; | |
371 | } | |
372 | SuprErrs = FALSE; | |
373 | ||
374 | # ifdef DEBUG | |
375 | if (Debug) | |
376 | printf("From person = \"%s\"\n", From.q_paddr); | |
377 | # endif DEBUG | |
378 | ||
379 | if (argc <= 0) | |
380 | usrerr("Usage: /etc/delivermail [flags] addr..."); | |
381 | ||
382 | /* | |
383 | ** Process Hop count. | |
384 | ** The Hop count tells us how many times this message has | |
385 | ** been processed by delivermail. If it exceeds some | |
386 | ** fairly large threshold, then we assume that we have | |
387 | ** an infinite forwarding loop and die. | |
388 | */ | |
389 | ||
390 | if (++HopCount > MAXHOP) | |
391 | syserr("Infinite forwarding loop (%s->%s)", From.q_paddr, *argv); | |
392 | ||
b3cbe40f EA |
393 | /* |
394 | ** Scan argv and deliver the message to everyone. | |
395 | */ | |
396 | ||
397 | for (; argc-- > 0; argv++) | |
398 | { | |
399 | sendto(*argv, 0); | |
400 | } | |
401 | ||
a4b004a6 EA |
402 | /* if we have had errors sofar, drop out now */ |
403 | if (Error && ExitStat == EX_OK) | |
404 | ExitStat = EX_USAGE; | |
405 | if (ExitStat != EX_OK) | |
406 | finis(); | |
407 | ||
b3cbe40f EA |
408 | /* |
409 | ** See if we have anyone to send to at all. | |
410 | */ | |
411 | ||
412 | if (nxtinq(&SendQ) == NULL && ExitStat == EX_OK) | |
413 | { | |
414 | syserr("Noone to send to!"); | |
415 | ExitStat = EX_USAGE; | |
416 | finis(); | |
417 | } | |
418 | ||
419 | /* | |
420 | ** Do aliasing. | |
421 | ** First arrange that the person who is sending the mail | |
422 | ** will not be expanded (unless explicitly requested). | |
423 | */ | |
424 | ||
425 | if (!MeToo) | |
426 | recipient(&From, &AliasQ); | |
427 | To = NULL; | |
428 | alias(); | |
429 | if (nxtinq(&SendQ) == NULL && ExitStat == EX_OK) | |
430 | { | |
431 | /* | |
432 | syserr("Vacant send queue; probably aliasing loop"); | |
433 | ExitStat = EX_SOFTWARE; | |
434 | finis(); | |
435 | */ | |
436 | recipient(&From, &SendQ); | |
437 | } | |
438 | ||
439 | /* | |
440 | ** Actually send everything. | |
441 | */ | |
442 | ||
443 | for (q = &SendQ; (q = nxtinq(q)) != NULL; ) | |
444 | deliver(q, (fnptr) NULL); | |
445 | ||
446 | /* | |
447 | ** All done. | |
448 | */ | |
449 | ||
450 | finis(); | |
451 | } | |
452 | \f/* | |
453 | ** FINIS -- Clean up and exit. | |
454 | ** | |
455 | ** Algorithm: | |
456 | ** if we should remove the input | |
457 | ** remove the input | |
458 | ** exit | |
459 | ** | |
460 | ** Parameters: | |
461 | ** none | |
462 | ** | |
463 | ** Returns: | |
464 | ** never | |
465 | ** | |
466 | ** Side Effects: | |
467 | ** exits delivermail | |
468 | ** | |
469 | ** Requires: | |
470 | ** unlink (sys) | |
471 | ** exit (sys) | |
472 | ** savemail | |
473 | ** InFileName -- the file to remove | |
474 | ** ExitStat -- the status to exit with | |
475 | ** | |
476 | ** Called By: | |
477 | ** main | |
478 | ** via signal on interrupt. | |
479 | ** | |
480 | ** Deficiencies: | |
481 | ** It may be that it should only remove the input | |
482 | ** file if there have been no errors. | |
483 | ** | |
484 | ** History: | |
485 | ** 12/26/79 -- written. | |
486 | */ | |
487 | ||
488 | finis() | |
489 | { | |
490 | /* mail back the transcript on errors */ | |
491 | if (ExitStat != EX_OK) | |
492 | savemail(); | |
493 | ||
494 | if (HasXscrpt) | |
495 | unlink(Transcript); | |
496 | unlink(InFileName); | |
497 | exit(ExitStat); | |
498 | } | |
499 | \f/* | |
500 | ** MAKETEMP -- Make temporary file | |
501 | ** | |
502 | ** Creates a temporary file name and copies the standard | |
503 | ** input to that file. While it is doing it, it looks for | |
504 | ** "From:" and "Sender:" fields to use as the from-person | |
505 | ** (but only if the -a flag is specified). It prefers to | |
506 | ** to use the "Sender:" field -- the protocol says that | |
507 | ** "Sender:" must come after "From:", so this works easily. | |
508 | ** MIT seems to like to produce "Sent-By:" fields instead | |
509 | ** of "Sender:" fields. We used to catch this, but it turns | |
510 | ** out that the "Sent-By:" field doesn't always correspond | |
511 | ** to someone real, as required by the protocol. So we limp | |
512 | ** by..... | |
513 | ** | |
514 | ** Parameters: | |
515 | ** none | |
516 | ** | |
517 | ** Returns: | |
518 | ** Name of temp file. | |
519 | ** | |
520 | ** Side Effects: | |
521 | ** Temp file is created and filled. | |
522 | ** | |
523 | ** Requires: | |
524 | ** creat (sys) | |
525 | ** close (sys) | |
526 | ** syserr | |
527 | ** mktemp (sys) | |
528 | ** fopen (sys) | |
529 | ** fgets (sys) | |
530 | ** makemsgid | |
531 | ** fprintf (sys) | |
532 | ** fputs (sys) | |
533 | ** isspace (sys) | |
534 | ** matchhdr | |
535 | ** prescan | |
536 | ** ferror (sys) | |
537 | ** clearerr (sys) | |
538 | ** freopen (sys) | |
539 | ** | |
540 | ** Called By: | |
541 | ** main | |
542 | ** | |
543 | ** Notes: | |
544 | ** This is broken off from main largely so that the | |
545 | ** temp buffer can be deallocated. | |
546 | ** | |
547 | ** Deficiencies: | |
548 | ** It assumes that the From: field will preceed the | |
549 | ** Sender: field. This violates the Arpanet NIC 733 | |
550 | ** protocol, but seems reasonable in practice. In | |
551 | ** any case, the only problem is that error responses | |
552 | ** may be sent to the wrong person. | |
553 | ** | |
554 | ** History: | |
555 | ** 12/26/79 -- written. | |
556 | */ | |
557 | ||
558 | char * | |
559 | maketemp() | |
560 | { | |
561 | register FILE *tf; | |
562 | char buf[MAXLINE+1]; | |
563 | static char fbuf[sizeof buf]; | |
564 | extern char *prescan(); | |
565 | extern char *matchhdr(); | |
566 | register char *p; | |
567 | bool inheader; | |
568 | bool firstline; | |
569 | ||
570 | /* | |
571 | ** Create the temp file name and create the file. | |
572 | */ | |
573 | ||
574 | mktemp(InFileName); | |
575 | close(creat(InFileName, 0600)); | |
576 | if ((tf = fopen(InFileName, "w")) == NULL) | |
577 | { | |
578 | syserr("Cannot create %s", InFileName); | |
579 | return (NULL); | |
580 | } | |
581 | ||
582 | /* | |
583 | ** Copy stdin to temp file & do message editting. | |
584 | ** From person gets copied into fbuf. At the end of | |
585 | ** this loop, if fbuf[0] == '\0' then there was no | |
586 | ** recognized from person in the message. We also | |
587 | ** save the message id in MsgId. The | |
588 | ** flag 'inheader' keeps track of whether we are | |
589 | ** in the header or in the body of the message. | |
590 | ** The flag 'firstline' is only true on the first | |
591 | ** line of a message. | |
592 | ** To keep certain mailers from getting confused, | |
593 | ** and to keep the output clean, lines that look | |
594 | ** like UNIX "From" lines are deleted in the header, | |
595 | ** and prepended with ">" in the body. | |
596 | */ | |
597 | ||
598 | inheader = TRUE; | |
599 | firstline = TRUE; | |
600 | fbuf[0] = '\0'; | |
601 | while (fgets(buf, sizeof buf, stdin) != NULL) | |
602 | { | |
603 | if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) | |
604 | break; | |
605 | ||
606 | /* are we still in the header? */ | |
607 | if ((buf[0] == '\n' || buf[0] == '\0') && inheader) | |
608 | { | |
609 | inheader = FALSE; | |
610 | if (MsgId[0] == '\0') | |
611 | { | |
612 | makemsgid(); | |
613 | # ifdef MESSAGEID | |
614 | fprintf(tf, "Message-Id: <%s>\n", MsgId); | |
615 | # endif MESSAGEID | |
616 | } | |
617 | } | |
618 | ||
619 | /* Hide UNIX-like From lines */ | |
620 | if (buf[0] == 'F' && buf[1] == 'r' && buf[2] == 'o' && | |
621 | buf[3] == 'm' && buf[4] == ' ') | |
622 | { | |
623 | if (firstline && !SaveFrom) | |
624 | continue; | |
625 | fputs(">", tf); | |
626 | } | |
627 | ||
628 | if (inheader && !isspace(buf[0])) | |
629 | { | |
630 | /* find out if this is really a header */ | |
631 | for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++) | |
632 | continue; | |
633 | while (*p != ':' && isspace(*p)) | |
634 | p++; | |
635 | if (*p != ':') | |
636 | inheader = FALSE; | |
637 | } | |
638 | ||
639 | if (inheader) | |
640 | { | |
641 | /* find the sender */ | |
642 | p = matchhdr(buf, "from"); | |
643 | if (p == NULL) | |
644 | p = matchhdr(buf, "sender"); | |
645 | if (p != NULL) | |
646 | prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0'); | |
647 | ||
648 | /* find the message id */ | |
649 | p = matchhdr(buf, "message-id"); | |
650 | if (p != NULL && MsgId[0] == '\0') | |
651 | prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0'); | |
652 | } | |
653 | fputs(buf, tf); | |
654 | firstline = FALSE; | |
655 | if (ferror(tf)) | |
656 | { | |
657 | syserr("Cannot write %s", InFileName); | |
658 | clearerr(tf); | |
659 | break; | |
660 | } | |
661 | } | |
662 | fclose(tf); | |
663 | if (MsgId[0] == '\0') | |
664 | makemsgid(); | |
665 | if (freopen(InFileName, "r", stdin) == NULL) | |
666 | syserr("Cannot reopen %s", InFileName); | |
667 | return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL); | |
668 | } | |
669 | \f/* | |
670 | ** MAKEMSGID -- Compute a message id for this process. | |
671 | ** | |
672 | ** This routine creates a message id for a message if | |
673 | ** it did not have one already. If the MESSAGEID compile | |
674 | ** flag is set, the messageid will be added to any message | |
675 | ** that does not already have one. Currently it is more | |
676 | ** of an artifact, but I suggest that if you are hacking, | |
677 | ** you leave it in -- I may want to use it someday if | |
678 | ** duplicate messages turn out to be a problem. | |
679 | ** | |
680 | ** Parameters: | |
681 | ** none. | |
682 | ** | |
683 | ** Returns: | |
684 | ** none. | |
685 | ** | |
686 | ** Side Effects: | |
687 | ** Stores a message-id into MsgId. | |
688 | ** | |
689 | ** Requires: | |
690 | ** sprintf (sys) | |
691 | ** getpid (sys) | |
692 | ** time (sys) | |
693 | ** | |
694 | ** Called By: | |
695 | ** maketemp | |
696 | ** | |
697 | ** History: | |
698 | ** 2/3/80 -- written. | |
699 | */ | |
700 | ||
701 | makemsgid() | |
702 | { | |
703 | auto long t; | |
704 | extern char *MyLocName; | |
705 | ||
706 | time(&t); | |
707 | sprintf(MsgId, "%ld.%d.%s@Berkeley", t, getpid(), MyLocName); | |
708 | } | |
709 | \f/* | |
710 | ** OPENXSCRPT -- Open transcript file | |
711 | ** | |
712 | ** Creates a transcript file for possible eventual mailing or | |
713 | ** sending back. | |
714 | ** | |
715 | ** Parameters: | |
716 | ** none | |
717 | ** | |
718 | ** Returns: | |
719 | ** none | |
720 | ** | |
721 | ** Side Effects: | |
722 | ** Turns the standard output into a special file | |
723 | ** somewhere. | |
724 | ** | |
725 | ** Requires: | |
726 | ** mktemp (sys) | |
727 | ** chmod (sys) | |
728 | ** freopen (sys) | |
729 | ** syserr | |
730 | ** setbuf (sys) | |
731 | ** | |
732 | ** Called By: | |
733 | ** main | |
734 | ** | |
735 | ** History: | |
736 | ** 1/11/80 -- written. | |
737 | */ | |
738 | ||
739 | openxscrpt() | |
740 | { | |
741 | mktemp(Transcript); | |
742 | HasXscrpt++; | |
743 | if (freopen(Transcript, "w", stdout) == NULL) | |
744 | syserr("Can't create %s", Transcript); | |
745 | chmod(Transcript, 0600); | |
746 | setbuf(stdout, (char *) NULL); | |
747 | } |