/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1985-2009 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * * * * Information and Software Systems Research * * AT&T Research * * Florham Park NJ * * * * Glenn Fowler * * David Korn * * Phong Vo * * * ***********************************************************************/ #pragma prototyped /* * POSIX 1003.2 wordexp implementation */ #include #include #include struct list { struct list *next; }; /* * elimnates shell quoting as inserted with sh_fmtq * result relaces * length of resulting string is returned. */ static int sh_unquote(char* string) { register char *sp=string, *dp; register int c; while((c= *sp) && c!='\'') sp++; if(c==0) return(sp-string); if((dp=sp) > string && sp[-1]=='$') { register int n=stresc(sp+1); /* copy all but trailing ' */ while(--n>0) *dp++ = *++sp; } else { while((c= *++sp) && c!='\'') *dp++ = c; } *dp=0; return(dp-string); } int wordexp(const char *string, wordexp_t *wdarg, register int flags) { register Sfio_t *iop; register char *cp=(char*)string; register int c,quoted=0,literal=0,ac=0; int offset; char *savebase,**av; if(offset=staktell()) savebase = stakfreeze(0); if(flags&WRDE_REUSE) wordfree(wdarg); else if(!(flags&WRDE_APPEND)) { wdarg->we_wordv = 0; wdarg->we_wordc = 0; } if(flags&WRDE_UNDEF) stakwrite("set -u\n",7); if(!(flags&WRDE_SHOWERR)) stakwrite("exec 2> /dev/null\n",18); stakwrite("print -f \"%q\\n\" ",16); if(*cp=='#') stakputc('\\'); while(c = *cp++) { if(c=='\'' && !quoted) literal = !literal; else if(!literal) { if(c=='\\' && (!quoted || strchr("\\\"`\n$",c))) { stakputc('\\'); if(c= *cp) cp++; else c = '\\'; } else if(c=='"') quoted = !quoted; else if(c=='`' || (c=='$' && *cp=='(')) { if(flags&WRDE_NOCMD) { c=WRDE_CMDSUB; goto err; } /* only the shell can parse the rest */ stakputs(cp-1); break; } else if(!quoted && strchr("|&\n;<>"+ac,c)) { c=WRDE_BADCHAR; goto err; } else if(c=='(') /* allow | and & inside pattern */ ac=2; } stakputc(c); } stakputc(0); if(!(iop = sfpopen((Sfio_t*)0,stakptr(0),"r"))) { c = WRDE_NOSHELL; goto err; } stakseek(0); ac = 0; while((c=sfgetc(iop)) != EOF) { if(c=='\'') quoted = ! quoted; else if(!quoted && (c==' ' || c=='\n')) { ac++; c = 0; } stakputc(c); } if(c=sfclose(iop)) { if(c==3 || !(flags&WRDE_UNDEF)) c=WRDE_SYNTAX; else c=WRDE_BADVAL; goto err; } c = ac+2; if(flags&WRDE_DOOFFS) c += wdarg->we_offs; if(flags&WRDE_APPEND) av = (char**)realloc((void*)&wdarg->we_wordv[-1], (wdarg->we_wordc+c)*sizeof(char*)); else if(av = (char**)malloc(c*sizeof(char*))) { if(flags&WRDE_DOOFFS) memset((void*)av,0,(wdarg->we_offs+1)*sizeof(char*)); else av[0] = 0; } if(!av) return(WRDE_NOSPACE); c = staktell(); if(!(cp = (char*)malloc(sizeof(char*)+c))) { c=WRDE_NOSPACE; goto err; } ((struct list*)cp)->next = (struct list*)(*av); *av++ = (char*)cp; cp += sizeof(char*); wdarg->we_wordv = av; if(flags&WRDE_APPEND) av += wdarg->we_wordc; wdarg->we_wordc += ac; if(flags&WRDE_DOOFFS) av += wdarg->we_offs; memcpy((void*)cp,stakptr(offset),c); while(ac-- > 0) { *av++ = cp; sh_unquote(cp); while(c= *cp++); } *av = 0; c=0; err: if(offset) stakset(savebase,offset); else stakseek(0); return(c); } /* * free fields in */ int wordfree(register wordexp_t *wdarg) { struct list *arg, *argnext; if(wdarg->we_wordv) { argnext = (struct list*)wdarg->we_wordv[-1]; while(arg=argnext) { argnext = arg->next; free((void*)arg); } free((void*)&wdarg->we_wordv[-1]); wdarg->we_wordv = 0; } wdarg->we_wordc=0; return(0); }