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