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