xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 24286)
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.5 (Berkeley) 08/13/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 				if (pw != NULL)
350 					myname = pw->pw_name;
351 			}
352 		}
353 		if (myname == NULL || myname[0] == '\0')
354 		{
355 			syserr("Who are you?");
356 			myname = "postmaster";
357 		}
358 	}
359 
360 	return (myname);
361 }
362 /*
363 **  TTYPATH -- Get the path of the user's tty
364 **
365 **	Returns the pathname of the user's tty.  Returns NULL if
366 **	the user is not logged in or if s/he has write permission
367 **	denied.
368 **
369 **	Parameters:
370 **		none
371 **
372 **	Returns:
373 **		pathname of the user's tty.
374 **		NULL if not logged in or write permission denied.
375 **
376 **	Side Effects:
377 **		none.
378 **
379 **	WARNING:
380 **		Return value is in a local buffer.
381 **
382 **	Called By:
383 **		savemail
384 */
385 
386 # include <sys/stat.h>
387 
388 char *
389 ttypath()
390 {
391 	struct stat stbuf;
392 	register char *pathn;
393 	extern char *ttyname();
394 	extern char *getlogin();
395 
396 	/* compute the pathname of the controlling tty */
397 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
398 	    (pathn = ttyname(0)) == NULL)
399 	{
400 		errno = 0;
401 		return (NULL);
402 	}
403 
404 	/* see if we have write permission */
405 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
406 	{
407 		errno = 0;
408 		return (NULL);
409 	}
410 
411 	/* see if the user is logged in */
412 	if (getlogin() == NULL)
413 		return (NULL);
414 
415 	/* looks good */
416 	return (pathn);
417 }
418 /*
419 **  CHECKCOMPAT -- check for From and To person compatible.
420 **
421 **	This routine can be supplied on a per-installation basis
422 **	to determine whether a person is allowed to send a message.
423 **	This allows restriction of certain types of internet
424 **	forwarding or registration of users.
425 **
426 **	If the hosts are found to be incompatible, an error
427 **	message should be given using "usrerr" and FALSE should
428 **	be returned.
429 **
430 **	'NoReturn' can be set to suppress the return-to-sender
431 **	function; this should be done on huge messages.
432 **
433 **	Parameters:
434 **		to -- the person being sent to.
435 **
436 **	Returns:
437 **		TRUE -- ok to send.
438 **		FALSE -- not ok.
439 **
440 **	Side Effects:
441 **		none (unless you include the usrerr stuff)
442 */
443 
444 bool
445 checkcompat(to)
446 	register ADDRESS *to;
447 {
448 # ifdef lint
449 	if (to == NULL)
450 		to++;
451 # endif lint
452 # ifdef EXAMPLE_CODE
453 	/* this code is intended as an example only */
454 	register STAB *s;
455 
456 	s = stab("arpa", ST_MAILER, ST_FIND);
457 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
458 	    to->q_mailer == s->s_mailer)
459 	{
460 		usrerr("No ARPA mail through this machine: see your system administration");
461 		/* NoReturn = TRUE; to supress return copy */
462 		return (FALSE);
463 	}
464 # endif EXAMPLE_CODE
465 	return (TRUE);
466 }
467 /*
468 **  HOLDSIGS -- arrange to hold all signals
469 **
470 **	Parameters:
471 **		none.
472 **
473 **	Returns:
474 **		none.
475 **
476 **	Side Effects:
477 **		Arranges that signals are held.
478 */
479 
480 holdsigs()
481 {
482 }
483 /*
484 **  RLSESIGS -- arrange to release all signals
485 **
486 **	This undoes the effect of holdsigs.
487 **
488 **	Parameters:
489 **		none.
490 **
491 **	Returns:
492 **		none.
493 **
494 **	Side Effects:
495 **		Arranges that signals are released.
496 */
497 
498 rlsesigs()
499 {
500 }
501 /*
502 **  GETLA -- get the current load average
503 **
504 **	This code stolen from la.c.
505 **
506 **	Parameters:
507 **		none.
508 **
509 **	Returns:
510 **		The current load average as an integer.
511 **
512 **	Side Effects:
513 **		none.
514 */
515 
516 #ifdef VMUNIX
517 
518 #include <nlist.h>
519 
520 struct	nlist Nl[] =
521 {
522 	{ "_avenrun" },
523 #define	X_AVENRUN	0
524 	{ 0 },
525 };
526 
527 getla()
528 {
529 	static int kmem = -1;
530 	double avenrun[3];
531 
532 	if (kmem < 0)
533 	{
534 		kmem = open("/dev/kmem", 0, 0);
535 		if (kmem < 0)
536 			return (-1);
537 		(void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
538 		nlist("/vmunix", Nl);
539 		if (Nl[0].n_type == 0)
540 			return (-1);
541 	}
542 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
543 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
544 	{
545 		/* thank you Ian */
546 		return (-1);
547 	}
548 	return ((int) (avenrun[0] + 0.5));
549 }
550 
551 #else VMUNIX
552 
553 getla()
554 {
555 	return (0);
556 }
557 
558 #endif VMUNIX
559