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