LINT
[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
62fff4f9 10static 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 105int NextMailer = 0; /* "free" index into Mailer struct */
cbdb7357 106static char *FullName; /* sender's full name */
b3cbe40f
EA
107
108
109
110
111
112
113main(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
546setfrom(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
620finis()
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
659openxscrpt()
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
689setsender(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
782initsys()
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}