14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 */ 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 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 */ 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