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