1 /* $Header: /home/yav/catty/fkiss/RCS/dir.c,v 1.14 2000/09/02 03:23:52 yav Exp $
2  * Simple directory access routine
3  * written by yav <yav@bigfoot.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * #define USE_BSD_DIRLIB 1
20  *  use opendir, readdir and closedir library routines.
21  * #define USE_BSD_DIRLIB 0
22  *  use popen to execute "ls -af".
23  *
24  * #define DIR_STANDALONE_TEST
25  * for self checking
26  *
27  */
28 
29 char id_dir[] = "$Id: dir.c,v 1.14 2000/09/02 03:23:52 yav Exp $";
30 
31 #include <stdio.h>
32 
33 #ifdef DIR_STANDALONE_TEST
34 # include "config.h"
35 #else
36 # include <X11/Xlib.h>
37 # include "config.h"
38 # include "headers.h"
39 # include "fkiss.h"
40 # define PUBLIC_DIR_C
41 # include "extern.h"
42 #endif
43 
44 #if HAVE_DIRENT_H
45 # include <dirent.h>
46 # define NAMLEN(dirent) strlen((dirent)->d_name)
47 #else
48 # define dirent direct
49 # define NAMLEN(dirent) (dirent)->d_namlen
50 # if HAVE_SYS_NDIR_H
51 #  include <sys/ndir.h>
52 # endif
53 # if HAVE_SYS_DIR_H
54 #  include <sys/dir.h>
55 # endif
56 # if HAVE_NDIR_H
57 #  include <ndir.h>
58 # endif
59 #endif
60 
61 
62 #if HAVE_SYS_STAT_H
63 # include <sys/stat.h>
64 #else
65 # if HAVE_STAT_H
66 #  include <stat.h>
67 # endif
68 #endif
69 
70 #ifdef DIR_STANDALONE_TEST
71 #define ks_malloc malloc
72 #define ks_realloc realloc
73 #define ks_strdup strdup
74 extern char *malloc();
75 extern char *realloc();
76 extern void free();
77 extern char *strdup();
78 extern char *strncpy();
79 #endif
80 
81 #ifndef USE_BSD_DIRLIB
82 #warning USE_BSD_DIRLIB not defined!
83 #define USE_BSD_DIRLIB 0
84 #endif
85 
86 #if !USE_BSD_DIRLIB
87 # ifndef MAXPATH
88 #  ifdef MAXPATHLEN
89 #   define MAXPATH MAXPATHLEN
90 #  else
91 #   define MAXPATH 1024
92 #  endif
93 # endif
94 #endif
95 
96 /* free all allocated filename list */
dir_free(list)97 void dir_free(list)
98      char **list;
99 {
100   char **p;
101 
102   if (list != NULL) {
103     for (p = list; *p != NULL; p++)
104       free(*p);
105     free(list);
106   }
107 }
108 
109 /* dir_ls - get filename list in directory
110  * return filename pointer list (NULL : directory open error)
111  */
dir_ls(path,func)112 char **dir_ls(path, func)
113      char *path;		/* directory */
114      int (*func)();		/* filename matching function (NULL:all) */
115 {
116   int r;
117   int i;
118   char **list;
119 #if USE_BSD_DIRLIB
120   DIR *dp;
121   struct dirent *p;
122 #else
123   FILE *fp;
124 #endif
125   char *buf;
126   char *subdir;
127   struct stat st;
128   char **sublist, **sublist0;
129   char *ss;
130 
131   r = 0;
132   list = NULL;
133 #if USE_BSD_DIRLIB
134   if ((dp = opendir(path)) != NULL) {
135     list = (char **)ks_malloc(sizeof(char *));
136     while ((p = readdir(dp)) != NULL) {
137       i = NAMLEN(p);
138       buf = ks_malloc(i + 1);
139       strncpy(buf, p->d_name, i);
140       buf[i] = '\0';
141       subdir = ks_malloc(strlen(path) + 1 + strlen(buf) + 1);
142       sprintf(subdir, "%s/%s", path, buf);
143       if (strcmp(buf, ".") && strcmp(buf, "..") &&
144 	  stat(subdir, &st) == 0 && (st.st_mode & S_IFDIR)) {
145 	sublist0 = sublist = dir_ls(subdir, func);
146 	if (sublist0 != NULL) {
147 	  while (*sublist) {
148 	    ss = ks_malloc(strlen(buf) + 1 + strlen(*sublist) + 1);
149 	    sprintf(ss, "%s/%s", buf, *sublist);
150 	    *(list+r++) = ss;
151 	    list = (char **)ks_realloc(list, sizeof(char *) * (r+1));
152 	    sublist++;
153 	  }
154 	  dir_free(sublist0);
155 	}
156 	free(buf);
157       } else {
158 	if (func == NULL || (*func)(buf)) {
159 	  *(list+r++) = buf;
160 	  list = (char **)ks_realloc(list, sizeof(char *) * (r+1));
161 	} else {
162 	  free(buf);
163 	}
164       }
165       buf = NULL;
166     }
167     *(list+r) = NULL;
168     closedir(dp);
169   }
170 #else /* USE_BSD_DIRLIB */
171   buf = ks_malloc(7 + strlen(path) + 1);
172   sprintf(buf, "ls -af %s", path);
173   if ((fp = popen(buf, "r")) != NULL) {
174     list = (char **)ks_malloc(sizeof(char *));
175     buf = ks_realloc(buf, MAXPATH);
176     while (fgets(buf, MAXPATH, fp) != NULL) {
177       i = strlen(buf) - 1;
178       if (i >= 0 && buf[i] == '\n')
179 	buf[i] = '\0';		/* cut '\n' */
180       subdir = ks_malloc(strlen(path) + 1 + strlen(buf) + 1);
181       sprintf(subdir, "%s/%s", path, buf);
182       if (strcmp(buf, ".") && strcmp(buf, "..") &&
183 	  stat(subdir, &st) == 0 && (st.st_mode & S_IFDIR)) {
184 	sublist0 = sublist = dir_ls(subdir, func);
185 	if (sublist0 != NULL) {
186 	  while (*sublist) {
187 	    ss = ks_malloc(strlen(buf) + 1 + strlen(*sublist) + 1);
188 	    sprintf(ss, "%s/%s", buf, *sublist);
189 	    *(list+r++) = ss;
190 	    list = (char **)ks_realloc(list, sizeof(char *) * (r+1));
191 	    sublist++;
192 	  }
193 	  dir_free(sublist0);
194 	}
195       } else {
196 	if (func == NULL || (*func)(buf)) {
197 	  *(list+r++) = ks_strdup(buf);
198 	  list = (char **)ks_realloc(list, sizeof(char *) * (r+1));
199 	}
200       }
201     }
202     free(buf);
203     *(list+r) = NULL;
204     pclose(fp);
205   }
206 #endif /* USE_BSD_DIRLIB */
207   return list;
208 }
209 
210 #ifdef DIR_STANDALONE_TEST
211 
cmpfunc(char * name)212 int cmpfunc(char *name)
213 {
214 #if 0
215   return (*name == 'f');
216 #else
217   return 1;
218 #endif
219 }
220 
main(argc,argv)221 int main(argc, argv)
222      int argc;
223      char **argv;
224 {
225   int i;
226   char **buf;
227 
228   if (argc < 2)
229     exit(1);
230 #if USE_BSD_DIRLIB
231   printf("* dir lib *\n");
232 #else
233   printf("* dir ls  *\n");
234 #endif
235   buf = dir_ls(*++argv, cmpfunc);
236   if (buf == NULL) {
237     fprintf(stderr, "``%s'' read error!\n", *argv);
238     exit(1);
239   }
240   for (i = 0; *(buf+i) != NULL; i++) {
241     printf("[%s]\n", *(buf+i));
242   }
243   dir_free(buf);
244   printf("Total %d files\n", i);
245   return 0;
246 }
247 
248 #endif /* DIR_STANDALONE_TEST */
249 
250 /* End of file */
251