1 /*
2 * Copyright (C) 1999 Sasha Vasko <sasha at aftercode.net>
3 * merged with envvar.c originally created by :
4 * Copyright (C) 1999 Ethan Fischer <allanon@crystaltokyo.com>
5 * Copyright (C) 1998 Pierre Clerissi <pierre.clerissi@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 #undef LOCAL_DEBUG
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stddef.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <sys/stat.h>
33 #include <limits.h>
34
35 #if HAVE_DIRENT_H
36 # include <dirent.h>
37 # define NAMLEN(dirent) strlen((dirent)->d_name)
38 #else
39 # if HAVE_SYS_DIRENT_H
40 # include <sys/dirent.h>
41 # define NAMLEN(dirent) strlen((dirent)->d_name)
42 # else
43 # define dirent direct
44 # define NAMLEN(dirent) (dirent)->d_namlen
45 # if HAVE_SYS_NDIR_H
46 # include <sys/ndir.h>
47 # endif
48 # if HAVE_SYS_DIR_H
49 # include <sys/dir.h>
50 # endif
51 # if HAVE_NDIR_H
52 # include <ndir.h>
53 # endif
54 # endif
55 #endif
56
57 /* Even if limits.h is included, allow PATH_MAX to sun unices */
58 #ifndef PATH_MAX
59 #define PATH_MAX 255
60 #endif
61
62
63 #include "astypes.h"
64 #include "mystring.h"
65 #include "safemalloc.h"
66 #include "fs.h"
67 #include "output.h"
68 #include "audit.h"
69
70
71 /*
72 * get the date stamp on a file
73 */
get_file_modified_time(const char * filename)74 time_t get_file_modified_time (const char *filename)
75 {
76 struct stat st;
77 time_t stamp = 0;
78
79 if (stat (filename, &st) != -1)
80 stamp = st.st_mtime;
81 return stamp;
82 }
83
84 int
check_file_mode(const char * file,int mode)85 check_file_mode (const char *file, int mode)
86 {
87 struct stat st;
88
89 if ((stat (file, &st) == -1) || (st.st_mode & S_IFMT) != mode)
90 return (-1);
91 else
92 return (0);
93 }
94
95 /* copy file1 into file2 */
96 int
copy_file(const char * realfilename1,const char * realfilename2)97 copy_file (const char *realfilename1, const char *realfilename2)
98 {
99 FILE *targetfile, *sourcefile;
100 int c;
101
102 #ifdef __CYGWIN__
103 targetfile = fopen (realfilename2, "wb");
104 #else
105 targetfile = fopen (realfilename2, "w");
106 #endif
107 if (targetfile == NULL)
108 {
109 fprintf (stderr, "can't open %s !\n", realfilename2);
110 return (-1);
111 }
112 #ifdef __CYGWIN__
113 sourcefile = fopen (realfilename1, "rb");
114 #else
115 sourcefile = fopen (realfilename1, "r");
116 #endif
117 if (sourcefile == NULL)
118 {
119 fprintf (stderr, "can't open %s !\n", realfilename1);
120 fclose (targetfile);
121 return (-2);
122 }
123 while ((c = getc (sourcefile)) != EOF)
124 putc (c, targetfile);
125
126 fclose (targetfile);
127 fclose (sourcefile);
128 return 0;
129 }
130
131 char*
load_binary_file(const char * realfilename,long * file_size_return)132 load_binary_file(const char* realfilename, long *file_size_return)
133 {
134 struct stat st;
135 FILE* fp;
136 char* data = NULL ;
137
138 /* Get the file size. */
139 if (stat(realfilename, &st)) return NULL;
140 /* Open the file. */
141 fp = fopen(realfilename, "rb");
142 if ( fp != NULL )
143 {
144 long len ;
145 /* Read in the file. */
146 data = safemalloc(st.st_size + 1);
147 len = fread(data, 1, st.st_size, fp);
148 if( file_size_return )
149 *file_size_return = len ;
150 fclose(fp);
151 }
152 return data;
153 }
154
155 char*
load_file(const char * realfilename)156 load_file(const char* realfilename)
157 {
158 long len;
159 char* str = load_binary_file( realfilename, &len );
160
161 if (str != NULL && len >= 0)
162 str[len] = '\0';
163
164 return str;
165 }
166
167 void
parse_file_name(const char * filename,char ** path,char ** file)168 parse_file_name(const char *filename, char **path, char **file)
169 {
170 register int i = 0 ;
171 register char *ptr = (char*)filename;
172 int len = 0 ;
173 while( ptr[i] ) ++i ;
174 len = i ;
175 while( --i >= 0 )
176 if( ptr[i] == '/' )
177 break;
178 ++i ;
179 if( path )
180 *path = mystrndup(ptr, i);
181 if( file )
182 *file = mystrndup(&(ptr[i]), len-i);
183 }
184
185 char *
add_file_extension(const char * file,const char * ext)186 add_file_extension (const char *file, const char *ext)
187 {
188 char *res;
189 int fname_len;
190 if (file == NULL)
191 return NULL;
192 if (ext == NULL)
193 return mystrdup (file);
194 fname_len = strlen(file);
195 res = safemalloc (fname_len+1+strlen(ext) + 1);
196 strcpy (res, file);
197 res[fname_len] = '.';
198 strcpy (&res[fname_len+1], ext);
199 return res;
200 }
201
202 char *
make_file_name(const char * path,const char * file)203 make_file_name (const char *path, const char *file)
204 {
205 register int i = 0;
206 register char *ptr;
207 char *filename;
208 int len;
209
210 if( file == NULL )
211 {
212 if( path == NULL )
213 return NULL;
214 return mystrdup(path);
215 }else if( path == NULL )
216 return mystrdup(file);
217 /* getting length */
218 for (ptr = (char *)path; ptr[i]; i++);
219 len = i+1;
220 ptr = (char *)file ;
221 for ( i = 0; ptr[i]; i++);
222 len += i+1;
223 ptr = filename = safemalloc (len);
224 /* copying path */
225 for (i = 0; path[i]; i++)
226 ptr[i] = path[i];
227 /* copying filename */
228 ptr[i] = '/';
229 ptr += i+1 ;
230 for (i = 0; file[i]; i++)
231 ptr[i] = file[i];
232 ptr[i] = '\0'; /* zero byte */
233
234 return filename;
235 }
236
237 char *
put_file_home(const char * path_with_home)238 put_file_home (const char *path_with_home)
239 {
240 static char *home = NULL; /* the HOME environment variable */
241 static char default_home[3] = "./";
242 static int home_len = 0;
243 char *str = NULL, *ptr;
244 register int i;
245 if (path_with_home == NULL)
246 return NULL;
247 /* home dir ? */
248 if ( strncmp( path_with_home, "$HOME/", 6 ) == 0 )
249 path_with_home += 5 ;
250 else if (path_with_home[0] == '~' && path_with_home[1] == '/')
251 path_with_home += 1 ;
252 else
253 return mystrdup(path_with_home);
254
255 if (home == NULL)
256 {
257 if ((home = getenv ("HOME")) == NULL)
258 home = &(default_home[0]);
259 home_len = strlen (home);
260 }
261
262 for (i = 0; path_with_home[i]; i++);
263 str = safemalloc (home_len + i + 1);
264 for (ptr = str + home_len; i >= 0; i--)
265 ptr[i] = path_with_home[i];
266 for (i = 0; i < home_len; i++)
267 str[i] = home[i];
268 return str;
269 }
270
271
272 /****************************************************************************
273 *
274 * Find the specified icon file somewhere along the given path.
275 *
276 * There is a possible race condition here: We check the file and later
277 * do something with it. By then, the file might not be accessible.
278 * Oh well.
279 *
280 ****************************************************************************/
281 /* supposedly pathlist should not include any environment variables
282 including things like ~/
283 */
284
285 char *
find_file(const char * file,const char * pathlist,int type)286 find_file (const char *file, const char *pathlist, int type)
287 {
288 char *path;
289 register int len;
290 int max_path = 0;
291 register char *ptr;
292 register int i;
293 Bool local = False ;
294 LOCAL_DEBUG_CALLER_OUT( "file \"%s\", pathlist = \"%s\"", file, pathlist );
295 if (file == NULL)
296 return NULL;
297
298 if (*file == '/' || *file == '~' || ((pathlist == NULL) || (*pathlist == '\0')))
299 local = True ;
300 else if( file[0] == '.' && (file[1] == '/' || (file[1] == '.' && file[2] == '/')))
301 local = True ;
302 else if( strncmp( file, "$HOME", 5) == 0 )
303 local = True ;
304 if( local )
305 {
306 path = put_file_home (file);
307 if ( access (path, type) == 0 )
308 {
309 return path;
310 }
311 free (path);
312 return NULL;
313 }
314 /* return put_file_home(file); */
315 for (i = 0; file[i]; ++i);
316 len = i ;
317 for (ptr = (char *)pathlist; *ptr; ptr += i)
318 {
319 if (*ptr == ':')
320 ptr++;
321 for (i = 0; ptr[i] && ptr[i] != ':'; i++);
322 if (i > max_path)
323 max_path = i;
324 }
325
326 path = safecalloc (1, max_path + 1 + len + 1);
327 strcpy( path+max_path+1, file );
328 path[max_path] = '/' ;
329
330 ptr = (char*)&(pathlist[0]) ;
331 while( ptr[0] != '\0' )
332 {
333 int skip ;
334 for( i = 0 ; ptr[i] == ':' ; ++i );
335 ptr += i ;
336 for( i = 0 ; ptr[i] != ':' && ptr[i] != '\0' ; ++i );
337 skip = i ;
338 if( i > 0 && ptr[i-1] == '/' )
339 i-- ;
340 if( i > 0 )
341 {
342 register char *try_path = path+max_path-i;
343 strncpy( try_path, ptr, i );
344 LOCAL_DEBUG_OUT( "errno = %d, file %s: checking path \"%s\"", errno, file, try_path );
345 if ( access(try_path, type) == 0 )
346 {
347 char* res = mystrdup(try_path);
348 free( path );
349 LOCAL_DEBUG_OUT( " found at: \"%s\"", res );
350 return res;
351 }
352 #ifdef LOCAL_DEBUG
353 else
354 show_system_error(" looking for file %s:", file );
355 #endif
356 }
357 ptr += skip ;
358 }
359 free (path);
360 return NULL;
361 }
362
363 static char *default_kdegnome_dir = "/usr" ;
364 static char *default_kdehome_dir = "~/.kde" ;
365
366 static char *
find_envvar(char * var_start,int * end_pos)367 find_envvar (char *var_start, int *end_pos)
368 {
369 register int i;
370 static char tmp[256];
371 char *result ;
372
373 if (var_start[0] == '{')
374 {
375 for (i = 1; var_start[i] && var_start[i] != '}' && i < 255; i++)
376 tmp[i-1] = var_start[i] ;
377 tmp[i-1] = '\0' ;
378 } else
379 {
380 for (i = 0; (isalnum ((int)var_start[i]) || var_start[i] == '_') && i < 255; i++)
381 tmp[i] = var_start[i] ;
382 tmp[i] = '\0';
383 }
384 *end_pos = i;
385 if (var_start[i] == '}')
386 (*end_pos)++;
387
388 result = getenv (tmp);
389 if( result == NULL )
390 {
391 if( strcmp( tmp, "KDEDIR" ) == 0 || strcmp( tmp, "GNOMEDIR" ) == 0 )
392 result = default_kdegnome_dir ;
393 else if( strcmp( tmp, "KDEHOME" ) == 0 )
394 result = default_kdehome_dir ;
395 }
396 return result;
397 }
398
399 static char *
do_replace_envvar(const char * path)400 do_replace_envvar (const char *path)
401 {
402 char *data = (char*)path, *tmp;
403 char *home = getenv ("HOME");
404 int pos = 0, len, home_len = 0;
405
406 if (path == NULL)
407 return NULL;
408 if (*path == '\0')
409 return (char*)path;
410 len = strlen (path);
411 if (home)
412 home_len = strlen (home);
413
414 while (*(data + pos))
415 {
416 char *var;
417 int var_len, end_pos;
418
419 while (*(data + pos) != '$' && *(data + pos))
420 {
421 if (*(data + pos) == '~' && *(data + pos + 1) == '/')
422 {
423 if (pos > 0)
424 if (*(data + pos - 1) != ':')
425 {
426 pos += 2;
427 continue;
428 }
429 if (home == NULL)
430 *(data + (pos++)) = '.';
431 else
432 {
433 len += home_len;
434 tmp = safemalloc (len);
435 strncpy (tmp, data, pos);
436 strcpy (tmp + pos, home);
437 strcpy (tmp + pos + home_len, data + pos + 1);
438 if( data != path )
439 free (data);
440 data = tmp;
441 pos += home_len;
442 }
443 }
444 pos++;
445 }
446 if (*(data + pos) == '\0')
447 break;
448 /* found $ sign - trying to replace var */
449 if ((var = find_envvar (data + pos + 1, &end_pos)) == NULL)
450 {
451 ++pos;
452 continue;
453 }
454 var_len = strlen (var);
455 len += var_len;
456 tmp = safemalloc (len);
457 strncpy (tmp, data, pos);
458 strcpy (tmp + pos, var);
459 strcpy (tmp + pos + var_len, data + pos + end_pos + 1);
460 if( data != path )
461 free (data);
462 data = tmp;
463 }
464 return data;
465 }
466
467 void
replace_envvar(char ** path)468 replace_envvar (char **path)
469 {
470 char *res = do_replace_envvar( *path );
471 if( res != *path )
472 {
473 free( *path );
474 *path = res ;
475 }
476 }
477
478 char*
copy_replace_envvar(const char * path)479 copy_replace_envvar (const char *path)
480 {
481 char *res = do_replace_envvar( path );
482 return ( res == path )?mystrdup( res ):res;
483 }
484
485 /*
486 * only checks first word in name, to allow full command lines with
487 * options to be passed
488 */
489 int
get_executable_in_path(const char * name,char ** fullname_return)490 get_executable_in_path (const char *name, char **fullname_return)
491 {
492 static char *cache = NULL;
493 static char *cache_path = NULL;
494 static int cache_result = 0, cache_len = 0, cache_size = 0;
495 static char *env_path = NULL;
496 static int max_path = 0;
497 register int i;
498
499 if (name == NULL)
500 {
501 if (cache)
502 {
503 free (cache);
504 cache = NULL;
505 }
506 if (cache_path)
507 {
508 free (cache_path);
509 cache_path = NULL;
510 }
511 cache_size = 0;
512 cache_len = 0;
513 if (env_path)
514 {
515 free (env_path);
516 env_path = NULL;
517 }
518 max_path = 0;
519 return 0;
520 }
521
522 /* cut leading "exec" enclosed in spaces */
523 for (; isspace ((int)*name); name++);
524 if (!mystrncasecmp(name, "exec", 4) && isspace ((int)name[4]))
525 name += 4;
526 for (; isspace ((int)*name); name++);
527 if (*name == '\0')
528 return 0;
529
530 for (i = 0; name[i] && !isspace ((int)name[i]); i++);
531 if (i == 0)
532 return 0;
533
534 if (cache)
535 if (i == cache_len && strncmp (cache, name, i) == 0)
536 {
537 if (cache_result && fullname_return)
538 *fullname_return = mystrdup(cache_path);
539 return cache_result;
540 }
541
542 if (i > cache_size)
543 {
544 if (cache)
545 free (cache);
546 /* allocating slightly more space then needed to avoid
547 too many reallocations */
548 cache = (char *)safemalloc (i + (i >> 1) + 1);
549 cache_size = i + (i >> 1);
550 }
551 strncpy (cache, name, i);
552 cache[i] = '\0';
553 cache_len = i;
554 if (cache_path)
555 {
556 free(cache_path);
557 cache_path = NULL;
558 }
559
560 if (*cache == '/')
561 {
562 cache_result = (CheckFile (cache) == 0) ? 1 : 0;
563 cache_path = mystrdup (cache);
564 }else
565 {
566 char *ptr, *path;
567 struct stat st;
568
569 if (env_path == NULL)
570 {
571 env_path = mystrdup (getenv ("PATH"));
572 replace_envvar (&env_path);
573 for (ptr = env_path; *ptr; ptr += i)
574 {
575 if (*ptr == ':')
576 ptr++;
577 for (i = 0; ptr[i] && ptr[i] != ':'; i++);
578 if (i > max_path)
579 max_path = i;
580 }
581 }
582 path = safemalloc (max_path + cache_len + 2);
583 cache_result = 0;
584 for (ptr = env_path; *ptr ; ptr += i)
585 {
586 if (*ptr == ':')
587 ptr++;
588 for (i = 0; ptr[i] && ptr[i] != ':'; i++)
589 path[i] = ptr[i];
590 path[i] = '/';
591 path[i + 1] = '\0';
592 strcat (path, cache);
593 if ((stat (path, &st) != -1) && (st.st_mode & S_IXUSR))
594 {
595 cache_result = 1;
596 cache_path = path;
597 path = NULL;
598 break;
599 }
600 LOCAL_DEBUG_OUT( "%s found \"%s\"", path, cache_result?"":"not" );
601 }
602 if (path)
603 free (path);
604 }
605
606 if (cache_result && fullname_return)
607 *fullname_return = mystrdup(cache_path);
608 return cache_result;
609 }
610
611 int
is_executable_in_path(const char * name)612 is_executable_in_path (const char *name)
613 {
614 return get_executable_in_path (name, NULL);
615 }
616
617
618
619 int
my_scandir_ext(const char * dirname,int (* filter_func)(const char *),Bool (* handle_direntry_func)(const char * fname,const char * fullname,struct stat * stat_info,void * aux_data),void * aux_data)620 my_scandir_ext ( const char *dirname, int (*filter_func) (const char *),
621 Bool (*handle_direntry_func)( const char *fname, const char *fullname, struct stat *stat_info, void *aux_data),
622 void *aux_data)
623 {
624 DIR *d;
625 struct dirent *e; /* Pointer to static struct inside readdir() */
626 int n = 0; /* Count of nl used so far */
627 char *filename; /* For building filename to pass to stat */
628 char *p; /* Place where filename starts */
629 struct stat stat_info;
630
631 d = opendir (dirname);
632
633 if (d == NULL)
634 return -1;
635
636 filename = (char *)safemalloc (strlen (dirname) + PATH_MAX + 2);
637 if (filename == NULL)
638 {
639 closedir (d);
640 return -1;
641 }
642 strcpy (filename, dirname);
643 p = filename + strlen (filename);
644 if( *p != '/' )
645 {
646 *p++ = '/';
647 *p = 0; /* Just in case... */
648 }
649
650 while ((e = readdir (d)) != NULL)
651 {
652 if ((filter_func == NULL) || filter_func (&(e->d_name[0])))
653 {
654 /* Fill in the fields using stat() */
655 strcpy (p, e->d_name);
656 if (stat (filename, &stat_info) != -1)
657 {
658 if( handle_direntry_func( e->d_name, filename, &stat_info, aux_data) )
659 n++;
660 }
661 }
662 }
663 free (filename);
664
665 if (closedir (d) == -1)
666 return -1;
667 /* Return the count of the entries */
668 return n;
669 }
670
671
672 /*
673 * Non-NULL select and dcomp pointers are *NOT* tested, but should be OK.
674 * They are not used by afterstep however, so this implementation should
675 * be good enough.
676 *
677 * c.ridd@isode.com
678 */
679 /* essentially duplicates whats above,
680 * but for performance sake we don't want to merge them together :*/
681
682 /* sort entries based on their type; directories come first */
683 int
direntry_compar_type(const struct direntry ** d1,const struct direntry ** d2)684 direntry_compar_type (const struct direntry ** d1, const struct direntry ** d2)
685 {
686
687 return S_ISDIR ((**d2).d_mode) - S_ISDIR ((**d1).d_mode);
688 }
689
690 /* sort entries based on their names; A comes before Z */
691 int
direntry_compar_alpha(const struct direntry ** d1,const struct direntry ** d2)692 direntry_compar_alpha (const struct direntry ** d1, const struct direntry ** d2)
693 {
694 return strcmp ((**d1).d_name, (**d2).d_name);
695 }
696
697 int
direntry_compar_type_alpha(const struct direntry ** d1,const struct direntry ** d2)698 direntry_compar_type_alpha (const struct direntry ** d1, const struct direntry ** d2)
699 {
700 int d = (S_ISDIR ((**d2).d_mode) - S_ISDIR ((**d1).d_mode)) ;
701 if( d == 0 )
702 return strcmp ((**d1).d_name, (**d2).d_name);
703 return d;
704 }
705
706 /* sort entries based on their mtimes; old entries before new entries */
707 int
direntry_compar_mtime(const struct direntry ** d1,const struct direntry ** d2)708 direntry_compar_mtime (const struct direntry ** d1, const struct direntry ** d2)
709 {
710 return (**d1).d_mtime - (**d2).d_mtime;
711 }
712
713 int
direntry_compar_size(const struct direntry ** d1,const struct direntry ** d2)714 direntry_compar_size (const struct direntry ** d1, const struct direntry ** d2)
715 {
716 return (**d1).d_size - (**d2).d_size;
717 }
718
719
720 int
my_scandir(char * dirname,struct direntry * (* namelist[]),int (* filter_func)(const char *),my_sort_f dcomp)721 my_scandir (char *dirname, struct direntry *(*namelist[]),
722 int (*filter_func) (const char *), my_sort_f dcomp)
723 {
724 DIR *d;
725 struct dirent *e; /* Pointer to static struct inside readdir() */
726 struct direntry **nl; /* Array of pointers to dirents */
727 struct direntry **nnl;
728 int n; /* Count of nl used so far */
729 int sizenl; /* Number of entries in nl array */
730 int j;
731 char *filename; /* For building filename to pass to stat */
732 char *p; /* Place where filename starts */
733 struct stat buf;
734
735 *namelist = NULL ;
736
737 d = opendir (dirname);
738
739 if (d == NULL)
740 return -1;
741
742 filename = (char *)safemalloc (strlen (dirname) + PATH_MAX + 2);
743 if (filename == NULL)
744 {
745 closedir (d);
746 return -1;
747 }
748 strcpy (filename, dirname);
749 p = filename + strlen (filename);
750 if( *p != '/' )
751 {
752 *p++ = '/';
753 *p = 0; /* Just in case... */
754 }
755
756 nl = NULL;
757 n = 0;
758 sizenl = 0;
759
760 while ((e = readdir (d)) != NULL)
761 {
762 if ((filter_func == NULL) || filter_func (&(e->d_name[0])))
763 {
764 /* add */
765 if (sizenl == n)
766 {
767 /* Grow array */
768 sizenl += 32; /* arbitrary delta */
769 nnl = realloc (nl, sizenl * sizeof (struct direntry *));
770 if (nnl == NULL)
771 {
772 /* Free the old array */
773 for (j = 0; j < n; j++)
774 free (nl[j]);
775 free (nl);
776 free (filename);
777 closedir (d);
778 return -1;
779 }
780 nl = nnl;
781 }
782 /* Fill in the fields using stat() */
783 strcpy (p, e->d_name);
784 if (stat (filename, &buf) != -1)
785 {
786 size_t realsize = offsetof (struct direntry, d_name)+strlen (e->d_name) + 1;
787 nl[n] = (struct direntry *)safemalloc (realsize);
788 nl[n]->d_mode = buf.st_mode;
789 nl[n]->d_mtime = buf.st_mtime;
790 nl[n]->d_size = buf.st_size;
791 strcpy (nl[n]->d_name, e->d_name);
792 n++;
793 }
794 }
795 }
796 free (filename);
797
798 if (closedir (d) == -1)
799 {
800 free (nl);
801 return -1;
802 }
803 if (n == 0)
804 {
805 if (nl)
806 free (nl);
807 /* OK, but not point sorting or freeing anything */
808 return 0;
809 }
810 *namelist = realloc (nl, n * sizeof (struct direntry *));
811
812 if (*namelist == NULL)
813 {
814 for (j = 0; j < n; j++)
815 free (nl[j]);
816 free (nl);
817 return -1;
818 }
819 /* Optionally sort the list */
820 if (dcomp)
821 qsort (*namelist, n, sizeof (struct direntry *), (int (*)())dcomp);
822
823 /* Return the count of the entries */
824 return n;
825 }
826
827 /*
828 * Use this function as the filter_func argument to my_scandir to make it ignore
829 * all files and directories starting with "."
830 */
831 int
ignore_dots(const char * d_name)832 ignore_dots (const char *d_name)
833 {
834 return (d_name[0] != '.');
835 }
836
837 int
no_dots_except_include(const char * d_name)838 no_dots_except_include (const char *d_name)
839 {
840 if( d_name[0] != '.' || mystrcasecmp (d_name, ".include") == 0 )
841 {
842 register int i = 0;
843 while( d_name[i] != '\0' ) ++i ;
844 return (i > 0 && d_name[i-1] != '~');
845 }
846 return False;
847 }
848
849 int
no_dots_except_directory(const char * d_name)850 no_dots_except_directory (const char *d_name)
851 {
852 if( d_name[0] != '.' || mystrcasecmp (d_name, ".directory") == 0 )
853 {
854 register int i = 0;
855 while( d_name[i] != '\0' ) ++i ;
856 return (i > 0 && d_name[i-1] != '~');
857 }
858 return False;
859 }
860
861
862