1 /*
2  * Copyright (c) 1995 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation for any purpose, without fee, and without written agreement is
7  * hereby granted, provided that the above copyright notice and the following
8  * two paragraphs appear in all copies of this software.
9  *
10  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
11  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
12  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
13  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
18  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
19  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
20  */
21 
22 /*
23  *  $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/file.c,v 1.2 1993/06/30 20:06:09 keving Exp $
24  *  $Log: file.c,v $
25  * Revision 1.2  1993/06/30  20:06:09  keving
26  * nothing
27  *
28  * Revision 1.1  1993/06/03  21:08:08  keving
29  * nothing
30  *
31  */
32 
33 #include "tk.h"
34 
35 #include "all.h"
36 
37 #include <sys/file.h>
38 #include <sys/stat.h>
39 #include <sys/param.h>
40 #include <time.h>
41 #include <string.h>
42 #include <dirent.h>
43 #include <strings.h>
44 
45 #define MAX_FILES   1000
46 #define MAX_NAME_LEN	256
47 #define MAX_STRING_LEN	MAX_NAME_LEN
48 
49 typedef int boolean;
50 #define TRUE 1
51 #define FALSE 0
52 
53 extern char currentPath[MAXPATHLEN];
54 
55 char	globString[1024];
56 
57 static DIR *dfd;
58 
59 void	ResetPath(void);
60 int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
61 		  char **argv);
62 int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
63 		  char **argv);
64 void	SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN],
65 		  boolean *dirList, int permute[]);
66 
67 static void	UpdatePath(Tcl_Interp *interp, char *directory);
68 static boolean	MatchesGlob(char *string, char *glob);
69 
70 
71 
ResetPath()72 void	ResetPath()
73 {
74     if ( getwd(currentPath) == 0 )
75     {
76 	fprintf(stderr, "Error getting pathname!!!\n");
77 	exit(1);
78     }
79 
80     strcpy(&currentPath[strlen(currentPath)], "/");
81 
82     dfd = opendir(currentPath);
83     if ( dfd == NULL )
84     {
85 	fprintf(stderr, "can't open '%s'\n", currentPath);
86 	exit(1);
87     }
88 }
89 
90 
UpdatePath(Tcl_Interp * interp,char * directory)91 static void	UpdatePath(Tcl_Interp *interp, char *directory)
92 {
93     int length;
94     char *charPtr;
95 
96     length = strlen(currentPath);
97 
98     if ( strcmp(directory, "./") == 0 )
99 	return /* nothing */ ;
100     else if ( strcmp(directory, "../") == 0 )
101     {
102 	/* delete backwards up to '/' */
103 
104 	if ( length < 2 )
105 	{
106 	    fprintf(stderr, "Error:  backing up from root directory!!!\n");
107 	    exit(1);
108 	}
109 
110 	charPtr = &currentPath[length-2];
111 	while ( (charPtr != currentPath) && (*charPtr != '/') )
112 	    charPtr--;
113 	charPtr++;	/* leave the '/' */
114 	*charPtr = '\0';
115     }
116     else
117     {
118 	strcpy(&currentPath[length], directory);
119     }
120 }
121 
122 
ChangeDirectory(ClientData nulldata,Tcl_Interp * interp,int argc,char ** argv)123 int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
124 		  char **argv)
125 {
126     char *directory = argv[1];
127 
128     UpdatePath(interp, directory);
129 
130     fprintf(stdout, "Opening directory: '%s'\n", currentPath);
131 
132     dfd = opendir(currentPath);
133     if ( dfd == NULL )
134     {
135 	fprintf(stderr, "can't open '%s'\n", currentPath);
136 	return TCL_OK;	/* shouldn't, really */
137     }
138 
139     return TCL_OK;
140 }
141 
142 
ListDirectory(ClientData nulldata,Tcl_Interp * interp,int argc,char ** argv)143 int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
144 		  char **argv)
145 {
146     struct dirent *dp;
147     struct stat stbuf;
148     char command[256];
149     char fileName[MAX_FILES][MAX_NAME_LEN];
150     boolean dirList[MAX_FILES];
151     int permute[MAX_FILES];
152     int	fileCount = 0;
153     register int index;
154     char fullName[MAXPATHLEN];
155     char    *restPtr;
156 
157     sprintf(command, "ShowCurrentDirectory %s", currentPath);
158     Tcl_Eval(interp, command, 0, (char **) NULL);
159 
160     if ( dfd == NULL )
161     {
162 	fprintf(stderr, "TRIED TO LIST NULL DIRECTORY\n");
163 
164 	return TCL_OK;
165     }
166 
167 /* check if root directory */
168     if ( strlen(currentPath) != 1 )
169     {
170 	sprintf(fileName[fileCount], "../");
171 	dirList[fileCount] = TRUE;
172 	fileCount++;
173     }
174 
175     strcpy(fullName, currentPath);
176     restPtr = &fullName[strlen(fullName)];
177 
178     while ( (dp = readdir(dfd)) != NULL )
179     {
180 	strcpy(restPtr, dp->d_name);
181 	stat(fullName, &stbuf);
182 
183 	if ( dp->d_name[0] != '.' )
184 	{
185 	    if ( S_ISDIR(stbuf.st_mode) )
186 	    {
187 		sprintf(fileName[fileCount], "%s/", dp->d_name);
188 		dirList[fileCount] = TRUE;
189 		fileCount++;
190 	    }
191 	    else
192 	    {
193 		if ( MatchesGlob(dp->d_name, globString) )
194 		{
195 		    strcpy(fileName[fileCount], dp->d_name);
196 		    dirList[fileCount] = FALSE;
197 		    fileCount++;
198 		}
199 	    }
200 	}
201     }
202 
203     SortFiles(fileCount, fileName, dirList, permute);
204 
205     for ( index = 0; index < fileCount; index++ )
206     {
207 	sprintf(command, "AddBrowseFile %s", fileName[permute[index]]);
208 	Tcl_Eval(interp, command, 0, (char **) NULL);
209     }
210 
211     closedir(dfd);
212 
213     return TCL_OK;
214 }
215 
216 
SortFiles(int numStrings,char strings[MAX_FILES][MAX_NAME_LEN],boolean * dirList,int permute[])217 void	SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN],
218 		  boolean *dirList, int permute[])
219 {
220     register int i, j;
221     int temp;
222     int	numDirs;
223     int	ptr;
224 
225     for ( i = 0; i < numStrings; i++ )
226 	permute[i] = i;
227 
228     /* put all directories at front */
229     numDirs = 0;
230     ptr = numStrings-1;
231     while ( numDirs != ptr )
232     {
233 	/* go past dirs */
234 	while ( (numDirs < ptr) && (dirList[permute[numDirs]]) )
235 	    numDirs++;
236 
237 	/* go past non-dirs */
238 	while ( (numDirs < ptr) && (! dirList[permute[ptr]]) )
239 	    ptr--;
240 
241 	if ( numDirs != ptr )
242 	{
243 	    temp = permute[numDirs];
244 	    permute[numDirs] = ptr;
245 	    permute[ptr] = temp;
246 	}
247     }
248 
249     if ( dirList[permute[numDirs]] )
250 	numDirs++;
251 
252     for ( i = 0; i < numDirs; i++ )
253 	for ( j = i+1; j < numDirs; j++ )
254 	{
255 	    if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 )
256 	    {
257 		temp = permute[j];
258 		permute[j] = permute[i];
259 		permute[i] = temp;
260 	    }
261 	}
262 
263     for ( i = numDirs; i < numStrings; i++ )
264 	for ( j = i+1; j < numStrings; j++ )
265 	{
266 	    if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 )
267 	    {
268 		temp = permute[j];
269 		permute[j] = permute[i];
270 		permute[i] = temp;
271 	    }
272 	}
273 }
274 
275 
SetBrowseGlob(ClientData nulldata,Tcl_Interp * interp,int argc,char ** argv)276 int SetBrowseGlob (ClientData nulldata, Tcl_Interp *interp,
277 		   int argc, char **argv)
278 {
279     if (argc == 2 )
280     {
281 	strcpy(globString, argv[1]);
282 
283 	fprintf(stdout, "GLOB:  %s\n", globString);
284 
285 	return TCL_OK;
286     }
287 
288 	Tcl_AppendResult (interp,
289             "wrong args: should be \"", argv[0]," string\"", (char *) NULL);
290 	return TCL_ERROR;
291 }
292 
293 
MatchesGlob(char * string,char * glob)294 static boolean	MatchesGlob(char *string, char *glob)
295 {
296     char    *stringRight, *globRight;
297 
298     while ( (*glob != '\0') && (*glob != '*') )	    /* match left side */
299     {
300 	if ( (*string == '\0') || (*string != *glob) )
301 	    return FALSE;
302 	string++;
303 	glob++;
304     }
305 
306     if ( *glob == '\0' )	/* no star */
307 	return TRUE;
308 
309     /* now match right side */
310     stringRight = &string[strlen(string)-1];
311     globRight = &glob[strlen(glob)-1];
312 
313     while ( *globRight != '*' )
314     {
315 	if ( (stringRight < string) || (*stringRight != *globRight) )
316 	    return FALSE;
317 	globRight--;
318 	stringRight--;
319     }
320 
321     return TRUE;
322 }
323