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