xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 2897)
1 # include <stdio.h>
2 # include <pwd.h>
3 # include "dlvrmail.h"
4 
5 /*
6 **  CONF.C -- Delivermail Configuration Tables.
7 **
8 **	Defines the configuration of this installation.
9 **
10 **	Compilation Flags:
11 **		HASARPA -- set if this machine has a connection to
12 **			the Arpanet.
13 **		HASUUCP -- set if this machine has a connection to
14 **			the UUCP network.
15 **		NETV6MAIL -- set if you want to use "v6mail" that
16 **			comes with the Berkeley network.  Normally
17 **			/bin/mail will work fine, but around Berkeley
18 **			we use v6mail because it is a "fixed target".
19 **			Also, only v6mail has the "/dev/mail" stuff
20 **			in it (for biff(1)).
21 **		V6 -- running on a version 6 system.  This determines
22 **			whether to define certain routines between
23 **			the two systems.  If you are running a funny
24 **			system, e.g., V6 with long tty names, this
25 **			should be checked carefully.
26 **		DUMBMAIL -- set if your /bin/mail doesn't have the
27 **			-d flag.
28 **
29 **	Configuration Variables:
30 **		ArpaHost -- the arpanet name of the host through
31 **			which arpanet mail will be sent.
32 **		MyLocName -- the name of the host on a local network.
33 **			This is used to disambiguate the contents of
34 **			ArpaHost among many hosts who may be sharing
35 **			a gateway.
36 **		DaemonName -- the name of this agent for use in
37 **			error messages, typically "~MAILER~DAEMON~"
38 **			at this host on the local net.
39 **		ArpaLocal -- a list of local names for this host on
40 **			the arpanet.  Only functional if HASARPA set.
41 **		UucpLocal -- ditto for the Arpanet.
42 **		BerkLocal -- ditto for the Berknet.
43 **		Mailer -- a table of mailers known to the system.
44 **			The fields are:
45 **			- the pathname of the mailer.
46 **			- a list of flags describing the properties
47 **			  of this mailer:
48 **			   M_FOPT -- if set, the mailer has a picky "-f"
49 **				option.  In this mode, the mailer will
50 **				only accept the "-f" option if the
51 **				sender is actually "root", "network",
52 **				and possibly (but not necessarily) if
53 **				the -f argument matches the real sender.
54 **				The effect is that if the "-f" option
55 **				is given to delivermail then it will be
56 **				passed through (as arguments 1 & 2) to
57 **				the mailer.
58 **			   M_ROPT -- identical to M_FOPT, except uses
59 **				-r instead.
60 **			   M_QUIET -- if set, don't print a message if
61 **				the mailer returns bad status.
62 **			   M_RESTR -- if set, this mailer is restricted
63 **				to use by "daemon"; otherwise, we do a
64 **				setuid(getuid()) before calling the
65 **				mailer.
66 **			   M_HDR -- if set, the mailer wants us to
67 **				insert a UNIX "From" line before
68 **				outputing.
69 **			   M_FHDR -- if set, the header that we
70 **				generate will be used literally, so
71 **				we must force it to be correct.  The
72 **				effect is that we generate a header
73 **				even if one exists.
74 **			   M_NOHOST -- if set, this mailer doesn't care
75 **				about the host part (e.g., the local
76 **				mailer).
77 **			   M_STRIPQ -- if set, strip quote (`"')
78 **				characters out of parameters as you
79 **				transliterate them into the argument
80 **				vector.  For example, the local mailer
81 **				is called directly, so these should be
82 **				stripped, but the program-mailer (i.e.,
83 **				csh) should leave them in.
84 **			   M_NEEDDATE -- this mailer requires a Date:
85 **				field in the message.
86 **			   M_NEEDFROM -- this mailer requires a From:
87 **				field in the message.
88 **			   M_MSGID -- this mailer requires a Message-Id
89 **				field in the message.
90 **			   M_COMMAS -- this mailer wants comma-
91 **				seperated To: and Cc: fields.
92 **			   M_ARPAFMT == M_NEEDDATE|M_NEEDFROM|M_MSGID|
93 **				M_COMMAS.
94 **			- an exit status to use as the code for the
95 **			  error message print if the mailer returns
96 **			  something we don't understand.
97 **			- A list of names that are to be considered
98 **			  "local" (and hence are stripped off) for
99 **			  this mailer.
100 **			- An argument vector to be passed to the
101 **			  mailer with the following substitutions:
102 **			   $f - the from person name.
103 **			   $u - the target user name.
104 **			   $h - the target user host.
105 **			   $c - the hop count.
106 **			>>>>>>>>>> Entry zero must be for the local
107 **			>> NOTE >> mailer and entry one must be for
108 **			>>>>>>>>>> the shell.
109 **		ParseTab -- a table driving the parsing process.  Each
110 **			entry contains:
111 **			- a character that will trigger this entry.
112 **			- an index into the Mailer table.
113 **			- a word of flags, described in dlvrmail.h.
114 **			- an argument.  If we have P_MAP, it is the
115 **			  character to turn the trigger character into.
116 **			  If we have P_MOVE, it is the site to send it
117 **			  to, using the mailer specified above.
118 **			This table will almost certainly have to be
119 **			changed on your site if you have anything more
120 **			than the UUCP net.
121 **		HdrInfo -- a table describing well-known header fields.
122 **			Each entry has the field name and some flags,
123 **			which can be:
124 **			H_CONCAT -- if there is more than one field
125 **				of this name, turn it into a comma-
126 **				seperated list.
127 **			H_DELETE -- delete this field.
128 */
129 
130 
131 
132 
133 static char SccsId[] = "@(#)conf.c	3.1	03/04/81";
134 
135 
136 bool	UseMsgId = FALSE;	/* don't put message id's in anywhere */
137 
138 # include <whoami.h>		/* definitions of machine id's at berkeley */
139 
140 # ifdef BERKELEY
141 
142 char	*ArpaHost = "Berkeley";	/* host name of gateway on Arpanet */
143 char	*UucpHost = "ucbvax";	/* host name of gateway on UUCP net */
144 # define BerkHost   MyLocName	/* host name of gateway on Berk net */
145 # define NETV6MAIL		/* use /usr/net/bin/v6mail for local delivery */
146 
147 # else BERKELEY
148 
149 char	*ArpaHost = "[unknown]";
150 char	*MyLocName = sysname;
151 # define HASUUCP		/* default to having UUCP net */
152 char	*UucpLocal[] = { sysname, NULL };
153 
154 # endif BERKELEY
155 
156 
157 /* Specific Configurations for Berkeley Machines */
158 
159 /* Berkeley people: mail changes to csvax:eric or they will be lost! */
160 
161 # ifdef ING70
162 static char	*BerkLocal[] = { "i", "ingres", "ing70", NULL };
163 char		*ArpaLocal = { "berkeley", "ucb", NULL };
164 char		*MyLocName = "Ing70";
165 char		*DaemonName = "Ing70:~MAILER~DAEMON~";
166 # define HASARPA
167 # define V6
168 # endif ING70
169 
170 # ifdef INGVAX
171 static char	*BerkLocal[] = { "j", "ingvax", NULL };
172 char		*MyLocName = "IngVax";
173 char		*DaemonName = "IngVax:~MAILER~DAEMON~";
174 # endif INGVAX
175 
176 # ifdef CSVAX
177 static char	*BerkLocal[] = { "v", "csvax", "vax", NULL };
178 static char	*UucpLocal[] = { "ucbvax", "ernie", NULL };
179 char		*MyLocName = "CSVAX";
180 char		*DaemonName = "CSVAX:~MAILER~DAEMON~";
181 # define HASUUCP
182 # endif CSVAX
183 
184 # ifdef ARPAVAX
185 static char	*BerkLocal[] = { "r", "arpavax", NULL };
186 char		*MyLocName = "ARPAVAX";
187 char		*DaemonName = "ARPAVAX:~MAILER~DAEMON~";
188 # endif ARPAVAX
189 
190 # ifdef CORY
191 static char	*BerkLocal[] = { "y", "cory", NULL };
192 char		*MyLocName = "Cory";
193 char		*DaemonName = "Cory:~MAILER~DAEMON~";
194 # endif CORY
195 
196 # ifdef ONYX
197 static char	*BerkLocal[[] = { "x", "onyx", NULL };
198 char		*MyLocName = "Onyx";
199 char		*DaemonName = "Onyx:~MAILER~DAEMON~";
200 # endif ONYX
201 
202 # ifdef IMAGE
203 /* untested */
204 static char	*BerkLocal[] = { "m", "image", NULL };
205 char		*MyLocName = "Image";
206 char		*DaemonName = "Image:~MAILER~DAEMON~";
207 # define V6
208 # endif IMAGE
209 
210 # ifdef ESVAX
211 static char	*BerkLocal[] = { "o", "esvax", NULL };
212 char		*MyLocName = "ESVAX";
213 char		*DaemonName = "ESVAX:~MAILER~DAEMON~";
214 # endif ESVAX
215 
216 # ifdef EECS40
217 /* untested */
218 static char	*BerkLocal[] = { "z", "eecs40", NULL };
219 char		*MyLocName = "EECS40";
220 char		*DaemonName = "EECS40:~MAILER~DAEMON~";
221 # define V6
222 # endif EECS40
223 
224 
225 # ifndef HASARPA
226 # define ArpaLocal	NULL
227 # endif HASARPA
228 
229 # ifndef HASUUCP
230 # define UucpLocal	NULL
231 # endif HASUUCP
232 
233 
234 struct mailer Mailer[] =
235 {
236 	/* local mail -- must be #0 */
237 	{
238 # ifdef NETV6MAIL
239 		"/usr/net/bin/v6mail",
240 # else
241 		"/bin/mail",
242 # endif
243 		M_ROPT|M_NOHOST|M_STRIPQ|M_ARPAFMT,	EX_NOUSER,	NULL,
244 		"$f",		NULL,
245 		{ "...local%mail", "-d", "$u", NULL }
246 	},
247 	/* pipes through programs -- must be #1 */
248 	{
249 		"/bin/csh",
250 		M_HDR|M_FHDR|M_NOHOST,		EX_UNAVAILABLE,	NULL,
251 		"$f",		NULL,
252 		{ "...prog%mail", "-fc", "$u", NULL }
253 	},
254 	/* local berkeley mail */
255 	{
256 		"/usr/net/bin/sendberkmail",
257 		M_FOPT|M_HDR|M_STRIPQ,		EX_UNAVAILABLE,	BerkLocal,
258 		"$B:$f",	NULL,
259 		{ "...berk%mail", "-m", "$h", "-t", "$u", "-h", "$c", NULL }
260 	},
261 	/* arpanet mail */
262 	{
263 		"/usr/lib/mailers/arpa",
264 		M_STRIPQ|M_ARPAFMT,		0,		ArpaLocal,
265 		"$f@$A",	NULL,
266 		{ "...arpa%mail", "$f", "$h", "$u", NULL }
267 	},
268 	/* uucp mail (cheat & use Bell's v7 mail) */
269 	{
270 		"/bin/mail",
271 		M_ROPT|M_STRIPQ,		EX_NOUSER,	UucpLocal,
272 		"$U!$f",	NULL,
273 # ifdef DUMBMAIL
274 		{ "...uucp%mail", "$h!$u", NULL }
275 # else
276 		{ "...uucp%mail", "-d", "$h!$u", NULL }
277 # endif DUMBMAIL
278 	},
279 };
280 
281 # define M_LOCAL	0
282 # define M_BERK		2
283 # define M_ARPA		3
284 # define M_UUCP		4
285 
286 
287 
288 # ifdef BERKELEY
289 struct parsetab ParseTab[] =
290 {
291 	':',	M_BERK,		P_ONE,				NULL,
292 # ifdef HASARPA
293 	'@',	M_ARPA,		P_HLAST|P_USR_UPPER,		NULL,
294 # else
295 	'@',	M_BERK,		P_HLAST|P_USR_UPPER|P_MOVE,	"ing70",
296 # endif HASARPA
297 	'^',	-1,		P_MAP,				"!",
298 # ifdef HASUUCP
299 	'!',	M_UUCP,		0,				NULL,
300 # else
301 	'!',	M_BERK,		P_MOVE,				"csvax",
302 # endif HASUUCP
303 	'.',	-1,		P_MAP|P_ONE,			":",
304 	'\0',	M_LOCAL,	P_MOVE,				"",
305 };
306 # else BERKELEY
307 struct parsetab ParseTab[] =
308 {
309 # ifdef HASARPA
310 	'@',	M_ARPA,		P_HLAST|P_USR_UPPER,		NULL,
311 # endif HASARPA
312 # ifdef HASUUCP
313 	'^',	-1,		P_MAP,				"!",
314 	'!',	M_UUCP,		0,				NULL,
315 # endif HASUUCP
316 	'\0',	M_LOCAL,	P_MOVE,				"",
317 };
318 # endif BERKELEY
319 
320 
321 /*
322 **  Header info table
323 */
324 
325 struct hdrinfo	HdrInfo[] =
326 {
327 	"date",		0,
328 	"from",		0,
329 	"to",		H_CONCAT,
330 	"cc",		H_CONCAT,
331 	"subject",	0,
332 	"message-id",	0,
333 	NULL,		0
334 };
335 /*
336 **  INITMACS -- initialize predefined macros.
337 **
338 **	Parameters:
339 **		none.
340 **
341 **	Returns:
342 **		none.
343 **
344 **	Side Effects:
345 **		Macros array gets initialized.
346 */
347 
348 char	*Macro[26];
349 
350 # define MACRO(x)	Macro[x - 'A']
351 
352 initmacs()
353 {
354 	MACRO('A') = ArpaHost;
355 	MACRO('B') = BerkHost;
356 	MACRO('U') = UucpHost;
357 }
358 /*
359 **  GETNAME -- Get the current users login name.
360 **
361 **	This is in config.c because it is somewhat machine dependent.
362 **	Examine it carefully for your installation.
363 **
364 **	Algorithm:
365 **		See if the person is logged in.  If so, return
366 **			the name s/he is logged in as.
367 **		Look up the user id in /etc/passwd.  If found,
368 **			return that name.
369 **		Return NULL.
370 **
371 **	Parameters:
372 **		none
373 **
374 **	Returns:
375 **		The login name of this user.
376 **		NULL if this person is noone.
377 **
378 **	Side Effects:
379 **		none
380 **
381 **	Called By:
382 **		main
383 */
384 
385 char *
386 getname()
387 {
388 	register char *p;
389 	register struct passwd *w;
390 	extern char *getlogin();
391 	extern struct passwd *getpwuid();
392 	static char namebuf[9];
393 
394 	p = getlogin();
395 	if (p != NULL && p[0] != '\0')
396 		return (p);
397 # ifdef V6
398 	w = getpwuid(getuid() & 0377);
399 # else
400 	w = getpwuid(getuid());
401 # endif V6
402 	if (w != NULL)
403 	{
404 		strcpy(namebuf, w->pw_name);
405 		return (namebuf);
406 	}
407 	return (NULL);
408 }
409 
410 # ifdef V6
411 /*
412 **  TTYPATH -- Get the path of the user's tty -- Version 6 version.
413 **
414 **	Returns the pathname of the user's tty.  Returns NULL if
415 **	the user is not logged in or if s/he has write permission
416 **	denied.
417 **
418 **	Parameters:
419 **		none
420 **
421 **	Returns:
422 **		pathname of the user's tty.
423 **		NULL if not logged in or write permission denied.
424 **
425 **	Side Effects:
426 **		none.
427 **
428 **	WARNING:
429 **		Return value is in a local buffer.
430 **
431 **	Called By:
432 **		savemail
433 */
434 
435 # include <sys/types.h>
436 # include <sys/stat.h>
437 
438 char *
439 ttypath()
440 {
441 	struct stat stbuf;
442 	register int i;
443 	static char pathn[] = "/dev/ttyx";
444 	extern int errno;
445 
446 	/* compute the pathname of the controlling tty */
447 	if ((i = ttyn(2)) == 'x' && (i = ttyn(1)) == 'x' && (i = ttyn(0)) == 'x')
448 	{
449 		errno = 0;
450 		return (NULL);
451 	}
452 	pathn[8] = i;
453 
454 	/* see if we have write permission */
455 	if (stat(pathn, &stbuf) < 0 || !flagset(02, stbuf.st_mode))
456 	{
457 		errno = 0;
458 		return (NULL);
459 	}
460 
461 	/* see if the user is logged in */
462 	if (getlogin() == NULL)
463 		return (NULL);
464 
465 	/* looks good */
466 	return (pathn);
467 }
468 /*
469 **  FDOPEN -- Open a stdio file given an open file descriptor.
470 **
471 **	This is included here because it is standard in v7, but we
472 **	need it in v6.
473 **
474 **	Algorithm:
475 **		Open /dev/null to create a descriptor.
476 **		Close that descriptor.
477 **		Copy the existing fd into the descriptor.
478 **
479 **	Parameters:
480 **		fd -- the open file descriptor.
481 **		type -- "r", "w", or whatever.
482 **
483 **	Returns:
484 **		The file descriptor it creates.
485 **
486 **	Side Effects:
487 **		none
488 **
489 **	Called By:
490 **		deliver
491 **
492 **	Notes:
493 **		The mode of fd must match "type".
494 */
495 
496 FILE *
497 fdopen(fd, type)
498 	int fd;
499 	char *type;
500 {
501 	register FILE *f;
502 
503 	f = fopen("/dev/null", type);
504 	close(fileno(f));
505 	fileno(f) = fd;
506 	return (f);
507 }
508 /*
509 **  INDEX -- Return pointer to character in string
510 **
511 **	For V7 compatibility.
512 **
513 **	Parameters:
514 **		s -- a string to scan.
515 **		c -- a character to look for.
516 **
517 **	Returns:
518 **		If c is in s, returns the address of the first
519 **			instance of c in s.
520 **		NULL if c is not in s.
521 **
522 **	Side Effects:
523 **		none.
524 */
525 
526 index(s, c)
527 	register char *s;
528 	register char c;
529 {
530 	while (*s != '\0')
531 	{
532 		if (*s++ == c)
533 			return (--s);
534 	}
535 	return (NULL);
536 }
537 # endif V6
538 
539 # ifndef V6
540 /*
541 **  TTYPATH -- Get the path of the user's tty -- Version 7 version.
542 **
543 **	Returns the pathname of the user's tty.  Returns NULL if
544 **	the user is not logged in or if s/he has write permission
545 **	denied.
546 **
547 **	Parameters:
548 **		none
549 **
550 **	Returns:
551 **		pathname of the user's tty.
552 **		NULL if not logged in or write permission denied.
553 **
554 **	Side Effects:
555 **		none.
556 **
557 **	WARNING:
558 **		Return value is in a local buffer.
559 **
560 **	Called By:
561 **		savemail
562 */
563 
564 # include <sys/types.h>
565 # include <sys/stat.h>
566 
567 char *
568 ttypath()
569 {
570 	struct stat stbuf;
571 	register char *pathn;
572 	extern int errno;
573 	extern char *ttyname();
574 
575 	/* compute the pathname of the controlling tty */
576 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && (pathn = ttyname(0)) == NULL)
577 	{
578 		errno = 0;
579 		return (NULL);
580 	}
581 
582 	/* see if we have write permission */
583 	if (stat(pathn, &stbuf) < 0 || !flagset(02, stbuf.st_mode))
584 	{
585 		errno = 0;
586 		return (NULL);
587 	}
588 
589 	/* see if the user is logged in */
590 	if (getlogin() == NULL)
591 		return (NULL);
592 
593 	/* looks good */
594 	return (pathn);
595 }
596 # endif V6
597