home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / glob / glob.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  21KB  |  907 lines

  1. /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
  2.  
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public License as
  5. published by the Free Software Foundation; either version 2 of the
  6. License, or (at your option) any later version.
  7.  
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. Library General Public License for more details.
  12.  
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; see the file COPYING.LIB.  If
  15. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16. Cambridge, MA 02139, USA.  */
  17.  
  18. /* AIX requires this to be the first thing in the file.  */
  19. #if defined (_AIX) && !defined (__GNUC__)
  20.  #pragma alloca
  21. #endif
  22.  
  23. #ifdef    HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. /* Enable GNU extensions in glob.h.  */
  28. #ifndef _GNU_SOURCE
  29. #define    _GNU_SOURCE    1
  30. #endif
  31.  
  32. #include <errno.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35.  
  36.  
  37. /* Comment out all this code if we are using the GNU C Library, and are not
  38.    actually compiling the library itself.  This code is part of the GNU C
  39.    Library, but also included in many other GNU distributions.  Compiling
  40.    and linking in this code is a waste when using the GNU C library
  41.    (especially if it is a shared library).  Rather than having every GNU
  42.    program understand `configure --with-gnu-libc' and omit the object files,
  43.    it is simpler to just do this in the source for each such file.  */
  44.  
  45. #define GLOB_INTERFACE_VERSION 1
  46. #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
  47. #include <gnu-versions.h>
  48. #if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
  49. #define ELIDE_CODE
  50. #endif
  51. #endif
  52.  
  53. #ifndef ELIDE_CODE
  54.  
  55. #ifdef    STDC_HEADERS
  56. #include <stddef.h>
  57. #endif
  58.  
  59. #ifdef    HAVE_UNISTD_H
  60. #include <unistd.h>
  61. #ifndef POSIX
  62. #ifdef    _POSIX_VERSION
  63. #define    POSIX
  64. #endif
  65. #endif
  66. #endif
  67.  
  68. #if !defined (_AMIGA) && !defined (VMS) && !defined(WIN32)
  69. #include <pwd.h>
  70. #endif
  71.  
  72. #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
  73. extern int errno;
  74. #endif
  75.  
  76. #ifndef    NULL
  77. #define    NULL    0
  78. #endif
  79.  
  80.  
  81. #if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
  82. # include <dirent.h>
  83. # define NAMLEN(dirent) strlen((dirent)->d_name)
  84. #else
  85. # define dirent direct
  86. # define NAMLEN(dirent) (dirent)->d_namlen
  87. # ifdef HAVE_SYS_NDIR_H
  88. #  include <sys/ndir.h>
  89. # endif
  90. # ifdef HAVE_SYS_DIR_H
  91. #  include <sys/dir.h>
  92. # endif
  93. # ifdef HAVE_NDIR_H
  94. #  include <ndir.h>
  95. # endif
  96. # ifdef HAVE_VMSDIR_H
  97. #  include "vmsdir.h"
  98. # endif /* HAVE_VMSDIR_H */
  99. #endif
  100.  
  101.  
  102. /* In GNU systems, <dirent.h> defines this macro for us.  */
  103. #ifdef _D_NAMLEN
  104. #undef NAMLEN
  105. #define NAMLEN(d) _D_NAMLEN(d)
  106. #endif
  107.  
  108.  
  109. #if (defined (POSIX) || defined (WIN32)) && !defined (__GNU_LIBRARY__)
  110. /* Posix does not require that the d_ino field be present, and some
  111.    systems do not provide it. */
  112. #define REAL_DIR_ENTRY(dp) 1
  113. #else
  114. #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
  115. #endif /* POSIX */
  116.  
  117. #if    (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
  118. #include <stdlib.h>
  119. #include <string.h>
  120. #define    ANSI_STRING
  121. #else    /* No standard headers.  */
  122.  
  123. extern char *getenv ();
  124.  
  125. #ifdef HAVE_STRING_H
  126. #include <string.h>
  127. #define    ANSI_STRING
  128. #else
  129. #include <strings.h>
  130. #endif
  131. #ifdef    HAVE_MEMORY_H
  132. #include <memory.h>
  133. #endif
  134.  
  135. extern char *malloc (), *realloc ();
  136. extern void free ();
  137.  
  138. extern void qsort ();
  139. extern void abort (), exit ();
  140.  
  141. #endif    /* Standard headers.  */
  142.  
  143. #ifndef    ANSI_STRING
  144.  
  145. #ifndef    bzero
  146. extern void bzero ();
  147. #endif
  148. #ifndef    bcopy
  149. extern void bcopy ();
  150. #endif
  151.  
  152. #define    memcpy(d, s, n)    bcopy ((s), (d), (n))
  153. #define    strrchr    rindex
  154. /* memset is only used for zero here, but let's be paranoid.  */
  155. #define    memset(s, better_be_zero, n) \
  156.   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
  157. #endif    /* Not ANSI_STRING.  */
  158.  
  159. #ifndef    HAVE_STRCOLL
  160. #define    strcoll    strcmp
  161. #endif
  162.  
  163.  
  164. #ifndef    __GNU_LIBRARY__
  165. #ifdef    __GNUC__
  166. __inline
  167. #endif
  168. #ifndef __SASC
  169. #ifdef WIN32
  170. static void *
  171. #else
  172. static char *
  173. #endif
  174. my_realloc (p, n)
  175.      char *p;
  176.      unsigned int n;
  177. {
  178.   /* These casts are the for sake of the broken Ultrix compiler,
  179.      which warns of illegal pointer combinations otherwise.  */
  180.   if (p == NULL)
  181.     return (char *) malloc (n);
  182.   return (char *) realloc (p, n);
  183. }
  184. #define    realloc    my_realloc
  185. #endif /* __SASC */
  186. #endif /* __GNU_LIBRARY__ */
  187.  
  188.  
  189. #if    !defined(__alloca) && !defined(__GNU_LIBRARY__)
  190.  
  191. #ifdef    __GNUC__
  192. #undef    alloca
  193. #define    alloca(n)    __builtin_alloca (n)
  194. #else    /* Not GCC.  */
  195. #ifdef HAVE_ALLOCA_H
  196. #include <alloca.h>
  197. #else    /* Not HAVE_ALLOCA_H.  */
  198. #ifndef    _AIX
  199. #ifdef WIN32
  200. #include <malloc.h>
  201. #else
  202. extern char *alloca ();
  203. #endif /* WIN32 */
  204. #endif    /* Not _AIX.  */
  205. #endif    /* sparc or HAVE_ALLOCA_H.  */
  206. #endif    /* GCC.  */
  207.  
  208. #define    __alloca    alloca
  209.  
  210. #endif
  211.  
  212. #ifndef __GNU_LIBRARY__
  213. #define __stat stat
  214. #ifdef STAT_MACROS_BROKEN
  215. #undef S_ISDIR
  216. #endif
  217. #ifndef S_ISDIR
  218. #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
  219. #endif
  220. #endif
  221.  
  222. #ifndef    STDC_HEADERS
  223. #undef    size_t
  224. #define    size_t    unsigned int
  225. #endif
  226.  
  227. /* Some system header files erroneously define these.
  228.    We want our own definitions from <fnmatch.h> to take precedence.  */
  229. #undef    FNM_PATHNAME
  230. #undef    FNM_NOESCAPE
  231. #undef    FNM_PERIOD
  232. #include <fnmatch.h>
  233.  
  234. /* Some system header files erroneously define these.
  235.    We want our own definitions from <glob.h> to take precedence.  */
  236. #undef    GLOB_ERR
  237. #undef    GLOB_MARK
  238. #undef    GLOB_NOSORT
  239. #undef    GLOB_DOOFFS
  240. #undef    GLOB_NOCHECK
  241. #undef    GLOB_APPEND
  242. #undef    GLOB_NOESCAPE
  243. #undef    GLOB_PERIOD
  244. #include <glob.h>
  245.  
  246. static int glob_pattern_p __P ((const char *pattern, int quote));
  247. static int glob_in_dir __P ((const char *pattern, const char *directory,
  248.                  int flags,
  249.                  int (*errfunc) __P ((const char *, int)),
  250.                  glob_t *pglob));
  251. static int prefix_array __P ((const char *prefix, char **array, size_t n));
  252. static int collated_compare __P ((const __ptr_t, const __ptr_t));
  253.  
  254. /* Do glob searching for PATTERN, placing results in PGLOB.
  255.    The bits defined above may be set in FLAGS.
  256.    If a directory cannot be opened or read and ERRFUNC is not nil,
  257.    it is called with the pathname that caused the error, and the
  258.    `errno' value from the failing call; if it returns non-zero
  259.    `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
  260.    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
  261.    Otherwise, `glob' returns zero.  */
  262. int
  263. glob (pattern, flags, errfunc, pglob)
  264.      const char *pattern;
  265.      int flags;
  266.      int (*errfunc) __P ((const char *, int));
  267.      glob_t *pglob;
  268. {
  269.   const char *filename;
  270.   char *dirname;
  271.   size_t dirlen;
  272.   int status;
  273.   int oldcount;
  274.  
  275.   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
  276.     {
  277.       errno = EINVAL;
  278.       return -1;
  279.     }
  280.  
  281.   if (flags & GLOB_BRACE)
  282.     {
  283.       const char *begin = strchr (pattern, '{');
  284.       if (begin != NULL)
  285.     {
  286.       int firstc;
  287.       size_t restlen;
  288.       const char *p, *end, *next;
  289.       unsigned int depth = 0;
  290.  
  291.       /* Find the end of the brace expression, by counting braces.
  292.          While we're at it, notice the first comma at top brace level.  */
  293.       end = begin + 1;
  294.       next = NULL;
  295.       while (1)
  296.         {
  297.           switch (*end++)
  298.         {
  299.         case ',':
  300.           if (depth == 0 && next == NULL)
  301.             next = end;
  302.           continue;
  303.         case '{':
  304.           ++depth;
  305.           continue;
  306.         case '}':
  307.           if (depth-- == 0)
  308.             break;
  309.           continue;
  310.         case '\0':
  311.           return glob (pattern, flags &~ GLOB_BRACE, errfunc, pglob);
  312.         }
  313.           break;
  314.         }
  315.       restlen = strlen (end) + 1;
  316.       if (next == NULL)
  317.         next = end;
  318.  
  319.       /* We have a brace expression.  BEGIN points to the opening {,
  320.          NEXT points past the terminator of the first element, and END
  321.          points past the final }.  We will accumulate result names from
  322.          recursive runs for each brace alternative in the buffer using
  323.          GLOB_APPEND.  */
  324.  
  325.       if (!(flags & GLOB_APPEND))
  326.         {
  327.           /* This call is to set a new vector, so clear out the
  328.          vector so we can append to it.  */
  329.           pglob->gl_pathc = 0;
  330.           pglob->gl_pathv = NULL;
  331.         }
  332.       firstc = pglob->gl_pathc;
  333.  
  334.       /* In this loop P points to the beginning of the current element
  335.          and NEXT points past its terminator.  */
  336.       p = begin + 1;
  337.       while (1)
  338.         {
  339.           /* Construct a whole name that is one of the brace
  340.          alternatives in a temporary buffer.  */
  341.           int result;
  342.           size_t bufsz = (begin - pattern) + (next - 1 - p) + restlen;
  343. #ifdef __GNUC__
  344.           char onealt[bufsz];
  345. #else
  346.           char *onealt = malloc (bufsz);
  347.           if (onealt == NULL)
  348.         {
  349.           if (!(flags & GLOB_APPEND))
  350.             globfree (pglob);
  351.           return GLOB_NOSPACE;
  352.         }
  353. #endif
  354.           memcpy (onealt, pattern, begin - pattern);
  355.           memcpy (&onealt[begin - pattern], p, next - 1 - p);
  356.           memcpy (&onealt[(begin - pattern) + (next - 1 - p)],
  357.               end, restlen);
  358.           result = glob (onealt,
  359.                  ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) |
  360.                   GLOB_APPEND), errfunc, pglob);
  361. #ifndef __GNUC__
  362.           free (onealt);
  363. #endif
  364.  
  365.           /* If we got an error, return it.  */
  366.           if (result && result != GLOB_NOMATCH)
  367.         {
  368.           if (!(flags & GLOB_APPEND))
  369.             globfree (pglob);
  370.           return result;
  371.         }
  372.  
  373.           /* Advance past this alternative and process the next.  */
  374.           p = next;
  375.           depth = 0;
  376.         scan:
  377.           switch (*p++)
  378.         {
  379.         case ',':
  380.           if (depth == 0)
  381.             {
  382.               /* Found the next alternative.  Loop to glob it.  */
  383.               next = p;
  384.               continue;
  385.             }
  386.           goto scan;
  387.         case '{':
  388.           ++depth;
  389.           goto scan;
  390.         case '}':
  391.           if (depth-- == 0)
  392.             /* End of the brace expression.  Break out of the loop.  */
  393.             break;
  394.           goto scan;
  395.         }
  396.         }
  397.  
  398.       if (pglob->gl_pathc == firstc &&
  399.           !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
  400.         return GLOB_NOMATCH;
  401.     }
  402.     }
  403.  
  404.   /* Find the filename.  */
  405.   filename = strrchr (pattern, '/');
  406.   if (filename == NULL)
  407.     {
  408.       filename = pattern;
  409. #ifdef _AMIGA
  410.       dirname = (char *) "";
  411. #else
  412.       dirname = (char *) ".";
  413. #endif
  414.       dirlen = 0;
  415.     }
  416.   else if (filename == pattern)
  417.     {
  418.       /* "/pattern".  */
  419.       dirname = (char *) "/";
  420.       dirlen = 1;
  421.       ++filename;
  422.     }
  423.   else
  424.     {
  425.       dirlen = filename - pattern;
  426.       dirname = (char *) __alloca (dirlen + 1);
  427.       memcpy (dirname, pattern, dirlen);
  428.       dirname[dirlen] = '\0';
  429.       ++filename;
  430.     }
  431.  
  432.   if (filename[0] == '\0' && dirlen > 1)
  433.     /* "pattern/".  Expand "pattern", appending slashes.  */
  434.     {
  435.       int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
  436.       if (val == 0)
  437.     pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
  438.       return val;
  439.     }
  440.  
  441.   if (!(flags & GLOB_APPEND))
  442.     {
  443.       pglob->gl_pathc = 0;
  444.       pglob->gl_pathv = NULL;
  445.     }
  446.  
  447.   oldcount = pglob->gl_pathc;
  448.  
  449. #ifndef VMS
  450.   if ((flags & GLOB_TILDE) && dirname[0] == '~')
  451.     {
  452.       if (dirname[1] == '\0')
  453.     {
  454.       /* Look up home directory.  */
  455.       dirname = getenv ("HOME");
  456. #ifdef _AMIGA
  457.       if (dirname == NULL || dirname[0] == '\0')
  458.         dirname = "SYS:";
  459. #else
  460. #ifdef WIN32
  461.       if (dirname == NULL || dirname[0] == '\0')
  462.             dirname = "c:/users/default"; /* poor default */
  463. #else
  464.       if (dirname == NULL || dirname[0] == '\0')
  465.         {
  466.           extern char *getlogin __P ((void));
  467.           char *name = getlogin ();
  468.           if (name != NULL)
  469.         {
  470.           struct passwd *p = getpwnam (name);
  471.           if (p != NULL)
  472.             dirname = p->pw_dir;
  473.         }
  474.         }
  475.       if (dirname == NULL || dirname[0] == '\0')
  476.         dirname = (char *) "~"; /* No luck.  */
  477. #endif /* WIN32 */
  478. #endif
  479.     }
  480.       else
  481.     {
  482. #ifdef _AMIGA
  483.       if (dirname == NULL || dirname[0] == '\0')
  484.         dirname = "SYS:";
  485. #else
  486. #ifdef WIN32
  487.       if (dirname == NULL || dirname[0] == '\0')
  488.             dirname = "c:/users/default"; /* poor default */
  489. #else
  490.       /* Look up specific user's home directory.  */
  491.       struct passwd *p = getpwnam (dirname + 1);
  492.       if (p != NULL)
  493.         dirname = p->pw_dir;
  494. #endif /* WIN32 */
  495. #endif
  496.     }
  497.     }
  498. #endif    /* Not VMS.  */
  499.  
  500.   if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
  501.     {
  502.       /* The directory name contains metacharacters, so we
  503.      have to glob for the directory, and then glob for
  504.      the pattern in each directory found.  */
  505.       glob_t dirs;
  506.       register int i;
  507.  
  508.       status = glob (dirname,
  509.              ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
  510.               GLOB_NOSORT),
  511.              errfunc, &dirs);
  512.       if (status != 0)
  513.     return status;
  514.  
  515.       /* We have successfully globbed the preceding directory name.
  516.      For each name we found, call glob_in_dir on it and FILENAME,
  517.      appending the results to PGLOB.  */
  518.       for (i = 0; i < dirs.gl_pathc; ++i)
  519.     {
  520.       int oldcount;
  521.  
  522. #ifdef    SHELL
  523.       {
  524.         /* Make globbing interruptible in the bash shell. */
  525.         extern int interrupt_state;
  526.  
  527.         if (interrupt_state)
  528.           {
  529.         globfree (&dirs);
  530.         globfree (&files);
  531.         return GLOB_ABEND;
  532.           }
  533.       }
  534. #endif /* SHELL.  */
  535.  
  536.       oldcount = pglob->gl_pathc;
  537.       status = glob_in_dir (filename, dirs.gl_pathv[i],
  538.                 (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
  539.                 errfunc, pglob);
  540.       if (status == GLOB_NOMATCH)
  541.         /* No matches in this directory.  Try the next.  */
  542.         continue;
  543.  
  544.       if (status != 0)
  545.         {
  546.           globfree (&dirs);
  547.           globfree (pglob);
  548.           return status;
  549.         }
  550.  
  551.       /* Stick the directory on the front of each name.  */
  552.       if (prefix_array (dirs.gl_pathv[i],
  553.                 &pglob->gl_pathv[oldcount],
  554.                 pglob->gl_pathc - oldcount))
  555.         {
  556.           globfree (&dirs);
  557.           globfree (pglob);
  558.           return GLOB_NOSPACE;
  559.         }
  560.     }
  561.  
  562.       flags |= GLOB_MAGCHAR;
  563.  
  564.       if (pglob->gl_pathc == oldcount)
  565.     /* No matches.  */
  566.     if (flags & GLOB_NOCHECK)
  567.       {
  568.         size_t len = strlen (pattern) + 1;
  569.         char *patcopy = (char *) malloc (len);
  570.         if (patcopy == NULL)
  571.           return GLOB_NOSPACE;
  572.         memcpy (patcopy, pattern, len);
  573.  
  574.         pglob->gl_pathv
  575.           = (char **) realloc (pglob->gl_pathv,
  576.                    (pglob->gl_pathc +
  577.                     ((flags & GLOB_DOOFFS) ?
  578.                      pglob->gl_offs : 0) +
  579.                     1 + 1) *
  580.                    sizeof (char *));
  581.         if (pglob->gl_pathv == NULL)
  582.           {
  583.         free (patcopy);
  584.         return GLOB_NOSPACE;
  585.           }
  586.  
  587.         if (flags & GLOB_DOOFFS)
  588.           while (pglob->gl_pathc < pglob->gl_offs)
  589.         pglob->gl_pathv[pglob->gl_pathc++] = NULL;
  590.  
  591.         pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
  592.         pglob->gl_pathv[pglob->gl_pathc] = NULL;
  593.         pglob->gl_flags = flags;
  594.       }
  595.     else
  596.       return GLOB_NOMATCH;
  597.     }
  598.   else
  599.     {
  600.       status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
  601.       if (status != 0)
  602.     return status;
  603.  
  604.       if (dirlen > 0)
  605.     {
  606.       /* Stick the directory on the front of each name.  */
  607.       if (prefix_array (dirname,
  608.                 &pglob->gl_pathv[oldcount],
  609.                 pglob->gl_pathc - oldcount))
  610.         {
  611.           globfree (pglob);
  612.           return GLOB_NOSPACE;
  613.         }
  614.     }
  615.     }
  616.  
  617.   if (flags & GLOB_MARK)
  618.     {
  619.       /* Append slashes to directory names.  */
  620.       int i;
  621.       struct stat st;
  622.       for (i = oldcount; i < pglob->gl_pathc; ++i)
  623.     if (((flags & GLOB_ALTDIRFUNC) ?
  624.          (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
  625.          __stat (pglob->gl_pathv[i], &st)) == 0 &&
  626.         S_ISDIR (st.st_mode))
  627.       {
  628.          size_t len = strlen (pglob->gl_pathv[i]) + 2;
  629.         char *new = realloc (pglob->gl_pathv[i], len);
  630.          if (new == NULL)
  631.           {
  632.         globfree (pglob);
  633.         return GLOB_NOSPACE;
  634.           }
  635.         strcpy (&new[len - 2], "/");
  636.         pglob->gl_pathv[i] = new;
  637.       }
  638.     }
  639.  
  640.   if (!(flags & GLOB_NOSORT))
  641.     /* Sort the vector.  */
  642.     qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
  643.        pglob->gl_pathc - oldcount,
  644.        sizeof (char *), collated_compare);
  645.  
  646.   return 0;
  647. }
  648.  
  649.  
  650. /* Free storage allocated in PGLOB by a previous `glob' call.  */
  651. void
  652. globfree (pglob)
  653.      register glob_t *pglob;
  654. {
  655.   if (pglob->gl_pathv != NULL)
  656.     {
  657.       register int i;
  658.       for (i = 0; i < pglob->gl_pathc; ++i)
  659.     if (pglob->gl_pathv[i] != NULL)
  660.       free ((__ptr_t) pglob->gl_pathv[i]);
  661.       free ((__ptr_t) pglob->gl_pathv);
  662.     }
  663. }
  664.  
  665.  
  666. /* Do a collated comparison of A and B.  */
  667. static int
  668. collated_compare (a, b)
  669.      const __ptr_t a;
  670.      const __ptr_t b;
  671. {
  672.   const char *const s1 = *(const char *const * const) a;
  673.   const char *const s2 = *(const char *const * const) b;
  674.  
  675.   if (s1 == s2)
  676.     return 0;
  677.   if (s1 == NULL)
  678.     return 1;
  679.   if (s2 == NULL)
  680.     return -1;
  681.   return strcoll (s1, s2);
  682. }
  683.  
  684.  
  685. /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
  686.    elements in place.  Return nonzero if out of memory, zero if successful.
  687.    A slash is inserted between DIRNAME and each elt of ARRAY,
  688.    unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
  689. static int
  690. prefix_array (dirname, array, n)
  691.      const char *dirname;
  692.      char **array;
  693.      size_t n;
  694. {
  695.   register size_t i;
  696.   size_t dirlen = strlen (dirname);
  697.  
  698.   if (dirlen == 1 && dirname[0] == '/')
  699.     /* DIRNAME is just "/", so normal prepending would get us "//foo".
  700.        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
  701.     dirlen = 0;
  702.  
  703.   for (i = 0; i < n; ++i)
  704.     {
  705.       size_t eltlen = strlen (array[i]) + 1;
  706.       char *new = (char *) malloc (dirlen + 1 + eltlen);
  707.       if (new == NULL)
  708.     {
  709.       while (i > 0)
  710.         free ((__ptr_t) array[--i]);
  711.       return 1;
  712.     }
  713.  
  714.       memcpy (new, dirname, dirlen);
  715.       new[dirlen] = '/';
  716.       memcpy (&new[dirlen + 1], array[i], eltlen);
  717.       free ((__ptr_t) array[i]);
  718.       array[i] = new;
  719.     }
  720.  
  721.   return 0;
  722. }
  723.  
  724.  
  725. /* Return nonzero if PATTERN contains any metacharacters.
  726.    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
  727. static int
  728. glob_pattern_p (pattern, quote)
  729.      const char *pattern;
  730.      int quote;
  731. {
  732.   register const char *p;
  733.   int open = 0;
  734.  
  735.   for (p = pattern; *p != '\0'; ++p)
  736.     switch (*p)
  737.       {
  738.       case '?':
  739.       case '*':
  740.     return 1;
  741.  
  742.       case '\\':
  743.     if (quote && p[1] != '\0')
  744.       ++p;
  745.     break;
  746.  
  747.       case '[':
  748.     open = 1;
  749.     break;
  750.  
  751.       case ']':
  752.     if (open)
  753.       return 1;
  754.     break;
  755.       }
  756.  
  757.   return 0;
  758. }
  759.  
  760.  
  761. /* Like `glob', but PATTERN is a final pathname component,
  762.    and matches are searched for in DIRECTORY.
  763.    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
  764.    The GLOB_APPEND flag is assumed to be set (always appends).  */
  765. static int
  766. glob_in_dir (pattern, directory, flags, errfunc, pglob)
  767.      const char *pattern;
  768.      const char *directory;
  769.      int flags;
  770.      int (*errfunc) __P ((const char *, int));
  771.      glob_t *pglob;
  772. {
  773.   __ptr_t stream;
  774.  
  775.   struct globlink
  776.     {
  777.       struct globlink *next;
  778.       char *name;
  779.     };
  780.   struct globlink *names = NULL;
  781.   size_t nfound = 0;
  782.  
  783.   if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
  784.     {
  785.       stream = NULL;
  786.       flags |= GLOB_NOCHECK;
  787.     }
  788.   else
  789.     {
  790.       flags |= GLOB_MAGCHAR;
  791.  
  792.       stream = ((flags & GLOB_ALTDIRFUNC) ?
  793.         (*pglob->gl_opendir) (directory) :
  794.         (__ptr_t) opendir (directory));
  795.       if (stream == NULL)
  796.     {
  797.       if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
  798.           (flags & GLOB_ERR))
  799.         return GLOB_ABEND;
  800.     }
  801.       else
  802.     while (1)
  803.       {
  804.         const char *name;
  805.         size_t len;
  806.         struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
  807.                 (*pglob->gl_readdir) (stream) :
  808.                 readdir ((DIR *) stream));
  809.         if (d == NULL)
  810.           break;
  811.         if (! REAL_DIR_ENTRY (d))
  812.           continue;
  813.  
  814.         name = d->d_name;
  815.  
  816.         if (fnmatch (pattern, name,
  817.              (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
  818.              ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
  819. #ifdef _AMIGA
  820.              | FNM_CASEFOLD
  821. #endif
  822.              ) == 0)
  823.           {
  824.         struct globlink *new
  825.           = (struct globlink *) __alloca (sizeof (struct globlink));
  826.         len = NAMLEN (d);
  827.         new->name
  828.           = (char *) malloc (len + 1);
  829.         if (new->name == NULL)
  830.           goto memory_error;
  831.         memcpy ((__ptr_t) new->name, name, len);
  832.         new->name[len] = '\0';
  833.         new->next = names;
  834.         names = new;
  835.         ++nfound;
  836.           }
  837.       }
  838.     }
  839.  
  840.   if (nfound == 0 && (flags & GLOB_NOMAGIC) &&
  841.       ! glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
  842.     flags |= GLOB_NOCHECK;
  843.  
  844.   if (nfound == 0 && (flags & GLOB_NOCHECK))
  845.     {
  846.       size_t len = strlen (pattern);
  847.       nfound = 1;
  848.       names = (struct globlink *) __alloca (sizeof (struct globlink));
  849.       names->next = NULL;
  850.       names->name = (char *) malloc (len + 1);
  851.       if (names->name == NULL)
  852.     goto memory_error;
  853.       memcpy (names->name, pattern, len);
  854.       names->name[len] = '\0';
  855.     }
  856.  
  857.   pglob->gl_pathv
  858.     = (char **) realloc (pglob->gl_pathv,
  859.              (pglob->gl_pathc +
  860.               ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
  861.               nfound + 1) *
  862.              sizeof (char *));
  863.   if (pglob->gl_pathv == NULL)
  864.     goto memory_error;
  865.  
  866.   if (flags & GLOB_DOOFFS)
  867.     while (pglob->gl_pathc < pglob->gl_offs)
  868.       pglob->gl_pathv[pglob->gl_pathc++] = NULL;
  869.  
  870.   for (; names != NULL; names = names->next)
  871.     pglob->gl_pathv[pglob->gl_pathc++] = names->name;
  872.   pglob->gl_pathv[pglob->gl_pathc] = NULL;
  873.  
  874.   pglob->gl_flags = flags;
  875.  
  876.   if (stream != NULL)
  877.     {
  878.       int save = errno;
  879.       if (flags & GLOB_ALTDIRFUNC)
  880.     (*pglob->gl_closedir) (stream);
  881.       else
  882.     closedir ((DIR *) stream);
  883.       errno = save;
  884.     }
  885.   return nfound == 0 ? GLOB_NOMATCH : 0;
  886.  
  887.  memory_error:
  888.   {
  889.     int save = errno;
  890.     if (flags & GLOB_ALTDIRFUNC)
  891.       (*pglob->gl_closedir) (stream);
  892.     else
  893.       closedir ((DIR *) stream);
  894.     errno = save;
  895.   }
  896.   while (names != NULL)
  897.     {
  898.       if (names->name != NULL)
  899.     free ((__ptr_t) names->name);
  900.       names = names->next;
  901.     }
  902.   return GLOB_NOSPACE;
  903. }
  904.  
  905. #endif    /* Not ELIDE_CODE.  */
  906.  
  907.