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