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