1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin  * POSIX 1003.2 wordexp implementation
25da2e3ebdSchin  */
26da2e3ebdSchin 
27da2e3ebdSchin #include	<ast.h>
28da2e3ebdSchin #include	<wordexp.h>
29da2e3ebdSchin #include	<stak.h>
30da2e3ebdSchin 
31da2e3ebdSchin struct list
32da2e3ebdSchin {
33da2e3ebdSchin 	struct list *next;
34da2e3ebdSchin };
35da2e3ebdSchin 
36da2e3ebdSchin /*
37da2e3ebdSchin  * elimnates shell quoting as inserted with sh_fmtq
38da2e3ebdSchin  * result relaces <string>
39da2e3ebdSchin  * length of resulting string is returned.
40da2e3ebdSchin  */
sh_unquote(char * string)41da2e3ebdSchin static int	sh_unquote(char* string)
42da2e3ebdSchin {
43da2e3ebdSchin 	register char *sp=string, *dp;
44da2e3ebdSchin 	register int c;
45da2e3ebdSchin 	while((c= *sp) && c!='\'')
46da2e3ebdSchin 		sp++;
47da2e3ebdSchin 	if(c==0)
48da2e3ebdSchin 		return(sp-string);
49da2e3ebdSchin 	if((dp=sp) > string && sp[-1]=='$')
50da2e3ebdSchin 	{
51da2e3ebdSchin 		register int n=stresc(sp+1);
52da2e3ebdSchin 		/* copy all but trailing ' */
53da2e3ebdSchin 		while(--n>0)
54da2e3ebdSchin 			*dp++ = *++sp;
55da2e3ebdSchin 	}
56da2e3ebdSchin 	else
57da2e3ebdSchin 	{
58da2e3ebdSchin 		while((c= *++sp) && c!='\'')
59da2e3ebdSchin 			*dp++ = c;
60da2e3ebdSchin 	}
61da2e3ebdSchin 	*dp=0;
62da2e3ebdSchin 	return(dp-string);
63da2e3ebdSchin }
64da2e3ebdSchin 
wordexp(const char * string,wordexp_t * wdarg,register int flags)65da2e3ebdSchin int	wordexp(const char *string, wordexp_t *wdarg, register int flags)
66da2e3ebdSchin {
67da2e3ebdSchin 	register Sfio_t *iop;
68da2e3ebdSchin 	register char *cp=(char*)string;
69da2e3ebdSchin 	register int c,quoted=0,literal=0,ac=0;
70da2e3ebdSchin 	int offset;
71da2e3ebdSchin 	char *savebase,**av;
72da2e3ebdSchin 	if(offset=staktell())
73da2e3ebdSchin 		savebase = stakfreeze(0);
74da2e3ebdSchin 	if(flags&WRDE_REUSE)
75da2e3ebdSchin 		wordfree(wdarg);
76da2e3ebdSchin 	else if(!(flags&WRDE_APPEND))
77da2e3ebdSchin 	{
78da2e3ebdSchin 		wdarg->we_wordv = 0;
79da2e3ebdSchin 		wdarg->we_wordc = 0;
80da2e3ebdSchin 	}
81da2e3ebdSchin 	if(flags&WRDE_UNDEF)
82da2e3ebdSchin 		stakwrite("set -u\n",7);
83da2e3ebdSchin 	if(!(flags&WRDE_SHOWERR))
84da2e3ebdSchin 		stakwrite("exec 2> /dev/null\n",18);
85da2e3ebdSchin 	stakwrite("print -f \"%q\\n\" ",16);
86da2e3ebdSchin 	if(*cp=='#')
87da2e3ebdSchin 		stakputc('\\');
88da2e3ebdSchin 	while(c = *cp++)
89da2e3ebdSchin 	{
90da2e3ebdSchin 		if(c=='\'' && !quoted)
91da2e3ebdSchin 			literal = !literal;
92da2e3ebdSchin 		else if(!literal)
93da2e3ebdSchin 		{
94da2e3ebdSchin 			if(c=='\\' && (!quoted || strchr("\\\"`\n$",c)))
95da2e3ebdSchin 			{
96da2e3ebdSchin 				stakputc('\\');
97da2e3ebdSchin 				if(c= *cp)
98da2e3ebdSchin 					cp++;
99da2e3ebdSchin 				else
100da2e3ebdSchin 					c = '\\';
101da2e3ebdSchin 			}
102da2e3ebdSchin 			else if(c=='"')
103da2e3ebdSchin 				quoted = !quoted;
104da2e3ebdSchin 			else if(c=='`' || (c=='$' && *cp=='('))
105da2e3ebdSchin 			{
106da2e3ebdSchin 				if(flags&WRDE_NOCMD)
107da2e3ebdSchin 				{
108da2e3ebdSchin 					c=WRDE_CMDSUB;
109da2e3ebdSchin 					goto err;
110da2e3ebdSchin 				}
111da2e3ebdSchin 				/* only the shell can parse the rest */
112da2e3ebdSchin 				stakputs(cp-1);
113da2e3ebdSchin 				break;
114da2e3ebdSchin 			}
115da2e3ebdSchin 			else if(!quoted && strchr("|&\n;<>"+ac,c))
116da2e3ebdSchin 			{
117da2e3ebdSchin 				c=WRDE_BADCHAR;
118da2e3ebdSchin 				goto err;
119da2e3ebdSchin 			}
120da2e3ebdSchin 			else if(c=='(') /* allow | and & inside pattern */
121da2e3ebdSchin 				ac=2;
122da2e3ebdSchin 		}
123da2e3ebdSchin 		stakputc(c);
124da2e3ebdSchin 	}
125da2e3ebdSchin 	stakputc(0);
126da2e3ebdSchin 	if(!(iop = sfpopen((Sfio_t*)0,stakptr(0),"r")))
127da2e3ebdSchin 	{
128da2e3ebdSchin 		c = WRDE_NOSHELL;
129da2e3ebdSchin 		goto err;
130da2e3ebdSchin 	}
131da2e3ebdSchin 	stakseek(0);
132da2e3ebdSchin 	ac = 0;
133da2e3ebdSchin 	while((c=sfgetc(iop)) != EOF)
134da2e3ebdSchin 	{
135da2e3ebdSchin 		if(c=='\'')
136da2e3ebdSchin 			quoted = ! quoted;
137da2e3ebdSchin 		else if(!quoted && (c==' ' || c=='\n'))
138da2e3ebdSchin 		{
139da2e3ebdSchin 			ac++;
140da2e3ebdSchin 			c = 0;
141da2e3ebdSchin 		}
142da2e3ebdSchin 		stakputc(c);
143da2e3ebdSchin 	}
144da2e3ebdSchin 	if(c=sfclose(iop))
145da2e3ebdSchin 	{
146da2e3ebdSchin 		if(c==3 || !(flags&WRDE_UNDEF))
147da2e3ebdSchin 			c=WRDE_SYNTAX;
148da2e3ebdSchin 		else
149da2e3ebdSchin 			c=WRDE_BADVAL;
150da2e3ebdSchin 		goto err;
151da2e3ebdSchin 	}
152da2e3ebdSchin 	c = ac+2;
153da2e3ebdSchin 	if(flags&WRDE_DOOFFS)
154da2e3ebdSchin 		c += wdarg->we_offs;
155da2e3ebdSchin 	if(flags&WRDE_APPEND)
156da2e3ebdSchin 		av = (char**)realloc((void*)&wdarg->we_wordv[-1], (wdarg->we_wordc+c)*sizeof(char*));
157da2e3ebdSchin 	else if(av = (char**)malloc(c*sizeof(char*)))
158da2e3ebdSchin 	{
159da2e3ebdSchin 		if(flags&WRDE_DOOFFS)
160da2e3ebdSchin 			memset((void*)av,0,(wdarg->we_offs+1)*sizeof(char*));
161da2e3ebdSchin 		else
162da2e3ebdSchin 			av[0] = 0;
163da2e3ebdSchin 	}
164da2e3ebdSchin 	if(!av)
165da2e3ebdSchin 		return(WRDE_NOSPACE);
166da2e3ebdSchin 	c = staktell();
167da2e3ebdSchin 	if(!(cp = (char*)malloc(sizeof(char*)+c)))
168da2e3ebdSchin 	{
169da2e3ebdSchin 		c=WRDE_NOSPACE;
170da2e3ebdSchin 		goto err;
171da2e3ebdSchin 	}
172da2e3ebdSchin 	((struct list*)cp)->next = (struct list*)(*av);
173da2e3ebdSchin 	*av++ = (char*)cp;
174da2e3ebdSchin 	cp += sizeof(char*);
175da2e3ebdSchin 	wdarg->we_wordv = av;
176da2e3ebdSchin 	if(flags&WRDE_APPEND)
177da2e3ebdSchin 		av += wdarg->we_wordc;
178da2e3ebdSchin 	wdarg->we_wordc += ac;
179da2e3ebdSchin 	if(flags&WRDE_DOOFFS)
180da2e3ebdSchin 		av += wdarg->we_offs;
181da2e3ebdSchin 	memcpy((void*)cp,stakptr(offset),c);
182da2e3ebdSchin 	while(ac-- > 0)
183da2e3ebdSchin 	{
184da2e3ebdSchin 		*av++ = cp;
185da2e3ebdSchin 		sh_unquote(cp);
186da2e3ebdSchin 		while(c= *cp++);
187da2e3ebdSchin 	}
188da2e3ebdSchin 	*av = 0;
189da2e3ebdSchin 	c=0;
190da2e3ebdSchin err:
191da2e3ebdSchin 	if(offset)
192da2e3ebdSchin 		stakset(savebase,offset);
193da2e3ebdSchin 	else
194da2e3ebdSchin 		stakseek(0);
195da2e3ebdSchin 	return(c);
196da2e3ebdSchin }
197da2e3ebdSchin 
198da2e3ebdSchin /*
199da2e3ebdSchin  * free fields in <wdarg>
200da2e3ebdSchin  */
wordfree(register wordexp_t * wdarg)201da2e3ebdSchin int wordfree(register wordexp_t *wdarg)
202da2e3ebdSchin {
203da2e3ebdSchin 	struct list *arg, *argnext;
204da2e3ebdSchin 	if(wdarg->we_wordv)
205da2e3ebdSchin 	{
206da2e3ebdSchin 		argnext = (struct list*)wdarg->we_wordv[-1];
207da2e3ebdSchin 		while(arg=argnext)
208da2e3ebdSchin 		{
209da2e3ebdSchin 			argnext = arg->next;
210da2e3ebdSchin 			free((void*)arg);
211da2e3ebdSchin 		}
212da2e3ebdSchin 		free((void*)&wdarg->we_wordv[-1]);
213da2e3ebdSchin 		wdarg->we_wordv = 0;
214da2e3ebdSchin 	}
215da2e3ebdSchin 	wdarg->we_wordc=0;
216da2e3ebdSchin 	return(0);
217da2e3ebdSchin }
218