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