14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin * POSIX 1003.2 wordexp implementation
254887Schin */
264887Schin
274887Schin #include <ast.h>
284887Schin #include <wordexp.h>
294887Schin #include <stak.h>
304887Schin
314887Schin struct list
324887Schin {
334887Schin struct list *next;
344887Schin };
354887Schin
364887Schin /*
374887Schin * elimnates shell quoting as inserted with sh_fmtq
384887Schin * result relaces <string>
394887Schin * length of resulting string is returned.
404887Schin */
sh_unquote(char * string)414887Schin static int sh_unquote(char* string)
424887Schin {
434887Schin register char *sp=string, *dp;
444887Schin register int c;
454887Schin while((c= *sp) && c!='\'')
464887Schin sp++;
474887Schin if(c==0)
484887Schin return(sp-string);
494887Schin if((dp=sp) > string && sp[-1]=='$')
504887Schin {
514887Schin register int n=stresc(sp+1);
524887Schin /* copy all but trailing ' */
534887Schin while(--n>0)
544887Schin *dp++ = *++sp;
554887Schin }
564887Schin else
574887Schin {
584887Schin while((c= *++sp) && c!='\'')
594887Schin *dp++ = c;
604887Schin }
614887Schin *dp=0;
624887Schin return(dp-string);
634887Schin }
644887Schin
wordexp(const char * string,wordexp_t * wdarg,register int flags)654887Schin int wordexp(const char *string, wordexp_t *wdarg, register int flags)
664887Schin {
674887Schin register Sfio_t *iop;
684887Schin register char *cp=(char*)string;
694887Schin register int c,quoted=0,literal=0,ac=0;
704887Schin int offset;
714887Schin char *savebase,**av;
724887Schin if(offset=staktell())
734887Schin savebase = stakfreeze(0);
744887Schin if(flags&WRDE_REUSE)
754887Schin wordfree(wdarg);
764887Schin else if(!(flags&WRDE_APPEND))
774887Schin {
784887Schin wdarg->we_wordv = 0;
794887Schin wdarg->we_wordc = 0;
804887Schin }
814887Schin if(flags&WRDE_UNDEF)
824887Schin stakwrite("set -u\n",7);
834887Schin if(!(flags&WRDE_SHOWERR))
844887Schin stakwrite("exec 2> /dev/null\n",18);
854887Schin stakwrite("print -f \"%q\\n\" ",16);
864887Schin if(*cp=='#')
874887Schin stakputc('\\');
884887Schin while(c = *cp++)
894887Schin {
904887Schin if(c=='\'' && !quoted)
914887Schin literal = !literal;
924887Schin else if(!literal)
934887Schin {
944887Schin if(c=='\\' && (!quoted || strchr("\\\"`\n$",c)))
954887Schin {
964887Schin stakputc('\\');
974887Schin if(c= *cp)
984887Schin cp++;
994887Schin else
1004887Schin c = '\\';
1014887Schin }
1024887Schin else if(c=='"')
1034887Schin quoted = !quoted;
1044887Schin else if(c=='`' || (c=='$' && *cp=='('))
1054887Schin {
1064887Schin if(flags&WRDE_NOCMD)
1074887Schin {
1084887Schin c=WRDE_CMDSUB;
1094887Schin goto err;
1104887Schin }
1114887Schin /* only the shell can parse the rest */
1124887Schin stakputs(cp-1);
1134887Schin break;
1144887Schin }
1154887Schin else if(!quoted && strchr("|&\n;<>"+ac,c))
1164887Schin {
1174887Schin c=WRDE_BADCHAR;
1184887Schin goto err;
1194887Schin }
1204887Schin else if(c=='(') /* allow | and & inside pattern */
1214887Schin ac=2;
1224887Schin }
1234887Schin stakputc(c);
1244887Schin }
1254887Schin stakputc(0);
1264887Schin if(!(iop = sfpopen((Sfio_t*)0,stakptr(0),"r")))
1274887Schin {
1284887Schin c = WRDE_NOSHELL;
1294887Schin goto err;
1304887Schin }
1314887Schin stakseek(0);
1324887Schin ac = 0;
1334887Schin while((c=sfgetc(iop)) != EOF)
1344887Schin {
1354887Schin if(c=='\'')
1364887Schin quoted = ! quoted;
1374887Schin else if(!quoted && (c==' ' || c=='\n'))
1384887Schin {
1394887Schin ac++;
1404887Schin c = 0;
1414887Schin }
1424887Schin stakputc(c);
1434887Schin }
1444887Schin if(c=sfclose(iop))
1454887Schin {
1464887Schin if(c==3 || !(flags&WRDE_UNDEF))
1474887Schin c=WRDE_SYNTAX;
1484887Schin else
1494887Schin c=WRDE_BADVAL;
1504887Schin goto err;
1514887Schin }
1524887Schin c = ac+2;
1534887Schin if(flags&WRDE_DOOFFS)
1544887Schin c += wdarg->we_offs;
1554887Schin if(flags&WRDE_APPEND)
1564887Schin av = (char**)realloc((void*)&wdarg->we_wordv[-1], (wdarg->we_wordc+c)*sizeof(char*));
1574887Schin else if(av = (char**)malloc(c*sizeof(char*)))
1584887Schin {
1594887Schin if(flags&WRDE_DOOFFS)
1604887Schin memset((void*)av,0,(wdarg->we_offs+1)*sizeof(char*));
1614887Schin else
1624887Schin av[0] = 0;
1634887Schin }
1644887Schin if(!av)
1654887Schin return(WRDE_NOSPACE);
1664887Schin c = staktell();
1674887Schin if(!(cp = (char*)malloc(sizeof(char*)+c)))
1684887Schin {
1694887Schin c=WRDE_NOSPACE;
1704887Schin goto err;
1714887Schin }
1724887Schin ((struct list*)cp)->next = (struct list*)(*av);
1734887Schin *av++ = (char*)cp;
1744887Schin cp += sizeof(char*);
1754887Schin wdarg->we_wordv = av;
1764887Schin if(flags&WRDE_APPEND)
1774887Schin av += wdarg->we_wordc;
1784887Schin wdarg->we_wordc += ac;
1794887Schin if(flags&WRDE_DOOFFS)
1804887Schin av += wdarg->we_offs;
1814887Schin memcpy((void*)cp,stakptr(offset),c);
1824887Schin while(ac-- > 0)
1834887Schin {
1844887Schin *av++ = cp;
1854887Schin sh_unquote(cp);
1864887Schin while(c= *cp++);
1874887Schin }
1884887Schin *av = 0;
1894887Schin c=0;
1904887Schin err:
1914887Schin if(offset)
1924887Schin stakset(savebase,offset);
1934887Schin else
1944887Schin stakseek(0);
1954887Schin return(c);
1964887Schin }
1974887Schin
1984887Schin /*
1994887Schin * free fields in <wdarg>
2004887Schin */
wordfree(register wordexp_t * wdarg)2014887Schin int wordfree(register wordexp_t *wdarg)
2024887Schin {
2034887Schin struct list *arg, *argnext;
2044887Schin if(wdarg->we_wordv)
2054887Schin {
2064887Schin argnext = (struct list*)wdarg->we_wordv[-1];
2074887Schin while(arg=argnext)
2084887Schin {
2094887Schin argnext = arg->next;
2104887Schin free((void*)arg);
2114887Schin }
2124887Schin free((void*)&wdarg->we_wordv[-1]);
2134887Schin wdarg->we_wordv = 0;
2144887Schin }
2154887Schin wdarg->we_wordc=0;
2164887Schin return(0);
2174887Schin }
218