|
|
1.1 root 1: /*
2: ** Sendmail
3: ** Copyright (c) 1983 Eric P. Allman
4: ** Berkeley, California
5: **
6: ** Copyright (c) 1983 Regents of the University of California.
7: ** All rights reserved. The Berkeley software License Agreement
8: ** specifies the terms and conditions for redistribution.
9: */
10:
11: #ifndef lint
12: static char SccsId[] = "@(#)conf.c 5.14 (Berkeley) 1/10/86";
13: #endif not lint
14:
15: # include <pwd.h>
16: # include <sys/ioctl.h>
17: # ifdef sun
18: # include <sys/param.h>
19: # endif sun
20: # include "sendmail.h"
21:
22: /*
23: ** CONF.C -- Sendmail Configuration Tables.
24: **
25: ** Defines the configuration of this installation.
26: **
27: ** Compilation Flags:
28: ** V6 -- running on a version 6 system. This determines
29: ** whether to define certain routines between
30: ** the two systems. If you are running a funny
31: ** system, e.g., V6 with long tty names, this
32: ** should be checked carefully.
33: ** VMUNIX -- running on a Berkeley UNIX system.
34: **
35: ** Configuration Variables:
36: ** HdrInfo -- a table describing well-known header fields.
37: ** Each entry has the field name and some flags,
38: ** which are described in sendmail.h.
39: **
40: ** Notes:
41: ** I have tried to put almost all the reasonable
42: ** configuration information into the configuration
43: ** file read at runtime. My intent is that anything
44: ** here is a function of the version of UNIX you
45: ** are running, or is really static -- for example
46: ** the headers are a superset of widely used
47: ** protocols. If you find yourself playing with
48: ** this file too much, you may be making a mistake!
49: */
50:
51:
52:
53:
54: /*
55: ** Header info table
56: ** Final (null) entry contains the flags used for any other field.
57: **
58: ** Not all of these are actually handled specially by sendmail
59: ** at this time. They are included as placeholders, to let
60: ** you know that "someday" I intend to have sendmail do
61: ** something with them.
62: */
63:
64: struct hdrinfo HdrInfo[] =
65: {
66: /* originator fields, most to least significant */
67: "resent-sender", H_FROM|H_RESENT,
68: "resent-from", H_FROM|H_RESENT,
69: "resent-reply-to", H_FROM|H_RESENT,
70: "sender", H_FROM,
71: "from", H_FROM,
72: "reply-to", H_FROM,
73: "full-name", H_ACHECK,
74: "return-receipt-to", H_FROM,
75: "errors-to", H_FROM,
76: /* destination fields */
77: "to", H_RCPT,
78: "resent-to", H_RCPT|H_RESENT,
79: "cc", H_RCPT,
80: "resent-cc", H_RCPT|H_RESENT,
81: "bcc", H_RCPT|H_ACHECK,
82: "resent-bcc", H_RCPT|H_ACHECK|H_RESENT,
83: /* message identification and control */
84: "message-id", 0,
85: "resent-message-id", H_RESENT,
86: "message", H_EOH,
87: "text", H_EOH,
88: /* date fields */
89: "date", 0,
90: "resent-date", H_RESENT,
91: /* trace fields */
92: "received", H_TRACE|H_FORCE,
93: "via", H_TRACE|H_FORCE,
94: "mail-from", H_TRACE|H_FORCE,
95:
96: NULL, 0,
97: };
98:
99:
100: /*
101: ** ARPANET error message numbers.
102: */
103:
104: char Arpa_Info[] = "050"; /* arbitrary info */
105: char Arpa_TSyserr[] = "451"; /* some (transient) system error */
106: char Arpa_PSyserr[] = "554"; /* some (permanent) system error */
107: char Arpa_Usrerr[] = "554"; /* some (fatal) user error */
108:
109:
110:
111: /*
112: ** Location of system files/databases/etc.
113: */
114:
115: char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */
116: char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */
117:
118:
119:
120: /*
121: ** Miscellaneous stuff.
122: */
123:
124: int DtableSize = 50; /* max open files; reset in 4.2bsd */
125: /*
126: ** SETDEFAULTS -- set default values
127: **
128: ** Because of the way freezing is done, these must be initialized
129: ** using direct code.
130: **
131: ** Parameters:
132: ** none.
133: **
134: ** Returns:
135: ** none.
136: **
137: ** Side Effects:
138: ** Initializes a bunch of global variables to their
139: ** default values.
140: */
141:
142: setdefaults()
143: {
144: QueueLA = 8;
145: QueueFactor = 10000;
146: RefuseLA = 12;
147: SpaceSub = ' ';
148: WkRecipFact = 1000;
149: WkClassFact = 1800;
150: WkTimeFact = 9000;
151: FileMode = 0644;
152: DefUid = 1;
153: DefGid = 1;
154: }
155:
156: # ifdef V6
157: /*
158: ** TTYNAME -- return name of terminal.
159: **
160: ** Parameters:
161: ** fd -- file descriptor to check.
162: **
163: ** Returns:
164: ** pointer to full path of tty.
165: ** NULL if no tty.
166: **
167: ** Side Effects:
168: ** none.
169: */
170:
171: char *
172: ttyname(fd)
173: int fd;
174: {
175: register char tn;
176: static char pathn[] = "/dev/ttyx";
177:
178: /* compute the pathname of the controlling tty */
179: if ((tn = ttyn(fd)) == NULL)
180: {
181: errno = 0;
182: return (NULL);
183: }
184: pathn[8] = tn;
185: return (pathn);
186: }
187: /*
188: ** FDOPEN -- Open a stdio file given an open file descriptor.
189: **
190: ** This is included here because it is standard in v7, but we
191: ** need it in v6.
192: **
193: ** Algorithm:
194: ** Open /dev/null to create a descriptor.
195: ** Close that descriptor.
196: ** Copy the existing fd into the descriptor.
197: **
198: ** Parameters:
199: ** fd -- the open file descriptor.
200: ** type -- "r", "w", or whatever.
201: **
202: ** Returns:
203: ** The file descriptor it creates.
204: **
205: ** Side Effects:
206: ** none
207: **
208: ** Called By:
209: ** deliver
210: **
211: ** Notes:
212: ** The mode of fd must match "type".
213: */
214:
215: FILE *
216: fdopen(fd, type)
217: int fd;
218: char *type;
219: {
220: register FILE *f;
221:
222: f = fopen("/dev/null", type);
223: (void) close(fileno(f));
224: fileno(f) = fd;
225: return (f);
226: }
227: /*
228: ** INDEX -- Return pointer to character in string
229: **
230: ** For V7 compatibility.
231: **
232: ** Parameters:
233: ** s -- a string to scan.
234: ** c -- a character to look for.
235: **
236: ** Returns:
237: ** If c is in s, returns the address of the first
238: ** instance of c in s.
239: ** NULL if c is not in s.
240: **
241: ** Side Effects:
242: ** none.
243: */
244:
245: char *
246: index(s, c)
247: register char *s;
248: register char c;
249: {
250: while (*s != '\0')
251: {
252: if (*s++ == c)
253: return (--s);
254: }
255: return (NULL);
256: }
257: /*
258: ** UMASK -- fake the umask system call.
259: **
260: ** Since V6 always acts like the umask is zero, we will just
261: ** assume the same thing.
262: */
263:
264: /*ARGSUSED*/
265: umask(nmask)
266: {
267: return (0);
268: }
269:
270:
271: /*
272: ** GETRUID -- get real user id.
273: */
274:
275: getruid()
276: {
277: return (getuid() & 0377);
278: }
279:
280:
281: /*
282: ** GETRGID -- get real group id.
283: */
284:
285: getrgid()
286: {
287: return (getgid() & 0377);
288: }
289:
290:
291: /*
292: ** GETEUID -- get effective user id.
293: */
294:
295: geteuid()
296: {
297: return ((getuid() >> 8) & 0377);
298: }
299:
300:
301: /*
302: ** GETEGID -- get effective group id.
303: */
304:
305: getegid()
306: {
307: return ((getgid() >> 8) & 0377);
308: }
309:
310: # endif V6
311:
312: # ifndef V6
313:
314: /*
315: ** GETRUID -- get real user id (V7)
316: */
317:
318: getruid()
319: {
320: if (OpMode == MD_DAEMON)
321: return (RealUid);
322: else
323: return (getuid());
324: }
325:
326:
327: /*
328: ** GETRGID -- get real group id (V7).
329: */
330:
331: getrgid()
332: {
333: if (OpMode == MD_DAEMON)
334: return (RealGid);
335: else
336: return (getgid());
337: }
338:
339: # endif V6
340: /*
341: ** USERNAME -- return the user id of the logged in user.
342: **
343: ** Parameters:
344: ** none.
345: **
346: ** Returns:
347: ** The login name of the logged in user.
348: **
349: ** Side Effects:
350: ** none.
351: **
352: ** Notes:
353: ** The return value is statically allocated.
354: */
355:
356: char *
357: username()
358: {
359: static char *myname = NULL;
360: extern char *getlogin();
361: register struct passwd *pw;
362: extern struct passwd *getpwuid();
363:
364: /* cache the result */
365: if (myname == NULL)
366: {
367: myname = getlogin();
368: if (myname == NULL || myname[0] == '\0')
369: {
370:
371: pw = getpwuid(getruid());
372: if (pw != NULL)
373: myname = pw->pw_name;
374: }
375: else
376: {
377:
378: pw = getpwnam(myname);
379: if(getuid() != pw->pw_uid)
380: {
381: pw = getpwuid(getuid());
382: if (pw != NULL)
383: myname = pw->pw_name;
384: }
385: }
386: if (myname == NULL || myname[0] == '\0')
387: {
388: syserr("Who are you?");
389: myname = "postmaster";
390: }
391: }
392:
393: return (myname);
394: }
395: /*
396: ** TTYPATH -- Get the path of the user's tty
397: **
398: ** Returns the pathname of the user's tty. Returns NULL if
399: ** the user is not logged in or if s/he has write permission
400: ** denied.
401: **
402: ** Parameters:
403: ** none
404: **
405: ** Returns:
406: ** pathname of the user's tty.
407: ** NULL if not logged in or write permission denied.
408: **
409: ** Side Effects:
410: ** none.
411: **
412: ** WARNING:
413: ** Return value is in a local buffer.
414: **
415: ** Called By:
416: ** savemail
417: */
418:
419: # include <sys/stat.h>
420:
421: char *
422: ttypath()
423: {
424: struct stat stbuf;
425: register char *pathn;
426: extern char *ttyname();
427: extern char *getlogin();
428:
429: /* compute the pathname of the controlling tty */
430: if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
431: (pathn = ttyname(0)) == NULL)
432: {
433: errno = 0;
434: return (NULL);
435: }
436:
437: /* see if we have write permission */
438: if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
439: {
440: errno = 0;
441: return (NULL);
442: }
443:
444: /* see if the user is logged in */
445: if (getlogin() == NULL)
446: return (NULL);
447:
448: /* looks good */
449: return (pathn);
450: }
451: /*
452: ** CHECKCOMPAT -- check for From and To person compatible.
453: **
454: ** This routine can be supplied on a per-installation basis
455: ** to determine whether a person is allowed to send a message.
456: ** This allows restriction of certain types of internet
457: ** forwarding or registration of users.
458: **
459: ** If the hosts are found to be incompatible, an error
460: ** message should be given using "usrerr" and FALSE should
461: ** be returned.
462: **
463: ** 'NoReturn' can be set to suppress the return-to-sender
464: ** function; this should be done on huge messages.
465: **
466: ** Parameters:
467: ** to -- the person being sent to.
468: **
469: ** Returns:
470: ** TRUE -- ok to send.
471: ** FALSE -- not ok.
472: **
473: ** Side Effects:
474: ** none (unless you include the usrerr stuff)
475: */
476:
477: bool
478: checkcompat(to)
479: register ADDRESS *to;
480: {
481: # ifdef lint
482: if (to == NULL)
483: to++;
484: # endif lint
485: # ifdef EXAMPLE_CODE
486: /* this code is intended as an example only */
487: register STAB *s;
488:
489: s = stab("arpa", ST_MAILER, ST_FIND);
490: if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
491: to->q_mailer == s->s_mailer)
492: {
493: usrerr("No ARPA mail through this machine: see your system administration");
494: /* NoReturn = TRUE; to supress return copy */
495: return (FALSE);
496: }
497: # endif EXAMPLE_CODE
498: return (TRUE);
499: }
500: /*
501: ** HOLDSIGS -- arrange to hold all signals
502: **
503: ** Parameters:
504: ** none.
505: **
506: ** Returns:
507: ** none.
508: **
509: ** Side Effects:
510: ** Arranges that signals are held.
511: */
512:
513: holdsigs()
514: {
515: }
516: /*
517: ** RLSESIGS -- arrange to release all signals
518: **
519: ** This undoes the effect of holdsigs.
520: **
521: ** Parameters:
522: ** none.
523: **
524: ** Returns:
525: ** none.
526: **
527: ** Side Effects:
528: ** Arranges that signals are released.
529: */
530:
531: rlsesigs()
532: {
533: }
534: /*
535: ** GETLA -- get the current load average
536: **
537: ** This code stolen from la.c.
538: **
539: ** Parameters:
540: ** none.
541: **
542: ** Returns:
543: ** The current load average as an integer.
544: **
545: ** Side Effects:
546: ** none.
547: */
548:
549: #ifdef VMUNIX
550:
551: #include <nlist.h>
552:
553: struct nlist Nl[] =
554: {
555: { "_avenrun" },
556: #define X_AVENRUN 0
557: { 0 },
558: };
559:
560: getla()
561: {
562: static int kmem = -1;
563: # ifdef sun
564: long avenrun[3];
565: # else
566: double avenrun[3];
567: # endif
568: extern off_t lseek();
569:
570: if (kmem < 0)
571: {
572: kmem = open("/dev/kmem", 0, 0);
573: if (kmem < 0)
574: return (-1);
575: (void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
576: nlist("/vmunix", Nl);
577: if (Nl[0].n_type == 0)
578: return (-1);
579: }
580: if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
581: read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
582: {
583: /* thank you Ian */
584: return (-1);
585: }
586: # ifdef sun
587: return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
588: # else
589: return ((int) (avenrun[0] + 0.5));
590: # endif
591: }
592:
593: #else VMUNIX
594:
595: getla()
596: {
597: return (0);
598: }
599:
600: #endif VMUNIX
601: /*
602: ** SHOULDQUEUE -- should this message be queued or sent?
603: **
604: ** Compares the message cost to the load average to decide.
605: **
606: ** Parameters:
607: ** pri -- the priority of the message in question.
608: **
609: ** Returns:
610: ** TRUE -- if this message should be queued up for the
611: ** time being.
612: ** FALSE -- if the load is low enough to send this message.
613: **
614: ** Side Effects:
615: ** none.
616: */
617:
618: bool
619: shouldqueue(pri)
620: long pri;
621: {
622: int la;
623:
624: la = getla();
625: if (la < QueueLA)
626: return (FALSE);
627: return (pri > (QueueFactor / (la - QueueLA + 1)));
628: }
629: /*
630: ** SETPROCTITLE -- set process title for ps
631: **
632: ** Parameters:
633: ** fmt -- a printf style format string.
634: ** a, b, c -- possible parameters to fmt.
635: **
636: ** Returns:
637: ** none.
638: **
639: ** Side Effects:
640: ** Clobbers argv of our main procedure so ps(1) will
641: ** display the title.
642: */
643:
644: /*VARARGS1*/
645: setproctitle(fmt, a, b, c)
646: char *fmt;
647: {
648: # ifdef SETPROCTITLE
649: register char *p;
650: register int i;
651: extern char **Argv;
652: extern char *LastArgv;
653: char buf[MAXLINE];
654:
655: (void) sprintf(buf, fmt, a, b, c);
656:
657: /* make ps print "(sendmail)" */
658: p = Argv[0];
659: *p++ = '-';
660:
661: i = strlen(buf);
662: if (i > LastArgv - p - 2)
663: {
664: i = LastArgv - p - 2;
665: buf[i] = '\0';
666: }
667: (void) strcpy(p, buf);
668: p += i;
669: while (p < LastArgv)
670: *p++ = ' ';
671: # endif SETPROCTITLE
672: }
673: /*
674: ** REAPCHILD -- pick up the body of my child, lest it become a zombie
675: **
676: ** Parameters:
677: ** none.
678: **
679: ** Returns:
680: ** none.
681: **
682: ** Side Effects:
683: ** Picks up extant zombies.
684: */
685:
686: # ifdef VMUNIX
687: # include <sys/wait.h>
688: # endif VMUNIX
689:
690: reapchild()
691: {
692: # ifdef WNOHANG
693: union wait status;
694:
695: while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
696: continue;
697: # else WNOHANG
698: auto int status;
699:
700: while (wait(&status) > 0)
701: continue;
702: # endif WNOHANG
703: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.