xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 22908)
1 /*
2 **  Sendmail
3 **  Copyright (c) 1983  Eric P. Allman
4 **  Berkeley, California
5 **
6 **  Copyright (c) 1983 Regents of the University of California.
7 **  All rights reserved.  The Berkeley software License Agreement
8 **  specifies the terms and conditions for redistribution.
9 */
10 
11 #ifndef lint
12 static char	SccsId[] = "@(#)conf.c	5.2 (Berkeley) 06/07/85";
13 #endif not lint
14 
15 # include <pwd.h>
16 # include <sys/ioctl.h>
17 # include "sendmail.h"
18 
19 /*
20 **  CONF.C -- Sendmail Configuration Tables.
21 **
22 **	Defines the configuration of this installation.
23 **
24 **	Compilation Flags:
25 **		V6 -- running on a version 6 system.  This determines
26 **			whether to define certain routines between
27 **			the two systems.  If you are running a funny
28 **			system, e.g., V6 with long tty names, this
29 **			should be checked carefully.
30 **		VMUNIX -- running on a Berkeley UNIX system.
31 **
32 **	Configuration Variables:
33 **		HdrInfo -- a table describing well-known header fields.
34 **			Each entry has the field name and some flags,
35 **			which are described in sendmail.h.
36 **
37 **	Notes:
38 **		I have tried to put almost all the reasonable
39 **		configuration information into the configuration
40 **		file read at runtime.  My intent is that anything
41 **		here is a function of the version of UNIX you
42 **		are running, or is really static -- for example
43 **		the headers are a superset of widely used
44 **		protocols.  If you find yourself playing with
45 **		this file too much, you may be making a mistake!
46 */
47 
48 
49 
50 
51 /*
52 **  Header info table
53 **	Final (null) entry contains the flags used for any other field.
54 **
55 **	Not all of these are actually handled specially by sendmail
56 **	at this time.  They are included as placeholders, to let
57 **	you know that "someday" I intend to have sendmail do
58 **	something with them.
59 */
60 
61 struct hdrinfo	HdrInfo[] =
62 {
63 		/* originator fields, most to least significant  */
64 	"resent-sender",	H_FROM|H_RESENT,
65 	"resent-from",		H_FROM|H_RESENT,
66 	"sender",		H_FROM,
67 	"from",			H_FROM,
68 	"full-name",		H_ACHECK,
69 	"return-receipt-to",	H_FROM,
70 	"errors-to",		H_FROM,
71 		/* destination fields */
72 	"to",			H_RCPT,
73 	"resent-to",		H_RCPT|H_RESENT,
74 	"cc",			H_RCPT,
75 	"resent-cc",		H_RCPT|H_RESENT,
76 	"bcc",			H_RCPT|H_ACHECK,
77 	"resent-bcc",		H_RCPT|H_ACHECK|H_RESENT,
78 		/* message identification and control */
79 	"message-id",		0,
80 	"resent-message-id",	H_RESENT,
81 	"message",		H_EOH,
82 	"text",			H_EOH,
83 		/* date fields */
84 	"date",			0,
85 	"resent-date",		H_RESENT,
86 		/* trace fields */
87 	"received",		H_TRACE|H_FORCE,
88 	"via",			H_TRACE|H_FORCE,
89 	"mail-from",		H_TRACE|H_FORCE,
90 
91 	NULL,			0,
92 };
93 
94 
95 /*
96 **  ARPANET error message numbers.
97 */
98 
99 char	Arpa_Info[] =		"050";	/* arbitrary info */
100 char	Arpa_TSyserr[] =	"451";	/* some (transient) system error */
101 char	Arpa_PSyserr[] =	"554";	/* some (permanent) system error */
102 char	Arpa_Usrerr[] =		"554";	/* some (fatal) user error */
103 
104 
105 
106 /*
107 **  Location of system files/databases/etc.
108 */
109 
110 char	*ConfFile =	"/usr/lib/sendmail.cf";	/* runtime configuration */
111 char	*FreezeFile =	"/usr/lib/sendmail.fc";	/* frozen version of above */
112 
113 
114 
115 /*
116 **  Some other configuration....
117 */
118 
119 char	SpaceSub;		/* character to replace <lwsp> in addrs */
120 int	QueueLA;		/* load avg > QueueLA -> just queue */
121 int	RefuseLA;		/* load avg > RefuseLA -> refuse connections */
122 
123 # ifdef V6
124 /*
125 **  TTYNAME -- return name of terminal.
126 **
127 **	Parameters:
128 **		fd -- file descriptor to check.
129 **
130 **	Returns:
131 **		pointer to full path of tty.
132 **		NULL if no tty.
133 **
134 **	Side Effects:
135 **		none.
136 */
137 
138 char *
139 ttyname(fd)
140 	int fd;
141 {
142 	register char tn;
143 	static char pathn[] = "/dev/ttyx";
144 
145 	/* compute the pathname of the controlling tty */
146 	if ((tn = ttyn(fd)) == NULL)
147 	{
148 		errno = 0;
149 		return (NULL);
150 	}
151 	pathn[8] = tn;
152 	return (pathn);
153 }
154 /*
155 **  FDOPEN -- Open a stdio file given an open file descriptor.
156 **
157 **	This is included here because it is standard in v7, but we
158 **	need it in v6.
159 **
160 **	Algorithm:
161 **		Open /dev/null to create a descriptor.
162 **		Close that descriptor.
163 **		Copy the existing fd into the descriptor.
164 **
165 **	Parameters:
166 **		fd -- the open file descriptor.
167 **		type -- "r", "w", or whatever.
168 **
169 **	Returns:
170 **		The file descriptor it creates.
171 **
172 **	Side Effects:
173 **		none
174 **
175 **	Called By:
176 **		deliver
177 **
178 **	Notes:
179 **		The mode of fd must match "type".
180 */
181 
182 FILE *
183 fdopen(fd, type)
184 	int fd;
185 	char *type;
186 {
187 	register FILE *f;
188 
189 	f = fopen("/dev/null", type);
190 	(void) close(fileno(f));
191 	fileno(f) = fd;
192 	return (f);
193 }
194 /*
195 **  INDEX -- Return pointer to character in string
196 **
197 **	For V7 compatibility.
198 **
199 **	Parameters:
200 **		s -- a string to scan.
201 **		c -- a character to look for.
202 **
203 **	Returns:
204 **		If c is in s, returns the address of the first
205 **			instance of c in s.
206 **		NULL if c is not in s.
207 **
208 **	Side Effects:
209 **		none.
210 */
211 
212 char *
213 index(s, c)
214 	register char *s;
215 	register char c;
216 {
217 	while (*s != '\0')
218 	{
219 		if (*s++ == c)
220 			return (--s);
221 	}
222 	return (NULL);
223 }
224 /*
225 **  UMASK -- fake the umask system call.
226 **
227 **	Since V6 always acts like the umask is zero, we will just
228 **	assume the same thing.
229 */
230 
231 /*ARGSUSED*/
232 umask(nmask)
233 {
234 	return (0);
235 }
236 
237 
238 /*
239 **  GETRUID -- get real user id.
240 */
241 
242 getruid()
243 {
244 	return (getuid() & 0377);
245 }
246 
247 
248 /*
249 **  GETRGID -- get real group id.
250 */
251 
252 getrgid()
253 {
254 	return (getgid() & 0377);
255 }
256 
257 
258 /*
259 **  GETEUID -- get effective user id.
260 */
261 
262 geteuid()
263 {
264 	return ((getuid() >> 8) & 0377);
265 }
266 
267 
268 /*
269 **  GETEGID -- get effective group id.
270 */
271 
272 getegid()
273 {
274 	return ((getgid() >> 8) & 0377);
275 }
276 
277 # endif V6
278 
279 # ifndef V6
280 
281 /*
282 **  GETRUID -- get real user id (V7)
283 */
284 
285 getruid()
286 {
287 	if (OpMode == MD_DAEMON)
288 		return (RealUid);
289 	else
290 		return (getuid());
291 }
292 
293 
294 /*
295 **  GETRGID -- get real group id (V7).
296 */
297 
298 getrgid()
299 {
300 	if (OpMode == MD_DAEMON)
301 		return (RealGid);
302 	else
303 		return (getgid());
304 }
305 
306 # endif V6
307 /*
308 **  USERNAME -- return the user id of the logged in user.
309 **
310 **	Parameters:
311 **		none.
312 **
313 **	Returns:
314 **		The login name of the logged in user.
315 **
316 **	Side Effects:
317 **		none.
318 **
319 **	Notes:
320 **		The return value is statically allocated.
321 */
322 
323 char *
324 username()
325 {
326 	static char *myname = NULL;
327 	extern char *getlogin();
328 	register struct passwd *pw;
329 	extern struct passwd *getpwuid();
330 
331 	/* cache the result */
332 	if (myname == NULL)
333 	{
334 		myname = getlogin();
335 		if (myname == NULL || myname[0] == '\0')
336 		{
337 
338 			pw = getpwuid(getruid());
339 			if (pw != NULL)
340 				myname = pw->pw_name;
341 		}
342 		else
343 		{
344 
345 			pw = getpwnam(myname);
346 			if(getuid() != pw->pw_uid)
347 			{
348 				pw = getpwuid(getuid());
349 				myname = pw->pw_name;
350 			}
351 		}
352 		if (myname == NULL || myname[0] == '\0')
353 		{
354 			syserr("Who are you?");
355 			myname = "postmaster";
356 		}
357 	}
358 
359 	return (myname);
360 }
361 /*
362 **  TTYPATH -- Get the path of the user's tty
363 **
364 **	Returns the pathname of the user's tty.  Returns NULL if
365 **	the user is not logged in or if s/he has write permission
366 **	denied.
367 **
368 **	Parameters:
369 **		none
370 **
371 **	Returns:
372 **		pathname of the user's tty.
373 **		NULL if not logged in or write permission denied.
374 **
375 **	Side Effects:
376 **		none.
377 **
378 **	WARNING:
379 **		Return value is in a local buffer.
380 **
381 **	Called By:
382 **		savemail
383 */
384 
385 # include <sys/stat.h>
386 
387 char *
388 ttypath()
389 {
390 	struct stat stbuf;
391 	register char *pathn;
392 	extern char *ttyname();
393 	extern char *getlogin();
394 
395 	/* compute the pathname of the controlling tty */
396 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
397 	    (pathn = ttyname(0)) == NULL)
398 	{
399 		errno = 0;
400 		return (NULL);
401 	}
402 
403 	/* see if we have write permission */
404 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
405 	{
406 		errno = 0;
407 		return (NULL);
408 	}
409 
410 	/* see if the user is logged in */
411 	if (getlogin() == NULL)
412 		return (NULL);
413 
414 	/* looks good */
415 	return (pathn);
416 }
417 /*
418 **  CHECKCOMPAT -- check for From and To person compatible.
419 **
420 **	This routine can be supplied on a per-installation basis
421 **	to determine whether a person is allowed to send a message.
422 **	This allows restriction of certain types of internet
423 **	forwarding or registration of users.
424 **
425 **	If the hosts are found to be incompatible, an error
426 **	message should be given using "usrerr" and FALSE should
427 **	be returned.
428 **
429 **	'NoReturn' can be set to suppress the return-to-sender
430 **	function; this should be done on huge messages.
431 **
432 **	Parameters:
433 **		to -- the person being sent to.
434 **
435 **	Returns:
436 **		TRUE -- ok to send.
437 **		FALSE -- not ok.
438 **
439 **	Side Effects:
440 **		none (unless you include the usrerr stuff)
441 */
442 
443 bool
444 checkcompat(to)
445 	register ADDRESS *to;
446 {
447 # ifdef lint
448 	if (to == NULL)
449 		to++;
450 # endif lint
451 # ifdef EXAMPLE_CODE
452 	/* this code is intended as an example only */
453 	register STAB *s;
454 
455 	s = stab("arpa", ST_MAILER, ST_FIND);
456 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
457 	    to->q_mailer == s->s_mailer)
458 	{
459 		usrerr("No ARPA mail through this machine: see your system administration");
460 		/* NoReturn = TRUE; to supress return copy */
461 		return (FALSE);
462 	}
463 # endif EXAMPLE_CODE
464 	return (TRUE);
465 }
466 /*
467 **  HOLDSIGS -- arrange to hold all signals
468 **
469 **	Parameters:
470 **		none.
471 **
472 **	Returns:
473 **		none.
474 **
475 **	Side Effects:
476 **		Arranges that signals are held.
477 */
478 
479 holdsigs()
480 {
481 }
482 /*
483 **  RLSESIGS -- arrange to release all signals
484 **
485 **	This undoes the effect of holdsigs.
486 **
487 **	Parameters:
488 **		none.
489 **
490 **	Returns:
491 **		none.
492 **
493 **	Side Effects:
494 **		Arranges that signals are released.
495 */
496 
497 rlsesigs()
498 {
499 }
500 /*
501 **  GETLA -- get the current load average
502 **
503 **	This code stolen from la.c.
504 **
505 **	Parameters:
506 **		none.
507 **
508 **	Returns:
509 **		The current load average as an integer.
510 **
511 **	Side Effects:
512 **		none.
513 */
514 
515 #ifdef VMUNIX
516 
517 #include <nlist.h>
518 
519 struct	nlist Nl[] =
520 {
521 	{ "_avenrun" },
522 #define	X_AVENRUN	0
523 	{ 0 },
524 };
525 
526 getla()
527 {
528 	static int kmem = -1;
529 	double avenrun[3];
530 
531 	if (kmem < 0)
532 	{
533 		kmem = open("/dev/kmem", 0);
534 		if (kmem < 0)
535 			return (-1);
536 		(void) ioctl(kmem, FIOCLEX, 0);
537 		nlist("/vmunix", Nl);
538 		if (Nl[0].n_type == 0)
539 			return (-1);
540 	}
541 	if (lseek(kmem, (long) Nl[X_AVENRUN].n_value, 0) < 0 ||
542 	    read(kmem, avenrun, sizeof(avenrun)) < sizeof(avenrun))
543 	{
544 		/* thank you Ian */
545 		return (-1);
546 	}
547 	return ((int) (avenrun[0] + 0.5));
548 }
549 
550 #else VMUNIX
551 
552 getla()
553 {
554 	return (0);
555 }
556 
557 #endif VMUNIX
558 /*
559 **  DBMCLOSE -- close the DBM file
560 **
561 **	This depends on the implementation of the DBM library.  It
562 **	seems to work for all versions that I have come across.
563 **
564 **	Parameters:
565 **		none.
566 **
567 **	Returns:
568 **		none.
569 **
570 **	Side Effects:
571 **		Closes the current DBM file; dbminit must be
572 **		called again to continue using the DBM routines.
573 */
574 
575 dbmclose()
576 {
577 	extern int pagf, dirf;	/* defined in the DBM package */
578 
579 	(void) close(pagf);
580 	(void) close(dirf);
581 }
582