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