1292Seric # include <stdio.h>
2292Seric # include <ctype.h>
3292Seric # include <pwd.h>
43309Seric # include "sendmail.h"
5292Seric 
6*4106Seric # ifdef DBM
7*4106Seric static char SccsId[] = "@(#)alias.c	3.12	08/10/81	(with DBM)";
8*4106Seric # else DBM
9*4106Seric static char SccsId[] = "@(#)alias.c	3.12	08/10/81	(without DBM)";
10*4106Seric # endif DBM
11402Seric 
12292Seric /*
13292Seric **  ALIAS -- Compute aliases.
14292Seric **
154098Seric **	Scans the file /usr/lib/aliases for a set of aliases.
163185Seric **	If found, it arranges to deliver to them.  Uses libdbm
173185Seric **	database if -DDBM.
18292Seric **
19292Seric **	Parameters:
204097Seric **		a -- address to alias.
21292Seric **
22292Seric **	Returns:
23292Seric **		none
24292Seric **
25292Seric **	Side Effects:
263185Seric **		Aliases found are expanded.
27292Seric **
28292Seric **	Files:
294098Seric **		/usr/lib/aliases -- the mail aliases.  The format is
30569Seric **			a series of lines of the form:
31569Seric **				alias:name1,name2,name3,...
32569Seric **			where 'alias' expands to all of
33569Seric **			'name[i]'.  Continuations begin with
34569Seric **			space or tab.
354098Seric **		/usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version
361503Smark **			of alias file.  Keys are aliases, datums
371503Smark **			(data?) are name1,name2, ...
38292Seric **
39292Seric **	Notes:
40292Seric **		If NoAlias (the "-n" flag) is set, no aliasing is
41292Seric **			done.
42292Seric **
43292Seric **	Deficiencies:
44292Seric **		It should complain about names that are aliased to
45292Seric **			nothing.
46292Seric **		It is unsophisticated about line overflows.
47292Seric */
48292Seric 
49292Seric 
501503Smark #ifdef DBM
512966Seric typedef struct
522966Seric {
532966Seric 	char	*dptr;
542966Seric 	int dsize;
552966Seric } datum;
561503Smark datum lhs, rhs;
571515Seric extern datum fetch();
581503Smark #endif DBM
59292Seric 
604097Seric alias(a)
614097Seric 	register ADDRESS *a;
62292Seric {
634081Seric 	register char *p;
644081Seric # ifndef DBM
654098Seric 	register STAB *s;
664081Seric # endif DBM
67292Seric 
68292Seric 	if (NoAlias)
69292Seric 		return;
70292Seric # ifdef DEBUG
71292Seric 	if (Debug)
724098Seric 		printf("alias(%s)\n", a->q_paddr);
73292Seric # endif
74292Seric 
754098Seric 	/* don't realias already aliased names */
764098Seric 	if (bitset(QDONTSEND, a->q_flags))
774098Seric 		return;
784098Seric 
794098Seric 	To = a->q_paddr;
804098Seric 
814097Seric # ifdef DBM
824098Seric 	/* create a key for fetch */
834098Seric 	lhs.dptr = a->q_user;
844098Seric 	lhs.dsize = strlen(a->q_user) + 1;
854098Seric 	rhs = fetch(lhs);
864098Seric 
874098Seric 	/* find this alias? */
884098Seric 	p = rhs.dptr;
894098Seric 	if (p == NULL)
904098Seric 		return;
914098Seric # else DBM
924098Seric 	s = stab(a->q_user, ST_ALIAS, ST_FIND);
934098Seric 	if (s == NULL)
944098Seric 		return;
954098Seric 	p = s->s_alias;
964097Seric # endif DBM
97292Seric 
98292Seric 	/*
994098Seric 	**  Match on Alias.
1004098Seric 	**	Deliver to the target list.
1011515Seric 	*/
1021515Seric 
1034098Seric # ifdef DEBUG
1044098Seric 	if (Debug)
1054098Seric 		printf("%s (%s, %s) aliased to %s\n",
1064098Seric 		    a->q_paddr, a->q_host, a->q_user, p);
1074098Seric # endif
1084098Seric 	if (Verbose)
1094098Seric 		message("050", "aliased to %s", p);
1104098Seric 	a->q_flags |= QDONTSEND;
1114098Seric 	AliasLevel++;
1124098Seric 	sendto(p, 1);
1134098Seric 	AliasLevel--;
1144098Seric }
1154098Seric /*
1164098Seric **  INITALIASES -- initialize for aliasing
1174098Seric **
1184098Seric **	Very different depending on whether we are running DBM or not.
1194098Seric **
1204098Seric **	Parameters:
1214098Seric **		aliasfile -- location of aliases.
1224098Seric **
1234098Seric **	Returns:
1244098Seric **		none.
1254098Seric **
1264098Seric **	Side Effects:
1274098Seric **		initializes aliases:
1284098Seric **		if DBM:  opens the database.
1294098Seric **		if ~DBM: reads the aliases into the symbol table.
1304098Seric */
1314098Seric 
1324098Seric initaliases(aliasfile)
1334098Seric 	char *aliasfile;
1344098Seric {
1354098Seric # ifdef DBM
1364098Seric 	dbminit(aliasfile);
1374098Seric # else DBM
1384098Seric 	char line[BUFSIZ];
1394098Seric 	register char *p;
1404098Seric 	char *p2;
1414098Seric 	char *rhs;
1424098Seric 	bool skipping;
1434098Seric 	ADDRESS al, bl;
144*4106Seric 	FILE *af;
145*4106Seric 	int lineno;
146*4106Seric 	register STAB *s;
1474098Seric 
1484098Seric 	if ((af = fopen(aliasfile, "r")) == NULL)
1491515Seric 	{
1504098Seric # ifdef DEBUG
1514098Seric 		if (Debug)
152*4106Seric 			printf("Can't open %s\n", aliasfile);
1534098Seric # endif
1544098Seric 		errno = 0;
1554098Seric 		NoAlias++;
1564098Seric 		return;
1574098Seric 	}
1584098Seric 	/* read and interpret lines */
1594098Seric 	lineno = 0;
1604098Seric 	skipping = FALSE;
1614098Seric 	while (fgets(line, sizeof (line), af) != NULL)
1624098Seric 	{
1634098Seric 		lineno++;
1644098Seric 		switch (line[0])
1654098Seric 		{
1664098Seric 		  case '#':
1674098Seric 		  case '\n':
1684098Seric 		  case '\0':
1694098Seric 			skipping = FALSE;
1704098Seric 			continue;
1714065Seric 
1724098Seric 		  case ' ':
1734098Seric 		  case '\t':
1744098Seric 			if (!skipping)
1754098Seric 				syserr("aliases: %d: Non-continuation line starts with space", lineno);
1764098Seric 			skipping = TRUE;
1774097Seric 			continue;
1784098Seric 		}
1794098Seric 		skipping = FALSE;
1801874Seric 
1814098Seric 		/* process the LHS */
1824098Seric 		for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
1834097Seric 			continue;
1844098Seric 		if (*p == '\0' || *p == '\n')
1854098Seric 		{
1864098Seric 		 syntaxerr:
1874098Seric 			syserr("aliases: %d: missing colon", lineno);
1884097Seric 			continue;
1894098Seric 		}
1904098Seric 		*p++ = '\0';
1914098Seric 		if (parse(line, &al, 1) == NULL)
1924098Seric 		{
1934098Seric 			*--p = ':';
1944098Seric 			goto syntaxerr;
1954098Seric 		}
1964098Seric 		rhs = p;
1974098Seric 		for (;;)
1984098Seric 		{
1994098Seric 			register char c;
2001515Seric 
201*4106Seric # ifdef SECURE
2024098Seric 			/* do parsing & compression of addresses */
2034098Seric 			c = *p;
2044098Seric 			while (c != '\0')
2054098Seric 			{
2064098Seric 				p2 = p;
2074098Seric 				while (*p != '\n' && *p != ',' && *p != '\0')
2084098Seric 					p++;
2094098Seric 				c = *p;
2104098Seric 				*p++ = '\0';
2114098Seric 				if (*p2 == '\0')
2124098Seric 				{
2134098Seric 					p[-1] = c;
2144098Seric 					continue;
2154098Seric 				}
2164098Seric 				parse(p2, &bl, -1);
2174098Seric 				p[-1] = c;
2184098Seric 				while (isspace(*p))
2194098Seric 					p++;
2204098Seric 			}
221*4106Seric # else SECURE
222*4106Seric 			p = &p[strlen(p)];
223*4106Seric # endif SECURE
2241515Seric 
2254098Seric 			/* see if there should be a continuation line */
226*4106Seric 			c = fgetc(af);
227*4106Seric 			if (!feof(af))
228*4106Seric 				ungetc(c, af);
229*4106Seric 			if (c != ' ' && c != '\t')
2304098Seric 				break;
2314098Seric 
2324098Seric 			/* read continuation line */
2334098Seric 			p--;
2344098Seric 			if (fgets(p, sizeof line - (p - line), af) == NULL)
2354098Seric 				break;
2364098Seric 			lineno++;
2374098Seric 		}
2384098Seric 		if (al.q_mailer != M_LOCAL)
2394098Seric 		{
2404098Seric 			syserr("aliases: %d: cannot alias non-local names", lineno);
2414098Seric 			continue;
2424098Seric 		}
243*4106Seric 		s = stab(al.q_user, ST_ALIAS, ST_ENTER);
244*4106Seric 		s->s_alias = newstr(rhs);
2451515Seric 	}
2464098Seric 	(void) fclose(af);
2474098Seric # endif DBM
248292Seric }
249292Seric /*
250292Seric **  FORWARD -- Try to forward mail
251292Seric **
252292Seric **	This is similar but not identical to aliasing.
253292Seric **
254292Seric **	Parameters:
255292Seric **		user -- the name of the user who's mail we
256292Seric **			would like to forward to.
257292Seric **
258292Seric **	Returns:
2594098Seric **		none.
260292Seric **
261292Seric **	Side Effects:
2623185Seric **		New names are added to send queues.
2634098Seric **		Sets the QDONTSEND bit in addresses that are forwarded.
264292Seric */
265292Seric 
266292Seric forward(user)
2672966Seric 	ADDRESS *user;
268292Seric {
2694078Seric 	char buf[60];
2704069Seric 	register FILE *fp;
2714069Seric 	register char *p;
2724069Seric 
2734098Seric # ifdef DEBUG
2744098Seric 	if (Debug)
2754098Seric 		printf("forward(%s)\n", user->q_paddr);
2764098Seric # endif DEBUG
2774098Seric 
2784078Seric 	if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags))
2794098Seric 		return;
2804069Seric 
2814069Seric 	/* good address -- look for .forward file in home */
2824104Seric 	define('z', user->q_home);
2834081Seric 	(void) expand("$z/.forward", buf, &buf[sizeof buf - 1]);
2844069Seric 	fp = fopen(buf, "r");
2854069Seric 	if (fp == NULL)
2864098Seric 		return;
2874069Seric 
2884069Seric 	/* we do have an address to forward to -- do it */
2894098Seric 	user->q_flags |= QDONTSEND;
2904081Seric 	(void) fgets(buf, sizeof buf, fp);
2914069Seric 	if ((p = index(buf, '\n')) != NULL)
2924069Seric 		*p = '\0';
2934081Seric 	(void) fclose(fp);
2944069Seric 	if (buf[0] == '\0')
2954098Seric 		return;
2964069Seric 	if (Verbose)
2974069Seric 		message("050", "forwarded to %s", buf);
2984098Seric 	AliasLevel++;
2994069Seric 	sendto(buf, 1);
3004098Seric 	AliasLevel--;
3014098Seric 	return;
302292Seric }
303