Commit | Line | Data |
---|---|---|
ed45aae1 | 1 | # define _DEFINE |
b3cbe40f | 2 | # include <signal.h> |
1a12c7d6 | 3 | # include <pwd.h> |
96faada8 | 4 | # include "sendmail.h" |
ed45aae1 | 5 | # include <sys/stat.h> |
b3cbe40f | 6 | # ifdef LOG |
882642f7 | 7 | # include <syslog.h> |
b3cbe40f EA |
8 | # endif LOG |
9 | ||
62fff4f9 | 10 | static char SccsId[] = "@(#)main.c 3.53 %G%"; |
916b3375 | 11 | |
b3cbe40f | 12 | /* |
96faada8 | 13 | ** SENDMAIL -- Post mail to a set of destinations. |
b3cbe40f EA |
14 | ** |
15 | ** This is the basic mail router. All user mail programs should | |
96faada8 | 16 | ** call this routine to actually deliver mail. Sendmail in |
b3cbe40f EA |
17 | ** turn calls a bunch of mail servers that do the real work of |
18 | ** delivering the mail. | |
19 | ** | |
96faada8 | 20 | ** Sendmail is driven by tables defined in conf.c. This |
b3cbe40f EA |
21 | ** file will be different from system to system, but the rest |
22 | ** of the code will be the same. This table could be read in, | |
23 | ** but it seemed nicer to have it compiled in, since deliver- | |
24 | ** mail will potentially be exercised a lot. | |
25 | ** | |
26 | ** Usage: | |
96faada8 | 27 | ** /etc/sendmail [-f name] [-a] [-q] [-v] [-n] [-m] addr ... |
b3cbe40f EA |
28 | ** |
29 | ** Positional Parameters: | |
30 | ** addr -- the address to deliver the mail to. There | |
31 | ** can be several. | |
32 | ** | |
33 | ** Flags: | |
34 | ** -f name The mail is from "name" -- used for | |
35 | ** the header in local mail, and to | |
36 | ** deliver reports of failures to. | |
37 | ** -r name Same as -f; however, this flag is | |
38 | ** reserved to indicate special processing | |
39 | ** for remote mail delivery as needed | |
40 | ** in the future. So, network servers | |
41 | ** should use -r. | |
6da7b890 EA |
42 | ** -Ffullname Select what the full-name should be |
43 | ** listed as. | |
b3cbe40f | 44 | ** -a This mail should be in ARPANET std |
74c5fe7c EA |
45 | ** format (obsolete version). |
46 | ** -am Called from an FTP "MAIL" command. | |
47 | ** -af Called from an FTP "MLFL" command. | |
b3cbe40f EA |
48 | ** -n Don't do aliasing. This might be used |
49 | ** when delivering responses, for | |
50 | ** instance. | |
51 | ** -d Run in debug mode. | |
52 | ** -em Mail back a response if there was an | |
53 | ** error in processing. This should be | |
54 | ** used when the origin of this message | |
55 | ** is another machine. | |
56 | ** -ew Write back a response if the user is | |
57 | ** still logged in, otherwise, act like | |
58 | ** -em. | |
59 | ** -eq Don't print any error message (just | |
60 | ** return exit status). | |
61 | ** -ep (default) Print error messages | |
62 | ** normally. | |
3b661a43 EA |
63 | ** -ee Send BerkNet style errors. This |
64 | ** is equivalent to MailBack except | |
65 | ** that it has gives zero return code | |
66 | ** (unless there were errors during | |
67 | ** returning). This used to be | |
68 | ** "EchoBack", but you know how the old | |
69 | ** software bounces. | |
b3cbe40f EA |
70 | ** -m In group expansion, send to the |
71 | ** sender also (stands for the Mail metoo | |
72 | ** option. | |
73 | ** -i Do not terminate mail on a line | |
74 | ** containing just dot. | |
75 | ** -s Save UNIX-like "From" lines on the | |
76 | ** front of messages. | |
d59b067a EA |
77 | ** -v Give blow-by-blow description of |
78 | ** everything that happens. | |
bfcddd93 EA |
79 | ** -t Read "to" addresses from message. |
80 | ** Looks at To:, Cc:, and Bcc: lines. | |
74c5fe7c EA |
81 | ** -I Initialize the DBM alias files from |
82 | ** the text format files. | |
6da7b890 | 83 | ** -Cfilename Use alternate configuration file. |
cdb17311 | 84 | ** -Afilename Use alternate alias file. |
6da7b890 | 85 | ** -DXvalue Define macro X to have value. |
b3cbe40f EA |
86 | ** |
87 | ** Return Codes: | |
88 | ** As defined in <sysexits.h>. | |
89 | ** | |
90 | ** These codes are actually returned from the auxiliary | |
91 | ** mailers; it is their responsibility to make them | |
92 | ** correct. | |
93 | ** | |
b3cbe40f | 94 | ** Compilation Flags: |
b3cbe40f | 95 | ** LOG -- if set, everything is logged. |
b3cbe40f | 96 | ** |
b3cbe40f EA |
97 | ** Author: |
98 | ** Eric Allman, UCB/INGRES | |
b3cbe40f EA |
99 | */ |
100 | ||
101 | ||
102 | ||
103 | ||
104 | ||
327272f5 | 105 | int NextMailer = 0; /* "free" index into Mailer struct */ |
cbdb7357 | 106 | static char *FullName; /* sender's full name */ |
b3cbe40f EA |
107 | |
108 | ||
109 | ||
110 | ||
111 | ||
112 | ||
113 | main(argc, argv) | |
114 | int argc; | |
115 | char **argv; | |
116 | { | |
117 | register char *p; | |
1a12c7d6 | 118 | extern char *getlogin(); |
17df0fcb | 119 | char *locname; |
b3cbe40f | 120 | extern int finis(); |
b3cbe40f | 121 | extern char Version[]; |
b3cbe40f | 122 | char *from; |
b3cbe40f | 123 | typedef int (*fnptr)(); |
9e3c0a28 | 124 | register int i; |
8843e11d | 125 | bool verifyonly = FALSE; /* only verify names */ |
eb211e2c | 126 | bool safecf = TRUE; /* this conf file is sys default */ |
2768afe3 | 127 | char ibuf[30]; /* holds HostName */ |
aba51985 | 128 | bool queuemode = FALSE; /* process queue requests */ |
f4dbf345 | 129 | bool aliasinit = FALSE; |
f6a0cc15 | 130 | extern bool safefile(); |
179c1218 | 131 | STAB *st; |
ed45aae1 | 132 | extern time_t convtime(); |
17df0fcb | 133 | bool canrename; |
b3cbe40f | 134 | |
d6b27179 | 135 | argv[argc] = NULL; |
cbdb7357 EA |
136 | InChannel = stdin; |
137 | OutChannel = stdout; | |
b3cbe40f | 138 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) |
29871fef | 139 | (void) signal(SIGINT, finis); |
eb211e2c EA |
140 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) |
141 | (void) signal(SIGHUP, finis); | |
29871fef | 142 | (void) signal(SIGTERM, finis); |
a0554f81 | 143 | OldUmask = umask(0); |
b3cbe40f | 144 | # ifdef LOG |
96faada8 | 145 | openlog("sendmail", 0); |
b3cbe40f | 146 | # endif LOG |
49086753 | 147 | openxscrpt(); |
b3cbe40f EA |
148 | # ifdef DEBUG |
149 | # ifdef DEBUGFILE | |
150 | if ((i = open(DEBUGFILE, 1)) > 0) | |
151 | { | |
29871fef EA |
152 | (void) lseek(i, 0L, 2); |
153 | (void) close(1); | |
154 | (void) dup(i); | |
155 | (void) close(i); | |
b3cbe40f EA |
156 | Debug++; |
157 | } | |
158 | # endif DEBUGFILE | |
b3cbe40f EA |
159 | # endif |
160 | errno = 0; | |
161 | from = NULL; | |
162 | ||
163 | /* | |
164 | ** Crack argv. | |
165 | */ | |
166 | ||
167 | while (--argc > 0 && (p = *++argv)[0] == '-') | |
168 | { | |
169 | switch (p[1]) | |
170 | { | |
171 | case 'r': /* obsolete -f flag */ | |
172 | case 'f': /* from address */ | |
173 | p += 2; | |
174 | if (*p == '\0') | |
175 | { | |
176 | p = *++argv; | |
177 | if (--argc <= 0 || *p == '-') | |
178 | { | |
179 | syserr("No \"from\" person"); | |
180 | argc++; | |
181 | argv--; | |
182 | break; | |
183 | } | |
184 | } | |
185 | if (from != NULL) | |
186 | { | |
187 | syserr("More than one \"from\" person"); | |
188 | break; | |
189 | } | |
190 | from = p; | |
191 | break; | |
192 | ||
6da7b890 | 193 | case 'F': /* set full name */ |
74c5fe7c EA |
194 | p += 2; |
195 | if (*p == '\0') | |
196 | { | |
197 | p = *++argv; | |
198 | if (--argc <= 0 || *p == '-') | |
199 | { | |
200 | syserr("Bad -F flag"); | |
201 | argc++; | |
202 | argv--; | |
203 | break; | |
204 | } | |
205 | } | |
cbdb7357 | 206 | FullName = p; |
6da7b890 EA |
207 | break; |
208 | ||
b3cbe40f EA |
209 | case 'h': /* hop count */ |
210 | p += 2; | |
211 | if (*p == '\0') | |
212 | { | |
213 | p = *++argv; | |
214 | if (--argc <= 0 || *p < '0' || *p > '9') | |
215 | { | |
216 | syserr("Bad hop count (%s)", p); | |
217 | argc++; | |
218 | argv--; | |
219 | break; | |
220 | } | |
221 | } | |
222 | HopCount = atoi(p); | |
223 | break; | |
224 | ||
225 | case 'e': /* error message disposition */ | |
226 | switch (p[2]) | |
227 | { | |
228 | case 'p': /* print errors normally */ | |
229 | break; /* (default) */ | |
230 | ||
231 | case 'q': /* be silent about it */ | |
29871fef | 232 | (void) freopen("/dev/null", "w", stdout); |
b3cbe40f EA |
233 | break; |
234 | ||
235 | case 'm': /* mail back */ | |
49086753 EA |
236 | MailBack = TRUE; |
237 | HoldErrs = TRUE; | |
b3cbe40f EA |
238 | break; |
239 | ||
3b661a43 | 240 | case 'e': /* do berknet error processing */ |
49086753 EA |
241 | BerkNet = TRUE; |
242 | HoldErrs = TRUE; | |
b3cbe40f EA |
243 | break; |
244 | ||
245 | case 'w': /* write back (or mail) */ | |
49086753 EA |
246 | WriteBack = TRUE; |
247 | HoldErrs = TRUE; | |
b3cbe40f EA |
248 | break; |
249 | } | |
250 | break; | |
251 | ||
252 | # ifdef DEBUG | |
253 | case 'd': /* debug */ | |
6da7b890 EA |
254 | Debug = atoi(&p[2]); |
255 | if (Debug <= 0) | |
256 | Debug = 1; | |
62fff4f9 | 257 | setbuf(stdout, (char *) NULL); |
6da7b890 | 258 | printf("Version %s Debug %d\n", Version, Debug); |
b3cbe40f | 259 | break; |
1a12c7d6 | 260 | |
f6a0cc15 | 261 | case 'M': /* redefine internal macro */ |
dc39c568 | 262 | define(p[2], &p[3]); |
1a12c7d6 | 263 | break; |
b3cbe40f | 264 | # endif DEBUG |
d6a28dd8 | 265 | |
6da7b890 | 266 | case 'C': /* select configuration file */ |
6a5effbb | 267 | if (p[2] == '\0') |
4e1f4d4b | 268 | ConfFile = "sendmail.cf"; |
6a5effbb | 269 | else |
4e1f4d4b | 270 | ConfFile = &p[2]; |
eb211e2c | 271 | safecf = FALSE; |
d6a28dd8 | 272 | break; |
cdb17311 EA |
273 | |
274 | case 'A': /* select alias file */ | |
6a5effbb | 275 | if (p[2] == '\0') |
4e1f4d4b | 276 | AliasFile = "aliases"; |
6a5effbb | 277 | else |
4e1f4d4b | 278 | AliasFile = &p[2]; |
cdb17311 | 279 | break; |
ed45aae1 EA |
280 | |
281 | case 'Q': /* select queue dir */ | |
282 | if (p[2] == '\0') | |
283 | AliasFile = "mqueue"; | |
284 | else | |
285 | AliasFile = &p[2]; | |
286 | break; | |
287 | ||
288 | case 'T': /* set timeout interval */ | |
289 | TimeOut = convtime(&p[2]); | |
290 | break; | |
b3cbe40f EA |
291 | |
292 | case 'n': /* don't alias */ | |
293 | NoAlias++; | |
294 | break; | |
295 | ||
f4dbf345 EA |
296 | # ifdef DBM |
297 | case 'I': /* initialize alias DBM file */ | |
298 | aliasinit = TRUE; | |
d6b27179 | 299 | Verbose = TRUE; |
f4dbf345 EA |
300 | break; |
301 | # endif DBM | |
302 | ||
b3cbe40f EA |
303 | case 'm': /* send to me too */ |
304 | MeToo++; | |
305 | break; | |
306 | ||
307 | case 'i': /* don't let dot stop me */ | |
308 | IgnrDot++; | |
309 | break; | |
310 | ||
8843e11d EA |
311 | case 'V': /* verify only */ |
312 | verifyonly = TRUE; | |
313 | break; | |
314 | ||
b3cbe40f | 315 | case 'a': /* arpanet format */ |
49086753 EA |
316 | ArpaMode = TRUE; |
317 | if (p[2] == 's') | |
dc39c568 | 318 | { |
49086753 EA |
319 | /* running smtp */ |
320 | Smtp = TRUE; | |
dc39c568 | 321 | } |
b3cbe40f EA |
322 | break; |
323 | ||
324 | case 's': /* save From lines in headers */ | |
325 | SaveFrom++; | |
326 | break; | |
327 | ||
d59b067a EA |
328 | case 'v': /* give blow-by-blow description */ |
329 | Verbose++; | |
330 | break; | |
331 | ||
bfcddd93 EA |
332 | case 't': /* read recipients from message */ |
333 | GrabTo = TRUE; | |
334 | break; | |
335 | ||
f6a0cc15 EA |
336 | case 'D': /* run as a daemon */ |
337 | Daemon = TRUE; | |
cbdb7357 EA |
338 | /* explicit fall-through */ |
339 | ||
ed45aae1 | 340 | case 'q': /* run queue files at intervals */ |
aba51985 | 341 | queuemode = TRUE; |
ed45aae1 | 342 | QueueIntvl = atoi(&p[1]); |
ed45aae1 EA |
343 | break; |
344 | ||
b3cbe40f EA |
345 | default: |
346 | /* at Eric Schmidt's suggestion, this will not be an error.... | |
347 | syserr("Unknown flag %s", p); | |
348 | ... seems that upward compatibility will be easier. */ | |
349 | break; | |
350 | } | |
351 | } | |
352 | ||
9e3c0a28 | 353 | /* |
f6a0cc15 | 354 | ** Read system control file. |
179c1218 | 355 | ** Extract special fields for local use. |
9e3c0a28 EA |
356 | */ |
357 | ||
4e1f4d4b | 358 | readcf(ConfFile, safecf); |
ed45aae1 | 359 | initsys(); |
179c1218 EA |
360 | |
361 | /* our name for SMTP codes */ | |
2768afe3 EA |
362 | (void) expand("$i", ibuf, &ibuf[sizeof ibuf - 1]); |
363 | HostName = ibuf; | |
d6a28dd8 | 364 | |
179c1218 EA |
365 | /* the indices of local and program mailers */ |
366 | st = stab("local", ST_MAILER, ST_FIND); | |
367 | if (st == NULL) | |
368 | syserr("No local mailer defined"); | |
369 | else | |
370 | LocalMailer = st->s_mailer; | |
371 | st = stab("prog", ST_MAILER, ST_FIND); | |
372 | if (st == NULL) | |
373 | syserr("No prog mailer defined"); | |
374 | else | |
375 | ProgMailer = st->s_mailer; | |
376 | ||
f6a0cc15 EA |
377 | /* |
378 | ** Initialize aliases. | |
379 | */ | |
8acb5142 | 380 | |
4e1f4d4b | 381 | initaliases(AliasFile, aliasinit); |
f4dbf345 EA |
382 | # ifdef DBM |
383 | if (aliasinit) | |
384 | exit(EX_OK); | |
385 | # endif DBM | |
cdb17311 | 386 | |
9c6d4c70 EA |
387 | # ifdef DEBUG |
388 | if (Debug > 15) | |
389 | { | |
f6a0cc15 | 390 | /* print configuration table (or at least part of it) */ |
9c6d4c70 EA |
391 | printrules(); |
392 | for (i = 0; i < MAXMAILERS; i++) | |
393 | { | |
394 | register struct mailer *m = Mailer[i]; | |
395 | ||
396 | if (m == NULL) | |
397 | continue; | |
398 | printf("mailer %d: %s %s %o %s\n", i, m->m_name, | |
399 | m->m_mailer, m->m_flags, m->m_from); | |
400 | } | |
401 | } | |
402 | # endif DEBUG | |
403 | ||
f6a0cc15 EA |
404 | /* |
405 | ** If a daemon, wait for a request. | |
406 | ** getrequests will always return in a child. | |
407 | */ | |
408 | ||
409 | if (Daemon) | |
410 | getrequests(); | |
cbdb7357 | 411 | |
b3cbe40f | 412 | /* |
cbdb7357 | 413 | if (Smtp) |
2cf55cb7 EA |
414 | { |
415 | if (queuemode) | |
416 | runqueue(TRUE); | |
cbdb7357 | 417 | smtp(); |
2cf55cb7 | 418 | } |
a9e0e597 | 419 | |
ed45aae1 EA |
420 | /* |
421 | ** If collecting stuff from the queue, go start doing that. | |
422 | */ | |
423 | ||
aba51985 | 424 | if (queuemode) |
ed45aae1 | 425 | { |
2cf55cb7 | 426 | runqueue(FALSE); |
ed45aae1 EA |
427 | finis(); |
428 | } | |
429 | ||
f6a0cc15 | 430 | /* |
cbdb7357 | 431 | ** Set the sender |
f6a0cc15 EA |
432 | */ |
433 | ||
cbdb7357 | 434 | setsender(from); |
a9e0e597 | 435 | |
f6a0cc15 | 436 | if (!Daemon && argc <= 0 && !GrabTo) |
96faada8 | 437 | usrerr("Usage: /etc/sendmail [flags] addr..."); |
b3cbe40f EA |
438 | |
439 | /* | |
440 | ** Process Hop count. | |
441 | ** The Hop count tells us how many times this message has | |
96faada8 | 442 | ** been processed by sendmail. If it exceeds some |
b3cbe40f EA |
443 | ** fairly large threshold, then we assume that we have |
444 | ** an infinite forwarding loop and die. | |
445 | */ | |
446 | ||
447 | if (++HopCount > MAXHOP) | |
448 | syserr("Infinite forwarding loop (%s->%s)", From.q_paddr, *argv); | |
449 | ||
b3cbe40f | 450 | /* |
d6b27179 EA |
451 | ** Scan argv and deliver the message to everyone. |
452 | ** Actually, suppress delivery if we are taking To: | |
453 | ** lines from the message. | |
b3cbe40f EA |
454 | */ |
455 | ||
23a54ee3 EA |
456 | if (GrabTo) |
457 | DontSend = TRUE; | |
cbdb7357 | 458 | sendtoargv(argv); |
b3cbe40f | 459 | |
a4b004a6 | 460 | /* if we have had errors sofar, drop out now */ |
d916f0ca | 461 | if (Errors > 0 && ExitStat == EX_OK) |
a4b004a6 | 462 | ExitStat = EX_USAGE; |
a4b004a6 | 463 | |
dc39c568 EA |
464 | /* |
465 | ** Read the input mail. | |
466 | */ | |
467 | ||
23a54ee3 | 468 | DontSend = FALSE; |
d6b27179 | 469 | To = NULL; |
d6b27179 | 470 | if (!verifyonly || GrabTo) |
49086753 | 471 | collect(FALSE); |
d829793b | 472 | errno = 0; |
ed45aae1 | 473 | initsys(); |
bfcddd93 | 474 | |
4e1f4d4b | 475 | /* collect statistics */ |
179c1218 EA |
476 | Stat.stat_nf[From.q_mailer->m_mno]++; |
477 | Stat.stat_bf[From.q_mailer->m_mno] += kbytes(MsgSize); | |
4e1f4d4b | 478 | |
b3cbe40f | 479 | /* |
dc39c568 EA |
480 | ** Arrange that the person who is sending the mail |
481 | ** will not be expanded (unless explicitly requested). | |
b3cbe40f EA |
482 | */ |
483 | ||
d6b27179 EA |
484 | # ifdef DEBUG |
485 | if (Debug) | |
486 | printf("From person = \"%s\"\n", From.q_paddr); | |
487 | # endif DEBUG | |
488 | ||
9e3c0a28 | 489 | From.q_flags |= QDONTSEND; |
b3cbe40f | 490 | if (!MeToo) |
9e3c0a28 | 491 | recipient(&From); |
b3cbe40f | 492 | To = NULL; |
b3cbe40f EA |
493 | |
494 | /* | |
495 | ** Actually send everything. | |
d6b27179 | 496 | ** If verifying, just ack. |
b3cbe40f EA |
497 | */ |
498 | ||
cbdb7357 | 499 | sendall(verifyonly); |
b3cbe40f EA |
500 | |
501 | /* | |
502 | ** All done. | |
503 | */ | |
504 | ||
dc39c568 | 505 | To = NULL; |
d6b27179 EA |
506 | if (!verifyonly) |
507 | poststats(StatFile); | |
b3cbe40f EA |
508 | finis(); |
509 | } | |
510 | \f/* | |
f65e7ded EA |
511 | ** SETFROM -- set the person who this message is from |
512 | ** | |
513 | ** Under certain circumstances allow the user to say who | |
514 | ** s/he is (using -f or -r). These are: | |
515 | ** 1. The user's uid is zero (root). | |
516 | ** 2. The user's login name is "network" (mail from | |
517 | ** a network server). | |
518 | ** 3. The user's login name is "uucp" (mail from the | |
519 | ** uucp network). | |
520 | ** 4. The address the user is trying to claim has a | |
521 | ** "!" character in it (since #3 doesn't do it for | |
522 | ** us if we are dialing out). | |
523 | ** A better check to replace #3 & #4 would be if the | |
524 | ** effective uid is "UUCP" -- this would require me | |
525 | ** to rewrite getpwent to "grab" uucp as it went by, | |
526 | ** make getname more nasty, do another passwd file | |
527 | ** scan, or compile the UID of "UUCP" into the code, | |
528 | ** all of which are reprehensible. | |
529 | ** | |
530 | ** Assuming all of these fail, we figure out something | |
531 | ** ourselves. | |
532 | ** | |
533 | ** Parameters: | |
534 | ** from -- the person it is from. | |
535 | ** realname -- the actual person executing sendmail. | |
dc39c568 EA |
536 | ** If NULL, then take whoever we previously |
537 | ** thought was the from person. | |
f65e7ded EA |
538 | ** |
539 | ** Returns: | |
540 | ** none. | |
541 | ** | |
542 | ** Side Effects: | |
543 | ** sets sendmail's notion of who the from person is. | |
544 | */ | |
545 | ||
546 | setfrom(from, realname) | |
547 | char *from; | |
548 | char *realname; | |
549 | { | |
550 | register char **pvp; | |
551 | char frombuf[MAXNAME]; | |
552 | extern char **prescan(); | |
553 | extern char *index(); | |
554 | ||
dc39c568 EA |
555 | if (realname == NULL) |
556 | realname = From.q_paddr; | |
84b4028f EA |
557 | |
558 | # ifdef DEBUG | |
559 | if (Debug > 1) | |
560 | printf("setfrom(%s, %s)\n", from, realname); | |
561 | # endif DEBUG | |
562 | ||
f65e7ded EA |
563 | if (from != NULL) |
564 | { | |
565 | if (strcmp(realname, "network") != 0 && strcmp(realname, "uucp") != 0 && | |
d829793b EA |
566 | # ifdef DEBUG |
567 | (Debug == 0 || getuid() != geteuid()) && | |
568 | # endif DEBUG | |
f65e7ded EA |
569 | index(from, '!') == NULL && getuid() != 0) |
570 | { | |
571 | /* network sends -r regardless (why why why?) */ | |
572 | /* syserr("%s, you cannot use the -f flag", realname); */ | |
573 | from = NULL; | |
574 | } | |
575 | } | |
576 | ||
577 | SuprErrs = TRUE; | |
84b4028f | 578 | if (from == NULL || parse(from, &From, 1) == NULL) |
f65e7ded EA |
579 | { |
580 | from = newstr(realname); | |
84b4028f | 581 | (void) parse(from, &From, 1); |
f65e7ded EA |
582 | } |
583 | else | |
584 | FromFlag = TRUE; | |
585 | SuprErrs = FALSE; | |
1bf7c76b EA |
586 | From.q_uid = getuid(); |
587 | From.q_gid = getgid(); | |
588 | # ifndef V6 | |
589 | From.q_home = getenv("HOME"); | |
590 | # endif V6 | |
f65e7ded EA |
591 | |
592 | /* | |
593 | ** Rewrite the from person to dispose of possible implicit | |
594 | ** links in the net. | |
595 | */ | |
596 | ||
597 | pvp = prescan(from, '\0'); | |
598 | if (pvp == NULL) | |
599 | { | |
600 | syserr("cannot prescan from (%s)", from); | |
601 | finis(); | |
602 | } | |
603 | rewrite(pvp, 1); | |
31b33174 | 604 | cataddr(pvp, frombuf, sizeof frombuf); |
f65e7ded EA |
605 | define('f', newstr(frombuf)); |
606 | } | |
607 | \f/* | |
b3cbe40f EA |
608 | ** FINIS -- Clean up and exit. |
609 | ** | |
b3cbe40f EA |
610 | ** Parameters: |
611 | ** none | |
612 | ** | |
613 | ** Returns: | |
614 | ** never | |
615 | ** | |
616 | ** Side Effects: | |
96faada8 | 617 | ** exits sendmail |
b3cbe40f EA |
618 | */ |
619 | ||
620 | finis() | |
621 | { | |
aba51985 EA |
622 | # ifdef DEBUG |
623 | if (Debug > 2) | |
624 | printf("\n====finis: stat %d\n", ExitStat); | |
625 | # endif DEBUG | |
626 | ||
b3cbe40f EA |
627 | /* mail back the transcript on errors */ |
628 | if (ExitStat != EX_OK) | |
629 | savemail(); | |
630 | ||
ed45aae1 | 631 | if (Transcript != NULL) |
29871fef | 632 | (void) unlink(Transcript); |
ed45aae1 EA |
633 | if (QueueUp) |
634 | { | |
635 | if (!QueueRun) | |
636 | queueup(InFileName); | |
637 | } | |
638 | else | |
639 | (void) unlink(InFileName); | |
b3cbe40f EA |
640 | exit(ExitStat); |
641 | } | |
642 | \f/* | |
b3cbe40f EA |
643 | ** OPENXSCRPT -- Open transcript file |
644 | ** | |
645 | ** Creates a transcript file for possible eventual mailing or | |
646 | ** sending back. | |
647 | ** | |
648 | ** Parameters: | |
649 | ** none | |
650 | ** | |
651 | ** Returns: | |
652 | ** none | |
653 | ** | |
654 | ** Side Effects: | |
655 | ** Turns the standard output into a special file | |
656 | ** somewhere. | |
b3cbe40f EA |
657 | */ |
658 | ||
659 | openxscrpt() | |
660 | { | |
7b9c35c8 | 661 | extern char *mktemp(); |
49086753 | 662 | register char *p; |
7b9c35c8 | 663 | |
49086753 EA |
664 | p = newstr(XcriptFile); |
665 | (void) mktemp(p); | |
666 | Xscript = fopen(p, "w"); | |
667 | if (Xscript == NULL) | |
aba51985 | 668 | { |
49086753 EA |
669 | Xscript = stdout; |
670 | syserr("Can't create %s", p); | |
aba51985 | 671 | } |
49086753 EA |
672 | Transcript = p; |
673 | (void) chmod(p, 0600); | |
b3cbe40f | 674 | } |
cbdb7357 EA |
675 | \f/* |
676 | ** SETSENDER -- set sendmail's idea of the sender. | |
677 | ** | |
678 | ** Parameters: | |
679 | ** from -- the person we would like to believe this | |
680 | ** is from. | |
681 | ** | |
682 | ** Returns: | |
683 | ** none. | |
684 | ** | |
685 | ** Side Effects: | |
686 | ** Sets the idea of the sender. | |
687 | */ | |
688 | ||
689 | setsender(from) | |
690 | char *from; | |
691 | { | |
692 | register char *p; | |
693 | extern char *getlogin(); | |
694 | register struct passwd *pw; | |
695 | char *realname; | |
696 | char cfbuf[40]; | |
697 | ||
698 | /* | |
699 | ** Figure out the real user executing us. | |
700 | ** Getlogin can return errno != 0 on non-errors. | |
701 | */ | |
702 | ||
aba51985 | 703 | if (!Smtp && !QueueRun) |
cbdb7357 EA |
704 | { |
705 | errno = 0; | |
706 | p = getlogin(); | |
707 | errno = 0; | |
708 | } | |
df7a9713 EA |
709 | else |
710 | p = from; | |
711 | if (p != NULL) | |
712 | { | |
713 | extern struct passwd *getpwnam(); | |
714 | ||
715 | pw = getpwnam(p); | |
716 | if (pw == NULL) | |
717 | { | |
aba51985 | 718 | if (!Smtp && !QueueRun) |
df7a9713 EA |
719 | syserr("Who are you? (name=%s)", p); |
720 | p = NULL; | |
721 | } | |
722 | } | |
723 | if (p == NULL) | |
cbdb7357 EA |
724 | { |
725 | extern struct passwd *getpwuid(); | |
726 | int uid; | |
727 | ||
728 | uid = getruid(); | |
729 | pw = getpwuid(uid); | |
730 | if (pw == NULL) | |
731 | syserr("Who are you? (uid=%d)", uid); | |
732 | else | |
733 | p = pw->pw_name; | |
734 | } | |
cbdb7357 EA |
735 | if (p == NULL || p[0] == '\0' || pw == NULL) |
736 | finis(); | |
737 | ||
738 | realname = p; | |
739 | ||
740 | /* | |
741 | ** Process passwd file entry. | |
742 | */ | |
743 | ||
744 | /* run user's .mailcf file */ | |
745 | define('z', pw->pw_dir); | |
746 | (void) expand("$z/.mailcf", cfbuf, &cfbuf[sizeof cfbuf - 1]); | |
747 | if (safefile(cfbuf, getruid(), S_IREAD)) | |
748 | readcf(cfbuf, FALSE); | |
749 | ||
750 | /* extract full name from passwd file */ | |
751 | if ((FullName == NULL || FullName[0] == '\0') && | |
752 | pw != NULL && pw->pw_gecos != NULL) | |
753 | { | |
754 | char nbuf[MAXNAME]; | |
755 | ||
756 | buildfname(pw->pw_gecos, realname, nbuf); | |
df7a9713 | 757 | if (nbuf[0] != '\0') |
cbdb7357 EA |
758 | FullName = newstr(nbuf); |
759 | } | |
760 | if (FullName != NULL && FullName[0] != '\0') | |
761 | define('x', FullName); | |
762 | ||
763 | setfrom(from, realname); | |
764 | } | |
ed45aae1 EA |
765 | \f/* |
766 | ** INITSYS -- initialize instantiation of system | |
767 | ** | |
768 | ** In Daemon mode, this is done in the child. | |
769 | ** | |
770 | ** Parameters: | |
771 | ** none. | |
772 | ** | |
773 | ** Returns: | |
774 | ** none. | |
775 | ** | |
776 | ** Side Effects: | |
777 | ** Initializes the system macros, some global variables, | |
778 | ** etc. In particular, the current time in various | |
779 | ** forms is set. | |
780 | */ | |
781 | ||
782 | initsys() | |
783 | { | |
784 | static char cbuf[5]; /* holds hop count */ | |
785 | static char dbuf[30]; /* holds ctime(tbuf) */ | |
786 | static char pbuf[10]; /* holds pid */ | |
787 | static char tbuf[10]; /* holds "current" time */ | |
788 | static char ybuf[10]; /* holds tty id */ | |
789 | register char *p; | |
790 | extern char *ttyname(); | |
791 | extern char *arpadate(); | |
ed45aae1 EA |
792 | |
793 | /* convert timeout interval to absolute time */ | |
aba51985 | 794 | TimeOut -= CurTime; |
ed45aae1 EA |
795 | (void) time(&CurTime); |
796 | TimeOut += CurTime; | |
797 | ||
798 | /* process id */ | |
799 | (void) sprintf(pbuf, "%d", getpid()); | |
800 | define('p', pbuf); | |
801 | ||
802 | /* hop count */ | |
803 | (void) sprintf(cbuf, "%d", HopCount); | |
804 | define('c', cbuf); | |
805 | ||
806 | /* time as integer, unix time, arpa time */ | |
807 | (void) sprintf(tbuf, "%ld", &CurTime); | |
808 | define('t', tbuf); | |
809 | (void) strcpy(dbuf, ctime(&CurTime)); | |
810 | *index(dbuf, '\n') = '\0'; | |
811 | define('d', dbuf); | |
812 | p = newstr(arpadate(dbuf)); | |
813 | define('a', p); | |
814 | define('b', p); | |
815 | ||
816 | /* version */ | |
817 | define('v', Version); | |
818 | ||
819 | /* tty name */ | |
820 | p = ttyname(2); | |
821 | if (p != NULL) | |
822 | { | |
823 | if (rindex(p, '/') != NULL) | |
824 | p = rindex(p, '/') + 1; | |
825 | strcpy(ybuf, p); | |
826 | define('y', ybuf); | |
827 | } | |
828 | } |