xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 40980)
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.24 (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 = pw->pw_name;
237 		}
238 		else
239 		{
240 
241 			pw = getpwnam(myname);
242 			if(getuid() != pw->pw_uid)
243 			{
244 				pw = getpwuid(getuid());
245 				if (pw != NULL)
246 					myname = pw->pw_name;
247 			}
248 		}
249 		if (myname == NULL || myname[0] == '\0')
250 		{
251 			syserr("Who are you?");
252 			myname = "postmaster";
253 		}
254 	}
255 
256 	return (myname);
257 }
258 /*
259 **  TTYPATH -- Get the path of the user's tty
260 **
261 **	Returns the pathname of the user's tty.  Returns NULL if
262 **	the user is not logged in or if s/he has write permission
263 **	denied.
264 **
265 **	Parameters:
266 **		none
267 **
268 **	Returns:
269 **		pathname of the user's tty.
270 **		NULL if not logged in or write permission denied.
271 **
272 **	Side Effects:
273 **		none.
274 **
275 **	WARNING:
276 **		Return value is in a local buffer.
277 **
278 **	Called By:
279 **		savemail
280 */
281 
282 # include <sys/stat.h>
283 
284 char *
285 ttypath()
286 {
287 	struct stat stbuf;
288 	register char *pathn;
289 	extern char *ttyname();
290 	extern char *getlogin();
291 
292 	/* compute the pathname of the controlling tty */
293 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
294 	    (pathn = ttyname(0)) == NULL)
295 	{
296 		errno = 0;
297 		return (NULL);
298 	}
299 
300 	/* see if we have write permission */
301 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
302 	{
303 		errno = 0;
304 		return (NULL);
305 	}
306 
307 	/* see if the user is logged in */
308 	if (getlogin() == NULL)
309 		return (NULL);
310 
311 	/* looks good */
312 	return (pathn);
313 }
314 /*
315 **  CHECKCOMPAT -- check for From and To person compatible.
316 **
317 **	This routine can be supplied on a per-installation basis
318 **	to determine whether a person is allowed to send a message.
319 **	This allows restriction of certain types of internet
320 **	forwarding or registration of users.
321 **
322 **	If the hosts are found to be incompatible, an error
323 **	message should be given using "usrerr" and FALSE should
324 **	be returned.
325 **
326 **	'NoReturn' can be set to suppress the return-to-sender
327 **	function; this should be done on huge messages.
328 **
329 **	Parameters:
330 **		to -- the person being sent to.
331 **
332 **	Returns:
333 **		TRUE -- ok to send.
334 **		FALSE -- not ok.
335 **
336 **	Side Effects:
337 **		none (unless you include the usrerr stuff)
338 */
339 
340 bool
341 checkcompat(to)
342 	register ADDRESS *to;
343 {
344 # ifdef lint
345 	if (to == NULL)
346 		to++;
347 # endif lint
348 # ifdef EXAMPLE_CODE
349 	/* this code is intended as an example only */
350 	register STAB *s;
351 
352 	s = stab("arpa", ST_MAILER, ST_FIND);
353 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
354 	    to->q_mailer == s->s_mailer)
355 	{
356 		usrerr("No ARPA mail through this machine: see your system administration");
357 		/* NoReturn = TRUE; to supress return copy */
358 		return (FALSE);
359 	}
360 # endif EXAMPLE_CODE
361 	return (TRUE);
362 }
363 /*
364 **  HOLDSIGS -- arrange to hold all signals
365 **
366 **	Parameters:
367 **		none.
368 **
369 **	Returns:
370 **		none.
371 **
372 **	Side Effects:
373 **		Arranges that signals are held.
374 */
375 
376 holdsigs()
377 {
378 }
379 /*
380 **  RLSESIGS -- arrange to release all signals
381 **
382 **	This undoes the effect of holdsigs.
383 **
384 **	Parameters:
385 **		none.
386 **
387 **	Returns:
388 **		none.
389 **
390 **	Side Effects:
391 **		Arranges that signals are released.
392 */
393 
394 rlsesigs()
395 {
396 }
397 /*
398 **  GETLA -- get the current load average
399 **
400 **	This code stolen from la.c.
401 **
402 **	Parameters:
403 **		none.
404 **
405 **	Returns:
406 **		The current load average as an integer.
407 **
408 **	Side Effects:
409 **		none.
410 */
411 
412 #ifndef sun
413 
414 getla()
415 {
416 	double avenrun[3];
417 
418 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
419 		return (0);
420 	return ((int) (avenrun[0] + 0.5));
421 }
422 
423 #else /* sun */
424 
425 #include <nlist.h>
426 
427 struct	nlist Nl[] =
428 {
429 	{ "_avenrun" },
430 #define	X_AVENRUN	0
431 	{ 0 },
432 };
433 
434 
435 extern int la;
436 
437 getla()
438 {
439 	static int kmem = -1;
440 	long avenrun[3];
441 	extern off_t lseek();
442 
443 	if (kmem < 0)
444 	{
445 		kmem = open("/dev/kmem", 0, 0);
446 		if (kmem < 0)
447 			return (-1);
448 		(void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
449 		nlist("/vmunix", Nl);
450 		if (Nl[0].n_type == 0)
451 			return (-1);
452 	}
453 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
454 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
455 	{
456 		/* thank you Ian */
457 		return (-1);
458 	}
459 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
460 }
461 
462 #endif /* sun */
463 /*
464 **  SHOULDQUEUE -- should this message be queued or sent?
465 **
466 **	Compares the message cost to the load average to decide.
467 **
468 **	Parameters:
469 **		pri -- the priority of the message in question.
470 **
471 **	Returns:
472 **		TRUE -- if this message should be queued up for the
473 **			time being.
474 **		FALSE -- if the load is low enough to send this message.
475 **
476 **	Side Effects:
477 **		none.
478 */
479 
480 bool
481 shouldqueue(pri)
482 	long pri;
483 {
484 	if (la < QueueLA)
485 		return (FALSE);
486 	return (pri > (QueueFactor / (la - QueueLA + 1)));
487 }
488 /*
489 **  SETPROCTITLE -- set process title for ps
490 **
491 **	Parameters:
492 **		fmt -- a printf style format string.
493 **		a, b, c -- possible parameters to fmt.
494 **
495 **	Returns:
496 **		none.
497 **
498 **	Side Effects:
499 **		Clobbers argv of our main procedure so ps(1) will
500 **		display the title.
501 */
502 
503 /*VARARGS1*/
504 setproctitle(fmt, a, b, c)
505 	char *fmt;
506 {
507 # ifdef SETPROCTITLE
508 	register char *p;
509 	register int i;
510 	extern char **Argv;
511 	extern char *LastArgv;
512 	char buf[MAXLINE];
513 
514 	(void) sprintf(buf, fmt, a, b, c);
515 
516 	/* make ps print "(sendmail)" */
517 	p = Argv[0];
518 	*p++ = '-';
519 
520 	i = strlen(buf);
521 	if (i > LastArgv - p - 2)
522 	{
523 		i = LastArgv - p - 2;
524 		buf[i] = '\0';
525 	}
526 	(void) strcpy(p, buf);
527 	p += i;
528 	while (p < LastArgv)
529 		*p++ = ' ';
530 # endif SETPROCTITLE
531 }
532 /*
533 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
534 **
535 **	Parameters:
536 **		none.
537 **
538 **	Returns:
539 **		none.
540 **
541 **	Side Effects:
542 **		Picks up extant zombies.
543 */
544 
545 # ifdef VMUNIX
546 # include <sys/wait.h>
547 # endif VMUNIX
548 
549 reapchild()
550 {
551 # ifdef WNOHANG
552 	union wait status;
553 
554 	while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
555 		continue;
556 # else WNOHANG
557 	auto int status;
558 
559 	while (wait(&status) > 0)
560 		continue;
561 # endif WNOHANG
562 }
563