1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 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 */ 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 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 */ 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