expand.c revision 216387
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * Copyright (c) 1997-2005
5 *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef lint
36#if 0
37static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
38#endif
39#endif /* not lint */
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: head/bin/sh/expand.c 216387 2010-12-12 00:07:27Z jilles $");
42
43#include <sys/types.h>
44#include <sys/time.h>
45#include <sys/stat.h>
46#include <dirent.h>
47#include <errno.h>
48#include <inttypes.h>
49#include <limits.h>
50#include <pwd.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <unistd.h>
55
56/*
57 * Routines to expand arguments to commands.  We have to deal with
58 * backquotes, shell variables, and file metacharacters.
59 */
60
61#include "shell.h"
62#include "main.h"
63#include "nodes.h"
64#include "eval.h"
65#include "expand.h"
66#include "syntax.h"
67#include "parser.h"
68#include "jobs.h"
69#include "options.h"
70#include "var.h"
71#include "input.h"
72#include "output.h"
73#include "memalloc.h"
74#include "error.h"
75#include "mystring.h"
76#include "arith.h"
77#include "show.h"
78
79/*
80 * Structure specifying which parts of the string should be searched
81 * for IFS characters.
82 */
83
84struct ifsregion {
85	struct ifsregion *next;	/* next region in list */
86	int begoff;		/* offset of start of region */
87	int endoff;		/* offset of end of region */
88	int inquotes;		/* search for nul bytes only */
89};
90
91
92static char *expdest;			/* output of current string */
93static struct nodelist *argbackq;	/* list of back quote expressions */
94static struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
95static struct ifsregion *ifslastp;	/* last struct in list */
96static struct arglist exparg;		/* holds expanded arg list */
97
98static void argstr(char *, int);
99static char *exptilde(char *, int);
100static void expbackq(union node *, int, int);
101static int subevalvar(char *, char *, int, int, int, int, int);
102static char *evalvar(char *, int);
103static int varisset(char *, int);
104static void varvalue(char *, int, int, int);
105static void recordregion(int, int, int);
106static void removerecordregions(int);
107static void ifsbreakup(char *, struct arglist *);
108static void expandmeta(struct strlist *, int);
109static void expmeta(char *, char *);
110static void addfname(char *);
111static struct strlist *expsort(struct strlist *);
112static struct strlist *msort(struct strlist *, int);
113static char *cvtnum(int, char *);
114static int collate_range_cmp(int, int);
115
116static int
117collate_range_cmp(int c1, int c2)
118{
119	static char s1[2], s2[2];
120
121	s1[0] = c1;
122	s2[0] = c2;
123	return (strcoll(s1, s2));
124}
125
126/*
127 * Expand shell variables and backquotes inside a here document.
128 *	union node *arg		the document
129 *	int fd;			where to write the expanded version
130 */
131
132void
133expandhere(union node *arg, int fd)
134{
135	expandarg(arg, (struct arglist *)NULL, 0);
136	xwrite(fd, stackblock(), expdest - stackblock());
137}
138
139static char *
140stputs_quotes(const char *data, const char *syntax, char *p)
141{
142	while (*data) {
143		CHECKSTRSPACE(2, p);
144		if (syntax[(int)*data] == CCTL)
145			USTPUTC(CTLESC, p);
146		USTPUTC(*data++, p);
147	}
148	return (p);
149}
150#define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p)
151
152/*
153 * Perform expansions on an argument, placing the resulting list of arguments
154 * in arglist.  Parameter expansion, command substitution and arithmetic
155 * expansion are always performed; additional expansions can be requested
156 * via flag (EXP_*).
157 * The result is left in the stack string.
158 * When arglist is NULL, perform here document expansion.  A partial result
159 * may be written to herefd, which is then not included in the stack string.
160 *
161 * Caution: this function uses global state and is not reentrant.
162 * However, a new invocation after an interrupted invocation is safe
163 * and will reset the global state for the new call.
164 */
165void
166expandarg(union node *arg, struct arglist *arglist, int flag)
167{
168	struct strlist *sp;
169	char *p;
170
171	argbackq = arg->narg.backquote;
172	STARTSTACKSTR(expdest);
173	ifsfirst.next = NULL;
174	ifslastp = NULL;
175	argstr(arg->narg.text, flag);
176	if (arglist == NULL) {
177		return;			/* here document expanded */
178	}
179	STPUTC('\0', expdest);
180	p = grabstackstr(expdest);
181	exparg.lastp = &exparg.list;
182	/*
183	 * TODO - EXP_REDIR
184	 */
185	if (flag & EXP_FULL) {
186		ifsbreakup(p, &exparg);
187		*exparg.lastp = NULL;
188		exparg.lastp = &exparg.list;
189		expandmeta(exparg.list, flag);
190	} else {
191		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
192			rmescapes(p);
193		sp = (struct strlist *)stalloc(sizeof (struct strlist));
194		sp->text = p;
195		*exparg.lastp = sp;
196		exparg.lastp = &sp->next;
197	}
198	while (ifsfirst.next != NULL) {
199		struct ifsregion *ifsp;
200		INTOFF;
201		ifsp = ifsfirst.next->next;
202		ckfree(ifsfirst.next);
203		ifsfirst.next = ifsp;
204		INTON;
205	}
206	*exparg.lastp = NULL;
207	if (exparg.list) {
208		*arglist->lastp = exparg.list;
209		arglist->lastp = exparg.lastp;
210	}
211}
212
213
214
215/*
216 * Perform parameter expansion, command substitution and arithmetic
217 * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE.
218 * Processing ends at a CTLENDVAR character as well as '\0'.
219 * This is used to expand word in ${var+word} etc.
220 * If EXP_FULL, EXP_CASE or EXP_REDIR are set, keep and/or generate CTLESC
221 * characters to allow for further processing.
222 * If EXP_FULL is set, also preserve CTLQUOTEMARK characters.
223 */
224static void
225argstr(char *p, int flag)
226{
227	char c;
228	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);	/* do CTLESC */
229	int firsteq = 1;
230	int split_lit;
231	int lit_quoted;
232
233	split_lit = flag & EXP_SPLIT_LIT;
234	lit_quoted = flag & EXP_LIT_QUOTED;
235	flag &= ~(EXP_SPLIT_LIT | EXP_LIT_QUOTED);
236	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
237		p = exptilde(p, flag);
238	for (;;) {
239		CHECKSTRSPACE(2, expdest);
240		switch (c = *p++) {
241		case '\0':
242		case CTLENDVAR:
243			goto breakloop;
244		case CTLQUOTEMARK:
245			lit_quoted = 1;
246			/* "$@" syntax adherence hack */
247			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
248				break;
249			if ((flag & EXP_FULL) != 0)
250				USTPUTC(c, expdest);
251			break;
252		case CTLQUOTEEND:
253			lit_quoted = 0;
254			break;
255		case CTLESC:
256			if (quotes)
257				USTPUTC(c, expdest);
258			c = *p++;
259			USTPUTC(c, expdest);
260			if (split_lit && !lit_quoted)
261				recordregion(expdest - stackblock() -
262				    (quotes ? 2 : 1),
263				    expdest - stackblock(), 0);
264			break;
265		case CTLVAR:
266			p = evalvar(p, flag);
267			break;
268		case CTLBACKQ:
269		case CTLBACKQ|CTLQUOTE:
270			expbackq(argbackq->n, c & CTLQUOTE, flag);
271			argbackq = argbackq->next;
272			break;
273		case CTLENDARI:
274			expari(flag);
275			break;
276		case ':':
277		case '=':
278			/*
279			 * sort of a hack - expand tildes in variable
280			 * assignments (after the first '=' and after ':'s).
281			 */
282			USTPUTC(c, expdest);
283			if (split_lit && !lit_quoted)
284				recordregion(expdest - stackblock() - 1,
285				    expdest - stackblock(), 0);
286			if (flag & EXP_VARTILDE && *p == '~' &&
287			    (c != '=' || firsteq)) {
288				if (c == '=')
289					firsteq = 0;
290				p = exptilde(p, flag);
291			}
292			break;
293		default:
294			USTPUTC(c, expdest);
295			if (split_lit && !lit_quoted)
296				recordregion(expdest - stackblock() - 1,
297				    expdest - stackblock(), 0);
298		}
299	}
300breakloop:;
301}
302
303/*
304 * Perform tilde expansion, placing the result in the stack string and
305 * returning the next position in the input string to process.
306 */
307static char *
308exptilde(char *p, int flag)
309{
310	char c, *startp = p;
311	struct passwd *pw;
312	char *home;
313	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
314
315	while ((c = *p) != '\0') {
316		switch(c) {
317		case CTLESC: /* This means CTL* are always considered quoted. */
318		case CTLVAR:
319		case CTLBACKQ:
320		case CTLBACKQ | CTLQUOTE:
321		case CTLARI:
322		case CTLENDARI:
323		case CTLQUOTEMARK:
324			return (startp);
325		case ':':
326			if (flag & EXP_VARTILDE)
327				goto done;
328			break;
329		case '/':
330		case CTLENDVAR:
331			goto done;
332		}
333		p++;
334	}
335done:
336	*p = '\0';
337	if (*(startp+1) == '\0') {
338		if ((home = lookupvar("HOME")) == NULL)
339			goto lose;
340	} else {
341		if ((pw = getpwnam(startp+1)) == NULL)
342			goto lose;
343		home = pw->pw_dir;
344	}
345	if (*home == '\0')
346		goto lose;
347	*p = c;
348	if (quotes)
349		STPUTS_QUOTES(home, SQSYNTAX, expdest);
350	else
351		STPUTS(home, expdest);
352	return (p);
353lose:
354	*p = c;
355	return (startp);
356}
357
358
359static void
360removerecordregions(int endoff)
361{
362	if (ifslastp == NULL)
363		return;
364
365	if (ifsfirst.endoff > endoff) {
366		while (ifsfirst.next != NULL) {
367			struct ifsregion *ifsp;
368			INTOFF;
369			ifsp = ifsfirst.next->next;
370			ckfree(ifsfirst.next);
371			ifsfirst.next = ifsp;
372			INTON;
373		}
374		if (ifsfirst.begoff > endoff)
375			ifslastp = NULL;
376		else {
377			ifslastp = &ifsfirst;
378			ifsfirst.endoff = endoff;
379		}
380		return;
381	}
382
383	ifslastp = &ifsfirst;
384	while (ifslastp->next && ifslastp->next->begoff < endoff)
385		ifslastp=ifslastp->next;
386	while (ifslastp->next != NULL) {
387		struct ifsregion *ifsp;
388		INTOFF;
389		ifsp = ifslastp->next->next;
390		ckfree(ifslastp->next);
391		ifslastp->next = ifsp;
392		INTON;
393	}
394	if (ifslastp->endoff > endoff)
395		ifslastp->endoff = endoff;
396}
397
398/*
399 * Expand arithmetic expression.  Backup to start of expression,
400 * evaluate, place result in (backed up) result, adjust string position.
401 */
402void
403expari(int flag)
404{
405	char *p, *q, *start;
406	arith_t result;
407	int begoff;
408	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
409	int quoted;
410
411	/*
412	 * This routine is slightly over-complicated for
413	 * efficiency.  First we make sure there is
414	 * enough space for the result, which may be bigger
415	 * than the expression.  Next we
416	 * scan backwards looking for the start of arithmetic.  If the
417	 * next previous character is a CTLESC character, then we
418	 * have to rescan starting from the beginning since CTLESC
419	 * characters have to be processed left to right.
420	 */
421	CHECKSTRSPACE(DIGITS(result) - 2, expdest);
422	USTPUTC('\0', expdest);
423	start = stackblock();
424	p = expdest - 2;
425	while (p >= start && *p != CTLARI)
426		--p;
427	if (p < start || *p != CTLARI)
428		error("missing CTLARI (shouldn't happen)");
429	if (p > start && *(p - 1) == CTLESC)
430		for (p = start; *p != CTLARI; p++)
431			if (*p == CTLESC)
432				p++;
433
434	if (p[1] == '"')
435		quoted=1;
436	else
437		quoted=0;
438	begoff = p - start;
439	removerecordregions(begoff);
440	if (quotes)
441		rmescapes(p+2);
442	q = grabstackstr(expdest);
443	result = arith(p+2);
444	ungrabstackstr(q, expdest);
445	fmtstr(p, DIGITS(result), ARITH_FORMAT_STR, result);
446	while (*p++)
447		;
448	if (quoted == 0)
449		recordregion(begoff, p - 1 - start, 0);
450	result = expdest - p + 1;
451	STADJUST(-result, expdest);
452}
453
454
455/*
456 * Perform command substitution.
457 */
458static void
459expbackq(union node *cmd, int quoted, int flag)
460{
461	struct backcmd in;
462	int i;
463	char buf[128];
464	char *p;
465	char *dest = expdest;
466	struct ifsregion saveifs, *savelastp;
467	struct nodelist *saveargbackq;
468	char lastc;
469	int startloc = dest - stackblock();
470	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
471	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
472	int nnl;
473
474	INTOFF;
475	saveifs = ifsfirst;
476	savelastp = ifslastp;
477	saveargbackq = argbackq;
478	p = grabstackstr(dest);
479	evalbackcmd(cmd, &in);
480	ungrabstackstr(p, dest);
481	ifsfirst = saveifs;
482	ifslastp = savelastp;
483	argbackq = saveargbackq;
484
485	p = in.buf;
486	lastc = '\0';
487	nnl = 0;
488	/* Don't copy trailing newlines */
489	for (;;) {
490		if (--in.nleft < 0) {
491			if (in.fd < 0)
492				break;
493			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
494			TRACE(("expbackq: read returns %d\n", i));
495			if (i <= 0)
496				break;
497			p = buf;
498			in.nleft = i - 1;
499		}
500		lastc = *p++;
501		if (lastc != '\0') {
502			if (quotes && syntax[(int)lastc] == CCTL)
503				STPUTC(CTLESC, dest);
504			if (lastc == '\n') {
505				nnl++;
506			} else {
507				while (nnl > 0) {
508					nnl--;
509					STPUTC('\n', dest);
510				}
511				STPUTC(lastc, dest);
512			}
513		}
514	}
515
516	if (in.fd >= 0)
517		close(in.fd);
518	if (in.buf)
519		ckfree(in.buf);
520	if (in.jp)
521		exitstatus = waitforjob(in.jp, (int *)NULL);
522	if (quoted == 0)
523		recordregion(startloc, dest - stackblock(), 0);
524	TRACE(("expbackq: size=%td: \"%.*s\"\n",
525		((dest - stackblock()) - startloc),
526		(int)((dest - stackblock()) - startloc),
527		stackblock() + startloc));
528	expdest = dest;
529	INTON;
530}
531
532
533
534static int
535subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
536  int varflags, int quotes)
537{
538	char *startp;
539	char *loc = NULL;
540	char *q;
541	int c = 0;
542	struct nodelist *saveargbackq = argbackq;
543	int amount;
544
545	argstr(p, (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX ||
546	    subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX ?
547	    EXP_CASE : 0) | EXP_TILDE);
548	STACKSTRNUL(expdest);
549	argbackq = saveargbackq;
550	startp = stackblock() + startloc;
551	if (str == NULL)
552	    str = stackblock() + strloc;
553
554	switch (subtype) {
555	case VSASSIGN:
556		setvar(str, startp, 0);
557		amount = startp - expdest;
558		STADJUST(amount, expdest);
559		varflags &= ~VSNUL;
560		if (c != 0)
561			*loc = c;
562		return 1;
563
564	case VSQUESTION:
565		if (*p != CTLENDVAR) {
566			outfmt(out2, "%s\n", startp);
567			error((char *)NULL);
568		}
569		error("%.*s: parameter %snot set", (int)(p - str - 1),
570		      str, (varflags & VSNUL) ? "null or "
571					      : nullstr);
572		return 0;
573
574	case VSTRIMLEFT:
575		for (loc = startp; loc < str; loc++) {
576			c = *loc;
577			*loc = '\0';
578			if (patmatch(str, startp, quotes)) {
579				*loc = c;
580				goto recordleft;
581			}
582			*loc = c;
583			if (quotes && *loc == CTLESC)
584				loc++;
585		}
586		return 0;
587
588	case VSTRIMLEFTMAX:
589		for (loc = str - 1; loc >= startp;) {
590			c = *loc;
591			*loc = '\0';
592			if (patmatch(str, startp, quotes)) {
593				*loc = c;
594				goto recordleft;
595			}
596			*loc = c;
597			loc--;
598			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
599				for (q = startp; q < loc; q++)
600					if (*q == CTLESC)
601						q++;
602				if (q > loc)
603					loc--;
604			}
605		}
606		return 0;
607
608	case VSTRIMRIGHT:
609		for (loc = str - 1; loc >= startp;) {
610			if (patmatch(str, loc, quotes)) {
611				amount = loc - expdest;
612				STADJUST(amount, expdest);
613				return 1;
614			}
615			loc--;
616			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
617				for (q = startp; q < loc; q++)
618					if (*q == CTLESC)
619						q++;
620				if (q > loc)
621					loc--;
622			}
623		}
624		return 0;
625
626	case VSTRIMRIGHTMAX:
627		for (loc = startp; loc < str - 1; loc++) {
628			if (patmatch(str, loc, quotes)) {
629				amount = loc - expdest;
630				STADJUST(amount, expdest);
631				return 1;
632			}
633			if (quotes && *loc == CTLESC)
634				loc++;
635		}
636		return 0;
637
638
639	default:
640		abort();
641	}
642
643recordleft:
644	amount = ((str - 1) - (loc - startp)) - expdest;
645	STADJUST(amount, expdest);
646	while (loc != str - 1)
647		*startp++ = *loc++;
648	return 1;
649}
650
651
652/*
653 * Expand a variable, and return a pointer to the next character in the
654 * input string.
655 */
656
657static char *
658evalvar(char *p, int flag)
659{
660	int subtype;
661	int varflags;
662	char *var;
663	char *val;
664	int patloc;
665	int c;
666	int set;
667	int special;
668	int startloc;
669	int varlen;
670	int easy;
671	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
672
673	varflags = (unsigned char)*p++;
674	subtype = varflags & VSTYPE;
675	var = p;
676	special = 0;
677	if (! is_name(*p))
678		special = 1;
679	p = strchr(p, '=') + 1;
680again: /* jump here after setting a variable with ${var=text} */
681	if (varflags & VSLINENO) {
682		set = 1;
683		special = 0;
684		val = var;
685		p[-1] = '\0';	/* temporarily overwrite '=' to have \0
686				   terminated string */
687	} else if (special) {
688		set = varisset(var, varflags & VSNUL);
689		val = NULL;
690	} else {
691		val = bltinlookup(var, 1);
692		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
693			val = NULL;
694			set = 0;
695		} else
696			set = 1;
697	}
698	varlen = 0;
699	startloc = expdest - stackblock();
700	if (!set && uflag && *var != '@' && *var != '*') {
701		switch (subtype) {
702		case VSNORMAL:
703		case VSTRIMLEFT:
704		case VSTRIMLEFTMAX:
705		case VSTRIMRIGHT:
706		case VSTRIMRIGHTMAX:
707		case VSLENGTH:
708			error("%.*s: parameter not set", (int)(p - var - 1),
709			    var);
710		}
711	}
712	if (set && subtype != VSPLUS) {
713		/* insert the value of the variable */
714		if (special) {
715			varvalue(var, varflags & VSQUOTE, subtype, flag);
716			if (subtype == VSLENGTH) {
717				varlen = expdest - stackblock() - startloc;
718				STADJUST(-varlen, expdest);
719			}
720		} else {
721			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
722								  : BASESYNTAX;
723
724			if (subtype == VSLENGTH) {
725				for (;*val; val++)
726					varlen++;
727			}
728			else {
729				if (quotes)
730					STPUTS_QUOTES(val, syntax, expdest);
731				else
732					STPUTS(val, expdest);
733
734			}
735		}
736	}
737
738	if (subtype == VSPLUS)
739		set = ! set;
740
741	easy = ((varflags & VSQUOTE) == 0 ||
742		(*var == '@' && shellparam.nparam != 1));
743
744
745	switch (subtype) {
746	case VSLENGTH:
747		expdest = cvtnum(varlen, expdest);
748		goto record;
749
750	case VSNORMAL:
751		if (!easy)
752			break;
753record:
754		recordregion(startloc, expdest - stackblock(),
755			     varflags & VSQUOTE);
756		break;
757
758	case VSPLUS:
759	case VSMINUS:
760		if (!set) {
761			argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) |
762			    (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0));
763			break;
764		}
765		if (easy)
766			goto record;
767		break;
768
769	case VSTRIMLEFT:
770	case VSTRIMLEFTMAX:
771	case VSTRIMRIGHT:
772	case VSTRIMRIGHTMAX:
773		if (!set)
774			break;
775		/*
776		 * Terminate the string and start recording the pattern
777		 * right after it
778		 */
779		STPUTC('\0', expdest);
780		patloc = expdest - stackblock();
781		if (subevalvar(p, NULL, patloc, subtype,
782		    startloc, varflags, quotes) == 0) {
783			int amount = (expdest - stackblock() - patloc) + 1;
784			STADJUST(-amount, expdest);
785		}
786		/* Remove any recorded regions beyond start of variable */
787		removerecordregions(startloc);
788		goto record;
789
790	case VSASSIGN:
791	case VSQUESTION:
792		if (!set) {
793			if (subevalvar(p, var, 0, subtype, startloc, varflags,
794			    quotes)) {
795				varflags &= ~VSNUL;
796				/*
797				 * Remove any recorded regions beyond
798				 * start of variable
799				 */
800				removerecordregions(startloc);
801				goto again;
802			}
803			break;
804		}
805		if (easy)
806			goto record;
807		break;
808
809	case VSERROR:
810		c = p - var - 1;
811		error("${%.*s%s}: Bad substitution", c, var,
812		    (c > 0 && *p != CTLENDVAR) ? "..." : "");
813
814	default:
815		abort();
816	}
817	p[-1] = '=';	/* recover overwritten '=' */
818
819	if (subtype != VSNORMAL) {	/* skip to end of alternative */
820		int nesting = 1;
821		for (;;) {
822			if ((c = *p++) == CTLESC)
823				p++;
824			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
825				if (set)
826					argbackq = argbackq->next;
827			} else if (c == CTLVAR) {
828				if ((*p++ & VSTYPE) != VSNORMAL)
829					nesting++;
830			} else if (c == CTLENDVAR) {
831				if (--nesting == 0)
832					break;
833			}
834		}
835	}
836	return p;
837}
838
839
840
841/*
842 * Test whether a specialized variable is set.
843 */
844
845static int
846varisset(char *name, int nulok)
847{
848
849	if (*name == '!')
850		return backgndpidset();
851	else if (*name == '@' || *name == '*') {
852		if (*shellparam.p == NULL)
853			return 0;
854
855		if (nulok) {
856			char **av;
857
858			for (av = shellparam.p; *av; av++)
859				if (**av != '\0')
860					return 1;
861			return 0;
862		}
863	} else if (is_digit(*name)) {
864		char *ap;
865		int num = atoi(name);
866
867		if (num > shellparam.nparam)
868			return 0;
869
870		if (num == 0)
871			ap = arg0;
872		else
873			ap = shellparam.p[num - 1];
874
875		if (nulok && (ap == NULL || *ap == '\0'))
876			return 0;
877	}
878	return 1;
879}
880
881static void
882strtodest(const char *p, int flag, int subtype, int quoted)
883{
884	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH)
885		STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest);
886	else
887		STPUTS(p, expdest);
888}
889
890/*
891 * Add the value of a specialized variable to the stack string.
892 */
893
894static void
895varvalue(char *name, int quoted, int subtype, int flag)
896{
897	int num;
898	char *p;
899	int i;
900	char sep;
901	char **ap;
902
903	switch (*name) {
904	case '$':
905		num = rootpid;
906		goto numvar;
907	case '?':
908		num = oexitstatus;
909		goto numvar;
910	case '#':
911		num = shellparam.nparam;
912		goto numvar;
913	case '!':
914		num = backgndpidval();
915numvar:
916		expdest = cvtnum(num, expdest);
917		break;
918	case '-':
919		for (i = 0 ; i < NOPTS ; i++) {
920			if (optlist[i].val)
921				STPUTC(optlist[i].letter, expdest);
922		}
923		break;
924	case '@':
925		if (flag & EXP_FULL && quoted) {
926			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
927				strtodest(p, flag, subtype, quoted);
928				if (*ap)
929					STPUTC('\0', expdest);
930			}
931			break;
932		}
933		/* FALLTHROUGH */
934	case '*':
935		if (ifsset())
936			sep = ifsval()[0];
937		else
938			sep = ' ';
939		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
940			strtodest(p, flag, subtype, quoted);
941			if (*ap && sep)
942				STPUTC(sep, expdest);
943		}
944		break;
945	case '0':
946		p = arg0;
947		strtodest(p, flag, subtype, quoted);
948		break;
949	default:
950		if (is_digit(*name)) {
951			num = atoi(name);
952			if (num > 0 && num <= shellparam.nparam) {
953				p = shellparam.p[num - 1];
954				strtodest(p, flag, subtype, quoted);
955			}
956		}
957		break;
958	}
959}
960
961
962
963/*
964 * Record the the fact that we have to scan this region of the
965 * string for IFS characters.
966 */
967
968static void
969recordregion(int start, int end, int inquotes)
970{
971	struct ifsregion *ifsp;
972
973	if (ifslastp == NULL) {
974		ifsp = &ifsfirst;
975	} else {
976		if (ifslastp->endoff == start
977		    && ifslastp->inquotes == inquotes) {
978			/* extend previous area */
979			ifslastp->endoff = end;
980			return;
981		}
982		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
983		ifslastp->next = ifsp;
984	}
985	ifslastp = ifsp;
986	ifslastp->next = NULL;
987	ifslastp->begoff = start;
988	ifslastp->endoff = end;
989	ifslastp->inquotes = inquotes;
990}
991
992
993
994/*
995 * Break the argument string into pieces based upon IFS and add the
996 * strings to the argument list.  The regions of the string to be
997 * searched for IFS characters have been stored by recordregion.
998 * CTLESC characters are preserved but have little effect in this pass
999 * other than escaping CTL* characters.  In particular, they do not escape
1000 * IFS characters: that should be done with the ifsregion mechanism.
1001 * CTLQUOTEMARK characters are used to preserve empty quoted strings.
1002 * This pass treats them as a regular character, making the string non-empty.
1003 * Later, they are removed along with the other CTL* characters.
1004 */
1005static void
1006ifsbreakup(char *string, struct arglist *arglist)
1007{
1008	struct ifsregion *ifsp;
1009	struct strlist *sp;
1010	char *start;
1011	char *p;
1012	char *q;
1013	const char *ifs;
1014	const char *ifsspc;
1015	int had_param_ch = 0;
1016
1017	start = string;
1018
1019	if (ifslastp == NULL) {
1020		/* Return entire argument, IFS doesn't apply to any of it */
1021		sp = (struct strlist *)stalloc(sizeof *sp);
1022		sp->text = start;
1023		*arglist->lastp = sp;
1024		arglist->lastp = &sp->next;
1025		return;
1026	}
1027
1028	ifs = ifsset() ? ifsval() : " \t\n";
1029
1030	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
1031		p = string + ifsp->begoff;
1032		while (p < string + ifsp->endoff) {
1033			q = p;
1034			if (*p == CTLESC)
1035				p++;
1036			if (ifsp->inquotes) {
1037				/* Only NULs (should be from "$@") end args */
1038				had_param_ch = 1;
1039				if (*p != 0) {
1040					p++;
1041					continue;
1042				}
1043				ifsspc = NULL;
1044			} else {
1045				if (!strchr(ifs, *p)) {
1046					had_param_ch = 1;
1047					p++;
1048					continue;
1049				}
1050				ifsspc = strchr(" \t\n", *p);
1051
1052				/* Ignore IFS whitespace at start */
1053				if (q == start && ifsspc != NULL) {
1054					p++;
1055					start = p;
1056					continue;
1057				}
1058				had_param_ch = 0;
1059			}
1060
1061			/* Save this argument... */
1062			*q = '\0';
1063			sp = (struct strlist *)stalloc(sizeof *sp);
1064			sp->text = start;
1065			*arglist->lastp = sp;
1066			arglist->lastp = &sp->next;
1067			p++;
1068
1069			if (ifsspc != NULL) {
1070				/* Ignore further trailing IFS whitespace */
1071				for (; p < string + ifsp->endoff; p++) {
1072					q = p;
1073					if (*p == CTLESC)
1074						p++;
1075					if (strchr(ifs, *p) == NULL) {
1076						p = q;
1077						break;
1078					}
1079					if (strchr(" \t\n", *p) == NULL) {
1080						p++;
1081						break;
1082					}
1083				}
1084			}
1085			start = p;
1086		}
1087	}
1088
1089	/*
1090	 * Save anything left as an argument.
1091	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
1092	 * generating 2 arguments, the second of which is empty.
1093	 * Some recent clarification of the Posix spec say that it
1094	 * should only generate one....
1095	 */
1096	if (had_param_ch || *start != 0) {
1097		sp = (struct strlist *)stalloc(sizeof *sp);
1098		sp->text = start;
1099		*arglist->lastp = sp;
1100		arglist->lastp = &sp->next;
1101	}
1102}
1103
1104
1105static char expdir[PATH_MAX];
1106#define expdir_end (expdir + sizeof(expdir))
1107
1108/*
1109 * Perform pathname generation and remove control characters.
1110 * At this point, the only control characters should be CTLESC and CTLQUOTEMARK.
1111 * The results are stored in the list exparg.
1112 */
1113static void
1114expandmeta(struct strlist *str, int flag __unused)
1115{
1116	char *p;
1117	struct strlist **savelastp;
1118	struct strlist *sp;
1119	char c;
1120	/* TODO - EXP_REDIR */
1121
1122	while (str) {
1123		if (fflag)
1124			goto nometa;
1125		p = str->text;
1126		for (;;) {			/* fast check for meta chars */
1127			if ((c = *p++) == '\0')
1128				goto nometa;
1129			if (c == '*' || c == '?' || c == '[')
1130				break;
1131		}
1132		savelastp = exparg.lastp;
1133		INTOFF;
1134		expmeta(expdir, str->text);
1135		INTON;
1136		if (exparg.lastp == savelastp) {
1137			/*
1138			 * no matches
1139			 */
1140nometa:
1141			*exparg.lastp = str;
1142			rmescapes(str->text);
1143			exparg.lastp = &str->next;
1144		} else {
1145			*exparg.lastp = NULL;
1146			*savelastp = sp = expsort(*savelastp);
1147			while (sp->next != NULL)
1148				sp = sp->next;
1149			exparg.lastp = &sp->next;
1150		}
1151		str = str->next;
1152	}
1153}
1154
1155
1156/*
1157 * Do metacharacter (i.e. *, ?, [...]) expansion.
1158 */
1159
1160static void
1161expmeta(char *enddir, char *name)
1162{
1163	char *p;
1164	char *q;
1165	char *start;
1166	char *endname;
1167	int metaflag;
1168	struct stat statb;
1169	DIR *dirp;
1170	struct dirent *dp;
1171	int atend;
1172	int matchdot;
1173	int esc;
1174
1175	metaflag = 0;
1176	start = name;
1177	for (p = name; esc = 0, *p; p += esc + 1) {
1178		if (*p == '*' || *p == '?')
1179			metaflag = 1;
1180		else if (*p == '[') {
1181			q = p + 1;
1182			if (*q == '!' || *q == '^')
1183				q++;
1184			for (;;) {
1185				while (*q == CTLQUOTEMARK)
1186					q++;
1187				if (*q == CTLESC)
1188					q++;
1189				if (*q == '/' || *q == '\0')
1190					break;
1191				if (*++q == ']') {
1192					metaflag = 1;
1193					break;
1194				}
1195			}
1196		} else if (*p == '\0')
1197			break;
1198		else if (*p == CTLQUOTEMARK)
1199			continue;
1200		else {
1201			if (*p == CTLESC)
1202				esc++;
1203			if (p[esc] == '/') {
1204				if (metaflag)
1205					break;
1206				start = p + esc + 1;
1207			}
1208		}
1209	}
1210	if (metaflag == 0) {	/* we've reached the end of the file name */
1211		if (enddir != expdir)
1212			metaflag++;
1213		for (p = name ; ; p++) {
1214			if (*p == CTLQUOTEMARK)
1215				continue;
1216			if (*p == CTLESC)
1217				p++;
1218			*enddir++ = *p;
1219			if (*p == '\0')
1220				break;
1221			if (enddir == expdir_end)
1222				return;
1223		}
1224		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
1225			addfname(expdir);
1226		return;
1227	}
1228	endname = p;
1229	if (start != name) {
1230		p = name;
1231		while (p < start) {
1232			while (*p == CTLQUOTEMARK)
1233				p++;
1234			if (*p == CTLESC)
1235				p++;
1236			*enddir++ = *p++;
1237			if (enddir == expdir_end)
1238				return;
1239		}
1240	}
1241	if (enddir == expdir) {
1242		p = ".";
1243	} else if (enddir == expdir + 1 && *expdir == '/') {
1244		p = "/";
1245	} else {
1246		p = expdir;
1247		enddir[-1] = '\0';
1248	}
1249	if ((dirp = opendir(p)) == NULL)
1250		return;
1251	if (enddir != expdir)
1252		enddir[-1] = '/';
1253	if (*endname == 0) {
1254		atend = 1;
1255	} else {
1256		atend = 0;
1257		*endname = '\0';
1258		endname += esc + 1;
1259	}
1260	matchdot = 0;
1261	p = start;
1262	while (*p == CTLQUOTEMARK)
1263		p++;
1264	if (*p == CTLESC)
1265		p++;
1266	if (*p == '.')
1267		matchdot++;
1268	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
1269		if (dp->d_name[0] == '.' && ! matchdot)
1270			continue;
1271		if (patmatch(start, dp->d_name, 0)) {
1272			if (enddir + dp->d_namlen + 1 > expdir_end)
1273				continue;
1274			memcpy(enddir, dp->d_name, dp->d_namlen + 1);
1275			if (atend)
1276				addfname(expdir);
1277			else {
1278				if (enddir + dp->d_namlen + 2 > expdir_end)
1279					continue;
1280				enddir[dp->d_namlen] = '/';
1281				enddir[dp->d_namlen + 1] = '\0';
1282				expmeta(enddir + dp->d_namlen + 1, endname);
1283			}
1284		}
1285	}
1286	closedir(dirp);
1287	if (! atend)
1288		endname[-esc - 1] = esc ? CTLESC : '/';
1289}
1290
1291
1292/*
1293 * Add a file name to the list.
1294 */
1295
1296static void
1297addfname(char *name)
1298{
1299	char *p;
1300	struct strlist *sp;
1301
1302	p = stalloc(strlen(name) + 1);
1303	scopy(name, p);
1304	sp = (struct strlist *)stalloc(sizeof *sp);
1305	sp->text = p;
1306	*exparg.lastp = sp;
1307	exparg.lastp = &sp->next;
1308}
1309
1310
1311/*
1312 * Sort the results of file name expansion.  It calculates the number of
1313 * strings to sort and then calls msort (short for merge sort) to do the
1314 * work.
1315 */
1316
1317static struct strlist *
1318expsort(struct strlist *str)
1319{
1320	int len;
1321	struct strlist *sp;
1322
1323	len = 0;
1324	for (sp = str ; sp ; sp = sp->next)
1325		len++;
1326	return msort(str, len);
1327}
1328
1329
1330static struct strlist *
1331msort(struct strlist *list, int len)
1332{
1333	struct strlist *p, *q = NULL;
1334	struct strlist **lpp;
1335	int half;
1336	int n;
1337
1338	if (len <= 1)
1339		return list;
1340	half = len >> 1;
1341	p = list;
1342	for (n = half ; --n >= 0 ; ) {
1343		q = p;
1344		p = p->next;
1345	}
1346	q->next = NULL;			/* terminate first half of list */
1347	q = msort(list, half);		/* sort first half of list */
1348	p = msort(p, len - half);		/* sort second half */
1349	lpp = &list;
1350	for (;;) {
1351		if (strcmp(p->text, q->text) < 0) {
1352			*lpp = p;
1353			lpp = &p->next;
1354			if ((p = *lpp) == NULL) {
1355				*lpp = q;
1356				break;
1357			}
1358		} else {
1359			*lpp = q;
1360			lpp = &q->next;
1361			if ((q = *lpp) == NULL) {
1362				*lpp = p;
1363				break;
1364			}
1365		}
1366	}
1367	return list;
1368}
1369
1370
1371
1372/*
1373 * Returns true if the pattern matches the string.
1374 */
1375
1376int
1377patmatch(const char *pattern, const char *string, int squoted)
1378{
1379	const char *p, *q;
1380	char c;
1381
1382	p = pattern;
1383	q = string;
1384	for (;;) {
1385		switch (c = *p++) {
1386		case '\0':
1387			goto breakloop;
1388		case CTLESC:
1389			if (squoted && *q == CTLESC)
1390				q++;
1391			if (*q++ != *p++)
1392				return 0;
1393			break;
1394		case CTLQUOTEMARK:
1395			continue;
1396		case '?':
1397			if (squoted && *q == CTLESC)
1398				q++;
1399			if (*q++ == '\0')
1400				return 0;
1401			break;
1402		case '*':
1403			c = *p;
1404			while (c == CTLQUOTEMARK || c == '*')
1405				c = *++p;
1406			if (c != CTLESC &&  c != CTLQUOTEMARK &&
1407			    c != '?' && c != '*' && c != '[') {
1408				while (*q != c) {
1409					if (squoted && *q == CTLESC &&
1410					    q[1] == c)
1411						break;
1412					if (*q == '\0')
1413						return 0;
1414					if (squoted && *q == CTLESC)
1415						q++;
1416					q++;
1417				}
1418			}
1419			do {
1420				if (patmatch(p, q, squoted))
1421					return 1;
1422				if (squoted && *q == CTLESC)
1423					q++;
1424			} while (*q++ != '\0');
1425			return 0;
1426		case '[': {
1427			const char *endp;
1428			int invert, found;
1429			char chr;
1430
1431			endp = p;
1432			if (*endp == '!' || *endp == '^')
1433				endp++;
1434			for (;;) {
1435				while (*endp == CTLQUOTEMARK)
1436					endp++;
1437				if (*endp == '\0')
1438					goto dft;		/* no matching ] */
1439				if (*endp == CTLESC)
1440					endp++;
1441				if (*++endp == ']')
1442					break;
1443			}
1444			invert = 0;
1445			if (*p == '!' || *p == '^') {
1446				invert++;
1447				p++;
1448			}
1449			found = 0;
1450			chr = *q++;
1451			if (squoted && chr == CTLESC)
1452				chr = *q++;
1453			if (chr == '\0')
1454				return 0;
1455			c = *p++;
1456			do {
1457				if (c == CTLQUOTEMARK)
1458					continue;
1459				if (c == CTLESC)
1460					c = *p++;
1461				if (*p == '-' && p[1] != ']') {
1462					p++;
1463					while (*p == CTLQUOTEMARK)
1464						p++;
1465					if (*p == CTLESC)
1466						p++;
1467					if (   collate_range_cmp(chr, c) >= 0
1468					    && collate_range_cmp(chr, *p) <= 0
1469					   )
1470						found = 1;
1471					p++;
1472				} else {
1473					if (chr == c)
1474						found = 1;
1475				}
1476			} while ((c = *p++) != ']');
1477			if (found == invert)
1478				return 0;
1479			break;
1480		}
1481dft:	        default:
1482			if (squoted && *q == CTLESC)
1483				q++;
1484			if (*q++ != c)
1485				return 0;
1486			break;
1487		}
1488	}
1489breakloop:
1490	if (*q != '\0')
1491		return 0;
1492	return 1;
1493}
1494
1495
1496
1497/*
1498 * Remove any CTLESC and CTLQUOTEMARK characters from a string.
1499 */
1500
1501void
1502rmescapes(char *str)
1503{
1504	char *p, *q;
1505
1506	p = str;
1507	while (*p != CTLESC && *p != CTLQUOTEMARK && *p != CTLQUOTEEND) {
1508		if (*p++ == '\0')
1509			return;
1510	}
1511	q = p;
1512	while (*p) {
1513		if (*p == CTLQUOTEMARK || *p == CTLQUOTEEND) {
1514			p++;
1515			continue;
1516		}
1517		if (*p == CTLESC)
1518			p++;
1519		*q++ = *p++;
1520	}
1521	*q = '\0';
1522}
1523
1524
1525
1526/*
1527 * See if a pattern matches in a case statement.
1528 */
1529
1530int
1531casematch(union node *pattern, const char *val)
1532{
1533	struct stackmark smark;
1534	int result;
1535	char *p;
1536
1537	setstackmark(&smark);
1538	argbackq = pattern->narg.backquote;
1539	STARTSTACKSTR(expdest);
1540	ifslastp = NULL;
1541	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
1542	STPUTC('\0', expdest);
1543	p = grabstackstr(expdest);
1544	result = patmatch(p, val, 0);
1545	popstackmark(&smark);
1546	return result;
1547}
1548
1549/*
1550 * Our own itoa().
1551 */
1552
1553static char *
1554cvtnum(int num, char *buf)
1555{
1556	char temp[32];
1557	int neg = num < 0;
1558	char *p = temp + 31;
1559
1560	temp[31] = '\0';
1561
1562	do {
1563		*--p = num % 10 + '0';
1564	} while ((num /= 10) != 0);
1565
1566	if (neg)
1567		*--p = '-';
1568
1569	STPUTS(p, buf);
1570	return buf;
1571}
1572
1573/*
1574 * Do most of the work for wordexp(3).
1575 */
1576
1577int
1578wordexpcmd(int argc, char **argv)
1579{
1580	size_t len;
1581	int i;
1582
1583	out1fmt("%08x", argc - 1);
1584	for (i = 1, len = 0; i < argc; i++)
1585		len += strlen(argv[i]);
1586	out1fmt("%08x", (int)len);
1587	for (i = 1; i < argc; i++)
1588		outbin(argv[i], strlen(argv[i]) + 1, out1);
1589        return (0);
1590}
1591