1 /*
2  * Copyright (c) 1983, 1995 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)parseaddr.c	8.65 (Berkeley) 04/21/95";
11 #endif /* not lint */
12 
13 # include "sendmail.h"
14 
15 /*
16 **  PARSEADDR -- Parse an address
17 **
18 **	Parses an address and breaks it up into three parts: a
19 **	net to transmit the message on, the host to transmit it
20 **	to, and a user on that host.  These are loaded into an
21 **	ADDRESS header with the values squirreled away if necessary.
22 **	The "user" part may not be a real user; the process may
23 **	just reoccur on that machine.  For example, on a machine
24 **	with an arpanet connection, the address
25 **		csvax.bill@berkeley
26 **	will break up to a "user" of 'csvax.bill' and a host
27 **	of 'berkeley' -- to be transmitted over the arpanet.
28 **
29 **	Parameters:
30 **		addr -- the address to parse.
31 **		a -- a pointer to the address descriptor buffer.
32 **			If NULL, a header will be created.
33 **		flags -- describe detail for parsing.  See RF_ definitions
34 **			in sendmail.h.
35 **		delim -- the character to terminate the address, passed
36 **			to prescan.
37 **		delimptr -- if non-NULL, set to the location of the
38 **			delim character that was found.
39 **		e -- the envelope that will contain this address.
40 **
41 **	Returns:
42 **		A pointer to the address descriptor header (`a' if
43 **			`a' is non-NULL).
44 **		NULL on error.
45 **
46 **	Side Effects:
47 **		none
48 */
49 
50 /* following delimiters are inherent to the internal algorithms */
51 # define DELIMCHARS	"()<>,;\r\n"	/* default word delimiters */
52 
53 ADDRESS *
54 parseaddr(addr, a, flags, delim, delimptr, e)
55 	char *addr;
56 	register ADDRESS *a;
57 	int flags;
58 	int delim;
59 	char **delimptr;
60 	register ENVELOPE *e;
61 {
62 	register char **pvp;
63 	auto char *delimptrbuf;
64 	bool queueup;
65 	char pvpbuf[PSBUFSIZE];
66 	extern ADDRESS *buildaddr();
67 	extern bool invalidaddr();
68 
69 	/*
70 	**  Initialize and prescan address.
71 	*/
72 
73 	e->e_to = addr;
74 	if (tTd(20, 1))
75 		printf("\n--parseaddr(%s)\n", addr);
76 
77 	if (delimptr == NULL)
78 		delimptr = &delimptrbuf;
79 
80 	pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL);
81 	if (pvp == NULL)
82 	{
83 		if (tTd(20, 1))
84 			printf("parseaddr-->NULL\n");
85 		return (NULL);
86 	}
87 
88 	if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr))
89 	{
90 		if (tTd(20, 1))
91 			printf("parseaddr-->bad address\n");
92 		return NULL;
93 	}
94 
95 	/*
96 	**  Save addr if we are going to have to.
97 	**
98 	**	We have to do this early because there is a chance that
99 	**	the map lookups in the rewriting rules could clobber
100 	**	static memory somewhere.
101 	*/
102 
103 	if (bitset(RF_COPYPADDR, flags) && addr != NULL)
104 	{
105 		char savec = **delimptr;
106 
107 		if (savec != '\0')
108 			**delimptr = '\0';
109 		e->e_to = addr = newstr(addr);
110 		if (savec != '\0')
111 			**delimptr = savec;
112 	}
113 
114 	/*
115 	**  Apply rewriting rules.
116 	**	Ruleset 0 does basic parsing.  It must resolve.
117 	*/
118 
119 	queueup = FALSE;
120 	if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
121 		queueup = TRUE;
122 	if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL)
123 		queueup = TRUE;
124 
125 
126 	/*
127 	**  Build canonical address from pvp.
128 	*/
129 
130 	a = buildaddr(pvp, a, flags, e);
131 
132 	/*
133 	**  Make local copies of the host & user and then
134 	**  transport them out.
135 	*/
136 
137 	allocaddr(a, flags, addr);
138 	if (bitset(QBADADDR, a->q_flags))
139 		return a;
140 
141 	/*
142 	**  If there was a parsing failure, mark it for queueing.
143 	*/
144 
145 	if (queueup)
146 	{
147 		char *msg = "Transient parse error -- message queued for future delivery";
148 
149 		if (tTd(20, 1))
150 			printf("parseaddr: queuing message\n");
151 		message(msg);
152 		if (e->e_message == NULL)
153 			e->e_message = newstr(msg);
154 		a->q_flags |= QQUEUEUP;
155 		a->q_status = "4.4.3";
156 	}
157 
158 	/*
159 	**  Compute return value.
160 	*/
161 
162 	if (tTd(20, 1))
163 	{
164 		printf("parseaddr-->");
165 		printaddr(a, FALSE);
166 	}
167 
168 	return (a);
169 }
170 /*
171 **  INVALIDADDR -- check for address containing meta-characters
172 **
173 **	Parameters:
174 **		addr -- the address to check.
175 **
176 **	Returns:
177 **		TRUE -- if the address has any "wierd" characters
178 **		FALSE -- otherwise.
179 */
180 
181 bool
182 invalidaddr(addr, delimptr)
183 	register char *addr;
184 	char *delimptr;
185 {
186 	char savedelim = '\0';
187 
188 	if (delimptr != NULL)
189 	{
190 		savedelim = *delimptr;
191 		if (savedelim != '\0')
192 			*delimptr = '\0';
193 	}
194 #if 0
195 	/* for testing.... */
196 	if (strcmp(addr, "INvalidADDR") == 0)
197 	{
198 		usrerr("553 INvalid ADDRess");
199 		goto addrfailure;
200 	}
201 #endif
202 	for (; *addr != '\0'; addr++)
203 	{
204 		if ((*addr & 0340) == 0200)
205 			break;
206 	}
207 	if (*addr == '\0')
208 	{
209 		if (delimptr != NULL && savedelim != '\0')
210 			*delimptr = savedelim;
211 		return FALSE;
212 	}
213 	setstat(EX_USAGE);
214 	usrerr("553 Address contained invalid control characters");
215   addrfailure:
216 	if (delimptr != NULL && savedelim != '\0')
217 		*delimptr = savedelim;
218 	return TRUE;
219 }
220 /*
221 **  ALLOCADDR -- do local allocations of address on demand.
222 **
223 **	Also lowercases the host name if requested.
224 **
225 **	Parameters:
226 **		a -- the address to reallocate.
227 **		flags -- the copy flag (see RF_ definitions in sendmail.h
228 **			for a description).
229 **		paddr -- the printname of the address.
230 **
231 **	Returns:
232 **		none.
233 **
234 **	Side Effects:
235 **		Copies portions of a into local buffers as requested.
236 */
237 
238 allocaddr(a, flags, paddr)
239 	register ADDRESS *a;
240 	int flags;
241 	char *paddr;
242 {
243 	if (tTd(24, 4))
244 		printf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr);
245 
246 	a->q_paddr = paddr;
247 
248 	if (a->q_user == NULL)
249 		a->q_user = "";
250 	if (a->q_host == NULL)
251 		a->q_host = "";
252 
253 	if (bitset(RF_COPYPARSE, flags))
254 	{
255 		a->q_host = newstr(a->q_host);
256 		if (a->q_user != a->q_paddr)
257 			a->q_user = newstr(a->q_user);
258 	}
259 
260 	if (a->q_paddr == NULL)
261 		a->q_paddr = a->q_user;
262 }
263 /*
264 **  PRESCAN -- Prescan name and make it canonical
265 **
266 **	Scans a name and turns it into a set of tokens.  This process
267 **	deletes blanks and comments (in parentheses).
268 **
269 **	This routine knows about quoted strings and angle brackets.
270 **
271 **	There are certain subtleties to this routine.  The one that
272 **	comes to mind now is that backslashes on the ends of names
273 **	are silently stripped off; this is intentional.  The problem
274 **	is that some versions of sndmsg (like at LBL) set the kill
275 **	character to something other than @ when reading addresses;
276 **	so people type "csvax.eric\@berkeley" -- which screws up the
277 **	berknet mailer.
278 **
279 **	Parameters:
280 **		addr -- the name to chomp.
281 **		delim -- the delimiter for the address, normally
282 **			'\0' or ','; \0 is accepted in any case.
283 **			If '\t' then we are reading the .cf file.
284 **		pvpbuf -- place to put the saved text -- note that
285 **			the pointers are static.
286 **		pvpbsize -- size of pvpbuf.
287 **		delimptr -- if non-NULL, set to the location of the
288 **			terminating delimiter.
289 **		toktab -- if set, a token table to use for parsing.
290 **			If NULL, use the default table.
291 **
292 **	Returns:
293 **		A pointer to a vector of tokens.
294 **		NULL on error.
295 */
296 
297 /* states and character types */
298 # define OPR		0	/* operator */
299 # define ATM		1	/* atom */
300 # define QST		2	/* in quoted string */
301 # define SPC		3	/* chewing up spaces */
302 # define ONE		4	/* pick up one character */
303 # define ILL		5	/* illegal character */
304 
305 # define NSTATES	6	/* number of states */
306 # define TYPE		017	/* mask to select state type */
307 
308 /* meta bits for table */
309 # define M		020	/* meta character; don't pass through */
310 # define B		040	/* cause a break */
311 # define MB		M|B	/* meta-break */
312 
313 static short StateTab[NSTATES][NSTATES] =
314 {
315    /*	oldst	chtype>	OPR	ATM	QST	SPC	ONE	ILL	*/
316 	/*OPR*/		OPR|B,	ATM|B,	QST|B,	SPC|MB,	ONE|B,	ILL|MB,
317 	/*ATM*/		OPR|B,	ATM,	QST|B,	SPC|MB,	ONE|B,	ILL|MB,
318 	/*QST*/		QST,	QST,	OPR,	QST,	QST,	QST,
319 	/*SPC*/		OPR,	ATM,	QST,	SPC|M,	ONE,	ILL|MB,
320 	/*ONE*/		OPR,	OPR,	OPR,	OPR,	OPR,	ILL|MB,
321 	/*ILL*/		OPR|B,	ATM|B,	QST|B,	SPC|MB,	ONE|B,	ILL|M,
322 };
323 
324 /* token type table -- it gets modified with $o characters */
325 static char TokTypeTab[256] =
326 {
327     /*	nul soh stx etx eot enq ack bel  bs  ht  nl  vt  np  cr  so  si   */
328 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
329     /*	dle dc1 dc2 dc3 dc4 nak syn etb  can em  sub esc fs  gs  rs  us   */
330 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
331     /*  sp  !   "   #   $   %   &   '    (   )   *   +   ,   -   .   /    */
332 	SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM,
333     /*	0   1   2   3   4   5   6   7    8   9   :   ;   <   =   >   ?    */
334 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
335     /*	@   A   B   C   D   E   F   G    H   I   J   K   L   M   N   O    */
336 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
337     /*  P   Q   R   S   T   U   V   W    X   Y   Z   [   \   ]   ^   _    */
338 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
339     /*	`   a   b   c   d   e   f   g    h   i   j   k   l   m   n   o    */
340 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
341     /*  p   q   r   s   t   u   v   w    x   y   z   {   |   }   ~   del  */
342 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
343 
344     /*	nul soh stx etx eot enq ack bel  bs  ht  nl  vt  np  cr  so  si   */
345 	OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
346     /*	dle dc1 dc2 dc3 dc4 nak syn etb  can em  sub esc fs  gs  rs  us   */
347 	OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
348     /*  sp  !   "   #   $   %   &   '    (   )   *   +   ,   -   .   /    */
349 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
350     /*	0   1   2   3   4   5   6   7    8   9   :   ;   <   =   >   ?    */
351 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
352     /*	@   A   B   C   D   E   F   G    H   I   J   K   L   M   N   O    */
353 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
354     /*  P   Q   R   S   T   U   V   W    X   Y   Z   [   \   ]   ^   _    */
355 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
356     /*	`   a   b   c   d   e   f   g    h   i   j   k   l   m   n   o    */
357 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
358     /*  p   q   r   s   t   u   v   w    x   y   z   {   |   }   ~   del  */
359 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
360 };
361 
362 /* token type table for MIME parsing */
363 char MimeTokenTab[256] =
364 {
365     /*	nul soh stx etx eot enq ack bel  bs  ht  nl  vt  np  cr  so  si   */
366 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,SPC,SPC,SPC,SPC,SPC,ILL,ILL,
367     /*	dle dc1 dc2 dc3 dc4 nak syn etb  can em  sub esc fs  gs  rs  us   */
368 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
369     /*  sp  !   "   #   $   %   &   '    (   )   *   +   ,   -   .   /    */
370 	SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,OPR,ATM,ATM,OPR,
371     /*	0   1   2   3   4   5   6   7    8   9   :   ;   <   =   >   ?    */
372 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,OPR,OPR,OPR,OPR,OPR,OPR,
373     /*	@   A   B   C   D   E   F   G    H   I   J   K   L   M   N   O    */
374 	OPR,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
375     /*  P   Q   R   S   T   U   V   W    X   Y   Z   [   \   ]   ^   _    */
376 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,OPR,OPR,OPR,ATM,ATM,
377     /*	`   a   b   c   d   e   f   g    h   i   j   k   l   m   n   o    */
378 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
379     /*  p   q   r   s   t   u   v   w    x   y   z   {   |   }   ~   del  */
380 	ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
381 
382     /*	nul soh stx etx eot enq ack bel  bs  ht  nl  vt  np  cr  so  si   */
383 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
384     /*	dle dc1 dc2 dc3 dc4 nak syn etb  can em  sub esc fs  gs  rs  us   */
385 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
386     /*  sp  !   "   #   $   %   &   '    (   )   *   +   ,   -   .   /    */
387 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
388     /*	0   1   2   3   4   5   6   7    8   9   :   ;   <   =   >   ?    */
389 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
390     /*	@   A   B   C   D   E   F   G    H   I   J   K   L   M   N   O    */
391 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
392     /*  P   Q   R   S   T   U   V   W    X   Y   Z   [   \   ]   ^   _    */
393 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
394     /*	`   a   b   c   d   e   f   g    h   i   j   k   l   m   n   o    */
395 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
396     /*  p   q   r   s   t   u   v   w    x   y   z   {   |   }   ~   del  */
397 	ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
398 };
399 
400 
401 # define NOCHAR		-1	/* signal nothing in lookahead token */
402 
403 char **
404 prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
405 	char *addr;
406 	int delim;
407 	char pvpbuf[];
408 	char **delimptr;
409 	char *toktab;
410 {
411 	register char *p;
412 	register char *q;
413 	register int c;
414 	char **avp;
415 	bool bslashmode;
416 	int cmntcnt;
417 	int anglecnt;
418 	char *tok;
419 	int state;
420 	int newstate;
421 	char *saveto = CurEnv->e_to;
422 	static char *av[MAXATOM+1];
423 	static char firsttime = TRUE;
424 	extern int errno;
425 
426 	if (firsttime)
427 	{
428 		/* initialize the token type table */
429 		char obuf[50];
430 
431 		firsttime = FALSE;
432 		expand("\201o", obuf, sizeof obuf - sizeof DELIMCHARS, CurEnv);
433 		strcat(obuf, DELIMCHARS);
434 		for (p = obuf; *p != '\0'; p++)
435 		{
436 			if (TokTypeTab[*p & 0xff] == ATM)
437 				TokTypeTab[*p & 0xff] = OPR;
438 		}
439 	}
440 	if (toktab == NULL)
441 		toktab = TokTypeTab;
442 
443 	/* make sure error messages don't have garbage on them */
444 	errno = 0;
445 
446 	q = pvpbuf;
447 	bslashmode = FALSE;
448 	cmntcnt = 0;
449 	anglecnt = 0;
450 	avp = av;
451 	state = ATM;
452 	c = NOCHAR;
453 	p = addr;
454 	CurEnv->e_to = p;
455 	if (tTd(22, 11))
456 	{
457 		printf("prescan: ");
458 		xputs(p);
459 		(void) putchar('\n');
460 	}
461 
462 	do
463 	{
464 		/* read a token */
465 		tok = q;
466 		for (;;)
467 		{
468 			/* store away any old lookahead character */
469 			if (c != NOCHAR && !bslashmode)
470 			{
471 				/* see if there is room */
472 				if (q >= &pvpbuf[pvpbsize - 5])
473 				{
474 					usrerr("553 Address too long");
475 					if (strlen(addr) > MAXNAME)
476 						addr[MAXNAME] = '\0';
477 	returnnull:
478 					if (delimptr != NULL)
479 						*delimptr = p;
480 					CurEnv->e_to = saveto;
481 					return (NULL);
482 				}
483 
484 				/* squirrel it away */
485 				*q++ = c;
486 			}
487 
488 			/* read a new input character */
489 			c = *p++;
490 			if (c == '\0')
491 			{
492 				/* diagnose and patch up bad syntax */
493 				if (state == QST)
494 				{
495 					usrerr("653 Unbalanced '\"'");
496 					c = '"';
497 				}
498 				else if (cmntcnt > 0)
499 				{
500 					usrerr("653 Unbalanced '('");
501 					c = ')';
502 				}
503 				else if (anglecnt > 0)
504 				{
505 					c = '>';
506 					usrerr("653 Unbalanced '<'");
507 				}
508 				else
509 					break;
510 
511 				p--;
512 			}
513 			else if (c == delim && anglecnt <= 0 &&
514 					cmntcnt <= 0 && state != QST)
515 				break;
516 
517 			if (tTd(22, 101))
518 				printf("c=%c, s=%d; ", c, state);
519 
520 			/* chew up special characters */
521 			*q = '\0';
522 			if (bslashmode)
523 			{
524 				bslashmode = FALSE;
525 
526 				/* kludge \! for naive users */
527 				if (cmntcnt > 0)
528 				{
529 					c = NOCHAR;
530 					continue;
531 				}
532 				else if (c != '!' || state == QST)
533 				{
534 					*q++ = '\\';
535 					continue;
536 				}
537 			}
538 
539 			if (c == '\\')
540 			{
541 				bslashmode = TRUE;
542 			}
543 			else if (state == QST)
544 			{
545 				/* do nothing, just avoid next clauses */
546 			}
547 			else if (c == '(')
548 			{
549 				cmntcnt++;
550 				c = NOCHAR;
551 			}
552 			else if (c == ')')
553 			{
554 				if (cmntcnt <= 0)
555 				{
556 					usrerr("653 Unbalanced ')'");
557 					c = NOCHAR;
558 				}
559 				else
560 					cmntcnt--;
561 			}
562 			else if (cmntcnt > 0)
563 				c = NOCHAR;
564 			else if (c == '<')
565 				anglecnt++;
566 			else if (c == '>')
567 			{
568 				if (anglecnt <= 0)
569 				{
570 					usrerr("653 Unbalanced '>'");
571 					c = NOCHAR;
572 				}
573 				else
574 					anglecnt--;
575 			}
576 			else if (delim == ' ' && isascii(c) && isspace(c))
577 				c = ' ';
578 
579 			if (c == NOCHAR)
580 				continue;
581 
582 			/* see if this is end of input */
583 			if (c == delim && anglecnt <= 0 && state != QST)
584 				break;
585 
586 			newstate = StateTab[state][toktab[c & 0xff]];
587 			if (tTd(22, 101))
588 				printf("ns=%02o\n", newstate);
589 			state = newstate & TYPE;
590 			if (state == ILL)
591 			{
592 				if (isascii(c) && isprint(c))
593 					usrerr("653 Illegal character %c", c);
594 				else
595 					usrerr("653 Illegal character 0x%02x", c);
596 			}
597 			if (bitset(M, newstate))
598 				c = NOCHAR;
599 			if (bitset(B, newstate))
600 				break;
601 		}
602 
603 		/* new token */
604 		if (tok != q)
605 		{
606 			*q++ = '\0';
607 			if (tTd(22, 36))
608 			{
609 				printf("tok=");
610 				xputs(tok);
611 				(void) putchar('\n');
612 			}
613 			if (avp >= &av[MAXATOM])
614 			{
615 				syserr("553 prescan: too many tokens");
616 				goto returnnull;
617 			}
618 			if (q - tok > MAXNAME)
619 			{
620 				syserr("553 prescan: token too long");
621 				goto returnnull;
622 			}
623 			*avp++ = tok;
624 		}
625 	} while (c != '\0' && (c != delim || anglecnt > 0));
626 	*avp = NULL;
627 	p--;
628 	if (delimptr != NULL)
629 		*delimptr = p;
630 	if (tTd(22, 12))
631 	{
632 		printf("prescan==>");
633 		printav(av);
634 	}
635 	CurEnv->e_to = saveto;
636 	if (av[0] == NULL)
637 	{
638 		if (tTd(22, 1))
639 			printf("prescan: null leading token\n");
640 		return (NULL);
641 	}
642 	return (av);
643 }
644 /*
645 **  REWRITE -- apply rewrite rules to token vector.
646 **
647 **	This routine is an ordered production system.  Each rewrite
648 **	rule has a LHS (called the pattern) and a RHS (called the
649 **	rewrite); 'rwr' points the the current rewrite rule.
650 **
651 **	For each rewrite rule, 'avp' points the address vector we
652 **	are trying to match against, and 'pvp' points to the pattern.
653 **	If pvp points to a special match value (MATCHZANY, MATCHANY,
654 **	MATCHONE, MATCHCLASS, MATCHNCLASS) then the address in avp
655 **	matched is saved away in the match vector (pointed to by 'mvp').
656 **
657 **	When a match between avp & pvp does not match, we try to
658 **	back out.  If we back up over MATCHONE, MATCHCLASS, or MATCHNCLASS
659 **	we must also back out the match in mvp.  If we reach a
660 **	MATCHANY or MATCHZANY we just extend the match and start
661 **	over again.
662 **
663 **	When we finally match, we rewrite the address vector
664 **	and try over again.
665 **
666 **	Parameters:
667 **		pvp -- pointer to token vector.
668 **		ruleset -- the ruleset to use for rewriting.
669 **		reclevel -- recursion level (to catch loops).
670 **		e -- the current envelope.
671 **
672 **	Returns:
673 **		A status code.  If EX_TEMPFAIL, higher level code should
674 **			attempt recovery.
675 **
676 **	Side Effects:
677 **		pvp is modified.
678 */
679 
680 struct match
681 {
682 	char	**first;	/* first token matched */
683 	char	**last;		/* last token matched */
684 	char	**pattern;	/* pointer to pattern */
685 };
686 
687 # define MAXMATCH	9	/* max params per rewrite */
688 
689 # ifndef MAXRULERECURSION
690 #  define MAXRULERECURSION	50	/* max recursion depth */
691 # endif
692 
693 
694 int
695 rewrite(pvp, ruleset, reclevel, e)
696 	char **pvp;
697 	int ruleset;
698 	int reclevel;
699 	register ENVELOPE *e;
700 {
701 	register char *ap;		/* address pointer */
702 	register char *rp;		/* rewrite pointer */
703 	register char **avp;		/* address vector pointer */
704 	register char **rvp;		/* rewrite vector pointer */
705 	register struct match *mlp;	/* cur ptr into mlist */
706 	register struct rewrite *rwr;	/* pointer to current rewrite rule */
707 	int ruleno;			/* current rule number */
708 	int rstat = EX_OK;		/* return status */
709 	int loopcount;
710 	struct match mlist[MAXMATCH];	/* stores match on LHS */
711 	char *npvp[MAXATOM+1];		/* temporary space for rebuild */
712 
713 	if (OpMode == MD_TEST || tTd(21, 1))
714 	{
715 		printf("rewrite: ruleset %2d   input:", ruleset);
716 		printav(pvp);
717 	}
718 	if (ruleset < 0 || ruleset >= MAXRWSETS)
719 	{
720 		syserr("554 rewrite: illegal ruleset number %d", ruleset);
721 		return EX_CONFIG;
722 	}
723 	if (reclevel++ > MAXRULERECURSION)
724 	{
725 		syserr("rewrite: infinite recursion, ruleset %d", ruleset);
726 		return EX_CONFIG;
727 	}
728 	if (pvp == NULL)
729 		return EX_USAGE;
730 
731 	/*
732 	**  Run through the list of rewrite rules, applying
733 	**	any that match.
734 	*/
735 
736 	ruleno = 1;
737 	loopcount = 0;
738 	for (rwr = RewriteRules[ruleset]; rwr != NULL; )
739 	{
740 		if (tTd(21, 12))
741 		{
742 			printf("-----trying rule:");
743 			printav(rwr->r_lhs);
744 		}
745 
746 		/* try to match on this rule */
747 		mlp = mlist;
748 		rvp = rwr->r_lhs;
749 		avp = pvp;
750 		if (++loopcount > 100)
751 		{
752 			syserr("554 Infinite loop in ruleset %d, rule %d",
753 				ruleset, ruleno);
754 			if (tTd(21, 1))
755 			{
756 				printf("workspace: ");
757 				printav(pvp);
758 			}
759 			break;
760 		}
761 
762 		while ((ap = *avp) != NULL || *rvp != NULL)
763 		{
764 			rp = *rvp;
765 			if (tTd(21, 35))
766 			{
767 				printf("ADVANCE rp=");
768 				xputs(rp);
769 				printf(", ap=");
770 				xputs(ap);
771 				printf("\n");
772 			}
773 			if (rp == NULL)
774 			{
775 				/* end-of-pattern before end-of-address */
776 				goto backup;
777 			}
778 			if (ap == NULL && (*rp & 0377) != MATCHZANY &&
779 			    (*rp & 0377) != MATCHZERO)
780 			{
781 				/* end-of-input with patterns left */
782 				goto backup;
783 			}
784 
785 			switch (*rp & 0377)
786 			{
787 				char buf[MAXLINE];
788 
789 			  case MATCHCLASS:
790 				/* match any phrase in a class */
791 				mlp->pattern = rvp;
792 				mlp->first = avp;
793 	extendclass:
794 				ap = *avp;
795 				if (ap == NULL)
796 					goto backup;
797 				mlp->last = avp++;
798 				cataddr(mlp->first, mlp->last, buf, sizeof buf, '\0');
799 				if (!wordinclass(buf, rp[1]))
800 				{
801 					if (tTd(21, 36))
802 					{
803 						printf("EXTEND  rp=");
804 						xputs(rp);
805 						printf(", ap=");
806 						xputs(ap);
807 						printf("\n");
808 					}
809 					goto extendclass;
810 				}
811 				if (tTd(21, 36))
812 					printf("CLMATCH\n");
813 				mlp++;
814 				break;
815 
816 			  case MATCHNCLASS:
817 				/* match any token not in a class */
818 				if (wordinclass(ap, rp[1]))
819 					goto backup;
820 
821 				/* fall through */
822 
823 			  case MATCHONE:
824 			  case MATCHANY:
825 				/* match exactly one token */
826 				mlp->pattern = rvp;
827 				mlp->first = avp;
828 				mlp->last = avp++;
829 				mlp++;
830 				break;
831 
832 			  case MATCHZANY:
833 				/* match zero or more tokens */
834 				mlp->pattern = rvp;
835 				mlp->first = avp;
836 				mlp->last = avp - 1;
837 				mlp++;
838 				break;
839 
840 			  case MATCHZERO:
841 				/* match zero tokens */
842 				break;
843 
844 			  case MACRODEXPAND:
845 				/*
846 				**  Match against run-time macro.
847 				**  This algorithm is broken for the
848 				**  general case (no recursive macros,
849 				**  improper tokenization) but should
850 				**  work for the usual cases.
851 				*/
852 
853 				ap = macvalue(rp[1], e);
854 				mlp->first = avp;
855 				if (tTd(21, 2))
856 					printf("rewrite: LHS $&%c => \"%s\"\n",
857 						rp[1],
858 						ap == NULL ? "(NULL)" : ap);
859 
860 				if (ap == NULL)
861 					break;
862 				while (*ap != '\0')
863 				{
864 					if (*avp == NULL ||
865 					    strncasecmp(ap, *avp, strlen(*avp)) != 0)
866 					{
867 						/* no match */
868 						avp = mlp->first;
869 						goto backup;
870 					}
871 					ap += strlen(*avp++);
872 				}
873 
874 				/* match */
875 				break;
876 
877 			  default:
878 				/* must have exact match */
879 				if (strcasecmp(rp, ap))
880 					goto backup;
881 				avp++;
882 				break;
883 			}
884 
885 			/* successful match on this token */
886 			rvp++;
887 			continue;
888 
889 	  backup:
890 			/* match failed -- back up */
891 			while (--mlp >= mlist)
892 			{
893 				rvp = mlp->pattern;
894 				rp = *rvp;
895 				avp = mlp->last + 1;
896 				ap = *avp;
897 
898 				if (tTd(21, 36))
899 				{
900 					printf("BACKUP  rp=");
901 					xputs(rp);
902 					printf(", ap=");
903 					xputs(ap);
904 					printf("\n");
905 				}
906 
907 				if (ap == NULL)
908 				{
909 					/* run off the end -- back up again */
910 					continue;
911 				}
912 				if ((*rp & 0377) == MATCHANY ||
913 				    (*rp & 0377) == MATCHZANY)
914 				{
915 					/* extend binding and continue */
916 					mlp->last = avp++;
917 					rvp++;
918 					mlp++;
919 					break;
920 				}
921 				if ((*rp & 0377) == MATCHCLASS)
922 				{
923 					/* extend binding and try again */
924 					mlp->last = avp;
925 					goto extendclass;
926 				}
927 			}
928 
929 			if (mlp < mlist)
930 			{
931 				/* total failure to match */
932 				break;
933 			}
934 		}
935 
936 		/*
937 		**  See if we successfully matched
938 		*/
939 
940 		if (mlp < mlist || *rvp != NULL)
941 		{
942 			if (tTd(21, 10))
943 				printf("----- rule fails\n");
944 			rwr = rwr->r_next;
945 			ruleno++;
946 			loopcount = 0;
947 			continue;
948 		}
949 
950 		rvp = rwr->r_rhs;
951 		if (tTd(21, 12))
952 		{
953 			printf("-----rule matches:");
954 			printav(rvp);
955 		}
956 
957 		rp = *rvp;
958 		if ((*rp & 0377) == CANONUSER)
959 		{
960 			rvp++;
961 			rwr = rwr->r_next;
962 			ruleno++;
963 			loopcount = 0;
964 		}
965 		else if ((*rp & 0377) == CANONHOST)
966 		{
967 			rvp++;
968 			rwr = NULL;
969 		}
970 		else if ((*rp & 0377) == CANONNET)
971 			rwr = NULL;
972 
973 		/* substitute */
974 		for (avp = npvp; *rvp != NULL; rvp++)
975 		{
976 			register struct match *m;
977 			register char **pp;
978 
979 			rp = *rvp;
980 			if ((*rp & 0377) == MATCHREPL)
981 			{
982 				/* substitute from LHS */
983 				m = &mlist[rp[1] - '1'];
984 				if (m < mlist || m >= mlp)
985 				{
986 					syserr("554 rewrite: ruleset %d: replacement $%c out of bounds",
987 						ruleset, rp[1]);
988 					return EX_CONFIG;
989 				}
990 				if (tTd(21, 15))
991 				{
992 					printf("$%c:", rp[1]);
993 					pp = m->first;
994 					while (pp <= m->last)
995 					{
996 						printf(" %x=\"", *pp);
997 						(void) fflush(stdout);
998 						printf("%s\"", *pp++);
999 					}
1000 					printf("\n");
1001 				}
1002 				pp = m->first;
1003 				while (pp <= m->last)
1004 				{
1005 					if (avp >= &npvp[MAXATOM])
1006 					{
1007 						syserr("554 rewrite: expansion too long");
1008 						return EX_DATAERR;
1009 					}
1010 					*avp++ = *pp++;
1011 				}
1012 			}
1013 			else
1014 			{
1015 				/* vanilla replacement */
1016 				if (avp >= &npvp[MAXATOM])
1017 				{
1018 	toolong:
1019 					syserr("554 rewrite: expansion too long");
1020 					return EX_DATAERR;
1021 				}
1022 				if ((*rp & 0377) != MACRODEXPAND)
1023 					*avp++ = rp;
1024 				else
1025 				{
1026 					*avp = macvalue(rp[1], e);
1027 					if (tTd(21, 2))
1028 						printf("rewrite: RHS $&%c => \"%s\"\n",
1029 							rp[1],
1030 							*avp == NULL ? "(NULL)" : *avp);
1031 					if (*avp != NULL)
1032 						avp++;
1033 				}
1034 			}
1035 		}
1036 		*avp++ = NULL;
1037 
1038 		/*
1039 		**  Check for any hostname/keyword lookups.
1040 		*/
1041 
1042 		for (rvp = npvp; *rvp != NULL; rvp++)
1043 		{
1044 			char **hbrvp;
1045 			char **xpvp;
1046 			int trsize;
1047 			char *replac;
1048 			int endtoken;
1049 			STAB *map;
1050 			char *mapname;
1051 			char **key_rvp;
1052 			char **arg_rvp;
1053 			char **default_rvp;
1054 			char buf[MAXNAME + 1];
1055 			char *pvpb1[MAXATOM + 1];
1056 			char *argvect[10];
1057 			char pvpbuf[PSBUFSIZE];
1058 			char *nullpvp[1];
1059 
1060 			if ((**rvp & 0377) != HOSTBEGIN &&
1061 			    (**rvp & 0377) != LOOKUPBEGIN)
1062 				continue;
1063 
1064 			/*
1065 			**  Got a hostname/keyword lookup.
1066 			**
1067 			**	This could be optimized fairly easily.
1068 			*/
1069 
1070 			hbrvp = rvp;
1071 			if ((**rvp & 0377) == HOSTBEGIN)
1072 			{
1073 				endtoken = HOSTEND;
1074 				mapname = "host";
1075 			}
1076 			else
1077 			{
1078 				endtoken = LOOKUPEND;
1079 				mapname = *++rvp;
1080 			}
1081 			map = stab(mapname, ST_MAP, ST_FIND);
1082 			if (map == NULL)
1083 				syserr("554 rewrite: map %s not found", mapname);
1084 
1085 			/* extract the match part */
1086 			key_rvp = ++rvp;
1087 			default_rvp = NULL;
1088 			arg_rvp = argvect;
1089 			xpvp = NULL;
1090 			replac = pvpbuf;
1091 			while (*rvp != NULL && (**rvp & 0377) != endtoken)
1092 			{
1093 				int nodetype = **rvp & 0377;
1094 
1095 				if (nodetype != CANONHOST && nodetype != CANONUSER)
1096 				{
1097 					rvp++;
1098 					continue;
1099 				}
1100 
1101 				*rvp++ = NULL;
1102 
1103 				if (xpvp != NULL)
1104 				{
1105 					cataddr(xpvp, NULL, replac,
1106 						&pvpbuf[sizeof pvpbuf] - replac,
1107 						'\0');
1108 					*++arg_rvp = replac;
1109 					replac += strlen(replac) + 1;
1110 					xpvp = NULL;
1111 				}
1112 				switch (nodetype)
1113 				{
1114 				  case CANONHOST:
1115 					xpvp = rvp;
1116 					break;
1117 
1118 				  case CANONUSER:
1119 					default_rvp = rvp;
1120 					break;
1121 				}
1122 			}
1123 			if (*rvp != NULL)
1124 				*rvp++ = NULL;
1125 			if (xpvp != NULL)
1126 			{
1127 				cataddr(xpvp, NULL, replac,
1128 					&pvpbuf[sizeof pvpbuf] - replac,
1129 					'\0');
1130 				*++arg_rvp = replac;
1131 			}
1132 			*++arg_rvp = NULL;
1133 
1134 			/* save the remainder of the input string */
1135 			trsize = (int) (avp - rvp + 1) * sizeof *rvp;
1136 			bcopy((char *) rvp, (char *) pvpb1, trsize);
1137 
1138 			/* look it up */
1139 			cataddr(key_rvp, NULL, buf, sizeof buf, '\0');
1140 			argvect[0] = buf;
1141 			if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))
1142 			{
1143 				auto int stat = EX_OK;
1144 
1145 				/* XXX should try to auto-open the map here */
1146 
1147 				if (tTd(60, 1))
1148 					printf("map_lookup(%s, %s) => ",
1149 						mapname, buf);
1150 				replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
1151 						buf, argvect, &stat);
1152 				if (tTd(60, 1))
1153 					printf("%s (%d)\n",
1154 						replac ? replac : "NOT FOUND",
1155 						stat);
1156 
1157 				/* should recover if stat == EX_TEMPFAIL */
1158 				if (stat == EX_TEMPFAIL || stat == EX_UNAVAILABLE)
1159 				{
1160 					rstat = EX_TEMPFAIL;
1161 					if (tTd(50, 1))
1162 						printf("map_lookup(%s, %s) failed (stat = %d)\n",
1163 							mapname, buf, stat);
1164 					if (e->e_message == NULL)
1165 					{
1166 						char mbuf[300];
1167 
1168 						sprintf(mbuf, "map %s: lookup (%s) failed",
1169 							mapname, buf);
1170 						e->e_message = newstr(mbuf);
1171 					}
1172 				}
1173 			}
1174 			else
1175 				replac = NULL;
1176 
1177 			/* if no replacement, use default */
1178 			if (replac == NULL && default_rvp != NULL)
1179 			{
1180 				/* create the default */
1181 				cataddr(default_rvp, NULL, buf, sizeof buf, '\0');
1182 				replac = buf;
1183 			}
1184 
1185 			if (replac == NULL)
1186 			{
1187 				xpvp = key_rvp;
1188 			}
1189 			else if (*replac == '\0')
1190 			{
1191 				/* null replacement */
1192 				nullpvp[0] = NULL;
1193 				xpvp = nullpvp;
1194 			}
1195 			else
1196 			{
1197 				/* scan the new replacement */
1198 				xpvp = prescan(replac, '\0', pvpbuf,
1199 					       sizeof pvpbuf, NULL, NULL);
1200 				if (xpvp == NULL)
1201 				{
1202 					/* prescan already printed error */
1203 					return EX_DATAERR;
1204 				}
1205 			}
1206 
1207 			/* append it to the token list */
1208 			for (avp = hbrvp; *xpvp != NULL; xpvp++)
1209 			{
1210 				*avp++ = newstr(*xpvp);
1211 				if (avp >= &npvp[MAXATOM])
1212 					goto toolong;
1213 			}
1214 
1215 			/* restore the old trailing information */
1216 			for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
1217 				if (avp >= &npvp[MAXATOM])
1218 					goto toolong;
1219 
1220 			break;
1221 		}
1222 
1223 		/*
1224 		**  Check for subroutine calls.
1225 		*/
1226 
1227 		if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)
1228 		{
1229 			int stat;
1230 
1231 			if (npvp[1] == NULL)
1232 			{
1233 				syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",
1234 					ruleset, ruleno);
1235 				*pvp = NULL;
1236 			}
1237 			else
1238 			{
1239 				int ruleset;
1240 				STAB *s;
1241 
1242 				bcopy((char *) &npvp[2], (char *) pvp,
1243 					(int) (avp - npvp - 2) * sizeof *avp);
1244 				if (tTd(21, 3))
1245 					printf("-----callsubr %s\n", npvp[1]);
1246 				s = stab(npvp[1], ST_RULESET, ST_FIND);
1247 				if (s == NULL)
1248 					ruleset = atoi(npvp[1]);
1249 				else
1250 					ruleset = s->s_ruleset;
1251 				stat = rewrite(pvp, ruleset, reclevel, e);
1252 				if (rstat == EX_OK || stat == EX_TEMPFAIL)
1253 					rstat = stat;
1254 				if (*pvp != NULL && (**pvp & 0377) == CANONNET)
1255 				rwr = NULL;
1256 			}
1257 		}
1258 		else
1259 		{
1260 			bcopy((char *) npvp, (char *) pvp,
1261 				(int) (avp - npvp) * sizeof *avp);
1262 		}
1263 		if (tTd(21, 4))
1264 		{
1265 			printf("rewritten as:");
1266 			printav(pvp);
1267 		}
1268 	}
1269 
1270 	if (OpMode == MD_TEST || tTd(21, 1))
1271 	{
1272 		printf("rewrite: ruleset %2d returns:", ruleset);
1273 		printav(pvp);
1274 	}
1275 
1276 	return rstat;
1277 }
1278 /*
1279 **  BUILDADDR -- build address from token vector.
1280 **
1281 **	Parameters:
1282 **		tv -- token vector.
1283 **		a -- pointer to address descriptor to fill.
1284 **			If NULL, one will be allocated.
1285 **		flags -- info regarding whether this is a sender or
1286 **			a recipient.
1287 **		e -- the current envelope.
1288 **
1289 **	Returns:
1290 **		NULL if there was an error.
1291 **		'a' otherwise.
1292 **
1293 **	Side Effects:
1294 **		fills in 'a'
1295 */
1296 
1297 struct errcodes
1298 {
1299 	char	*ec_name;		/* name of error code */
1300 	int	ec_code;		/* numeric code */
1301 } ErrorCodes[] =
1302 {
1303 	"usage",	EX_USAGE,
1304 	"nouser",	EX_NOUSER,
1305 	"nohost",	EX_NOHOST,
1306 	"unavailable",	EX_UNAVAILABLE,
1307 	"software",	EX_SOFTWARE,
1308 	"tempfail",	EX_TEMPFAIL,
1309 	"protocol",	EX_PROTOCOL,
1310 #ifdef EX_CONFIG
1311 	"config",	EX_CONFIG,
1312 #endif
1313 	NULL,		EX_UNAVAILABLE,
1314 };
1315 
1316 ADDRESS *
1317 buildaddr(tv, a, flags, e)
1318 	register char **tv;
1319 	register ADDRESS *a;
1320 	int flags;
1321 	register ENVELOPE *e;
1322 {
1323 	struct mailer **mp;
1324 	register struct mailer *m;
1325 	char *bp;
1326 	int spaceleft;
1327 	static MAILER errormailer;
1328 	static char *errorargv[] = { "ERROR", NULL };
1329 	static char buf[MAXNAME + 1];
1330 
1331 	if (tTd(24, 5))
1332 	{
1333 		printf("buildaddr, flags=%x, tv=", flags);
1334 		printav(tv);
1335 	}
1336 
1337 	if (a == NULL)
1338 		a = (ADDRESS *) xalloc(sizeof *a);
1339 	bzero((char *) a, sizeof *a);
1340 
1341 	/* set up default error return flags */
1342 	a->q_flags |= QPINGONFAILURE|QPINGONDELAY;
1343 
1344 	/* figure out what net/mailer to use */
1345 	if (*tv == NULL || (**tv & 0377) != CANONNET)
1346 	{
1347 		syserr("554 buildaddr: no net");
1348 badaddr:
1349 		a->q_flags |= QBADADDR;
1350 		a->q_mailer = &errormailer;
1351 		if (errormailer.m_name == NULL)
1352 		{
1353 			/* initialize the bogus mailer */
1354 			errormailer.m_name = "*error*";
1355 			errormailer.m_mailer = "ERROR";
1356 			errormailer.m_argv = errorargv;
1357 		}
1358 		return a;
1359 	}
1360 	tv++;
1361 	if (strcasecmp(*tv, "error") == 0)
1362 	{
1363 		if ((**++tv & 0377) == CANONHOST)
1364 		{
1365 			register struct errcodes *ep;
1366 
1367 			if (isascii(**++tv) && isdigit(**tv))
1368 			{
1369 				setstat(atoi(*tv));
1370 			}
1371 			else
1372 			{
1373 				for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
1374 					if (strcasecmp(ep->ec_name, *tv) == 0)
1375 						break;
1376 				setstat(ep->ec_code);
1377 			}
1378 			tv++;
1379 		}
1380 		else
1381 			setstat(EX_UNAVAILABLE);
1382 		if ((**tv & 0377) != CANONUSER)
1383 			syserr("554 buildaddr: error: no user");
1384 		cataddr(++tv, NULL, buf, sizeof buf, ' ');
1385 		stripquotes(buf);
1386 		if (isascii(buf[0]) && isdigit(buf[0]) &&
1387 		    isascii(buf[1]) && isdigit(buf[1]) &&
1388 		    isascii(buf[2]) && isdigit(buf[2]) &&
1389 		    buf[3] == ' ')
1390 		{
1391 			char fmt[10];
1392 
1393 			strncpy(fmt, buf, 3);
1394 			strcpy(&fmt[3], " %s");
1395 			usrerr(fmt, buf + 4);
1396 
1397 			/*
1398 			**  If this is a 4xx code and we aren't running
1399 			**  SMTP on our input, bounce this message;
1400 			**  otherwise it disappears without a trace.
1401 			*/
1402 
1403 			if (fmt[0] == '4' && OpMode != MD_SMTP &&
1404 			    OpMode != MD_DAEMON)
1405 			{
1406 				e->e_flags |= EF_FATALERRS;
1407 			}
1408 		}
1409 		else
1410 		{
1411 			usrerr("553 %s", buf);
1412 		}
1413 		goto badaddr;
1414 	}
1415 
1416 	for (mp = Mailer; (m = *mp++) != NULL; )
1417 	{
1418 		if (strcasecmp(m->m_name, *tv) == 0)
1419 			break;
1420 	}
1421 	if (m == NULL)
1422 	{
1423 		syserr("554 buildaddr: unknown mailer %s", *tv);
1424 		goto badaddr;
1425 	}
1426 	a->q_mailer = m;
1427 
1428 	/* figure out what host (if any) */
1429 	tv++;
1430 	if ((**tv & 0377) == CANONHOST)
1431 	{
1432 		bp = buf;
1433 		spaceleft = sizeof buf - 1;
1434 		while (*++tv != NULL && (**tv & 0377) != CANONUSER)
1435 		{
1436 			int i = strlen(*tv);
1437 
1438 			if (i > spaceleft)
1439 			{
1440 				/* out of space for this address */
1441 				if (spaceleft >= 0)
1442 					syserr("554 buildaddr: host too long (%.40s...)",
1443 						buf);
1444 				i = spaceleft;
1445 				spaceleft = 0;
1446 			}
1447 			if (i <= 0)
1448 				continue;
1449 			bcopy(*tv, bp, i);
1450 			bp += i;
1451 			spaceleft -= i;
1452 		}
1453 		*bp = '\0';
1454 		a->q_host = newstr(buf);
1455 	}
1456 	else
1457 	{
1458 		if (!bitnset(M_LOCALMAILER, m->m_flags))
1459 		{
1460 			syserr("554 buildaddr: no host");
1461 			goto badaddr;
1462 		}
1463 		a->q_host = NULL;
1464 	}
1465 
1466 	/* figure out the user */
1467 	if (*tv == NULL || (**tv & 0377) != CANONUSER)
1468 	{
1469 		syserr("554 buildaddr: no user");
1470 		goto badaddr;
1471 	}
1472 	tv++;
1473 
1474 	if (bitnset(M_CHECKUDB, m->m_flags) && *tv != NULL &&
1475 	    strcmp(*tv, "@") == 0)
1476 	{
1477 		tv++;
1478 		a->q_flags |= QNOTREMOTE;
1479 	}
1480 
1481 	/* do special mapping for local mailer */
1482 	if (*tv != NULL)
1483 	{
1484 		register char *p = *tv;
1485 
1486 		if (*p == '"')
1487 			p++;
1488 		if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
1489 			a->q_mailer = m = ProgMailer;
1490 		else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
1491 			a->q_mailer = m = FileMailer;
1492 		else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
1493 		{
1494 			/* may be :include: */
1495 			cataddr(tv, NULL, buf, sizeof buf, '\0');
1496 			stripquotes(buf);
1497 			if (strncasecmp(buf, ":include:", 9) == 0)
1498 			{
1499 				/* if :include:, don't need further rewriting */
1500 				a->q_mailer = m = InclMailer;
1501 				a->q_user = &buf[9];
1502 				return (a);
1503 			}
1504 		}
1505 	}
1506 
1507 	/* rewrite according recipient mailer rewriting rules */
1508 	define('h', a->q_host, e);
1509 	if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
1510 	{
1511 		/* sender addresses done later */
1512 		(void) rewrite(tv, 2, 0, e);
1513 		if (m->m_re_rwset > 0)
1514 		       (void) rewrite(tv, m->m_re_rwset, 0, e);
1515 	}
1516 	(void) rewrite(tv, 4, 0, e);
1517 
1518 	/* save the result for the command line/RCPT argument */
1519 	cataddr(tv, NULL, buf, sizeof buf, '\0');
1520 	a->q_user = buf;
1521 
1522 	/*
1523 	**  Do mapping to lower case as requested by mailer
1524 	*/
1525 
1526 	if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags))
1527 		makelower(a->q_host);
1528 	if (!bitnset(M_USR_UPPER, m->m_flags))
1529 		makelower(a->q_user);
1530 
1531 	return (a);
1532 }
1533 /*
1534 **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
1535 **
1536 **	Parameters:
1537 **		pvp -- parameter vector to rebuild.
1538 **		evp -- last parameter to include.  Can be NULL to
1539 **			use entire pvp.
1540 **		buf -- buffer to build the string into.
1541 **		sz -- size of buf.
1542 **		spacesub -- the space separator character; if null,
1543 **			use SpaceSub.
1544 **
1545 **	Returns:
1546 **		none.
1547 **
1548 **	Side Effects:
1549 **		Destroys buf.
1550 */
1551 
1552 cataddr(pvp, evp, buf, sz, spacesub)
1553 	char **pvp;
1554 	char **evp;
1555 	char *buf;
1556 	register int sz;
1557 	char spacesub;
1558 {
1559 	bool oatomtok = FALSE;
1560 	bool natomtok = FALSE;
1561 	register int i;
1562 	register char *p;
1563 
1564 	if (spacesub == '\0')
1565 		spacesub = SpaceSub;
1566 
1567 	if (pvp == NULL)
1568 	{
1569 		(void) strcpy(buf, "");
1570 		return;
1571 	}
1572 	p = buf;
1573 	sz -= 2;
1574 	while (*pvp != NULL && (i = strlen(*pvp)) < sz)
1575 	{
1576 		natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
1577 		if (oatomtok && natomtok)
1578 			*p++ = spacesub;
1579 		(void) strcpy(p, *pvp);
1580 		oatomtok = natomtok;
1581 		p += i;
1582 		sz -= i + 1;
1583 		if (pvp++ == evp)
1584 			break;
1585 	}
1586 	*p = '\0';
1587 }
1588 /*
1589 **  SAMEADDR -- Determine if two addresses are the same
1590 **
1591 **	This is not just a straight comparison -- if the mailer doesn't
1592 **	care about the host we just ignore it, etc.
1593 **
1594 **	Parameters:
1595 **		a, b -- pointers to the internal forms to compare.
1596 **
1597 **	Returns:
1598 **		TRUE -- they represent the same mailbox.
1599 **		FALSE -- they don't.
1600 **
1601 **	Side Effects:
1602 **		none.
1603 */
1604 
1605 bool
1606 sameaddr(a, b)
1607 	register ADDRESS *a;
1608 	register ADDRESS *b;
1609 {
1610 	register ADDRESS *ca, *cb;
1611 
1612 	/* if they don't have the same mailer, forget it */
1613 	if (a->q_mailer != b->q_mailer)
1614 		return (FALSE);
1615 
1616 	/* if the user isn't the same, we can drop out */
1617 	if (strcmp(a->q_user, b->q_user) != 0)
1618 		return (FALSE);
1619 
1620 	/* if we have good uids for both but they differ, these are different */
1621 	if (a->q_mailer == ProgMailer)
1622 	{
1623 		ca = getctladdr(a);
1624 		cb = getctladdr(b);
1625 		if (ca != NULL && cb != NULL &&
1626 		    bitset(QGOODUID, ca->q_flags & cb->q_flags) &&
1627 		    ca->q_uid != cb->q_uid)
1628 			return (FALSE);
1629 	}
1630 
1631 	/* otherwise compare hosts (but be careful for NULL ptrs) */
1632 	if (a->q_host == b->q_host)
1633 	{
1634 		/* probably both null pointers */
1635 		return (TRUE);
1636 	}
1637 	if (a->q_host == NULL || b->q_host == NULL)
1638 	{
1639 		/* only one is a null pointer */
1640 		return (FALSE);
1641 	}
1642 	if (strcmp(a->q_host, b->q_host) != 0)
1643 		return (FALSE);
1644 
1645 	return (TRUE);
1646 }
1647 /*
1648 **  PRINTADDR -- print address (for debugging)
1649 **
1650 **	Parameters:
1651 **		a -- the address to print
1652 **		follow -- follow the q_next chain.
1653 **
1654 **	Returns:
1655 **		none.
1656 **
1657 **	Side Effects:
1658 **		none.
1659 */
1660 
1661 struct qflags
1662 {
1663 	char	*qf_name;
1664 	u_long	qf_bit;
1665 };
1666 
1667 struct qflags	AddressFlags[] =
1668 {
1669 	"QDONTSEND",		QDONTSEND,
1670 	"QBADADDR",		QBADADDR,
1671 	"QGOODUID",		QGOODUID,
1672 	"QPRIMARY",		QPRIMARY,
1673 	"QQUEUEUP",		QQUEUEUP,
1674 	"QSENT",		QSENT,
1675 	"QNOTREMOTE",		QNOTREMOTE,
1676 	"QSELFREF",		QSELFREF,
1677 	"QVERIFIED",		QVERIFIED,
1678 	"QREPORT",		QREPORT,
1679 	"QBOGUSSHELL",		QBOGUSSHELL,
1680 	"QUNSAFEADDR",		QUNSAFEADDR,
1681 	"QPINGONSUCCESS",	QPINGONSUCCESS,
1682 	"QPINGONFAILURE",	QPINGONFAILURE,
1683 	"QPINGONDELAY",		QPINGONDELAY,
1684 	"QHASNOTIFY",		QHASNOTIFY,
1685 	"QRELAYED",		QRELAYED,
1686 	"QEXPLODED",		QEXPLODED,
1687 	"QTHISPASS",		QTHISPASS,
1688 	NULL
1689 };
1690 
1691 void
1692 printaddr(a, follow)
1693 	register ADDRESS *a;
1694 	bool follow;
1695 {
1696 	register MAILER *m;
1697 	MAILER pseudomailer;
1698 	register struct qflags *qfp;
1699 	bool firstone;
1700 
1701 	if (a == NULL)
1702 	{
1703 		printf("[NULL]\n");
1704 		return;
1705 	}
1706 
1707 	while (a != NULL)
1708 	{
1709 		printf("%x=", a);
1710 		(void) fflush(stdout);
1711 
1712 		/* find the mailer -- carefully */
1713 		m = a->q_mailer;
1714 		if (m == NULL)
1715 		{
1716 			m = &pseudomailer;
1717 			m->m_mno = -1;
1718 			m->m_name = "NULL";
1719 		}
1720 
1721 		printf("%s:\n\tmailer %d (%s), host `%s'\n",
1722 		       a->q_paddr, m->m_mno, m->m_name,
1723 		       a->q_host == NULL ? "<null>" : a->q_host);
1724 		printf("\tuser `%s', ruser `%s'\n",
1725 		       a->q_user,
1726 		       a->q_ruser == NULL ? "<null>" : a->q_ruser);
1727 		printf("\tnext=%x, alias %x, uid %d, gid %d\n",
1728 		       a->q_next, a->q_alias, a->q_uid, a->q_gid);
1729 		printf("\tflags=%lx<", a->q_flags);
1730 		firstone = TRUE;
1731 		for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++)
1732 		{
1733 			if (!bitset(qfp->qf_bit, a->q_flags))
1734 				continue;
1735 			if (!firstone)
1736 				printf(",");
1737 			firstone = FALSE;
1738 			printf("%s", qfp->qf_name);
1739 		}
1740 		printf(">\n");
1741 		printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
1742 		       a->q_owner == NULL ? "(none)" : a->q_owner,
1743 		       a->q_home == NULL ? "(none)" : a->q_home,
1744 		       a->q_fullname == NULL ? "(none)" : a->q_fullname);
1745 		printf("\torcpt=\"%s\", statmta=%s, rstatus=%s\n",
1746 		       a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
1747 		       a->q_statmta == NULL ? "(none)" : a->q_statmta,
1748 		       a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
1749 
1750 		if (!follow)
1751 			return;
1752 		a = a->q_next;
1753 	}
1754 }
1755 /*
1756 **  EMPTYADDR -- return TRUE if this address is empty (``<>'')
1757 **
1758 **	Parameters:
1759 **		a -- pointer to the address
1760 **
1761 **	Returns:
1762 **		TRUE -- if this address is "empty" (i.e., no one should
1763 **			ever generate replies to it.
1764 **		FALSE -- if it is a "regular" (read: replyable) address.
1765 */
1766 
1767 bool
1768 emptyaddr(a)
1769 	register ADDRESS *a;
1770 {
1771 	return strcmp(a->q_paddr, "<>") == 0 || strcmp(a->q_user, "<>") == 0;
1772 }
1773 /*
1774 **  REMOTENAME -- return the name relative to the current mailer
1775 **
1776 **	Parameters:
1777 **		name -- the name to translate.
1778 **		m -- the mailer that we want to do rewriting relative
1779 **			to.
1780 **		flags -- fine tune operations.
1781 **		pstat -- pointer to status word.
1782 **		e -- the current envelope.
1783 **
1784 **	Returns:
1785 **		the text string representing this address relative to
1786 **			the receiving mailer.
1787 **
1788 **	Side Effects:
1789 **		none.
1790 **
1791 **	Warnings:
1792 **		The text string returned is tucked away locally;
1793 **			copy it if you intend to save it.
1794 */
1795 
1796 char *
1797 remotename(name, m, flags, pstat, e)
1798 	char *name;
1799 	struct mailer *m;
1800 	int flags;
1801 	int *pstat;
1802 	register ENVELOPE *e;
1803 {
1804 	register char **pvp;
1805 	char *fancy;
1806 	char *oldg = macvalue('g', e);
1807 	int rwset;
1808 	static char buf[MAXNAME + 1];
1809 	char lbuf[MAXNAME + 1];
1810 	char pvpbuf[PSBUFSIZE];
1811 	extern char *crackaddr();
1812 
1813 	if (tTd(12, 1))
1814 		printf("remotename(%s)\n", name);
1815 
1816 	/* don't do anything if we are tagging it as special */
1817 	if (bitset(RF_SENDERADDR, flags))
1818 		rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset
1819 						     : m->m_se_rwset;
1820 	else
1821 		rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset
1822 						     : m->m_re_rwset;
1823 	if (rwset < 0)
1824 		return (name);
1825 
1826 	/*
1827 	**  Do a heuristic crack of this name to extract any comment info.
1828 	**	This will leave the name as a comment and a $g macro.
1829 	*/
1830 
1831 	if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags))
1832 		fancy = "\201g";
1833 	else
1834 		fancy = crackaddr(name);
1835 
1836 	/*
1837 	**  Turn the name into canonical form.
1838 	**	Normally this will be RFC 822 style, i.e., "user@domain".
1839 	**	If this only resolves to "user", and the "C" flag is
1840 	**	specified in the sending mailer, then the sender's
1841 	**	domain will be appended.
1842 	*/
1843 
1844 	pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
1845 	if (pvp == NULL)
1846 		return (name);
1847 	if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
1848 		*pstat = EX_TEMPFAIL;
1849 	if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
1850 	{
1851 		/* append from domain to this address */
1852 		register char **pxp = pvp;
1853 
1854 		/* see if there is an "@domain" in the current name */
1855 		while (*pxp != NULL && strcmp(*pxp, "@") != 0)
1856 			pxp++;
1857 		if (*pxp == NULL)
1858 		{
1859 			/* no.... append the "@domain" from the sender */
1860 			register char **qxq = e->e_fromdomain;
1861 
1862 			while ((*pxp++ = *qxq++) != NULL)
1863 				continue;
1864 			if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
1865 				*pstat = EX_TEMPFAIL;
1866 		}
1867 	}
1868 
1869 	/*
1870 	**  Do more specific rewriting.
1871 	**	Rewrite using ruleset 1 or 2 depending on whether this is
1872 	**		a sender address or not.
1873 	**	Then run it through any receiving-mailer-specific rulesets.
1874 	*/
1875 
1876 	if (bitset(RF_SENDERADDR, flags))
1877 	{
1878 		if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
1879 			*pstat = EX_TEMPFAIL;
1880 	}
1881 	else
1882 	{
1883 		if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
1884 			*pstat = EX_TEMPFAIL;
1885 	}
1886 	if (rwset > 0)
1887 	{
1888 		if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
1889 			*pstat = EX_TEMPFAIL;
1890 	}
1891 
1892 	/*
1893 	**  Do any final sanitation the address may require.
1894 	**	This will normally be used to turn internal forms
1895 	**	(e.g., user@host.LOCAL) into external form.  This
1896 	**	may be used as a default to the above rules.
1897 	*/
1898 
1899 	if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
1900 		*pstat = EX_TEMPFAIL;
1901 
1902 	/*
1903 	**  Now restore the comment information we had at the beginning.
1904 	*/
1905 
1906 	cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
1907 	define('g', lbuf, e);
1908 
1909 	/* need to make sure route-addrs have <angle brackets> */
1910 	if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
1911 		expand("<\201g>", buf, sizeof buf, e);
1912 	else
1913 		expand(fancy, buf, sizeof buf, e);
1914 
1915 	define('g', oldg, e);
1916 
1917 	if (tTd(12, 1))
1918 		printf("remotename => `%s'\n", buf);
1919 	return (buf);
1920 }
1921 /*
1922 **  MAPLOCALUSER -- run local username through ruleset 5 for final redirection
1923 **
1924 **	Parameters:
1925 **		a -- the address to map (but just the user name part).
1926 **		sendq -- the sendq in which to install any replacement
1927 **			addresses.
1928 **		aliaslevel -- the alias nesting depth.
1929 **		e -- the envelope.
1930 **
1931 **	Returns:
1932 **		none.
1933 */
1934 
1935 maplocaluser(a, sendq, aliaslevel, e)
1936 	register ADDRESS *a;
1937 	ADDRESS **sendq;
1938 	int aliaslevel;
1939 	ENVELOPE *e;
1940 {
1941 	register char **pvp;
1942 	register ADDRESS *a1 = NULL;
1943 	auto char *delimptr;
1944 	char pvpbuf[PSBUFSIZE];
1945 
1946 	if (tTd(29, 1))
1947 	{
1948 		printf("maplocaluser: ");
1949 		printaddr(a, FALSE);
1950 	}
1951 	pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL);
1952 	if (pvp == NULL)
1953 		return;
1954 
1955 	(void) rewrite(pvp, 5, 0, e);
1956 	if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
1957 		return;
1958 
1959 	/* if non-null, mailer destination specified -- has it changed? */
1960 	a1 = buildaddr(pvp, NULL, 0, e);
1961 	if (a1 == NULL || sameaddr(a, a1))
1962 		return;
1963 
1964 	/* mark old address as dead; insert new address */
1965 	a->q_flags |= QDONTSEND;
1966 	if (tTd(29, 5))
1967 	{
1968 		printf("maplocaluser: QDONTSEND ");
1969 		printaddr(a, FALSE);
1970 	}
1971 	a1->q_alias = a;
1972 	allocaddr(a1, RF_COPYALL, NULL);
1973 	(void) recipient(a1, sendq, aliaslevel, e);
1974 }
1975 /*
1976 **  DEQUOTE_INIT -- initialize dequote map
1977 **
1978 **	This is a no-op.
1979 **
1980 **	Parameters:
1981 **		map -- the internal map structure.
1982 **		args -- arguments.
1983 **
1984 **	Returns:
1985 **		TRUE.
1986 */
1987 
1988 bool
1989 dequote_init(map, args)
1990 	MAP *map;
1991 	char *args;
1992 {
1993 	register char *p = args;
1994 
1995 	for (;;)
1996 	{
1997 		while (isascii(*p) && isspace(*p))
1998 			p++;
1999 		if (*p != '-')
2000 			break;
2001 		switch (*++p)
2002 		{
2003 		  case 'a':
2004 			map->map_app = ++p;
2005 			break;
2006 
2007 		  case 's':
2008 			map->map_coldelim = *++p;
2009 			break;
2010 		}
2011 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
2012 			p++;
2013 		if (*p != '\0')
2014 			*p = '\0';
2015 	}
2016 	if (map->map_app != NULL)
2017 		map->map_app = newstr(map->map_app);
2018 
2019 	return TRUE;
2020 }
2021 /*
2022 **  DEQUOTE_MAP -- unquote an address
2023 **
2024 **	Parameters:
2025 **		map -- the internal map structure (ignored).
2026 **		name -- the name to dequote.
2027 **		av -- arguments (ignored).
2028 **		statp -- pointer to status out-parameter.
2029 **
2030 **	Returns:
2031 **		NULL -- if there were no quotes, or if the resulting
2032 **			unquoted buffer would not be acceptable to prescan.
2033 **		else -- The dequoted buffer.
2034 */
2035 
2036 char *
2037 dequote_map(map, name, av, statp)
2038 	MAP *map;
2039 	char *name;
2040 	char **av;
2041 	int *statp;
2042 {
2043 	register char *p;
2044 	register char *q;
2045 	register char c;
2046 	int anglecnt = 0;
2047 	int cmntcnt = 0;
2048 	int quotecnt = 0;
2049 	int spacecnt = 0;
2050 	bool quotemode = FALSE;
2051 	bool bslashmode = FALSE;
2052 	char spacesub = map->map_coldelim;
2053 
2054 	for (p = q = name; (c = *p++) != '\0'; )
2055 	{
2056 		if (bslashmode)
2057 		{
2058 			bslashmode = FALSE;
2059 			*q++ = c;
2060 			continue;
2061 		}
2062 
2063 		if (c == ' ' && spacesub != '\0')
2064 			c = spacesub;
2065 
2066 		switch (c)
2067 		{
2068 		  case '\\':
2069 			bslashmode = TRUE;
2070 			break;
2071 
2072 		  case '(':
2073 			cmntcnt++;
2074 			break;
2075 
2076 		  case ')':
2077 			if (cmntcnt-- <= 0)
2078 				return NULL;
2079 			break;
2080 
2081 		  case ' ':
2082 			spacecnt++;
2083 			break;
2084 		}
2085 
2086 		if (cmntcnt > 0)
2087 		{
2088 			*q++ = c;
2089 			continue;
2090 		}
2091 
2092 		switch (c)
2093 		{
2094 		  case '"':
2095 			quotemode = !quotemode;
2096 			quotecnt++;
2097 			continue;
2098 
2099 		  case '<':
2100 			anglecnt++;
2101 			break;
2102 
2103 		  case '>':
2104 			if (anglecnt-- <= 0)
2105 				return NULL;
2106 			break;
2107 		}
2108 		*q++ = c;
2109 	}
2110 
2111 	if (anglecnt != 0 || cmntcnt != 0 || bslashmode ||
2112 	    quotemode || quotecnt <= 0 || spacecnt != 0)
2113 		return NULL;
2114 	*q++ = '\0';
2115 	return name;
2116 }
2117