13308Seric # include <stdio.h>
23313Seric # include "sendmail.h"
33308Seric # include <ctype.h>
43308Seric 
5*4061Seric static char SccsId[] = "@(#)readcf.c	3.4	08/08/81";
63308Seric 
73308Seric /*
83308Seric **  READCF -- read control file.
93308Seric **
103308Seric **	This routine reads the control file and builds the internal
113308Seric **	form.
123308Seric **
133308Seric **	Parameters:
143308Seric **		cfname -- control file name.
153308Seric **
163308Seric **	Returns:
173308Seric **		none.
183308Seric **
193308Seric **	Side Effects:
203308Seric **		Builds several internal tables.
213308Seric */
223308Seric 
233308Seric struct rewrite	*RewriteRules;
243308Seric 
253308Seric 
263308Seric readcf(cfname)
273308Seric 	char *cfname;
283308Seric {
293308Seric 	FILE *cf;
303308Seric 	char buf[MAXLINE];
313308Seric 	register char *p;
323308Seric 	struct rewrite *rwp = NULL;
333308Seric 	extern char *xalloc();
343308Seric 	extern char **prescan();
353308Seric 	extern char **copyplist();
363308Seric 	extern char *rindex();
373308Seric 	extern char *newstr();
38*4061Seric 	int class;
393308Seric 
403308Seric 	cf = fopen(cfname, "r");
413308Seric 	if (cf == NULL)
423308Seric 	{
433308Seric 		syserr("cannot open %s", cfname);
443308Seric 		exit(EX_OSFILE);
453308Seric 	}
463308Seric 
473308Seric 	while (fgets(buf, sizeof buf, cf) != NULL)
483308Seric 	{
493308Seric 		p = rindex(buf, '\n');
503308Seric 		if (p != NULL)
513308Seric 			*p = '\0';
523308Seric 
533308Seric 		switch (buf[0])
543308Seric 		{
553308Seric 		  case '\n':
563308Seric 		  case '\0':
573308Seric 		  case ' ':
583308Seric 		  case '\t':
593308Seric 		  case '#':		/* comment */
603308Seric 			break;
613308Seric 
623308Seric 		  case 'R':		/* rewriting rule */
633308Seric 			for (p = &buf[1]; *p != '\0' && *p != '\t'; p++)
643308Seric 				continue;
653308Seric 
663308Seric 			if (*p == '\0')
673308Seric 				syserr("invalid rewrite line \"%s\"", buf);
683308Seric 			else
693308Seric 			{
703308Seric 				if (rwp == NULL)
713308Seric 					RewriteRules = rwp = (struct rewrite *) xalloc(sizeof *rwp);
723308Seric 				else
733308Seric 				{
743308Seric 					rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
753308Seric 					rwp = rwp->r_next;
763308Seric 				}
773308Seric 				rwp->r_next = NULL;
783308Seric 
793308Seric 				rwp->r_lhs = prescan(&buf[1], '\t');
803308Seric 				if (rwp->r_lhs != NULL)
813308Seric 					rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
823308Seric 				while (*p == '\t')
833308Seric 					p++;
843308Seric 				rwp->r_rhs = prescan(p, '\t');
853308Seric 				if (rwp->r_rhs != NULL)
863308Seric 					rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
873308Seric 			}
883308Seric 			break;
893308Seric 
903308Seric 		  case 'D':		/* macro definition */
913308Seric 			define(buf[1], newstr(&buf[2]));
923308Seric 			break;
933308Seric 
943387Seric 		  case 'H':		/* required header line */
953391Seric 			chompheader(&buf[1], TRUE);
963387Seric 			break;
973387Seric 
98*4061Seric 		  case 'C':		/* word class */
99*4061Seric 			class = buf[1];
100*4061Seric 			if (!isalpha(class))
101*4061Seric 				goto badline;
102*4061Seric 			if (isupper(class))
103*4061Seric 				class -= 'A';
104*4061Seric 			else
105*4061Seric 				class -= 'a';
106*4061Seric 
107*4061Seric 			/* scan the list of words and set class 'i' for all */
108*4061Seric 			for (p = &buf[2]; *p != '\0'; )
109*4061Seric 			{
110*4061Seric 				register char *wd;
111*4061Seric 				char delim;
112*4061Seric 				register STAB *s;
113*4061Seric 
114*4061Seric 				while (*p != '\0' && isspace(*p))
115*4061Seric 					p++;
116*4061Seric 				wd = p;
117*4061Seric 				while (*p != '\0' && !isspace(*p))
118*4061Seric 					p++;
119*4061Seric 				delim = *p;
120*4061Seric 				*p = '\0';
121*4061Seric 				if (wd[0] != '\0')
122*4061Seric 				{
123*4061Seric 					s = stab(wd, ST_ENTER);
124*4061Seric 					s->s_class |= 1 << class;
125*4061Seric 				}
126*4061Seric 				*p = delim;
127*4061Seric 			}
128*4061Seric 			break;
129*4061Seric 
1303308Seric 		  default:
131*4061Seric 		  badline:
1323308Seric 			syserr("unknown control line \"%s\"", buf);
1333308Seric 		}
1343308Seric 	}
1353308Seric 
1363308Seric /*
1373308Seric 	printrules();
1383308Seric */
1393308Seric }
1403308Seric /*
1413308Seric **  RWCRACK -- crack rewrite line.
1423308Seric **
1433308Seric **	Parameters:
1443308Seric **		l -- line to crack.
1453308Seric **
1463308Seric **	Returns:
1473308Seric **		local copy of cracked line.
1483308Seric **
1493308Seric **	Side Effects:
1503308Seric **		none.
1513308Seric */
1523308Seric 
1533308Seric char **
1543308Seric rwcrack(l)
1553308Seric 	register char *l;
1563308Seric {
1573308Seric 	char *av[MAXATOM];
1583308Seric 	int ac = 0;
1593308Seric 	register char **avp;
1603308Seric 	char buf[MAXNAME];
1613308Seric 	register char *b;
1623308Seric 	bool wasdelim = FALSE;
1633308Seric 	char *delims = ":@!^.";
1643308Seric 	extern char *index();
1653308Seric 	bool tchange;
1663308Seric 	extern char *newstr(), *xalloc();
1673308Seric 
1683308Seric 	for (avp = av; *l != '\0' && *l != '\n'; avp++)
1693308Seric 	{
1703308Seric 		b = buf;
1713308Seric 		tchange = FALSE;
1723308Seric 		while (!tchange)
1733308Seric 		{
1743308Seric 			if (*l != '$')
1753308Seric 			{
1763308Seric 				if (wasdelim || index(delims, *l) != NULL)
1773308Seric 					tchange = TRUE;
1783308Seric 				wasdelim = (index(delims, *l) != NULL);
1793308Seric 				if (wasdelim)
1803308Seric 					tchange = TRUE;
1813308Seric 				*b++ = *l++;
1823308Seric 				continue;
1833308Seric 			}
1843308Seric 
1853308Seric 			tchange = TRUE;
1863308Seric 			switch (*++l)
1873308Seric 			{
1883308Seric 			  case '$':		/* literal $ */
1893308Seric 				*b++ = *l;
1903308Seric 				break;
1913308Seric 
1923308Seric 			  case '+':		/* match anything */
1933308Seric 				*b++ = MATCHANY;
1943308Seric 				*b++ = *++l;
1953308Seric 				break;
1963308Seric 
1973308Seric 			  case '-':		/* match one token */
1983308Seric 				*b++ = MATCHONE;
1993308Seric 				*b++ = *++l;
2003308Seric 				break;
2013308Seric 
2023308Seric 			  case '#':		/* canonical net name */
2033308Seric 				*b++ = CANONNET;
2043308Seric 				break;
2053308Seric 
2063308Seric 			  case '@':		/* canonical host name */
2073308Seric 				*b++ = CANONHOST;
2083308Seric 				break;
2093308Seric 
2103308Seric 			  case ':':		/* canonical user name */
2113308Seric 				*b++ = CANONUSER;
2123308Seric 				break;
2133308Seric 
2143308Seric 			  default:
2153308Seric 				*b++ = '$';
2163308Seric 				l--;
2173308Seric 				break;
2183308Seric 			}
2193308Seric 			l++;
2203308Seric 		}
2213308Seric 
2223308Seric 		/* save the argument we have collected */
2233308Seric 		*b = '\0';
2243308Seric 		*avp = newstr(buf);
2253308Seric 		ac++;
2263308Seric 	}
2273308Seric 
2283308Seric 	/* allocate new space for vector */
2293308Seric 	ac++;
2303308Seric 	*avp = NULL;
2313308Seric 	avp = (char **) xalloc(ac * sizeof *av);
2323308Seric 	bmove(av, avp, ac * sizeof *av);
2333308Seric 
2343308Seric 	return (avp);
2353308Seric }
2363308Seric /*
2373308Seric **  PRINTRULES -- print rewrite rules (for debugging)
2383308Seric **
2393308Seric **	Parameters:
2403308Seric **		none.
2413308Seric **
2423308Seric **	Returns:
2433308Seric **		none.
2443308Seric **
2453308Seric **	Side Effects:
2463308Seric **		prints rewrite rules.
2473308Seric */
2483308Seric 
2493308Seric printrules()
2503308Seric {
2513308Seric 	register struct rewrite *rwp;
2523308Seric 
2533308Seric 	for (rwp = RewriteRules; rwp != NULL; rwp = rwp->r_next)
2543308Seric 	{
2553308Seric 		register char **av;
2563308Seric 
2573308Seric 		printf("\n");
2583308Seric 		for (av = rwp->r_lhs; *av != NULL; av++)
2593308Seric 		{
2603308Seric 			xputs(*av);
2613308Seric 			putchar('_');
2623308Seric 		}
2633308Seric 		printf("\n\t");
2643308Seric 		for (av = rwp->r_rhs; *av != NULL; av++)
2653308Seric 		{
2663308Seric 			xputs(*av);
2673308Seric 			putchar('_');
2683308Seric 		}
2693308Seric 		printf("\n");
2703308Seric 	}
2713308Seric }
272