xref: /onnv-gate/usr/src/lib/libast/common/comp/wordexp.c (revision 12068:08a39a083754)
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