home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / ms_sh22b.zip / src / glob.c < prev    next >
C/C++ Source or Header  |  1993-12-01  |  17KB  |  766 lines

  1. /* MS-DOS GLOB (3C) FUNCTION
  2.  *
  3.  * MS-DOS GLOB FUNCTION - Copyright (c) 1990,1,2 Data Logic Limited.
  4.  *
  5.  * This code is subject to the following copyright restrictions:
  6.  *
  7.  * 1.  Redistribution and use in source and binary forms are permitted
  8.  *     provided that the above copyright notice is duplicated in the
  9.  *     source form.
  10.  *
  11.  *    $Header: /usr/users/istewart/src/shell/sh2.2/RCS/glob.c,v 2.1 1993/06/14 10:59:32 istewart Exp $
  12.  *
  13.  *    $Log: glob.c,v $
  14.  * Revision 2.1  1993/06/14  10:59:32  istewart
  15.  * More changes for 223 beta
  16.  *
  17.  * Revision 2.0  1992/04/13  17:39:09  Ian_Stewartson
  18.  * MS-Shell 2.0 Baseline release
  19.  *
  20.  */
  21.  
  22. #include <sys/types.h>            /* MS-DOS type definitions      */
  23. #include <sys/stat.h>            /* File status definitions    */
  24. #include <stdio.h>            /* Standard I/O delarations     */
  25. #include <stdlib.h>            /* Standard library functions   */
  26. #include <string.h>            /* String library functions     */
  27. #include <limits.h>            /* String library functions     */
  28. #include <dirent.h>            /* Direction I/O functions    */
  29. #include <ctype.h>            /* Character types function    */
  30. #include <unistd.h>            /* Other functions        */
  31.  
  32. #ifdef __TURBOC__
  33. #  include <alloc.h>            /* Malloc functions        */
  34. #  include <dir.h>            /* Dos directory functions    */
  35. #else
  36. #  include <malloc.h>            /* Malloc functions        */
  37. #endif
  38.  
  39. #include <glob.h>
  40.  
  41. #if defined (MSDOS) || defined (__OS2__) || defined (__TURBOC__)
  42. #  if defined (OS2) || defined (__OS2__)
  43.  
  44. #    define INCL_DOSDEVICES
  45. #    define INCL_DOSMISC
  46. #    include <os2.h>            /* OS2 functions declarations       */
  47.  
  48. #    if defined (__OS2__)
  49. #      define DISABLE_HARD_ERRORS    DosError (FERR_DISABLEHARDERR)
  50. #      define ENABLE_HARD_ERRORS    DosError (FERR_ENABLEHARDERR)
  51. #    else
  52. #      define DISABLE_HARD_ERRORS    DosError (HARDERROR_DISABLE)
  53. #      define ENABLE_HARD_ERRORS    DosError (HARDERROR_ENABLE)
  54. #    endif
  55.  
  56. #  else
  57. #    include <bios.h>            /* DOS BIOS functions        */
  58. #    include <dos.h>            /* DOS functions        */
  59. #    define DISABLE_HARD_ERRORS
  60. #    define ENABLE_HARD_ERRORS
  61. #  endif
  62. #endif
  63.  
  64. /*
  65.  * OS/2 2.x has these missing
  66.  */
  67.  
  68. #ifndef S_IFMT
  69. #  define    S_IFMT    0xf000    /* type of file                */
  70. #endif
  71.  
  72. #ifndef S_ISDIR
  73. #  define S_ISDIR(m)    ((((m) & S_IFMT) == S_IFDIR))
  74. #endif
  75.  
  76. /*
  77.  * Functions
  78.  */
  79.  
  80. static int    _GP_SortCompare        _PROTO ((char **, char **));
  81. static int    _GP_ExpandField        _PROTO ((char *, char *, glob_t *));
  82. static int    _GP_ExpandMetaCharacters _PROTO ((char *, glob_t *));
  83. static int    _GP_AddArgument        _PROTO ((char *, glob_t *));
  84. static bool    _GP_MatchPattern    _PROTO ((char *, char *));
  85. static bool    _GP_access        _PROTO ((char *, int));
  86. static bool    _GP_stat        _PROTO ((char *, struct stat *));
  87.  
  88. static char    *_GP_MetaChars = "?*[\\";
  89. static char    *_GP_NullString = "";
  90.  
  91. #ifdef MSDOS
  92. static    int    _GP_GetNumberofFloppyDrives (void);
  93.  
  94. #if defined (OS2) || defined (__OS2__) || defined (__TURBOC__)
  95. static void     _dos_setdrive (unsigned int, unsigned int *);
  96. static void     _dos_getdrive (unsigned int *);
  97. #endif
  98.  
  99. static char    *_GP_CheckForMultipleDrives    _PROTO ((char *));
  100. #endif
  101.  
  102. /*
  103.  * There appears to be no alloca in TurboC
  104.  */
  105.  
  106. #ifdef __TURBOC__
  107. #  define alloca(x)        malloc (x)
  108. #  define alloca_free(x)    free (x)
  109. #else
  110. #  define alloca_free(x)
  111. #endif
  112.  
  113. /*
  114.  * Free up space
  115.  */
  116.  
  117. void    globfree (gp)
  118. glob_t    *gp;
  119. {
  120.     int        i = (gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0;
  121.  
  122.     while (i < gp->gl_pathc)
  123.     free (gp->gl_pathv[i++]);
  124.  
  125.     free (gp->gl_pathv);
  126. }
  127.  
  128. /* Main search function */
  129.  
  130. int    glob (Pattern, flags, ErrorFunction, gp)
  131. char    *Pattern;
  132. int    flags;
  133. int    (*ErrorFunction) _PROTO ((char *, int));
  134. glob_t    *gp;
  135. {
  136.     int        ReturnValue;
  137.     char    *PatternCopy;
  138.     char    *cp;
  139.  
  140. /* If no append mode - initialise */
  141.  
  142.     if (!(flags & GLOB_APPEND))
  143.     {
  144.     gp->gl_pathc = 0;
  145.     gp->gl_pathv = (char **)NULL;
  146.     }
  147.  
  148.     gp->gl_flags = flags;
  149.     gp->gl_ef = ErrorFunction;
  150.  
  151.     if ((PatternCopy = alloca (strlen (Pattern) + 1)) == (char *)NULL)
  152.     return GLOB_NOSPACE;
  153.  
  154. /* Expand and kill environment */
  155.  
  156.     if (ReturnValue = _GP_ExpandMetaCharacters (strcpy (PatternCopy, Pattern),
  157.                         gp))
  158.     {
  159.     alloca_free (PatternCopy);
  160.     return ReturnValue;
  161.     }
  162.  
  163. /* Check for no finds.  If add value, strip out \ from the string */
  164.  
  165.     if ((gp->gl_pathc == 0) && (flags & GLOB_NOCHECK))
  166.     {
  167.     cp = strcpy (PatternCopy, Pattern);
  168.  
  169.     while ((cp = strpbrk (cp, "?*[")) != (char *)NULL)
  170.     {
  171.         if ((cp == PatternCopy) || (*(cp - 1) != '\\'))
  172.         cp++;
  173.  
  174.         else
  175.         memmove (cp - 1, cp, strlen (cp) + 1);
  176.     }
  177.  
  178.     if (ReturnValue = _GP_AddArgument (PatternCopy, gp))
  179.     {
  180.         alloca_free (PatternCopy);
  181.         return ReturnValue;
  182.     }
  183.     }
  184.  
  185. /* Terminate string */
  186.  
  187.     if ((gp->gl_pathc != 0) &&
  188.     (ReturnValue = _GP_AddArgument ((char *)NULL, gp)))
  189.     {
  190.     alloca_free (PatternCopy);
  191.     return ReturnValue;
  192.     }
  193.  
  194. /* Get the sort length */
  195.  
  196.     ReturnValue = (gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0;
  197.  
  198.     if ((!(flags & GLOB_NOSORT)) && (gp->gl_pathc > 1))
  199.     qsort (&gp->gl_pathv[ReturnValue], gp->gl_pathc, sizeof (char *),
  200.         _GP_SortCompare);
  201.  
  202.     alloca_free (PatternCopy);
  203.     return 0;
  204. }
  205.  
  206. /* Compare function for sort */
  207.  
  208. static int    _GP_SortCompare (a1, a2)
  209. char        **a1, **a2;
  210. {
  211.     return strcmp (*a1, *a2);
  212. }
  213.  
  214. /* Expand a field if it has metacharacters in it */
  215.  
  216. static int    _GP_ExpandField (CurrentDirectoryPattern, AppendString, gp)
  217. char        *CurrentDirectoryPattern;    /* Prefix field        */
  218. char        *AppendString;            /* Postfix field        */
  219. glob_t        *gp;
  220. {
  221.     int         i;
  222.     int            ReturnValue = 0;    /* Return Value        */
  223.     char        *FullFileName;        /* Search file name    */
  224.     char        *FileNameStart;
  225.     char        *MatchString;        /* Match string        */
  226.     DIR            *DirHandler;
  227.     struct dirent    *CurrentDirectoryEntry;
  228. #ifdef MSDOS
  229.     unsigned int    CurrentDrive;        /* Current drive    */
  230.     unsigned int    MaxDrives;        /* Max drive        */
  231.     unsigned int    SelectedDrive;        /* Selected drive    */
  232.     unsigned int    x_drive, y_drive;    /* Dummies        */
  233.     char        *DriveCharacter;    /* Multi-drive flag    */
  234.     char        SDriveString[2];
  235.  
  236. /* Convert file name to lower case */
  237.  
  238. #if defined (OS2) || defined (__OS2__)
  239.     if (!IsHPFSFileSystem (CurrentDirectoryPattern))
  240.     strlwr (CurrentDirectoryPattern);
  241. #else
  242.     strlwr (CurrentDirectoryPattern);
  243. #endif
  244.  
  245. /* Search all drives ? */
  246.  
  247.     if ((DriveCharacter = _GP_CheckForMultipleDrives (CurrentDirectoryPattern))
  248.         != (char *)NULL)
  249.     {
  250.     _dos_getdrive (&CurrentDrive);    /* Get number of drives        */
  251.     _dos_setdrive (CurrentDrive, &MaxDrives);
  252.     SDriveString[1] = 0;
  253.  
  254.     for (SelectedDrive = 1; SelectedDrive <= MaxDrives; ++SelectedDrive)
  255.     {
  256.         _dos_setdrive (SelectedDrive, &x_drive);
  257.         _dos_getdrive (&y_drive);
  258.         _dos_setdrive (CurrentDrive, &x_drive);
  259.  
  260. /* Check to see if the second diskette drive is really there */
  261.  
  262.         if ((_GP_GetNumberofFloppyDrives () < 2) && (SelectedDrive == 2))
  263.         continue;
  264.  
  265. /* If the drive exists and is in our list - process it */
  266.  
  267.         *DriveCharacter = 0;
  268.         *SDriveString = (char)(SelectedDrive + 'a' - 1);
  269.         strlwr (CurrentDirectoryPattern);
  270.  
  271.         if ((y_drive == SelectedDrive) &&
  272.         _GP_MatchPattern (SDriveString, CurrentDirectoryPattern))
  273.         {
  274.         if ((FullFileName = alloca (strlen (DriveCharacter) + 3))
  275.                 == (char *)NULL)
  276.             return GLOB_NOSPACE;
  277.  
  278.         *DriveCharacter = ':';
  279.         *FullFileName = *SDriveString;
  280.         strcpy (FullFileName + 1, DriveCharacter);
  281.  
  282.         i = _GP_ExpandField (FullFileName, AppendString, gp);
  283.         alloca_free (FullFileName);
  284.  
  285.         if (i)
  286.             return i;
  287.         }
  288.  
  289.         *DriveCharacter = ':';
  290.     }
  291.  
  292.     return 0;
  293.     }
  294. #endif
  295.  
  296. /* Get the path length */
  297.  
  298.     MatchString = strrchr (CurrentDirectoryPattern, '/');
  299. #ifdef MSDOS
  300.     if ((MatchString == (char *)NULL) &&
  301.     (*(CurrentDirectoryPattern + 1) == ':'))
  302.     MatchString = CurrentDirectoryPattern + 1;
  303. #endif
  304.  
  305. /* Set up file name for search */
  306.  
  307.     if ((MatchString == (char *)NULL) || (*MatchString == ':'))
  308.     {
  309.     if ((FullFileName = alloca (NAME_MAX + 7 +
  310.                     strlen (AppendString))) == (char *)NULL)
  311.         return GLOB_NOSPACE;
  312.  
  313.     if (MatchString != (char *)NULL)
  314.         *(strcpy (FullFileName, "x:.")) = *CurrentDirectoryPattern;
  315.  
  316.     else
  317.         strcpy (FullFileName, ".");
  318.  
  319.     FileNameStart = FullFileName +
  320.             (int)((MatchString != (char *)NULL) ? 2 : 0);
  321.     }
  322.  
  323. /* Case of /<directory>/... */
  324.  
  325.     else if ((FullFileName = alloca (NAME_MAX + 4 + strlen (AppendString) +
  326.                 (i = (int)(MatchString - CurrentDirectoryPattern))))
  327.             == (char *)NULL)
  328.         return GLOB_NOSPACE;
  329.  
  330.     else
  331.     {
  332.     strncpy (FullFileName, CurrentDirectoryPattern, i);
  333.     *((FileNameStart = FullFileName + i)) = 0;
  334.     strcpy (FileNameStart++, "/");
  335.     }
  336.  
  337.     MatchString = (MatchString == (char *)NULL) ? CurrentDirectoryPattern
  338.                         : MatchString + 1;
  339.  
  340. /* Search for file names */
  341.  
  342.     if ((DirHandler = opendir (FullFileName)) == (DIR *)NULL)
  343.     {
  344.     i = 0;
  345.  
  346.     if (((gp->gl_ef != NULL) && (*gp->gl_ef)(FullFileName, errno)) ||
  347.         (gp->gl_flags & GLOB_ERR))
  348.         i = GLOB_ABEND;
  349.  
  350.     alloca_free (FullFileName);
  351.     return i;
  352.     }
  353.  
  354. /* Are there any matches */
  355.  
  356.     while ((CurrentDirectoryEntry = readdir (DirHandler)) !=
  357.         (struct dirent *)NULL)
  358.     {
  359.     if ((*CurrentDirectoryEntry->d_name == '.') && (*MatchString != '.'))
  360.         continue;
  361.  
  362. /* Check for match */
  363.  
  364.     if (_GP_MatchPattern (CurrentDirectoryEntry->d_name, MatchString))
  365.     {
  366.         strcpy (FileNameStart, CurrentDirectoryEntry->d_name);
  367.  
  368. /* If the postfix is not null, this must be a directory */
  369.  
  370.         if (strlen (AppendString))
  371.         {
  372.         struct stat        statb;
  373.         char            *p;
  374.  
  375. /* If not a directory - go to the next file */
  376.  
  377.         if (!_GP_stat (FullFileName, &statb) ||
  378.             !S_ISDIR (statb.st_mode & S_IFMT))
  379.             continue;
  380.  
  381. /* Are there any metacharacters in the postfix? */
  382.  
  383.         if ((p = strpbrk (AppendString, _GP_MetaChars)) == (char *)NULL)
  384.         {
  385.  
  386. /* No - build the file name and check it exists */
  387.  
  388.             strcat (strcat (FileNameStart, "/"), AppendString);
  389.  
  390.             if (_GP_access (FullFileName, F_OK) &&
  391.             (ReturnValue = _GP_AddArgument (FullFileName, gp)))
  392.             break;
  393.         }
  394.  
  395. /* Yes - build the filename upto the start of the meta characters */
  396.  
  397.         else
  398.         {
  399.             if ((p = strchr (p, '/')) != (char *)NULL)
  400.             *(p++) = 0;
  401.  
  402.             else
  403.             p = _GP_NullString;
  404.  
  405. /* Build the new directory name and check it out */
  406.  
  407.             strcat (strcat (FileNameStart, "/"), AppendString);
  408.             ReturnValue = _GP_ExpandField (FullFileName, p, gp);
  409.  
  410.             if (p != _GP_NullString)
  411.                *(--p) = '/';
  412.  
  413. /* Check for errors */
  414.  
  415.             if (ReturnValue)
  416.             break;
  417.         }
  418.         }
  419.  
  420. /* Process this file.  If error - terminate */
  421.  
  422.         else if (_GP_access (FullFileName, F_OK) &&
  423.              (ReturnValue = _GP_AddArgument (FullFileName, gp)))
  424.         break;
  425.     }
  426.     }
  427.  
  428.     closedir (DirHandler);
  429.     alloca_free (FullFileName);
  430.     return ReturnValue;
  431. }
  432.  
  433. /* Find the location of meta-characters.  If no meta, add the argument and
  434.  * return.  If meta characters, expand directory containing meta characters.
  435.  */
  436.  
  437. static int    _GP_ExpandMetaCharacters (file, gp)
  438. char        *file;
  439. glob_t        *gp;
  440. {
  441.     char    *p;
  442.     int        ReturnValue;
  443.  
  444. /* No metas - add to string */
  445.  
  446.     if ((p = strpbrk (file, _GP_MetaChars)) == (char *)NULL)
  447.     {
  448.     if (!_GP_access (file, F_OK))
  449.         return 0;
  450.  
  451.     return _GP_AddArgument (file, gp);
  452.     }
  453.  
  454. /* Ok - metas, find the end of the start of the directory */
  455.  
  456.     else if ((p = strchr (p, '/')) != (char *)NULL)
  457.     *(p++) = 0;
  458.  
  459.     else
  460.     p = _GP_NullString;
  461.  
  462. /* Continue recusive match */
  463.  
  464.     ReturnValue = _GP_ExpandField (file, p, gp);
  465.  
  466. /* Restore if necessary */
  467.  
  468.     if (p != _GP_NullString)
  469.        *(--p) = '/';
  470.  
  471.     return ReturnValue;
  472. }
  473.  
  474. /* Add an argument to the stack - file is assumed to be a array big enough
  475.  * for the file name + 2
  476.  */
  477.  
  478. static int    _GP_AddArgument (file, gp)
  479. char        *file;
  480. glob_t        *gp;
  481. {
  482.     int        Offset;
  483.     char    **p1;
  484.     struct stat    FileStatus;
  485.  
  486.     Offset = gp->gl_pathc + ((gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0);
  487.     p1  = gp->gl_pathv;
  488.  
  489. /* Malloc space if necessary */
  490.  
  491.     if (gp->gl_pathc == 0)
  492.     p1 = (char **)calloc (sizeof (char *), (50 + Offset));
  493.  
  494.     else if ((gp->gl_pathc % 50) == 0)
  495.     p1 = (char **)realloc (p1, (Offset + 50) * (sizeof (char *)));
  496.  
  497.     if (p1 == (char **)NULL)
  498.     return GLOB_NOSPACE;
  499.  
  500. /* OK got space */
  501.  
  502.     gp->gl_pathv = p1;
  503.  
  504. /* End of list ? */
  505.  
  506.     if (file == (char *)NULL)
  507.     p1[Offset] = (char *)NULL;
  508.  
  509.     else
  510.     {
  511.     if ((gp->gl_flags & GLOB_MARK) && (file[strlen (file) - 1] != '/') &&
  512.         _GP_stat (file, &FileStatus) && (S_ISDIR (FileStatus.st_mode)))
  513.         strcat (file, "/");
  514.  
  515.     if ((p1[Offset] = strdup (file)) == (char *)NULL)
  516.         return GLOB_NOSPACE;
  517.  
  518.     strcpy (p1[Offset], file);
  519.  
  520. /* Increment counter */
  521.  
  522.     ++(gp->gl_pathc);
  523.     }
  524.  
  525.     return 0;
  526. }
  527.  
  528. #ifdef MSDOS
  529. /* Check for multi_drive prefix */
  530.  
  531. static char    *_GP_CheckForMultipleDrives (prefix)
  532. char        *prefix;
  533. {
  534.     if (strlen (prefix) < 2)
  535.     return (char *)NULL;
  536.  
  537.     if (((*prefix == '*') || (*prefix == '?')) && (prefix[1] == ':'))
  538.     return prefix + 1;
  539.  
  540.     if (*prefix != '[')
  541.     return (char *)NULL;
  542.  
  543.     while (*prefix && (*prefix != ']'))
  544.     {
  545.     if ((*prefix == '\\') && (*(prefix + 1)))
  546.         ++prefix;
  547.  
  548.     ++prefix;
  549.     }
  550.  
  551.     return (*prefix && (*(prefix + 1) == ':')) ? prefix + 1 : (char *)NULL;
  552. }
  553.  
  554. /*
  555.  * Some Turboc Functions to emulate MSC functions
  556.  */
  557.  
  558. #if defined (__TURBOC__)
  559. static void     _dos_getdrive (cdp)
  560. unsigned int    *cdp;
  561. {
  562.     *cdp = (unsigned int)getdisk () + 1;
  563. }
  564.  
  565. static void     _dos_setdrive (cdr, ndp)
  566. unsigned int    cdr;
  567. unsigned int    *ndp;
  568. {
  569.    *ndp = (unsigned int)setdisk (cdr - 1);
  570. }
  571. #endif
  572.  
  573. /*
  574.  * Some OS/2 functions to emulate the DOS functions
  575.  */
  576.  
  577. #if defined (OS2) || defined (__OS2__)
  578. static void     _dos_getdrive (cdp)
  579. unsigned int    *cdp;
  580. {
  581.     USHORT    cdr;
  582.     ULONG    ndr;
  583.  
  584.     DosQCurDisk((PUSHORT)&cdr, (PULONG) &ndr);
  585.     *cdp = (unsigned int)cdr;
  586. }
  587.  
  588. static void     _dos_setdrive (cdr, ndp)
  589. unsigned int    cdr;
  590. unsigned int    *ndp;
  591. {
  592.     ULONG    ulDrives;
  593.     USHORT    usDisk;
  594.     int        i;
  595.  
  596.     DosSelectDisk ((USHORT)cdr);
  597.  
  598. /* Get the current disk and check that to see the number of drives */
  599.  
  600.     DosQCurDisk (&usDisk, &ulDrives);        /* gets current drive        */
  601.  
  602.     for (i = 25; (!(ulDrives & (1L << i))) && i >= 0; --i)
  603.     continue;
  604.  
  605.     *ndp = (unsigned int)(i + 1);
  606. }
  607. #endif
  608.  
  609. /* Return the number of floppy disks */
  610.  
  611. static    int    _GP_GetNumberofFloppyDrives ()
  612. {
  613. #if defined (OS2) || defined (__OS2__)
  614.     BYTE    nflop = 1;
  615.  
  616.     DosDevConfig (&nflop, DEVINFO_FLOPPY, 0);
  617.  
  618.     return nflop;
  619. #elif defined (__TURBOC__)
  620.     return ((biosequip () & 0x00c0) >> 6) + 1;
  621. #else
  622.     return ((_bios_equiplist () & 0x00c0) >> 6) + 1;
  623. #endif
  624. }
  625. #endif
  626.  
  627. /*
  628.  * Pattern Matching function
  629.  */
  630.  
  631. static bool    _GP_MatchPattern (string, pattern)
  632. char        *string;        /* String to match                  */
  633. char        *pattern;        /* Pattern to match against         */
  634. {
  635.     register int    cur_s;        /* Current string character         */
  636.     register int    cur_p;        /* Current pattern character        */
  637.  
  638. /* Match string */
  639.  
  640.     while (cur_p = *(pattern++))
  641.     {
  642.     cur_s = *(string++);        /* Load current string character    */
  643.  
  644.         switch (cur_p)            /* Switch on pattern character      */
  645.         {
  646.             case '[':            /* Match class of characters        */
  647.             {
  648.                 while(1)
  649.                 {
  650.                     if (!(cur_p = *(pattern++)))
  651.             return 0;
  652.  
  653.                     if (cur_p == ']')
  654.             return FALSE;
  655.  
  656.                     if (cur_s != cur_p)
  657.                     {
  658.                         if (*pattern == '-')
  659.                         {
  660.                             if(cur_p > cur_s)
  661.                                 continue;
  662.  
  663.                             if (cur_s > *(++pattern))
  664.                                 continue;
  665.                         }
  666.                         else
  667.                             continue;
  668.                     }
  669.  
  670.                     break;
  671.                 }
  672.  
  673.                 while (*pattern)
  674.                 {
  675.                     if (*(pattern++) == ']')
  676.                         break;
  677.                 }
  678.  
  679.         break;
  680.             }
  681.  
  682.             case '?':            /* Match any character              */
  683.             {
  684.                 if (!cur_s)
  685.             return FALSE;
  686.  
  687.                 break;
  688.             }
  689.  
  690.             case '*':            /* Match any number of any character*/
  691.             {
  692.                 string--;
  693.  
  694.                 do
  695.                 {
  696.                     if (_GP_MatchPattern (string, pattern))
  697.             return TRUE;
  698.                 }
  699.                 while (*(string++));
  700.  
  701.         return FALSE;
  702.             }
  703.  
  704.             case '\\':            /* Next character is non-meta       */
  705.             {
  706.                 if (!(cur_p = *(pattern++)))
  707.             return FALSE;
  708.             }
  709.  
  710.             default:            /* Match against current pattern    */
  711.             {
  712.                 if (cur_p != cur_s)
  713.             return FALSE;
  714.  
  715.                 break;
  716.             }
  717.         }
  718.     }
  719.  
  720.     return (!*string) ? TRUE : FALSE;
  721. }
  722.  
  723. /*
  724.  * Local Stat function to do some additional checks
  725.  */
  726.  
  727. static bool _GP_stat (char *FileName, struct stat *Status)
  728. {
  729.     int        rc;
  730.  
  731.     DISABLE_HARD_ERRORS;
  732.     rc = stat (FileName, Status);
  733.     ENABLE_HARD_ERRORS;
  734.  
  735.     return rc ? FALSE : TRUE;
  736. }
  737.  
  738. /*
  739.  * Local access function to do some additional checks
  740.  */
  741.  
  742. static bool _GP_access (char *FileName, int mode)
  743. {
  744.     int        rc;
  745.  
  746.     DISABLE_HARD_ERRORS;
  747.     rc = access (FileName, mode);
  748.     ENABLE_HARD_ERRORS;
  749.  
  750.     return rc ? FALSE : TRUE;
  751. }
  752.  
  753. /*
  754.  * Test program
  755.  */
  756.  
  757. #ifdef TEST
  758. main (int argc, char **argv)
  759. {
  760.     int        i;
  761.  
  762.     for (i = 0; i < argc; i++)
  763.     printf ("Arg %d = <%s>\n", i, argv[i]);
  764. }
  765. #endif
  766.