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