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