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