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.68 (Berkeley) 04/25/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)
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 	register char *p;
1326 	char *bp;
1327 	char *mname;
1328 	char **hostp;
1329 	char hbuf[MAXNAME + 1];
1330 	static MAILER errormailer;
1331 	static char *errorargv[] = { "ERROR", NULL };
1332 	static char ubuf[MAXNAME + 1];
1333 
1334 	if (tTd(24, 5))
1335 	{
1336 		printf("buildaddr, flags=%x, tv=", flags);
1337 		printav(tv);
1338 	}
1339 
1340 	if (a == NULL)
1341 		a = (ADDRESS *) xalloc(sizeof *a);
1342 	bzero((char *) a, sizeof *a);
1343 
1344 	/* set up default error return flags */
1345 	a->q_flags |= QPINGONFAILURE|QPINGONDELAY;
1346 
1347 	/* figure out what net/mailer to use */
1348 	if (*tv == NULL || (**tv & 0377) != CANONNET)
1349 	{
1350 		syserr("554 buildaddr: no net");
1351 badaddr:
1352 		a->q_flags |= QBADADDR;
1353 		a->q_mailer = &errormailer;
1354 		if (errormailer.m_name == NULL)
1355 		{
1356 			/* initialize the bogus mailer */
1357 			errormailer.m_name = "*error*";
1358 			errormailer.m_mailer = "ERROR";
1359 			errormailer.m_argv = errorargv;
1360 		}
1361 		return a;
1362 	}
1363 	mname = *++tv;
1364 
1365 	/* extract host and user portions */
1366 	if ((**++tv & 0377) == CANONHOST)
1367 		hostp = ++tv;
1368 	else
1369 		hostp = NULL;
1370 	while (*tv != NULL && (**tv & 0377) != CANONUSER)
1371 		tv++;
1372 	if (*tv == NULL)
1373 	{
1374 		syserr("554 buildaddr: no user");
1375 		goto badaddr;
1376 	}
1377 	if (hostp != NULL)
1378 		cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0');
1379 	cataddr(++tv, NULL, ubuf, sizeof ubuf, '\0');
1380 
1381 	/* save away the host name */
1382 	if (strcasecmp(mname, "error") == 0)
1383 	{
1384 		if (hostp != NULL)
1385 		{
1386 			register struct errcodes *ep;
1387 
1388 			if (strchr(hbuf, '.') != NULL)
1389 			{
1390 				a->q_status = newstr(hbuf);
1391 				setstat(dsntoexitstat(hbuf));
1392 			}
1393 			else if (isascii(hbuf[0]) && isdigit(hbuf[0]))
1394 			{
1395 				setstat(atoi(hbuf));
1396 			}
1397 			else
1398 			{
1399 				for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
1400 					if (strcasecmp(ep->ec_name, hbuf) == 0)
1401 						break;
1402 				setstat(ep->ec_code);
1403 			}
1404 		}
1405 		else
1406 			setstat(EX_UNAVAILABLE);
1407 		stripquotes(ubuf);
1408 		if (isascii(ubuf[0]) && isdigit(ubuf[0]) &&
1409 		    isascii(ubuf[1]) && isdigit(ubuf[1]) &&
1410 		    isascii(ubuf[2]) && isdigit(ubuf[2]) &&
1411 		    ubuf[3] == ' ')
1412 		{
1413 			char fmt[10];
1414 
1415 			strncpy(fmt, ubuf, 3);
1416 			strcpy(&fmt[3], " %s");
1417 			usrerr(fmt, ubuf + 4);
1418 
1419 			/*
1420 			**  If this is a 4xx code and we aren't running
1421 			**  SMTP on our input, bounce this message;
1422 			**  otherwise it disappears without a trace.
1423 			*/
1424 
1425 			if (fmt[0] == '4' && OpMode != MD_SMTP &&
1426 			    OpMode != MD_DAEMON)
1427 			{
1428 				e->e_flags |= EF_FATALERRS;
1429 			}
1430 		}
1431 		else
1432 		{
1433 			usrerr("553 %s", ubuf);
1434 		}
1435 		goto badaddr;
1436 	}
1437 
1438 	for (mp = Mailer; (m = *mp++) != NULL; )
1439 	{
1440 		if (strcasecmp(m->m_name, mname) == 0)
1441 			break;
1442 	}
1443 	if (m == NULL)
1444 	{
1445 		syserr("554 buildaddr: unknown mailer %s", mname);
1446 		goto badaddr;
1447 	}
1448 	a->q_mailer = m;
1449 
1450 	/* figure out what host (if any) */
1451 	if (hostp == NULL)
1452 	{
1453 		if (!bitnset(M_LOCALMAILER, m->m_flags))
1454 		{
1455 			syserr("554 buildaddr: no host");
1456 			goto badaddr;
1457 		}
1458 		a->q_host = NULL;
1459 	}
1460 	else
1461 		a->q_host = newstr(hbuf);
1462 
1463 	/* figure out the user */
1464 	p = ubuf;
1465 	if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@')
1466 	{
1467 		p++;
1468 		tv++;
1469 		a->q_flags |= QNOTREMOTE;
1470 	}
1471 
1472 	/* do special mapping for local mailer */
1473 	if (*p == '"')
1474 		p++;
1475 	if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
1476 		a->q_mailer = m = ProgMailer;
1477 	else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
1478 		a->q_mailer = m = FileMailer;
1479 	else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
1480 	{
1481 		/* may be :include: */
1482 		stripquotes(ubuf);
1483 		if (strncasecmp(ubuf, ":include:", 9) == 0)
1484 		{
1485 			/* if :include:, don't need further rewriting */
1486 			a->q_mailer = m = InclMailer;
1487 			a->q_user = newstr(&ubuf[9]);
1488 			return a;
1489 		}
1490 	}
1491 
1492 	/* rewrite according recipient mailer rewriting rules */
1493 	define('h', a->q_host, e);
1494 	if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
1495 	{
1496 		/* sender addresses done later */
1497 		(void) rewrite(tv, 2, 0, e);
1498 		if (m->m_re_rwset > 0)
1499 		       (void) rewrite(tv, m->m_re_rwset, 0, e);
1500 	}
1501 	(void) rewrite(tv, 4, 0, e);
1502 
1503 	/* save the result for the command line/RCPT argument */
1504 	cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
1505 	a->q_user = ubuf;
1506 
1507 	/*
1508 	**  Do mapping to lower case as requested by mailer
1509 	*/
1510 
1511 	if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags))
1512 		makelower(a->q_host);
1513 	if (!bitnset(M_USR_UPPER, m->m_flags))
1514 		makelower(a->q_user);
1515 
1516 	return a;
1517 }
1518 /*
1519 **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
1520 **
1521 **	Parameters:
1522 **		pvp -- parameter vector to rebuild.
1523 **		evp -- last parameter to include.  Can be NULL to
1524 **			use entire pvp.
1525 **		buf -- buffer to build the string into.
1526 **		sz -- size of buf.
1527 **		spacesub -- the space separator character; if null,
1528 **			use SpaceSub.
1529 **
1530 **	Returns:
1531 **		none.
1532 **
1533 **	Side Effects:
1534 **		Destroys buf.
1535 */
1536 
1537 cataddr(pvp, evp, buf, sz, spacesub)
1538 	char **pvp;
1539 	char **evp;
1540 	char *buf;
1541 	register int sz;
1542 	char spacesub;
1543 {
1544 	bool oatomtok = FALSE;
1545 	bool natomtok = FALSE;
1546 	register int i;
1547 	register char *p;
1548 
1549 	if (spacesub == '\0')
1550 		spacesub = SpaceSub;
1551 
1552 	if (pvp == NULL)
1553 	{
1554 		(void) strcpy(buf, "");
1555 		return;
1556 	}
1557 	p = buf;
1558 	sz -= 2;
1559 	while (*pvp != NULL && (i = strlen(*pvp)) < sz)
1560 	{
1561 		natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
1562 		if (oatomtok && natomtok)
1563 			*p++ = spacesub;
1564 		(void) strcpy(p, *pvp);
1565 		oatomtok = natomtok;
1566 		p += i;
1567 		sz -= i + 1;
1568 		if (pvp++ == evp)
1569 			break;
1570 	}
1571 	*p = '\0';
1572 }
1573 /*
1574 **  SAMEADDR -- Determine if two addresses are the same
1575 **
1576 **	This is not just a straight comparison -- if the mailer doesn't
1577 **	care about the host we just ignore it, etc.
1578 **
1579 **	Parameters:
1580 **		a, b -- pointers to the internal forms to compare.
1581 **
1582 **	Returns:
1583 **		TRUE -- they represent the same mailbox.
1584 **		FALSE -- they don't.
1585 **
1586 **	Side Effects:
1587 **		none.
1588 */
1589 
1590 bool
1591 sameaddr(a, b)
1592 	register ADDRESS *a;
1593 	register ADDRESS *b;
1594 {
1595 	register ADDRESS *ca, *cb;
1596 
1597 	/* if they don't have the same mailer, forget it */
1598 	if (a->q_mailer != b->q_mailer)
1599 		return (FALSE);
1600 
1601 	/* if the user isn't the same, we can drop out */
1602 	if (strcmp(a->q_user, b->q_user) != 0)
1603 		return (FALSE);
1604 
1605 	/* if we have good uids for both but they differ, these are different */
1606 	if (a->q_mailer == ProgMailer)
1607 	{
1608 		ca = getctladdr(a);
1609 		cb = getctladdr(b);
1610 		if (ca != NULL && cb != NULL &&
1611 		    bitset(QGOODUID, ca->q_flags & cb->q_flags) &&
1612 		    ca->q_uid != cb->q_uid)
1613 			return (FALSE);
1614 	}
1615 
1616 	/* otherwise compare hosts (but be careful for NULL ptrs) */
1617 	if (a->q_host == b->q_host)
1618 	{
1619 		/* probably both null pointers */
1620 		return (TRUE);
1621 	}
1622 	if (a->q_host == NULL || b->q_host == NULL)
1623 	{
1624 		/* only one is a null pointer */
1625 		return (FALSE);
1626 	}
1627 	if (strcmp(a->q_host, b->q_host) != 0)
1628 		return (FALSE);
1629 
1630 	return (TRUE);
1631 }
1632 /*
1633 **  PRINTADDR -- print address (for debugging)
1634 **
1635 **	Parameters:
1636 **		a -- the address to print
1637 **		follow -- follow the q_next chain.
1638 **
1639 **	Returns:
1640 **		none.
1641 **
1642 **	Side Effects:
1643 **		none.
1644 */
1645 
1646 struct qflags
1647 {
1648 	char	*qf_name;
1649 	u_long	qf_bit;
1650 };
1651 
1652 struct qflags	AddressFlags[] =
1653 {
1654 	"QDONTSEND",		QDONTSEND,
1655 	"QBADADDR",		QBADADDR,
1656 	"QGOODUID",		QGOODUID,
1657 	"QPRIMARY",		QPRIMARY,
1658 	"QQUEUEUP",		QQUEUEUP,
1659 	"QSENT",		QSENT,
1660 	"QNOTREMOTE",		QNOTREMOTE,
1661 	"QSELFREF",		QSELFREF,
1662 	"QVERIFIED",		QVERIFIED,
1663 	"QBOGUSSHELL",		QBOGUSSHELL,
1664 	"QUNSAFEADDR",		QUNSAFEADDR,
1665 	"QPINGONSUCCESS",	QPINGONSUCCESS,
1666 	"QPINGONFAILURE",	QPINGONFAILURE,
1667 	"QPINGONDELAY",		QPINGONDELAY,
1668 	"QHASNOTIFY",		QHASNOTIFY,
1669 	"QRELAYED",		QRELAYED,
1670 	"QEXPANDED",		QEXPANDED,
1671 	"QDELIVERED",		QDELIVERED,
1672 	"QDELAYED",		QDELAYED,
1673 	"QTHISPASS",		QTHISPASS,
1674 	NULL
1675 };
1676 
1677 void
1678 printaddr(a, follow)
1679 	register ADDRESS *a;
1680 	bool follow;
1681 {
1682 	register MAILER *m;
1683 	MAILER pseudomailer;
1684 	register struct qflags *qfp;
1685 	bool firstone;
1686 
1687 	if (a == NULL)
1688 	{
1689 		printf("[NULL]\n");
1690 		return;
1691 	}
1692 
1693 	while (a != NULL)
1694 	{
1695 		printf("%x=", a);
1696 		(void) fflush(stdout);
1697 
1698 		/* find the mailer -- carefully */
1699 		m = a->q_mailer;
1700 		if (m == NULL)
1701 		{
1702 			m = &pseudomailer;
1703 			m->m_mno = -1;
1704 			m->m_name = "NULL";
1705 		}
1706 
1707 		printf("%s:\n\tmailer %d (%s), host `%s'\n",
1708 		       a->q_paddr, m->m_mno, m->m_name,
1709 		       a->q_host == NULL ? "<null>" : a->q_host);
1710 		printf("\tuser `%s', ruser `%s'\n",
1711 		       a->q_user,
1712 		       a->q_ruser == NULL ? "<null>" : a->q_ruser);
1713 		printf("\tnext=%x, alias %x, uid %d, gid %d\n",
1714 		       a->q_next, a->q_alias, a->q_uid, a->q_gid);
1715 		printf("\tflags=%lx<", a->q_flags);
1716 		firstone = TRUE;
1717 		for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++)
1718 		{
1719 			if (!bitset(qfp->qf_bit, a->q_flags))
1720 				continue;
1721 			if (!firstone)
1722 				printf(",");
1723 			firstone = FALSE;
1724 			printf("%s", qfp->qf_name);
1725 		}
1726 		printf(">\n");
1727 		printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
1728 		       a->q_owner == NULL ? "(none)" : a->q_owner,
1729 		       a->q_home == NULL ? "(none)" : a->q_home,
1730 		       a->q_fullname == NULL ? "(none)" : a->q_fullname);
1731 		printf("\torcpt=\"%s\", statmta=%s, rstatus=%s\n",
1732 		       a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
1733 		       a->q_statmta == NULL ? "(none)" : a->q_statmta,
1734 		       a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
1735 
1736 		if (!follow)
1737 			return;
1738 		a = a->q_next;
1739 	}
1740 }
1741 /*
1742 **  EMPTYADDR -- return TRUE if this address is empty (``<>'')
1743 **
1744 **	Parameters:
1745 **		a -- pointer to the address
1746 **
1747 **	Returns:
1748 **		TRUE -- if this address is "empty" (i.e., no one should
1749 **			ever generate replies to it.
1750 **		FALSE -- if it is a "regular" (read: replyable) address.
1751 */
1752 
1753 bool
1754 emptyaddr(a)
1755 	register ADDRESS *a;
1756 {
1757 	return strcmp(a->q_paddr, "<>") == 0 || strcmp(a->q_user, "<>") == 0;
1758 }
1759 /*
1760 **  REMOTENAME -- return the name relative to the current mailer
1761 **
1762 **	Parameters:
1763 **		name -- the name to translate.
1764 **		m -- the mailer that we want to do rewriting relative
1765 **			to.
1766 **		flags -- fine tune operations.
1767 **		pstat -- pointer to status word.
1768 **		e -- the current envelope.
1769 **
1770 **	Returns:
1771 **		the text string representing this address relative to
1772 **			the receiving mailer.
1773 **
1774 **	Side Effects:
1775 **		none.
1776 **
1777 **	Warnings:
1778 **		The text string returned is tucked away locally;
1779 **			copy it if you intend to save it.
1780 */
1781 
1782 char *
1783 remotename(name, m, flags, pstat, e)
1784 	char *name;
1785 	struct mailer *m;
1786 	int flags;
1787 	int *pstat;
1788 	register ENVELOPE *e;
1789 {
1790 	register char **pvp;
1791 	char *fancy;
1792 	char *oldg = macvalue('g', e);
1793 	int rwset;
1794 	static char buf[MAXNAME + 1];
1795 	char lbuf[MAXNAME + 1];
1796 	char pvpbuf[PSBUFSIZE];
1797 	extern char *crackaddr();
1798 
1799 	if (tTd(12, 1))
1800 		printf("remotename(%s)\n", name);
1801 
1802 	/* don't do anything if we are tagging it as special */
1803 	if (bitset(RF_SENDERADDR, flags))
1804 		rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset
1805 						     : m->m_se_rwset;
1806 	else
1807 		rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset
1808 						     : m->m_re_rwset;
1809 	if (rwset < 0)
1810 		return (name);
1811 
1812 	/*
1813 	**  Do a heuristic crack of this name to extract any comment info.
1814 	**	This will leave the name as a comment and a $g macro.
1815 	*/
1816 
1817 	if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags))
1818 		fancy = "\201g";
1819 	else
1820 		fancy = crackaddr(name);
1821 
1822 	/*
1823 	**  Turn the name into canonical form.
1824 	**	Normally this will be RFC 822 style, i.e., "user@domain".
1825 	**	If this only resolves to "user", and the "C" flag is
1826 	**	specified in the sending mailer, then the sender's
1827 	**	domain will be appended.
1828 	*/
1829 
1830 	pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
1831 	if (pvp == NULL)
1832 		return (name);
1833 	if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
1834 		*pstat = EX_TEMPFAIL;
1835 	if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
1836 	{
1837 		/* append from domain to this address */
1838 		register char **pxp = pvp;
1839 
1840 		/* see if there is an "@domain" in the current name */
1841 		while (*pxp != NULL && strcmp(*pxp, "@") != 0)
1842 			pxp++;
1843 		if (*pxp == NULL)
1844 		{
1845 			/* no.... append the "@domain" from the sender */
1846 			register char **qxq = e->e_fromdomain;
1847 
1848 			while ((*pxp++ = *qxq++) != NULL)
1849 				continue;
1850 			if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
1851 				*pstat = EX_TEMPFAIL;
1852 		}
1853 	}
1854 
1855 	/*
1856 	**  Do more specific rewriting.
1857 	**	Rewrite using ruleset 1 or 2 depending on whether this is
1858 	**		a sender address or not.
1859 	**	Then run it through any receiving-mailer-specific rulesets.
1860 	*/
1861 
1862 	if (bitset(RF_SENDERADDR, flags))
1863 	{
1864 		if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
1865 			*pstat = EX_TEMPFAIL;
1866 	}
1867 	else
1868 	{
1869 		if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
1870 			*pstat = EX_TEMPFAIL;
1871 	}
1872 	if (rwset > 0)
1873 	{
1874 		if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
1875 			*pstat = EX_TEMPFAIL;
1876 	}
1877 
1878 	/*
1879 	**  Do any final sanitation the address may require.
1880 	**	This will normally be used to turn internal forms
1881 	**	(e.g., user@host.LOCAL) into external form.  This
1882 	**	may be used as a default to the above rules.
1883 	*/
1884 
1885 	if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
1886 		*pstat = EX_TEMPFAIL;
1887 
1888 	/*
1889 	**  Now restore the comment information we had at the beginning.
1890 	*/
1891 
1892 	cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
1893 	define('g', lbuf, e);
1894 
1895 	/* need to make sure route-addrs have <angle brackets> */
1896 	if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
1897 		expand("<\201g>", buf, sizeof buf, e);
1898 	else
1899 		expand(fancy, buf, sizeof buf, e);
1900 
1901 	define('g', oldg, e);
1902 
1903 	if (tTd(12, 1))
1904 		printf("remotename => `%s'\n", buf);
1905 	return (buf);
1906 }
1907 /*
1908 **  MAPLOCALUSER -- run local username through ruleset 5 for final redirection
1909 **
1910 **	Parameters:
1911 **		a -- the address to map (but just the user name part).
1912 **		sendq -- the sendq in which to install any replacement
1913 **			addresses.
1914 **		aliaslevel -- the alias nesting depth.
1915 **		e -- the envelope.
1916 **
1917 **	Returns:
1918 **		none.
1919 */
1920 
1921 maplocaluser(a, sendq, aliaslevel, e)
1922 	register ADDRESS *a;
1923 	ADDRESS **sendq;
1924 	int aliaslevel;
1925 	ENVELOPE *e;
1926 {
1927 	register char **pvp;
1928 	register ADDRESS *a1 = NULL;
1929 	auto char *delimptr;
1930 	char pvpbuf[PSBUFSIZE];
1931 
1932 	if (tTd(29, 1))
1933 	{
1934 		printf("maplocaluser: ");
1935 		printaddr(a, FALSE);
1936 	}
1937 	pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL);
1938 	if (pvp == NULL)
1939 		return;
1940 
1941 	(void) rewrite(pvp, 5, 0, e);
1942 	if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
1943 		return;
1944 
1945 	/* if non-null, mailer destination specified -- has it changed? */
1946 	a1 = buildaddr(pvp, NULL, 0, e);
1947 	if (a1 == NULL || sameaddr(a, a1))
1948 		return;
1949 
1950 	/* mark old address as dead; insert new address */
1951 	a->q_flags |= QDONTSEND;
1952 	if (tTd(29, 5))
1953 	{
1954 		printf("maplocaluser: QDONTSEND ");
1955 		printaddr(a, FALSE);
1956 	}
1957 	a1->q_alias = a;
1958 	allocaddr(a1, RF_COPYALL, NULL);
1959 	(void) recipient(a1, sendq, aliaslevel, e);
1960 }
1961 /*
1962 **  DEQUOTE_INIT -- initialize dequote map
1963 **
1964 **	This is a no-op.
1965 **
1966 **	Parameters:
1967 **		map -- the internal map structure.
1968 **		args -- arguments.
1969 **
1970 **	Returns:
1971 **		TRUE.
1972 */
1973 
1974 bool
1975 dequote_init(map, args)
1976 	MAP *map;
1977 	char *args;
1978 {
1979 	register char *p = args;
1980 
1981 	for (;;)
1982 	{
1983 		while (isascii(*p) && isspace(*p))
1984 			p++;
1985 		if (*p != '-')
1986 			break;
1987 		switch (*++p)
1988 		{
1989 		  case 'a':
1990 			map->map_app = ++p;
1991 			break;
1992 
1993 		  case 's':
1994 			map->map_coldelim = *++p;
1995 			break;
1996 		}
1997 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
1998 			p++;
1999 		if (*p != '\0')
2000 			*p = '\0';
2001 	}
2002 	if (map->map_app != NULL)
2003 		map->map_app = newstr(map->map_app);
2004 
2005 	return TRUE;
2006 }
2007 /*
2008 **  DEQUOTE_MAP -- unquote an address
2009 **
2010 **	Parameters:
2011 **		map -- the internal map structure (ignored).
2012 **		name -- the name to dequote.
2013 **		av -- arguments (ignored).
2014 **		statp -- pointer to status out-parameter.
2015 **
2016 **	Returns:
2017 **		NULL -- if there were no quotes, or if the resulting
2018 **			unquoted buffer would not be acceptable to prescan.
2019 **		else -- The dequoted buffer.
2020 */
2021 
2022 char *
2023 dequote_map(map, name, av, statp)
2024 	MAP *map;
2025 	char *name;
2026 	char **av;
2027 	int *statp;
2028 {
2029 	register char *p;
2030 	register char *q;
2031 	register char c;
2032 	int anglecnt = 0;
2033 	int cmntcnt = 0;
2034 	int quotecnt = 0;
2035 	int spacecnt = 0;
2036 	bool quotemode = FALSE;
2037 	bool bslashmode = FALSE;
2038 	char spacesub = map->map_coldelim;
2039 
2040 	for (p = q = name; (c = *p++) != '\0'; )
2041 	{
2042 		if (bslashmode)
2043 		{
2044 			bslashmode = FALSE;
2045 			*q++ = c;
2046 			continue;
2047 		}
2048 
2049 		if (c == ' ' && spacesub != '\0')
2050 			c = spacesub;
2051 
2052 		switch (c)
2053 		{
2054 		  case '\\':
2055 			bslashmode = TRUE;
2056 			break;
2057 
2058 		  case '(':
2059 			cmntcnt++;
2060 			break;
2061 
2062 		  case ')':
2063 			if (cmntcnt-- <= 0)
2064 				return NULL;
2065 			break;
2066 
2067 		  case ' ':
2068 			spacecnt++;
2069 			break;
2070 		}
2071 
2072 		if (cmntcnt > 0)
2073 		{
2074 			*q++ = c;
2075 			continue;
2076 		}
2077 
2078 		switch (c)
2079 		{
2080 		  case '"':
2081 			quotemode = !quotemode;
2082 			quotecnt++;
2083 			continue;
2084 
2085 		  case '<':
2086 			anglecnt++;
2087 			break;
2088 
2089 		  case '>':
2090 			if (anglecnt-- <= 0)
2091 				return NULL;
2092 			break;
2093 		}
2094 		*q++ = c;
2095 	}
2096 
2097 	if (anglecnt != 0 || cmntcnt != 0 || bslashmode ||
2098 	    quotemode || quotecnt <= 0 || spacecnt != 0)
2099 		return NULL;
2100 	*q++ = '\0';
2101 	return name;
2102 }
2103