1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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