Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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