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