xref: /csrg-svn/local/toolchest/ksh/sh/expand.c (revision 35141)
1*35141Smarc /*
2*35141Smarc 
3*35141Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35141Smarc  *      All Rights Reserved
5*35141Smarc 
6*35141Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35141Smarc  *      CODE OF AT&T.
8*35141Smarc  *      The copyright notice above does not
9*35141Smarc  *      evidence any actual or intended
10*35141Smarc  *      publication of such source code.
11*35141Smarc 
12*35141Smarc  */
13*35141Smarc /* @(#)expand.c	1.1 */
14*35141Smarc /*
15*35141Smarc  *	UNIX shell
16*35141Smarc  *
17*35141Smarc  *	S. R. Bourne
18*35141Smarc  *	Rewritten by David Korn
19*35141Smarc  *	AT&T Bell Laboratories
20*35141Smarc  *
21*35141Smarc  */
22*35141Smarc 
23*35141Smarc #include	<sys/types.h>
24*35141Smarc #include	<sys/stat.h>
25*35141Smarc #include	<sys/dir.h>
26*35141Smarc #include	"defs.h"
27*35141Smarc #include	"brkincr.h"
28*35141Smarc #include	"stak.h"
29*35141Smarc #include	"sym.h"
30*35141Smarc #include	"shtype.h"
31*35141Smarc 
32*35141Smarc void	rm_files();
33*35141Smarc int	expand();
34*35141Smarc 
35*35141Smarc extern	STKPTR locstak(),endstak();
36*35141Smarc extern	FILE *fdopen();
37*35141Smarc extern	char *movstr();
38*35141Smarc extern	char *strrchr();
39*35141Smarc extern	void trim();
40*35141Smarc 
41*35141Smarc 
42*35141Smarc /* globals (file name generation)
43*35141Smarc  *
44*35141Smarc  * "*" in params matches r.e ".*"
45*35141Smarc  * "?" in params matches r.e. "."
46*35141Smarc  * "[...]" in params matches character class
47*35141Smarc  * "[...a-z...]" in params matches a through z.
48*35141Smarc  *
49*35141Smarc  */
50*35141Smarc 
51*35141Smarc static void	addg();
52*35141Smarc 
expand(as,rcnt)53*35141Smarc int expand(as,rcnt)
54*35141Smarc char *as;
55*35141Smarc {
56*35141Smarc 	int 	count;
57*35141Smarc #ifdef BSD_4_2
58*35141Smarc 	DIR 	*dirf;
59*35141Smarc #else
60*35141Smarc 	FILE 	*dirf;
61*35141Smarc #endif	/* BSD_4_2 */
62*35141Smarc 	BOOL 	nometa=0;
63*35141Smarc 	BOOL 	dir=0;
64*35141Smarc 	char *rescan = 0;
65*35141Smarc 	char *slashsav = 0;
66*35141Smarc 	register char *s, *cs;
67*35141Smarc 	int quote = 0;
68*35141Smarc 	int slash;
69*35141Smarc 	int add_slash = 1;	/* insert a separator slash */
70*35141Smarc 	char *sname;
71*35141Smarc 	ARGPTR 	schain = gchain;
72*35141Smarc 	/* this union forces enough space for the NULL byte */
73*35141Smarc 	union Dirent
74*35141Smarc 	{
75*35141Smarc 		struct direct	entry;
76*35141Smarc 		char entrybuf[sizeof(struct direct)+1]; /* room for null byte */
77*35141Smarc 	};
78*35141Smarc 	union Dirent dirent;
79*35141Smarc 	struct direct	*entry = &dirent.entry;
80*35141Smarc #ifndef BSD_4_2
81*35141Smarc 	char dirbuff[BUFSIZ];
82*35141Smarc #endif	/* BSD_4_2 */
83*35141Smarc 	if(trapnote&SIGSET)
84*35141Smarc 		return(0);
85*35141Smarc 	s=cs=as;
86*35141Smarc #ifndef BSD_4_2
87*35141Smarc 	entry->d_name[DIRSIZ]=0; /* to end the string */
88*35141Smarc #endif	/* BSD_4_2 */
89*35141Smarc 	/* check for meta chars */
90*35141Smarc 	{
91*35141Smarc 		register int open = 0;
92*35141Smarc 		slash=0;
93*35141Smarc 		do
94*35141Smarc 		{
95*35141Smarc 			switch(*cs++)
96*35141Smarc 			{
97*35141Smarc 				case 0:
98*35141Smarc 				{
99*35141Smarc 					nometa = '/';
100*35141Smarc 					if (rcnt && slash)
101*35141Smarc 						break;
102*35141Smarc 					else
103*35141Smarc 						return(0);
104*35141Smarc 				}
105*35141Smarc 
106*35141Smarc 				case '/':
107*35141Smarc 					slash++;
108*35141Smarc 					open = 0;
109*35141Smarc 					continue;
110*35141Smarc 
111*35141Smarc 				case '[':
112*35141Smarc 					open++;
113*35141Smarc 					continue;
114*35141Smarc 
115*35141Smarc 				case ']':
116*35141Smarc 					if(open)
117*35141Smarc 						break;
118*35141Smarc 					continue;
119*35141Smarc 
120*35141Smarc 				case '?':
121*35141Smarc 				case '*':
122*35141Smarc 					if(rcnt > slash)
123*35141Smarc 						continue;
124*35141Smarc 					cs--;
125*35141Smarc 					break;
126*35141Smarc 
127*35141Smarc 				case ESCAPE:
128*35141Smarc 					quote++;
129*35141Smarc 					cs++;
130*35141Smarc 				default:
131*35141Smarc 					continue;
132*35141Smarc 			}
133*35141Smarc 			break;
134*35141Smarc 		}
135*35141Smarc 		while(1);
136*35141Smarc 	}
137*35141Smarc 	while(1)
138*35141Smarc 	{
139*35141Smarc 		if(cs==s)
140*35141Smarc 		{
141*35141Smarc 			s=nullstr;
142*35141Smarc 			break;
143*35141Smarc 		}
144*35141Smarc 		else if(*--cs == '/')
145*35141Smarc 		{
146*35141Smarc 			*cs=nometa;
147*35141Smarc 			if(s==cs)
148*35141Smarc 			{
149*35141Smarc 				s= "/";
150*35141Smarc 				add_slash = 0;
151*35141Smarc 			}
152*35141Smarc 			break;
153*35141Smarc 		}
154*35141Smarc 	}
155*35141Smarc 	if(quote && s!=cs)
156*35141Smarc 	{
157*35141Smarc 		s = cpystak(s);
158*35141Smarc 		trim(s);
159*35141Smarc 	}
160*35141Smarc 	/* special case where there are no meta-chars left in path */
161*35141Smarc 	if(nometa)
162*35141Smarc 	{
163*35141Smarc 		/* read permission on directories not needed */
164*35141Smarc 		if(access(s,0)==0)
165*35141Smarc 		{
166*35141Smarc 			addg(s,nullstr,NIL,0);
167*35141Smarc 			return(1);
168*35141Smarc 		}
169*35141Smarc 		return(0);
170*35141Smarc 	}
171*35141Smarc 	sname = (*s?s:dot);
172*35141Smarc 	if(ftype(sname,S_IFMT,S_IFDIR)
173*35141Smarc #ifdef BSD_4_2
174*35141Smarc 		   && (dirf=opendir(sname))!=NULL)
175*35141Smarc #else
176*35141Smarc 		   && (dirf=fdopen(open(sname,0),"r"))!=NULL)
177*35141Smarc #endif	/* BSD_4_2 */
178*35141Smarc 	{
179*35141Smarc 		dir++;
180*35141Smarc #ifndef BSD_4_2
181*35141Smarc 		setbuf(dirf,dirbuff);
182*35141Smarc #endif
183*35141Smarc 	}
184*35141Smarc 	count=0;
185*35141Smarc 	if(*cs==0)
186*35141Smarc 		slashsav = cs++;
187*35141Smarc 	if(dir)
188*35141Smarc 		/* check for rescan */
189*35141Smarc 	{
190*35141Smarc 		register char *rs = cs;
191*35141Smarc 		do
192*35141Smarc 		{
193*35141Smarc 			if(*rs=='/')
194*35141Smarc 			{
195*35141Smarc 				rescan=rs;
196*35141Smarc 				*rs=0;
197*35141Smarc 				gchain=0;
198*35141Smarc 			}
199*35141Smarc 		}
200*35141Smarc 		while(*rs++);
201*35141Smarc #ifdef BSD_4_2
202*35141Smarc 		while((entry=readdir(dirf)) && (trapnote&SIGSET)==0)
203*35141Smarc #else
204*35141Smarc 		while(fread((char*)entry,sizeof(struct direct),1,dirf)==1 && (trapnote&SIGSET)==0)
205*35141Smarc #endif	/* BSD_4_2 */
206*35141Smarc 		{
207*35141Smarc 			if(entry->d_ino==0 || (*entry->d_name=='.' && *cs!='.'))
208*35141Smarc 				continue;
209*35141Smarc 
210*35141Smarc 			if(gmatch(entry->d_name, cs))
211*35141Smarc 			{
212*35141Smarc 				addg(s,entry->d_name,rescan,add_slash);
213*35141Smarc 				count++;
214*35141Smarc 			}
215*35141Smarc 		}
216*35141Smarc #ifdef BSD_4_2
217*35141Smarc 		closedir(dirf);
218*35141Smarc #else
219*35141Smarc 		closefd(dirf);
220*35141Smarc #endif	/* BSD_4_2 */
221*35141Smarc 		if(rescan)
222*35141Smarc 		{
223*35141Smarc 			register ARGPTR	rchain;
224*35141Smarc 			rchain=gchain; gchain=schain;
225*35141Smarc 			if(count)
226*35141Smarc 			{
227*35141Smarc 				count=0;
228*35141Smarc 				while(rchain)
229*35141Smarc 				{
230*35141Smarc 					count += expand(rchain->argval,slash+1);
231*35141Smarc 					rchain=rchain->argchn;
232*35141Smarc 				}
233*35141Smarc 			}
234*35141Smarc 			*rescan='/';
235*35141Smarc 		}
236*35141Smarc 	}
237*35141Smarc 	if(slashsav)
238*35141Smarc 		*slashsav = '/';
239*35141Smarc 	return(count);
240*35141Smarc }
241*35141Smarc 
addg(as1,as2,as3,add_slash)242*35141Smarc static  void addg(as1,as2,as3,add_slash)
243*35141Smarc char *as1, *as2, *as3;
244*35141Smarc int add_slash;
245*35141Smarc {
246*35141Smarc 	register char *s1, *s2;
247*35141Smarc 	register int 	c;
248*35141Smarc 	register ARGPTR argp = (ARGPTR)locstak();
249*35141Smarc 	argp->argflag &= ~(A_MAKE|A_RAW);
250*35141Smarc 	s2 = argp->argval;
251*35141Smarc 	s1=as1;
252*35141Smarc 	/* directory */
253*35141Smarc 	while(c = *s1)
254*35141Smarc 	{
255*35141Smarc 		s1++;
256*35141Smarc 		if(c == ESCAPE)
257*35141Smarc 			*s2++ = ESCAPE;
258*35141Smarc 		*s2++ = c;
259*35141Smarc 	}
260*35141Smarc 	if(add_slash && s1 > as1 && *as2)
261*35141Smarc 		*s2++='/';
262*35141Smarc 	s1=as2;
263*35141Smarc 	/* component */
264*35141Smarc 	while(c = *s1++)
265*35141Smarc 	{
266*35141Smarc 		/* escape the ESCAPE characters */
267*35141Smarc 		if(c == ESCAPE)
268*35141Smarc 			*s2++ = ESCAPE;
269*35141Smarc 		*s2++ = c;
270*35141Smarc 	}
271*35141Smarc 	/* rescan */
272*35141Smarc 	if(s1=as3)
273*35141Smarc 	{
274*35141Smarc 		*s2++='/';
275*35141Smarc 		while(*s2++ = *++s1);
276*35141Smarc 	}
277*35141Smarc 	if(is_option(MARKDIR))
278*35141Smarc 	{
279*35141Smarc 		*s2 = 0;
280*35141Smarc 		if(ftype(argp->argval,S_IFMT,S_IFDIR))
281*35141Smarc 			*s2++ = '/';
282*35141Smarc 	}
283*35141Smarc 	endstak(s2);
284*35141Smarc 	argp->argchn= gchain;
285*35141Smarc 	gchain = argp;
286*35141Smarc }
287*35141Smarc 
288*35141Smarc 
289*35141Smarc /*
290*35141Smarc  * remove tmp files
291*35141Smarc  * template of the form /tmp/sh$$.???
292*35141Smarc  */
293*35141Smarc 
rm_files(template)294*35141Smarc void	rm_files(template)
295*35141Smarc register char *template;
296*35141Smarc {
297*35141Smarc 	register char *cp;
298*35141Smarc 	ARGPTR schain;
299*35141Smarc 	cp = strrchr(template,'.');
300*35141Smarc 	*(cp+1) = 0;
301*35141Smarc 	f_complete(template,"*");
302*35141Smarc 	schain = gchain;
303*35141Smarc 	while(schain)
304*35141Smarc 	{
305*35141Smarc 		unlink(schain->argval);
306*35141Smarc 		schain = schain->argchn;
307*35141Smarc 	}
308*35141Smarc }
309*35141Smarc 
310*35141Smarc /*
311*35141Smarc  * file name completion
312*35141Smarc  * generate the list of files found by adding an suffix to end of name
313*35141Smarc  * The number of matches is returned
314*35141Smarc  */
315*35141Smarc 
f_complete(name,suffix)316*35141Smarc f_complete(name,suffix)
317*35141Smarc char *name;
318*35141Smarc register char *suffix;
319*35141Smarc {
320*35141Smarc 	register char *cp;
321*35141Smarc 	register char *dp;
322*35141Smarc 	gchain =  NULL;
323*35141Smarc 	dp = (char*)locstak();
324*35141Smarc 	cp = movstr(name,dp);
325*35141Smarc 	if(suffix)
326*35141Smarc 		cp =  movstr(suffix,cp);
327*35141Smarc 	endstak(cp);
328*35141Smarc 	return(expand(dp,0));
329*35141Smarc }
330