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