xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 40993)
1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted
7  * provided that the above copyright notice and this paragraph are
8  * duplicated in all such forms and that any documentation,
9  * advertising materials, and other materials related to such
10  * distribution and use acknowledge that the software was developed
11  * by the University of California, Berkeley.  The name of the
12  * University may not be used to endorse or promote products derived
13  * from this software without specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18 
19 #ifndef lint
20 static char sccsid[] = "@(#)conf.c	5.25 (Berkeley) 04/19/90";
21 #endif /* not lint */
22 
23 # include <sys/ioctl.h>
24 # include <sys/param.h>
25 # include <pwd.h>
26 # include "sendmail.h"
27 # include "pathnames.h"
28 
29 /*
30 **  CONF.C -- Sendmail Configuration Tables.
31 **
32 **	Defines the configuration of this installation.
33 **
34 **	Compilation Flags:
35 **		VMUNIX -- running on a Berkeley UNIX system.
36 **
37 **	Configuration Variables:
38 **		HdrInfo -- a table describing well-known header fields.
39 **			Each entry has the field name and some flags,
40 **			which are described in sendmail.h.
41 **
42 **	Notes:
43 **		I have tried to put almost all the reasonable
44 **		configuration information into the configuration
45 **		file read at runtime.  My intent is that anything
46 **		here is a function of the version of UNIX you
47 **		are running, or is really static -- for example
48 **		the headers are a superset of widely used
49 **		protocols.  If you find yourself playing with
50 **		this file too much, you may be making a mistake!
51 */
52 
53 
54 
55 
56 /*
57 **  Header info table
58 **	Final (null) entry contains the flags used for any other field.
59 **
60 **	Not all of these are actually handled specially by sendmail
61 **	at this time.  They are included as placeholders, to let
62 **	you know that "someday" I intend to have sendmail do
63 **	something with them.
64 */
65 
66 struct hdrinfo	HdrInfo[] =
67 {
68 		/* originator fields, most to least significant  */
69 	"resent-sender",	H_FROM|H_RESENT,
70 	"resent-from",		H_FROM|H_RESENT,
71 	"resent-reply-to",	H_FROM|H_RESENT,
72 	"sender",		H_FROM,
73 	"from",			H_FROM,
74 	"reply-to",		H_FROM,
75 	"full-name",		H_ACHECK,
76 	"return-receipt-to",	H_FROM,
77 	"errors-to",		H_FROM,
78 		/* destination fields */
79 	"to",			H_RCPT,
80 	"resent-to",		H_RCPT|H_RESENT,
81 	"cc",			H_RCPT,
82 	"resent-cc",		H_RCPT|H_RESENT,
83 	"bcc",			H_RCPT|H_ACHECK,
84 	"resent-bcc",		H_RCPT|H_ACHECK|H_RESENT,
85 		/* message identification and control */
86 	"message-id",		0,
87 	"resent-message-id",	H_RESENT,
88 	"message",		H_EOH,
89 	"text",			H_EOH,
90 		/* date fields */
91 	"date",			0,
92 	"resent-date",		H_RESENT,
93 		/* trace fields */
94 	"received",		H_TRACE|H_FORCE,
95 	"via",			H_TRACE|H_FORCE,
96 	"mail-from",		H_TRACE|H_FORCE,
97 
98 	NULL,			0,
99 };
100 
101 
102 /*
103 **  ARPANET error message numbers.
104 */
105 
106 char	Arpa_Info[] =		"050";	/* arbitrary info */
107 char	Arpa_TSyserr[] =	"451";	/* some (transient) system error */
108 char	Arpa_PSyserr[] =	"554";	/* some (permanent) system error */
109 char	Arpa_Usrerr[] =		"554";	/* some (fatal) user error */
110 
111 
112 
113 /*
114 **  Location of system files/databases/etc.
115 */
116 
117 char	*ConfFile =	_PATH_SENDMAILCF;	/* runtime configuration */
118 char	*FreezeFile =	_PATH_SENDMAILFC;	/* frozen version of above */
119 
120 
121 
122 /*
123 **  Miscellaneous stuff.
124 */
125 
126 int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
127 extern int la;				/* load average */
128 /*
129 **  SETDEFAULTS -- set default values
130 **
131 **	Because of the way freezing is done, these must be initialized
132 **	using direct code.
133 **
134 **	Parameters:
135 **		none.
136 **
137 **	Returns:
138 **		none.
139 **
140 **	Side Effects:
141 **		Initializes a bunch of global variables to their
142 **		default values.
143 */
144 
145 setdefaults()
146 {
147 	QueueLA = 8;
148 	QueueFactor = 10000;
149 	RefuseLA = 12;
150 	SpaceSub = ' ';
151 	WkRecipFact = 1000;
152 	WkClassFact = 1800;
153 	WkTimeFact = 9000;
154 	FileMode = 0644;
155 	DefUid = 1;
156 	DefGid = 1;
157 	setdefuser();
158 }
159 
160 
161 /*
162 **  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
163 */
164 
165 setdefuser()
166 {
167 	struct passwd *defpwent;
168 
169 	if (DefUser != NULL)
170 		free(DefUser);
171 	if ((defpwent = getpwuid(DefUid)) != NULL)
172 		DefUser = newstr(defpwent->pw_name);
173 	else
174 		DefUser = newstr("nobody");
175 }
176 
177 
178 /*
179 **  GETRUID -- get real user id (V7)
180 */
181 
182 getruid()
183 {
184 	if (OpMode == MD_DAEMON)
185 		return (RealUid);
186 	else
187 		return (getuid());
188 }
189 
190 
191 /*
192 **  GETRGID -- get real group id (V7).
193 */
194 
195 getrgid()
196 {
197 	if (OpMode == MD_DAEMON)
198 		return (RealGid);
199 	else
200 		return (getgid());
201 }
202 
203 /*
204 **  USERNAME -- return the user id of the logged in user.
205 **
206 **	Parameters:
207 **		none.
208 **
209 **	Returns:
210 **		The login name of the logged in user.
211 **
212 **	Side Effects:
213 **		none.
214 **
215 **	Notes:
216 **		The return value is statically allocated.
217 */
218 
219 char *
220 username()
221 {
222 	static char *myname = NULL;
223 	extern char *getlogin();
224 	register struct passwd *pw;
225 	extern struct passwd *getpwuid();
226 
227 	/* cache the result */
228 	if (myname == NULL)
229 	{
230 		myname = getlogin();
231 		if (myname == NULL || myname[0] == '\0')
232 		{
233 
234 			pw = getpwuid(getruid());
235 			if (pw != NULL)
236 				myname = newstr(pw->pw_name);
237 		}
238 		else
239 		{
240 
241 			myname = newstr(myname);
242 			if ((pw = getpwnam(myname)) == NULL ||
243 			      getuid() != pw->pw_uid)
244 			{
245 				pw = getpwuid(getuid());
246 				if (pw != NULL)
247 					myname = newstr(pw->pw_name);
248 			}
249 		}
250 		if (myname == NULL || myname[0] == '\0')
251 		{
252 			syserr("Who are you?");
253 			myname = "postmaster";
254 		}
255 	}
256 
257 	return (myname);
258 }
259 /*
260 **  TTYPATH -- Get the path of the user's tty
261 **
262 **	Returns the pathname of the user's tty.  Returns NULL if
263 **	the user is not logged in or if s/he has write permission
264 **	denied.
265 **
266 **	Parameters:
267 **		none
268 **
269 **	Returns:
270 **		pathname of the user's tty.
271 **		NULL if not logged in or write permission denied.
272 **
273 **	Side Effects:
274 **		none.
275 **
276 **	WARNING:
277 **		Return value is in a local buffer.
278 **
279 **	Called By:
280 **		savemail
281 */
282 
283 # include <sys/stat.h>
284 
285 char *
286 ttypath()
287 {
288 	struct stat stbuf;
289 	register char *pathn;
290 	extern char *ttyname();
291 	extern char *getlogin();
292 
293 	/* compute the pathname of the controlling tty */
294 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
295 	    (pathn = ttyname(0)) == NULL)
296 	{
297 		errno = 0;
298 		return (NULL);
299 	}
300 
301 	/* see if we have write permission */
302 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
303 	{
304 		errno = 0;
305 		return (NULL);
306 	}
307 
308 	/* see if the user is logged in */
309 	if (getlogin() == NULL)
310 		return (NULL);
311 
312 	/* looks good */
313 	return (pathn);
314 }
315 /*
316 **  CHECKCOMPAT -- check for From and To person compatible.
317 **
318 **	This routine can be supplied on a per-installation basis
319 **	to determine whether a person is allowed to send a message.
320 **	This allows restriction of certain types of internet
321 **	forwarding or registration of users.
322 **
323 **	If the hosts are found to be incompatible, an error
324 **	message should be given using "usrerr" and FALSE should
325 **	be returned.
326 **
327 **	'NoReturn' can be set to suppress the return-to-sender
328 **	function; this should be done on huge messages.
329 **
330 **	Parameters:
331 **		to -- the person being sent to.
332 **
333 **	Returns:
334 **		TRUE -- ok to send.
335 **		FALSE -- not ok.
336 **
337 **	Side Effects:
338 **		none (unless you include the usrerr stuff)
339 */
340 
341 bool
342 checkcompat(to)
343 	register ADDRESS *to;
344 {
345 # ifdef lint
346 	if (to == NULL)
347 		to++;
348 # endif lint
349 # ifdef EXAMPLE_CODE
350 	/* this code is intended as an example only */
351 	register STAB *s;
352 
353 	s = stab("arpa", ST_MAILER, ST_FIND);
354 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
355 	    to->q_mailer == s->s_mailer)
356 	{
357 		usrerr("No ARPA mail through this machine: see your system administration");
358 		/* NoReturn = TRUE; to supress return copy */
359 		return (FALSE);
360 	}
361 # endif EXAMPLE_CODE
362 	return (TRUE);
363 }
364 /*
365 **  HOLDSIGS -- arrange to hold all signals
366 **
367 **	Parameters:
368 **		none.
369 **
370 **	Returns:
371 **		none.
372 **
373 **	Side Effects:
374 **		Arranges that signals are held.
375 */
376 
377 holdsigs()
378 {
379 }
380 /*
381 **  RLSESIGS -- arrange to release all signals
382 **
383 **	This undoes the effect of holdsigs.
384 **
385 **	Parameters:
386 **		none.
387 **
388 **	Returns:
389 **		none.
390 **
391 **	Side Effects:
392 **		Arranges that signals are released.
393 */
394 
395 rlsesigs()
396 {
397 }
398 /*
399 **  GETLA -- get the current load average
400 **
401 **	This code stolen from la.c.
402 **
403 **	Parameters:
404 **		none.
405 **
406 **	Returns:
407 **		The current load average as an integer.
408 **
409 **	Side Effects:
410 **		none.
411 */
412 
413 #ifndef sun
414 
415 getla()
416 {
417 	double avenrun[3];
418 
419 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
420 		return (0);
421 	return ((int) (avenrun[0] + 0.5));
422 }
423 
424 #else /* sun */
425 
426 #include <nlist.h>
427 
428 struct	nlist Nl[] =
429 {
430 	{ "_avenrun" },
431 #define	X_AVENRUN	0
432 	{ 0 },
433 };
434 
435 
436 extern int la;
437 
438 getla()
439 {
440 	static int kmem = -1;
441 	long avenrun[3];
442 	extern off_t lseek();
443 
444 	if (kmem < 0)
445 	{
446 		kmem = open("/dev/kmem", 0, 0);
447 		if (kmem < 0)
448 			return (-1);
449 		(void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
450 		nlist("/vmunix", Nl);
451 		if (Nl[0].n_type == 0)
452 			return (-1);
453 	}
454 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
455 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
456 	{
457 		/* thank you Ian */
458 		return (-1);
459 	}
460 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
461 }
462 
463 #endif /* sun */
464 /*
465 **  SHOULDQUEUE -- should this message be queued or sent?
466 **
467 **	Compares the message cost to the load average to decide.
468 **
469 **	Parameters:
470 **		pri -- the priority of the message in question.
471 **
472 **	Returns:
473 **		TRUE -- if this message should be queued up for the
474 **			time being.
475 **		FALSE -- if the load is low enough to send this message.
476 **
477 **	Side Effects:
478 **		none.
479 */
480 
481 bool
482 shouldqueue(pri)
483 	long pri;
484 {
485 	if (la < QueueLA)
486 		return (FALSE);
487 	return (pri > (QueueFactor / (la - QueueLA + 1)));
488 }
489 /*
490 **  SETPROCTITLE -- set process title for ps
491 **
492 **	Parameters:
493 **		fmt -- a printf style format string.
494 **		a, b, c -- possible parameters to fmt.
495 **
496 **	Returns:
497 **		none.
498 **
499 **	Side Effects:
500 **		Clobbers argv of our main procedure so ps(1) will
501 **		display the title.
502 */
503 
504 /*VARARGS1*/
505 setproctitle(fmt, a, b, c)
506 	char *fmt;
507 {
508 # ifdef SETPROCTITLE
509 	register char *p;
510 	register int i;
511 	extern char **Argv;
512 	extern char *LastArgv;
513 	char buf[MAXLINE];
514 
515 	(void) sprintf(buf, fmt, a, b, c);
516 
517 	/* make ps print "(sendmail)" */
518 	p = Argv[0];
519 	*p++ = '-';
520 
521 	i = strlen(buf);
522 	if (i > LastArgv - p - 2)
523 	{
524 		i = LastArgv - p - 2;
525 		buf[i] = '\0';
526 	}
527 	(void) strcpy(p, buf);
528 	p += i;
529 	while (p < LastArgv)
530 		*p++ = ' ';
531 # endif SETPROCTITLE
532 }
533 /*
534 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
535 **
536 **	Parameters:
537 **		none.
538 **
539 **	Returns:
540 **		none.
541 **
542 **	Side Effects:
543 **		Picks up extant zombies.
544 */
545 
546 # ifdef VMUNIX
547 # include <sys/wait.h>
548 # endif VMUNIX
549 
550 reapchild()
551 {
552 # ifdef WNOHANG
553 	union wait status;
554 
555 	while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
556 		continue;
557 # else WNOHANG
558 	auto int status;
559 
560 	while (wait(&status) > 0)
561 		continue;
562 # endif WNOHANG
563 }
564