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