-k works now
[unix-history] / usr / src / usr.sbin / sendmail / src / main.c
CommitLineData
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
da6a9b77 10SCCSID(@(#)main.c 3.81 %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
2654b031 105int NextMailer = 0; /* "free" index into Mailer struct */
cbdb7357 106static char *FullName; /* sender's full name */
2654b031 107ENVELOPE MainEnvelope; /* the envelope around the basic letter */
b3cbe40f 108
4aebfe5d
EA
109#ifdef DAEMON
110#ifndef SMTP
111ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR
112#endif SMTP
113#endif DAEMON
114
b3cbe40f
EA
115
116
117
118
119
120main(argc, argv)
121 int argc;
122 char **argv;
123{
124 register char *p;
17df0fcb 125 char *locname;
b3cbe40f 126 extern int finis();
b3cbe40f 127 extern char Version[];
b3cbe40f 128 char *from;
b3cbe40f 129 typedef int (*fnptr)();
9e3c0a28 130 register int i;
eb211e2c 131 bool safecf = TRUE; /* this conf file is sys default */
2768afe3 132 char ibuf[30]; /* holds HostName */
aba51985 133 bool queuemode = FALSE; /* process queue requests */
f4dbf345 134 bool aliasinit = FALSE;
f6a0cc15 135 extern bool safefile();
179c1218 136 STAB *st;
ed45aae1 137 extern time_t convtime();
dd1fe05b 138 extern putheader(), putbody();
abae7b2d 139 extern ADDRESS *recipient();
17df0fcb 140 bool canrename;
b3cbe40f 141
d6b27179 142 argv[argc] = NULL;
cbdb7357
EA
143 InChannel = stdin;
144 OutChannel = stdout;
b3cbe40f 145 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
29871fef 146 (void) signal(SIGINT, finis);
eb211e2c
EA
147 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
148 (void) signal(SIGHUP, finis);
29871fef 149 (void) signal(SIGTERM, finis);
a0554f81 150 OldUmask = umask(0);
d0bd03ce 151 Mode = MD_DEFAULT;
dd1fe05b
EA
152
153 /* set up the main envelope */
154 MainEnvelope.e_puthdr = putheader;
155 MainEnvelope.e_putbody = putbody;
2654b031 156 CurEnv = &MainEnvelope;
dd1fe05b 157
b3cbe40f 158# ifdef LOG
96faada8 159 openlog("sendmail", 0);
b3cbe40f 160# endif LOG
49086753 161 openxscrpt();
b3cbe40f
EA
162# ifdef DEBUG
163# ifdef DEBUGFILE
164 if ((i = open(DEBUGFILE, 1)) > 0)
165 {
29871fef
EA
166 (void) lseek(i, 0L, 2);
167 (void) close(1);
168 (void) dup(i);
169 (void) close(i);
b3cbe40f
EA
170 Debug++;
171 }
172# endif DEBUGFILE
b3cbe40f
EA
173# endif
174 errno = 0;
175 from = NULL;
2654b031 176 CurEnv->e_oldstyle = TRUE;
721fad23 177 initmacros();
b3cbe40f
EA
178
179 /*
180 ** Crack argv.
181 */
182
183 while (--argc > 0 && (p = *++argv)[0] == '-')
184 {
185 switch (p[1])
186 {
187 case 'r': /* obsolete -f flag */
188 case 'f': /* from address */
189 p += 2;
190 if (*p == '\0')
191 {
192 p = *++argv;
193 if (--argc <= 0 || *p == '-')
194 {
195 syserr("No \"from\" person");
196 argc++;
197 argv--;
198 break;
199 }
200 }
201 if (from != NULL)
202 {
203 syserr("More than one \"from\" person");
204 break;
205 }
206 from = p;
207 break;
208
6da7b890 209 case 'F': /* set full name */
74c5fe7c
EA
210 p += 2;
211 if (*p == '\0')
212 {
213 p = *++argv;
214 if (--argc <= 0 || *p == '-')
215 {
216 syserr("Bad -F flag");
217 argc++;
218 argv--;
219 break;
220 }
221 }
cbdb7357 222 FullName = p;
6da7b890
EA
223 break;
224
b3cbe40f
EA
225 case 'h': /* hop count */
226 p += 2;
227 if (*p == '\0')
228 {
229 p = *++argv;
230 if (--argc <= 0 || *p < '0' || *p > '9')
231 {
232 syserr("Bad hop count (%s)", p);
233 argc++;
234 argv--;
235 break;
236 }
237 }
238 HopCount = atoi(p);
239 break;
240
241 case 'e': /* error message disposition */
242 switch (p[2])
243 {
244 case 'p': /* print errors normally */
245 break; /* (default) */
246
247 case 'q': /* be silent about it */
29871fef 248 (void) freopen("/dev/null", "w", stdout);
b3cbe40f
EA
249 break;
250
251 case 'm': /* mail back */
49086753
EA
252 MailBack = TRUE;
253 HoldErrs = TRUE;
b3cbe40f
EA
254 break;
255
3b661a43 256 case 'e': /* do berknet error processing */
49086753
EA
257 BerkNet = TRUE;
258 HoldErrs = TRUE;
b3cbe40f
EA
259 break;
260
261 case 'w': /* write back (or mail) */
49086753
EA
262 WriteBack = TRUE;
263 HoldErrs = TRUE;
b3cbe40f
EA
264 break;
265 }
266 break;
267
268# ifdef DEBUG
269 case 'd': /* debug */
6da7b890
EA
270 Debug = atoi(&p[2]);
271 if (Debug <= 0)
272 Debug = 1;
62fff4f9 273 setbuf(stdout, (char *) NULL);
6da7b890 274 printf("Version %s Debug %d\n", Version, Debug);
b3cbe40f 275 break;
1a12c7d6 276
f6a0cc15 277 case 'M': /* redefine internal macro */
dc39c568 278 define(p[2], &p[3]);
1a12c7d6 279 break;
b3cbe40f 280# endif DEBUG
d6a28dd8 281
6da7b890 282 case 'C': /* select configuration file */
6a5effbb 283 if (p[2] == '\0')
4e1f4d4b 284 ConfFile = "sendmail.cf";
6a5effbb 285 else
4e1f4d4b 286 ConfFile = &p[2];
eb211e2c 287 safecf = FALSE;
d6a28dd8 288 break;
cdb17311
EA
289
290 case 'A': /* select alias file */
6a5effbb 291 if (p[2] == '\0')
4e1f4d4b 292 AliasFile = "aliases";
6a5effbb 293 else
4e1f4d4b 294 AliasFile = &p[2];
cdb17311 295 break;
ed45aae1
EA
296
297 case 'Q': /* select queue dir */
298 if (p[2] == '\0')
b715ed3c 299 QueueDir = "mqueue";
ed45aae1 300 else
b715ed3c 301 QueueDir = &p[2];
ed45aae1
EA
302 break;
303
304 case 'T': /* set timeout interval */
305 TimeOut = convtime(&p[2]);
306 break;
b3cbe40f
EA
307
308 case 'n': /* don't alias */
309 NoAlias++;
310 break;
311
f4dbf345
EA
312# ifdef DBM
313 case 'I': /* initialize alias DBM file */
314 aliasinit = TRUE;
d6b27179 315 Verbose = TRUE;
f4dbf345
EA
316 break;
317# endif DBM
318
b3cbe40f
EA
319 case 'm': /* send to me too */
320 MeToo++;
321 break;
322
323 case 'i': /* don't let dot stop me */
324 IgnrDot++;
325 break;
326
327 case 'a': /* arpanet format */
49086753
EA
328 ArpaMode = TRUE;
329 if (p[2] == 's')
dc39c568 330 {
49086753 331 /* running smtp */
884a20cb 332# ifdef SMTP
49086753 333 Smtp = TRUE;
884a20cb
EA
334# else SMTP
335 syserr("I don't speak SMTP");
336# endif SMTP
dc39c568 337 }
b3cbe40f 338 break;
3135d20c
EA
339
340# ifdef QUEUE
341 case 'c': /* don't connect to non-local mailers */
342 NoConnect = TRUE;
343 break;
344# endif QUEUE
b3cbe40f
EA
345
346 case 's': /* save From lines in headers */
347 SaveFrom++;
348 break;
349
d59b067a
EA
350 case 'v': /* give blow-by-blow description */
351 Verbose++;
352 break;
353
bfcddd93
EA
354 case 't': /* read recipients from message */
355 GrabTo = TRUE;
356 break;
357
d0bd03ce
EA
358 case 'b': /* operations mode */
359 Mode = p[2];
360 switch (Mode)
361 {
362 case MD_DAEMON: /* run as a daemon */
14a39063 363#ifdef DAEMON
d0bd03ce 364 ArpaMode = Smtp = TRUE;
4aebfe5d 365#else DAEMON
d0bd03ce 366 syserr("Daemon mode not implemented");
14a39063 367#endif DAEMON
d0bd03ce
EA
368 break;
369
370 case '\0': /* default: do full delivery */
371 Mode = MD_DEFAULT;
372 /* fall through....... */
373
374 case MD_DELIVER: /* do everything (default) */
375 case MD_FORK: /* fork after verification */
376 case MD_QUEUE: /* queue only */
377 case MD_VERIFY: /* verify only */
378 break;
379
380 default:
381 syserr("Unknown operation mode -b%c", Mode);
382 exit(EX_USAGE);
383 }
14a39063 384 break;
cbdb7357 385
ed45aae1 386 case 'q': /* run queue files at intervals */
884a20cb 387# ifdef QUEUE
aba51985 388 queuemode = TRUE;
25b9d645 389 QueueIntvl = convtime(&p[2]);
884a20cb
EA
390# else QUEUE
391 syserr("I don't know about queues");
392# endif QUEUE
ed45aae1
EA
393 break;
394
49a45ae5 395 case 'o': /* take new-style headers (with commas) */
2654b031 396 CurEnv->e_oldstyle = FALSE;
35cc3fad
EA
397 break;
398
b3cbe40f
EA
399 default:
400 /* at Eric Schmidt's suggestion, this will not be an error....
401 syserr("Unknown flag %s", p);
402 ... seems that upward compatibility will be easier. */
403 break;
404 }
405 }
406
9e3c0a28 407 /*
f6a0cc15 408 ** Read system control file.
179c1218 409 ** Extract special fields for local use.
9e3c0a28
EA
410 */
411
4e1f4d4b 412 readcf(ConfFile, safecf);
ed45aae1 413 initsys();
179c1218
EA
414
415 /* our name for SMTP codes */
dd1fe05b 416 expand("$i", ibuf, &ibuf[sizeof ibuf - 1], CurEnv);
2768afe3 417 HostName = ibuf;
d6a28dd8 418
179c1218
EA
419 /* the indices of local and program mailers */
420 st = stab("local", ST_MAILER, ST_FIND);
421 if (st == NULL)
422 syserr("No local mailer defined");
423 else
424 LocalMailer = st->s_mailer;
425 st = stab("prog", ST_MAILER, ST_FIND);
426 if (st == NULL)
427 syserr("No prog mailer defined");
428 else
429 ProgMailer = st->s_mailer;
430
f6a0cc15
EA
431 /*
432 ** Initialize aliases.
433 */
8acb5142 434
4e1f4d4b 435 initaliases(AliasFile, aliasinit);
f4dbf345
EA
436# ifdef DBM
437 if (aliasinit)
438 exit(EX_OK);
439# endif DBM
cdb17311 440
9c6d4c70
EA
441# ifdef DEBUG
442 if (Debug > 15)
443 {
f6a0cc15 444 /* print configuration table (or at least part of it) */
9c6d4c70
EA
445 printrules();
446 for (i = 0; i < MAXMAILERS; i++)
447 {
448 register struct mailer *m = Mailer[i];
449
450 if (m == NULL)
451 continue;
8a6c20a5 452 printf("mailer %d: %s %s %lo %s\n", i, m->m_name,
9c6d4c70
EA
453 m->m_mailer, m->m_flags, m->m_from);
454 }
455 }
456# endif DEBUG
457
14a39063 458#ifdef DAEMON
f6a0cc15
EA
459 /*
460 ** If a daemon, wait for a request.
461 ** getrequests will always return in a child.
25b9d645
EA
462 ** If we should also be processing the queue, start
463 ** doing it in background.
f6a0cc15
EA
464 */
465
d0bd03ce 466 if (Mode == MD_DAEMON)
25b9d645
EA
467 {
468# ifdef QUEUE
469 if (queuemode)
470 runqueue(TRUE);
471# endif QUEUE
f6a0cc15 472 getrequests();
25b9d645 473 }
14a39063 474#endif DAEMON
cbdb7357 475
884a20cb 476# ifdef SMTP
b3cbe40f 477 /*
cbdb7357
EA
478 if (Smtp)
479 smtp();
884a20cb 480# endif SMTP
a9e0e597 481
884a20cb 482# ifdef QUEUE
ed45aae1
EA
483 /*
484 ** If collecting stuff from the queue, go start doing that.
485 */
486
d0bd03ce 487 if (queuemode && Mode != MD_DAEMON)
ed45aae1 488 {
2cf55cb7 489 runqueue(FALSE);
ed45aae1
EA
490 finis();
491 }
884a20cb 492# endif QUEUE
ed45aae1 493
f6a0cc15 494 /*
cbdb7357 495 ** Set the sender
f6a0cc15
EA
496 */
497
cbdb7357 498 setsender(from);
a9e0e597 499
d0bd03ce 500 if (Mode != MD_DAEMON && argc <= 0 && !GrabTo)
e863b1fa 501 {
96faada8 502 usrerr("Usage: /etc/sendmail [flags] addr...");
e863b1fa
EA
503 finis();
504 }
b3cbe40f
EA
505
506 /*
507 ** Process Hop count.
508 ** The Hop count tells us how many times this message has
96faada8 509 ** been processed by sendmail. If it exceeds some
b3cbe40f
EA
510 ** fairly large threshold, then we assume that we have
511 ** an infinite forwarding loop and die.
512 */
513
514 if (++HopCount > MAXHOP)
2654b031 515 syserr("Infinite forwarding loop (%s->%s)", CurEnv->e_from.q_paddr, *argv);
b3cbe40f 516
b3cbe40f 517 /*
d6b27179
EA
518 ** Scan argv and deliver the message to everyone.
519 ** Actually, suppress delivery if we are taking To:
520 ** lines from the message.
b3cbe40f
EA
521 */
522
23a54ee3
EA
523 if (GrabTo)
524 DontSend = TRUE;
cbdb7357 525 sendtoargv(argv);
b3cbe40f 526
a4b004a6 527 /* if we have had errors sofar, drop out now */
d916f0ca 528 if (Errors > 0 && ExitStat == EX_OK)
a4b004a6 529 ExitStat = EX_USAGE;
a4b004a6 530
dc39c568
EA
531 /*
532 ** Read the input mail.
533 */
534
23a54ee3 535 DontSend = FALSE;
2654b031 536 CurEnv->e_to = NULL;
d0bd03ce 537 if (Mode != MD_VERIFY || GrabTo)
49086753 538 collect(FALSE);
d829793b 539 errno = 0;
35cc3fad
EA
540
541 /*
542 ** If we don't want to wait around for actual delivery, this
543 ** is a good time to fork off.
544 ** We have examined what we can without doing actual
545 ** delivery, so we will inform our caller of
546 ** whatever we can now.
547 ** Since the parent process will go away immediately,
548 ** the child will be caught by init.
549 ** If the fork fails, we will just continue in the
550 ** parent; this is perfectly safe, albeit
551 ** slower than it must be.
552 */
553
d0bd03ce 554 if (Mode == MD_FORK)
35cc3fad
EA
555 {
556 if (fork() > 0)
557 {
558 /* parent -- quit */
559 exit(ExitStat);
560 }
561 }
d0bd03ce
EA
562 else if (Mode == MD_QUEUE)
563 {
564 queueup(CurEnv, TRUE);
565 exit(ExitStat);
566 }
35cc3fad 567
ed45aae1 568 initsys();
bfcddd93 569
4e1f4d4b 570 /* collect statistics */
2654b031
EA
571 Stat.stat_nf[CurEnv->e_from.q_mailer->m_mno]++;
572 Stat.stat_bf[CurEnv->e_from.q_mailer->m_mno] += kbytes(CurEnv->e_msgsize);
4e1f4d4b 573
b3cbe40f 574 /*
dc39c568
EA
575 ** Arrange that the person who is sending the mail
576 ** will not be expanded (unless explicitly requested).
b3cbe40f
EA
577 */
578
d6b27179
EA
579# ifdef DEBUG
580 if (Debug)
2654b031 581 printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
d6b27179
EA
582# endif DEBUG
583
2654b031 584 CurEnv->e_from.q_flags |= QDONTSEND;
b3cbe40f 585 if (!MeToo)
2654b031
EA
586 recipient(&CurEnv->e_from, &CurEnv->e_sendqueue);
587 CurEnv->e_to = NULL;
b3cbe40f
EA
588
589 /*
590 ** Actually send everything.
d6b27179 591 ** If verifying, just ack.
b3cbe40f
EA
592 */
593
3c7fe765 594 sendall(CurEnv, Mode == MD_VERIFY);
b3cbe40f
EA
595
596 /*
597 ** All done.
598 */
599
2654b031 600 CurEnv->e_to = NULL;
d0bd03ce 601 if (Mode != MD_VERIFY)
d6b27179 602 poststats(StatFile);
b3cbe40f
EA
603 finis();
604}
605\f/*
f65e7ded
EA
606** SETFROM -- set the person who this message is from
607**
608** Under certain circumstances allow the user to say who
609** s/he is (using -f or -r). These are:
610** 1. The user's uid is zero (root).
611** 2. The user's login name is "network" (mail from
612** a network server).
613** 3. The user's login name is "uucp" (mail from the
614** uucp network).
615** 4. The address the user is trying to claim has a
616** "!" character in it (since #3 doesn't do it for
617** us if we are dialing out).
618** A better check to replace #3 & #4 would be if the
619** effective uid is "UUCP" -- this would require me
620** to rewrite getpwent to "grab" uucp as it went by,
621** make getname more nasty, do another passwd file
622** scan, or compile the UID of "UUCP" into the code,
623** all of which are reprehensible.
624**
625** Assuming all of these fail, we figure out something
626** ourselves.
627**
628** Parameters:
629** from -- the person it is from.
630** realname -- the actual person executing sendmail.
dc39c568
EA
631** If NULL, then take whoever we previously
632** thought was the from person.
f65e7ded
EA
633**
634** Returns:
635** none.
636**
637** Side Effects:
638** sets sendmail's notion of who the from person is.
639*/
640
641setfrom(from, realname)
642 char *from;
643 char *realname;
644{
645 register char **pvp;
646 char frombuf[MAXNAME];
647 extern char **prescan();
648 extern char *index();
da6a9b77 649 extern char *macvalue();
f65e7ded 650
dc39c568 651 if (realname == NULL)
2654b031 652 realname = CurEnv->e_from.q_paddr;
84b4028f
EA
653
654# ifdef DEBUG
655 if (Debug > 1)
656 printf("setfrom(%s, %s)\n", from, realname);
657# endif DEBUG
658
1bcdf0a2
EA
659 /*
660 ** Do validation to determine whether this user is allowed
661 ** to change the sender name.
662 */
663
f65e7ded
EA
664 if (from != NULL)
665 {
46af5a18
EA
666 if (strcmp(realname, "network") != 0 &&
667 strcmp(realname, "uucp") != 0 &&
668 strcmp(realname, "daemon") != 0 &&
d829793b
EA
669# ifdef DEBUG
670 (Debug == 0 || getuid() != geteuid()) &&
671# endif DEBUG
f65e7ded
EA
672 index(from, '!') == NULL && getuid() != 0)
673 {
674 /* network sends -r regardless (why why why?) */
675 /* syserr("%s, you cannot use the -f flag", realname); */
676 from = NULL;
677 }
678 }
679
1bcdf0a2
EA
680 /*
681 ** Parse the sender name.
682 ** Arrange to send return messages to the same person.
683 ** Set up some environment info.
684 */
685
f65e7ded 686 SuprErrs = TRUE;
2654b031 687 if (from == NULL || parse(from, &CurEnv->e_from, 1) == NULL)
f65e7ded
EA
688 {
689 from = newstr(realname);
2654b031 690 (void) parse(from, &CurEnv->e_from, 1);
f65e7ded
EA
691 }
692 else
693 FromFlag = TRUE;
1bcdf0a2 694 CurEnv->e_returnto = &CurEnv->e_from;
f65e7ded 695 SuprErrs = FALSE;
2654b031
EA
696 CurEnv->e_from.q_uid = getuid();
697 CurEnv->e_from.q_gid = getgid();
1bf7c76b 698# ifndef V6
2654b031 699 CurEnv->e_from.q_home = getenv("HOME");
1bf7c76b 700# endif V6
2654b031 701 if (CurEnv->e_from.q_uid != 0)
35cc3fad 702 {
2654b031
EA
703 DefUid = CurEnv->e_from.q_uid;
704 DefGid = CurEnv->e_from.q_gid;
35cc3fad 705 }
f65e7ded 706
d87a0dbb
EA
707 /*
708 ** Set up the $r and $s macros to show who it came from.
709 */
710
da6a9b77
EA
711 if (macvalue('s') == NULL && CurEnv->e_from.q_host != NULL &&
712 CurEnv->e_from.q_host[0] != '\0')
d87a0dbb 713 {
2654b031 714 define('s', CurEnv->e_from.q_host);
d87a0dbb
EA
715
716 /* should determine network type here */
717 }
718
f65e7ded
EA
719 /*
720 ** Rewrite the from person to dispose of possible implicit
721 ** links in the net.
722 */
723
724 pvp = prescan(from, '\0');
725 if (pvp == NULL)
726 {
727 syserr("cannot prescan from (%s)", from);
728 finis();
729 }
730 rewrite(pvp, 1);
31b33174 731 cataddr(pvp, frombuf, sizeof frombuf);
f65e7ded
EA
732 define('f', newstr(frombuf));
733}
734\f/*
b3cbe40f
EA
735** FINIS -- Clean up and exit.
736**
b3cbe40f
EA
737** Parameters:
738** none
739**
740** Returns:
741** never
742**
743** Side Effects:
96faada8 744** exits sendmail
b3cbe40f
EA
745*/
746
747finis()
748{
3c7fe765
EA
749 CurEnv = &MainEnvelope;
750
aba51985 751# ifdef DEBUG
79bd7c07 752 if (Debug > 0)
3c7fe765 753 {
2654b031
EA
754 printf("\n====finis: stat %d sendreceipt %d FatalErrors %d\n",
755 ExitStat, CurEnv->e_sendreceipt, FatalErrors);
3c7fe765 756 }
aba51985
EA
757# endif DEBUG
758
79bd7c07 759 /* send back return receipts as requested */
2654b031 760 if (CurEnv->e_sendreceipt && ExitStat == EX_OK)
f9566d23 761 (void) returntosender("Return receipt", &CurEnv->e_from, FALSE);
79bd7c07 762
3c7fe765
EA
763 /* do error handling */
764 checkerrors(CurEnv);
b3cbe40f 765
3c7fe765 766 /* now clean up bookeeping information */
ed45aae1 767 if (Transcript != NULL)
29871fef 768 (void) unlink(Transcript);
3c7fe765 769 if (!CurEnv->e_queueup)
1ff06f70 770 (void) unlink(CurEnv->e_df);
b3cbe40f
EA
771 exit(ExitStat);
772}
773\f/*
b3cbe40f
EA
774** OPENXSCRPT -- Open transcript file
775**
776** Creates a transcript file for possible eventual mailing or
777** sending back.
778**
779** Parameters:
780** none
781**
782** Returns:
783** none
784**
785** Side Effects:
786** Turns the standard output into a special file
787** somewhere.
b3cbe40f
EA
788*/
789
790openxscrpt()
791{
7b9c35c8 792 extern char *mktemp();
49086753 793 register char *p;
7b9c35c8 794
49086753
EA
795 p = newstr(XcriptFile);
796 (void) mktemp(p);
797 Xscript = fopen(p, "w");
798 if (Xscript == NULL)
aba51985 799 {
49086753
EA
800 Xscript = stdout;
801 syserr("Can't create %s", p);
aba51985 802 }
49086753
EA
803 Transcript = p;
804 (void) chmod(p, 0600);
b3cbe40f 805}
cbdb7357
EA
806\f/*
807** SETSENDER -- set sendmail's idea of the sender.
808**
809** Parameters:
810** from -- the person we would like to believe this
811** is from.
812**
813** Returns:
814** none.
815**
816** Side Effects:
817** Sets the idea of the sender.
818*/
819
820setsender(from)
821 char *from;
822{
823 register char *p;
824 extern char *getlogin();
825 register struct passwd *pw;
826 char *realname;
827 char cfbuf[40];
e863b1fa 828 bool nofullname;
61bc683a 829 extern char *macvalue();
cbdb7357
EA
830
831 /*
832 ** Figure out the real user executing us.
833 ** Getlogin can return errno != 0 on non-errors.
834 */
835
aba51985 836 if (!Smtp && !QueueRun)
cbdb7357
EA
837 {
838 errno = 0;
839 p = getlogin();
840 errno = 0;
e863b1fa 841 nofullname = (from != NULL);
cbdb7357 842 }
df7a9713 843 else
e863b1fa 844 {
df7a9713 845 p = from;
e863b1fa
EA
846 nofullname = FALSE;
847 }
110bf461 848 if (p != NULL && p[0] != '\0')
df7a9713
EA
849 {
850 extern struct passwd *getpwnam();
851
852 pw = getpwnam(p);
853 if (pw == NULL)
854 {
aba51985 855 if (!Smtp && !QueueRun)
df7a9713
EA
856 syserr("Who are you? (name=%s)", p);
857 p = NULL;
858 }
859 }
110bf461 860 if (p == NULL || p[0] == '\0')
cbdb7357
EA
861 {
862 extern struct passwd *getpwuid();
863 int uid;
864
e863b1fa 865 nofullname = TRUE;
cbdb7357
EA
866 uid = getruid();
867 pw = getpwuid(uid);
868 if (pw == NULL)
869 syserr("Who are you? (uid=%d)", uid);
870 else
871 p = pw->pw_name;
872 }
cbdb7357
EA
873 if (p == NULL || p[0] == '\0' || pw == NULL)
874 finis();
875
876 realname = p;
877
878 /*
879 ** Process passwd file entry.
880 */
881
882 /* run user's .mailcf file */
883 define('z', pw->pw_dir);
dd1fe05b 884 expand("$z/.mailcf", cfbuf, &cfbuf[sizeof cfbuf - 1], CurEnv);
e863b1fa 885 if (!nofullname && safefile(cfbuf, getruid(), S_IREAD))
cbdb7357
EA
886 readcf(cfbuf, FALSE);
887
61bc683a
EA
888 /* if the user has given fullname already, don't redefine */
889 if (FullName == NULL)
890 FullName = macvalue('x');
891
cbdb7357 892 /* extract full name from passwd file */
e863b1fa 893 if (!nofullname && (FullName == NULL || FullName[0] == '\0') &&
cbdb7357
EA
894 pw != NULL && pw->pw_gecos != NULL)
895 {
896 char nbuf[MAXNAME];
897
abae7b2d 898 fullname(pw, nbuf);
df7a9713 899 if (nbuf[0] != '\0')
cbdb7357
EA
900 FullName = newstr(nbuf);
901 }
902 if (FullName != NULL && FullName[0] != '\0')
903 define('x', FullName);
904
905 setfrom(from, realname);
906}
ed45aae1
EA
907\f/*
908** INITSYS -- initialize instantiation of system
909**
910** In Daemon mode, this is done in the child.
911**
912** Parameters:
913** none.
914**
915** Returns:
916** none.
917**
918** Side Effects:
919** Initializes the system macros, some global variables,
920** etc. In particular, the current time in various
921** forms is set.
922*/
923
924initsys()
925{
926 static char cbuf[5]; /* holds hop count */
927 static char dbuf[30]; /* holds ctime(tbuf) */
928 static char pbuf[10]; /* holds pid */
929 static char tbuf[10]; /* holds "current" time */
930 static char ybuf[10]; /* holds tty id */
931 register char *p;
932 extern char *ttyname();
933 extern char *arpadate();
ed45aae1
EA
934
935 /* convert timeout interval to absolute time */
aba51985 936 TimeOut -= CurTime;
ed45aae1
EA
937 (void) time(&CurTime);
938 TimeOut += CurTime;
939
940 /* process id */
941 (void) sprintf(pbuf, "%d", getpid());
942 define('p', pbuf);
943
944 /* hop count */
945 (void) sprintf(cbuf, "%d", HopCount);
946 define('c', cbuf);
947
948 /* time as integer, unix time, arpa time */
949 (void) sprintf(tbuf, "%ld", &CurTime);
950 define('t', tbuf);
951 (void) strcpy(dbuf, ctime(&CurTime));
952 *index(dbuf, '\n') = '\0';
e863b1fa
EA
953 if (macvalue('d') == NULL)
954 define('d', dbuf);
955 p = newstr(arpadate(dbuf));
956 if (macvalue('a') == NULL)
957 define('a', p);
ed45aae1
EA
958 define('b', p);
959
960 /* version */
961 define('v', Version);
962
963 /* tty name */
e863b1fa 964 if (macvalue('y') == NULL)
ed45aae1 965 {
e863b1fa
EA
966 p = ttyname(2);
967 if (p != NULL)
968 {
969 if (rindex(p, '/') != NULL)
970 p = rindex(p, '/') + 1;
f9566d23 971 (void) strcpy(ybuf, p);
e863b1fa
EA
972 define('y', ybuf);
973 }
ed45aae1
EA
974 }
975}
721fad23
EA
976\f/*
977** INITMACROS -- initialize the macro system
978**
979** This just involves defining some macros that are actually
980** used internally as metasymbols to be themselves.
981**
982** Parameters:
983** none.
984**
985** Returns:
986** none.
987**
988** Side Effects:
989** initializes several macros to be themselves.
990*/
991
9dbc8d99 992struct metamac
721fad23 993{
9dbc8d99
EA
994 char metaname;
995 char metaval;
996};
721fad23 997
9dbc8d99
EA
998struct metamac MetaMacros[] =
999{
721fad23 1000 /* these are important on the LHS */
9dbc8d99 1001 '+', MATCHANY, '-', MATCHONE, '=', MATCHCLASS,
721fad23
EA
1002
1003 /* these are RHS metasymbols */
9dbc8d99 1004 '#', CANONNET, '@', CANONHOST, ':', CANONUSER,
721fad23 1005
9dbc8d99
EA
1006 /* and finally the conditional operations */
1007 '?', CONDIF, '|', CONDELSE, '.', CONDFI,
1008
1009 '\0'
721fad23
EA
1010};
1011
1012initmacros()
1013{
9dbc8d99
EA
1014 register struct metamac *m;
1015 char buf[5];
1016 register int c;
721fad23 1017
9dbc8d99
EA
1018 for (m = MetaMacros; m->metaname != '\0'; m++)
1019 {
1020 buf[0] = m->metaval;
1021 buf[1] = '\0';
1022 define(m->metaname, newstr(buf));
1023 }
1024 buf[0] = MATCHREPL;
1025 buf[2] = '\0';
1026 for (c = '0'; c <= '9'; c++)
1027 {
1028 buf[1] = c;
1029 define(c, newstr(buf));
1030 }
721fad23 1031}
dd1fe05b
EA
1032\f/*
1033** NEWENVELOPE -- allocate a new envelope
1034**
1035** Supports inheritance.
1036**
1037** Parameters:
1038** e -- the new envelope to fill in.
1039**
1040** Returns:
1041** e.
1042**
1043** Side Effects:
1044** none.
1045*/
1046
1047ENVELOPE *
1048newenvelope(e)
1049 register ENVELOPE *e;
1050{
f9566d23 1051 bmove((char *) CurEnv, (char *) e, sizeof *e);
dd1fe05b
EA
1052 e->e_header = NULL;
1053 e->e_queueup = FALSE;
1054 e->e_oldstyle = FALSE;
1055 e->e_retreceipt = FALSE;
1056 e->e_sendreceipt = FALSE;
1057 e->e_origfrom = NULL;
1058 e->e_to = NULL;
1059 e->e_sendqueue = NULL;
3c7fe765 1060 e->e_errorqueue = NULL;
dd1fe05b
EA
1061 e->e_parent = CurEnv;
1062 e->e_df = NULL;
1ff06f70
EA
1063
1064 return (e);
dd1fe05b 1065}