home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8707 / 46 < prev    next >
Internet Message Format  |  1990-07-13  |  21KB

  1. From: root@hobbes.UUCP
  2. Newsgroups: comp.sources.misc
  3. Subject: "glob" in C for MS-DOS (sources)
  4. Message-ID: <2915@ncoast.UUCP>
  5. Date: 16 Jul 87 00:21:54 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Organization: U of Wisconsin - Madison  Spanish Department
  8. Lines: 747
  9. Approved: allbery@ncoast.UUCP
  10. X-Archive: comp.sources.misc/8707/46
  11.  
  12. [There were uuencodes with this.  I have split them off; they are in
  13. comp.binaries.ibm.pc.  ++bsa]
  14.  
  15.   Here is a routine which does wildcard expansion for MS-DOS.
  16.  
  17. The shar which follows contains:
  18.     glob.c  glob.h        - the actual wildcard expansion routines
  19.     example.c        - a very simple example of its usage
  20.     chd.c            - a more complex example - implements chdir
  21.  
  22. Have fun, mail me if you have problems...
  23.  
  24.  John Plocher        UUCP: <backbone>!uwvax!geowhiz!uwspan!plocher
  25. ==============      Internet: plocher%uwspan.UUCP@uwvax.cs.Wisc.EDU
  26. FidoNet: 121/0          BITNET: uwvax!geowhiz!uwspan!plocher@psuvax1
  27.  
  28.     *-----*-----*-----*-----*-----*-----*-----*-----*-----*-----*
  29.  
  30. #!/bin/sh
  31. #    This is a shell archive created by yasa (1.72jmp).
  32. #    Run the following text with /bin/sh to extract.
  33. #
  34. #    Archive: /usr/src/new/dos/cd/wildcard.shar        
  35. #
  36. #    This archive is a complete distribution by itself.
  37. #
  38. #    Packed under system5 by plocher@hobbes (John Plocher)
  39. #    Packed on Tue Jul 14 20:13:11 1987
  40. #
  41.  
  42. YASASTART=`pwd`
  43.  
  44. echo x - README
  45. if [ -s README ]    # exists & size>0
  46. then
  47.     echo "shar: will not overwrite 'README'"
  48. else
  49.     sed "s/^X//" << \!SHAR-EOF! > README
  50. X  Here is a routine which does wildcard expansion for MS-DOS.
  51. XIt could be spiffed up by using the regex routines by Henry Spencer, but
  52. Xfor now it expands DOS style wildcards (*,?):  (This is also found in
  53. Xthe file example.c)
  54. X
  55. X #include "glob.h"
  56. X main() {
  57. X     char **names;
  58. X     names = glob("*.c");
  59. X     if (names)
  60. X         printf("The first file which matches the wildcard: %s\n",names[0]);
  61. X     else
  62. X         printf("glob() error number %d\n",globerror);
  63. X }
  64. X
  65. XIt also handles the case of "/usr/pl*/bin/*.exe" where "/usr/pl*/bin" is unique.
  66. XUnfortunately, the code does not handle "/*/*/*.c" type expansions.  This is
  67. Xan arbitrary limitation which is left to the student to implement. :-)))))
  68. X
  69. XIt also does not handle "C:/bin/*.exe"  - the drive spec fouls it up,
  70. XMS-DOS seems to have problems with the find first/next functions in the
  71. Xroot directory so "/*.c" may give you problems.
  72. X
  73. XThe shar which follows contains:
  74. X    glob.c  glob.h        - the actual wildcard expansion routines
  75. X    example.c        - a very simple example of its usage
  76. X    chd.c            - a more complex example - implements chdir
  77. X    chd.exe (uuencoded)    - compiled version of chd.c
  78. X    glob.obj (uuencoded)    - linkable module containing glob()
  79. X
  80. XHave fun, mail me if you have problems...
  81. X
  82. X(PS I am not actively using MS-DOS for now, so this code has been sitting 
  83. X"on the shelf" for a bit.  I saw a few comments in comp.sys.ibm.pc concerning
  84. XTurbo C and its lack of wildcard support, so I figured I'd send this out.)
  85. X
  86. X John Plocher        UUCP: <backbone>!uwvax!geowhiz!uwspan!plocher
  87. X==============      Internet: plocher%uwspan.UUCP@uwvax.cs.Wisc.EDU
  88. XFidoNet: 121/0          BITNET: uwvax!geowhiz!uwspan!plocher@psuvax1
  89. !SHAR-EOF!
  90. if [ "`wc -c README`" != "   1638 README" ]
  91. then
  92. echo '   README may be bad'
  93. fi
  94. echo x - chd.c
  95. if [ -s chd.c ]    # exists & size>0
  96. then
  97.     echo "shar: will not overwrite 'chd.c'"
  98. else
  99.     sed "s/^X//" << \!SHAR-EOF! > chd.c
  100. X
  101. X/*
  102. X *    chd.c        change directory
  103. X *            John Plocher
  104. X *
  105. X *    usage:    chd [new directory]
  106. X *
  107. X *        [new directory] may contain wildcards; it may not be ambiguous
  108. X *        If no arguments, use $HOME variable in environment
  109. X *
  110. X *        C:\BIN > set HOME=/usr/plocher
  111. X *        C:\BIN > chd \u*\lo*
  112. X *        C:\USR\LOCAL > chd
  113. X *        C:\USR\PLOCHER >  
  114. X *
  115. X *        uses glob() to expand wildcards in pathname
  116. X *
  117. X *    returns (ERRORLEVEL)
  118. X *
  119. X *        0    No error
  120. X *        1    could not find directory
  121. X *        2    ambiguous pathname
  122. X *        3    directoryname expected, you gave a filename
  123. X *        4    internal error
  124. X *
  125. X *    Change log
  126. X *
  127. X *    Version    Date        Who    Comments
  128. X *    -------    ----        ---    --------
  129. X *    1.00    16-Jan-86    jmp    Initially coded
  130. X *    1.01    21-Jan-86    jmp    Expanded help menu (-?), fixed glob()
  131. X */
  132. X
  133. X#include <stdio.h>
  134. X#include "glob.h"
  135. X
  136. X#define VERSION    "1.01 21-Jan-86"
  137. X/* #define DEBUG */
  138. X
  139. Xchar *sccsid    = "21-Jan-86 (Plocher) @(#)chd.c    1.01";
  140. X
  141. Xextern char *strchr();
  142. Xextern char *getenv();
  143. Xextern char *strdup();
  144. Xextern void usage();
  145. X
  146. Xextern char *filename();
  147. Xextern char *fixslash();
  148. Xextern void recover();
  149. X
  150. Xmain(argc, argv)
  151. Xint argc;
  152. Xchar *argv[];
  153. X{
  154. X    char **names;    /* array of pointers to names returned by glob() */
  155. X    char *progname;    /* name of program (either argv[0] or hardcoded) */
  156. X    char *p;        /* temp string pointer */
  157. X    char errstring[150];/* for usage() errors */
  158. X    char path[127];    /* workspace for getting starting (un-globbed) path */
  159. X
  160. X    if (argv[0])    /* if there is something here, use it (DOS 3.xx+) */
  161. X        progname = filename(argv[0]);
  162. X    else        /* hardcode the program name */
  163. X        progname = "chd";
  164. X
  165. X    if (argc > 2) {    /* must have less than 2 arguments */
  166. X        usage(progname,"Too many arguments");
  167. X        exit(1);
  168. X    }
  169. X    if (argc == 1) {        /* need to get HOME */
  170. X        p = getenv("HOME");    /* p == NULL if not found ... */
  171. X        if (p != NULL)
  172. X            strcpy(path,p);
  173. X        else {
  174. X            usage(progname,"Environment variable HOME not found\n");
  175. X            exit(1);
  176. X        }
  177. X    } else {        /* we have a pathspec from command line */
  178. X        if (argv[1][0] == '-') {    /* if invoked chd -anything, just */
  179. X            usage(progname,NULL);    /* explain ourselves */
  180. X            exit(0);
  181. X        }
  182. X        strcpy(path,argv[1]);
  183. X    }
  184. X
  185. X    fixslash(path);    /* convert all '\'s into '/'s */
  186. X
  187. X    names = glob(path);            /* get files which match */
  188. X    
  189. X    if (names == NULL && globerror == GE_BADPATH) {
  190. X        sprintf(errstring,"Path not found: \"%s\"",path);
  191. X        usage(progname, errstring);
  192. X        recover(names);
  193. X        exit(1);
  194. X    }
  195. X    if ((names == NULL && globerror == GE_AMBIGUOUS) || names[1] != NULL) {
  196. X        sprintf(errstring,"Ambiguous pathname \"%s\"",path);
  197. X        usage(progname, errstring);
  198. X        recover(names);
  199. X        exit(2);
  200. X    }
  201. X    if (chdir(names[0])) {    /* do the actual chdir */
  202. X        usage(progname,"You must specify a DIRECTORY path");
  203. X        recover(names);
  204. X        exit(3);
  205. X    }
  206. X    if (names == NULL && (globerror == GE_MAXFILES || globerror == GE_NOMEM)) {
  207. X        sprintf(errstring,"Internal error: %s",
  208. X        globerror == GE_MAXFILES ? "Too many files" : "Out of memory");
  209. X        usage(progname, errstring);
  210. X        recover(names);
  211. X        exit(4);
  212. X    }
  213. X    recover(names);    /* free memory used by *names[] */
  214. X
  215. X    exit(0);        /* no errors */
  216. X}
  217. X
  218. X/*
  219. X *    usage        tell the workd about this program
  220. X */
  221. Xvoid usage(progname, error)
  222. Xchar *progname;
  223. X{
  224. Xfprintf(stderr,"%s version %s by John Plocher on FidoNet 121/90\n",
  225. X        progname,VERSION);
  226. Xif (error)
  227. X    fprintf(stderr,"\nERROR: %s\n",error);
  228. Xelse {
  229. X fprintf(stderr,"\n%s - a replacement for MS-DOS's chdir & cd commands\n",
  230. X        progname);
  231. X fprintf(stderr,"%s is Copyright 1986 by John Plocher\n\n",progname);
  232. X fprintf(stderr,"%s is released to the NON PROFIT, NON COMMERCIAL public.\n",
  233. X        progname);
  234. X fprintf(stderr,"Commercial rights to %s reserved by John Plocher\n", progname);
  235. X fprintf(stderr,"%s has some features which the DOS version lacks:\n",progname);
  236. X fprintf(stderr,"\t1) ALL wildcards (* and ?) are expanded, no matter where\n");
  237. X fprintf(stderr,"\t   they are in the path.\n");
  238. X fprintf(stderr,"\t\tC:\\ >%s \\u*\\p*\\w*\\?\n",progname);
  239. X fprintf(stderr,"\t\tC:\\USR\\PLOCHER\\WORK\\C >\n");
  240. X fprintf(stderr,"\t2) If %s is invoked without arguments, it will try to\n",progname);
  241. X fprintf(stderr,"\t   change to the directory found in the environment\n");
  242. X fprintf(stderr,"\t   variable HOME.\n");
  243. X fprintf(stderr,"\t\tC:\\ >SET HOME=\\usr\\plocher    -or-\n");
  244. X fprintf(stderr,"\t\tC:\\ >SET HOME=\\u*\\p*\n");
  245. X fprintf(stderr,"\t3) If %s fails, it leaves an indication in ERRORLEVEL.\n",progname);
  246. X fprintf(stderr,"\t   This exit code can be tested in batch files:\n");
  247. X fprintf(stderr,"\t    ERRORLEVEL  Meaning\n");
  248. X fprintf(stderr,"\t    ----------  -------\n");
  249. X fprintf(stderr,"\t\t0    No error\n");
  250. X fprintf(stderr,"\t\t1    could not find directory\n");
  251. X fprintf(stderr,"\t\t2    ambiguous pathname\n");
  252. X fprintf(stderr,"\t\t3    directoryname expected, you gave a filename\n");
  253. X fprintf(stderr,"\t\t4    internal error (let me know about this!)\n\n");
  254. X}
  255. Xfprintf(stderr,"usage: %s <directory name>     change to directory\n",progname);
  256. Xfprintf(stderr,"       %s                      change to HOME\n",progname);
  257. Xfprintf(stderr,"       %s -?                   help screen\n",progname);
  258. X}
  259. X
  260. X/*
  261. X *    filename        extract the filename from a pathname
  262. X *                ie C:\usr\plocher\chd.exe results in chd
  263. X */
  264. Xchar *filename(path)
  265. Xchar *path;
  266. X
  267. X{
  268. X    register char *p, *pd;
  269. X
  270. X    p = strchr(path,'\0');    /* work from the back... */
  271. X    while (--p != path && *p != ':' && *p != '\\' && *p != '/');
  272. X    if (*p == '\\' || *p == '/' || *p == ':')
  273. X        p++;
  274. X    pd = strchr(p,'.');        /* we don't want the .EXE */
  275. X    if (pd != NULL)
  276. X        *pd = '\0';
  277. X    strlwr(p);
  278. X    return (p);
  279. X}
  280. X
  281. X/*
  282. X *    fixslash    convert all '\'s to '/'s
  283. X */
  284. Xchar *fixslash(s)
  285. Xchar *s;
  286. X{
  287. X    register int x;
  288. X
  289. X    if (s == NULL) return;
  290. X    for (x=0; x < strlen(s); x++)
  291. X        if (s[x] == '\\')
  292. X            s[x] = '/';
  293. X}
  294. X
  295. X/*
  296. X *    recover        free up the space malloc()'d in *names[] by glob()
  297. X */
  298. Xvoid recover(names)
  299. Xchar **names;
  300. X{
  301. X    register int i;
  302. X
  303. X    i = 0;
  304. X    while (names[i] != (char *)0) {
  305. X        free(names[i]);
  306. X        i++;
  307. X    }
  308. X    free(names);
  309. X}
  310. X
  311. !SHAR-EOF!
  312. if [ "`wc -c chd.c`" != "   5981 chd.c" ]
  313. then
  314. echo '   chd.c may be bad'
  315. fi
  316. echo x - example.c
  317. if [ -s example.c ]    # exists & size>0
  318. then
  319.     echo "shar: will not overwrite 'example.c'"
  320. else
  321.     sed "s/^X//" << \!SHAR-EOF! > example.c
  322. X/* Example program demonstrating the use of glob() */
  323. X
  324. X#include "glob.h"
  325. X
  326. X main() {
  327. X     char **names;
  328. X     names = glob("*.?");
  329. X     if (names) {
  330. X        printf("expansion of *.? is:\n");
  331. X         print(names);
  332. X     } else
  333. X         printf("glob() error number %d (see glob.h)\n",globerror);
  334. X        recover(names);
  335. X }
  336. X recover(names)        /* free() all the space used up by **names; */
  337. X char **names;
  338. X {
  339. X     int i = 0;
  340. X     while (names[i] != (char *)0) {
  341. X     free(names[i]);
  342. X     i++;
  343. X     }
  344. X     free(names);
  345. X }
  346. X print(names)        /* print out all the filenames returned by glob() */
  347. X char **names;
  348. X {
  349. X     int i;
  350. X     i = 0;
  351. X     while (names[i] != (char *)0) {
  352. X     printf("%s\n",names[i]);
  353. X     i++;
  354. X     }
  355. X }
  356. !SHAR-EOF!
  357. if [ "`wc -c example.c`" != "    681 example.c" ]
  358. then
  359. echo '   example.c may be bad'
  360. fi
  361. echo x - glob.c
  362. if [ -s glob.c ]    # exists & size>0
  363. then
  364.     echo "shar: will not overwrite 'glob.c'"
  365. else
  366.     sed "s/^X//" << \!SHAR-EOF! > glob.c
  367. X
  368. X/*
  369. X *    Copyright 1985, 1986  by John Plocher  Non-commercial use approved
  370. X *
  371. X *    glob    expand a given pathname with wildcards into
  372. X *        an argv[] type array of 'strings' which are
  373. X *        the files (directories) which result from the
  374. X *        expansion of the pathname.  (All characters in
  375. X *        the returned list of filenames are in lower case)
  376. X *
  377. X *    usage:    char **glob(pathname) char *pathname;
  378. X *
  379. X *        pathname is an absolute or relative pathname which may
  380. X *        contain DOS type wildcards wherever desired:
  381. X *
  382. X *            names = glob("\\usr\\pl*\\*.c");
  383. X *
  384. X *    It requires an externally declared int in the main function
  385. X *    named globerror:
  386. X *
  387. X *        extern int globerror;
  388. X *
  389. X *    to be used to return an error indication if glob() fails.
  390. X *    If glob() fails, it returns NULL with
  391. X *
  392. X *    globerror set to GE_BADPATH    invalid path - directory not found
  393. X *    globerror set to GE_AMBIGUOUS    ambiguous directory spec
  394. X *    globerror set to GE_MAXFILES    too many files found (MAXFILES)
  395. X *    globerror set to GE_NOMEM    out of memory
  396. X *
  397. X *    else it returns a pointer to a NULL terminated array of pointers
  398. X *    to 'strings':
  399. X *
  400. X *    +-[ MAIN.C ]----------------------------------------------------+
  401. X *    |                                |
  402. X *    | #include "glob.h"                            |
  403. X *    | main() {                            |
  404. X *    |     char **glob();                        |
  405. X *    |     char **names;                        |
  406. X *    |     names = glob("/u??/p*");                |
  407. X *    |     if (names)                        |
  408. X *    |         printf("the first name returned is %s\n",names[0]);    |
  409. X *    |     else                            |
  410. X *    |         printf("glob() error number %d\n",globerror);    |
  411. X *    |    recover(names);                        |
  412. X *    | }                                |
  413. X *    |                                |
  414. X *    +---------------------------------------------------------------+
  415. X *
  416. X *    ALL strings and the array *names[] are made with calls to
  417. X *    malloc().  Thus, be sure to free() *names[x] AND names when done!
  418. X *
  419. X *    +-[sample routines]---------------------------------------------+
  420. X *    |                                |
  421. X *    |    (* free() all the space used up by **names; *)        |
  422. X *    | recover(names)                        |
  423. X *    | char **names;                            |
  424. X *    | {                                |
  425. X *    |     int i = 0;                        |
  426. X *    |                                |
  427. X *    |     while (names[i] != (char *)0) {                |
  428. X *    |     free(names[i]);                        |
  429. X *    |     i++;                            |
  430. X *    |     }                                |
  431. X *    |     free(names);                        |
  432. X *    | }                                |
  433. X *    |                                 |
  434. X *    |    (* print out all the filenames returned by glob() *)    |
  435. X *    | print(names)                            |
  436. X *    | char **names;                            |
  437. X *    | {                                |
  438. X *    |     int i;                            |
  439. X *    |     i = 0;                            |
  440. X *    |     while (names[i] != (char *)0) {                |
  441. X *    |     printf("%s\n",names[i]);                |
  442. X *    |     i++;                            |
  443. X *    |     }                                |
  444. X *    | }                                |
  445. X *    +---------------------------------------------------------------+
  446. X *
  447. X *    Compile as follows:    (Structures MUST be packed in order for 
  448. X *                 the program to interface correctly with DOS)
  449. X *        cl -c -Zp glob.c    ** Microsoft C v3 or 4 **
  450. X *
  451. X *    Using the example given above, compile and link main program:
  452. X *        cl main.c glob
  453. X *
  454. X *    Written December, 1985 by John Plocher with MicroSoft C 3.0
  455. X *    Change log:
  456. X *
  457. X *    version    date        who    comments
  458. X *    ------- ----        ---    --------
  459. X *    1.0    10-Dec-85    jmp    Orig. coding
  460. X *    1.1    16-Jan-86    jmp    added globerror
  461. X *    1.2    05-Feb-86    jmp    added comments and doccumentation
  462. X *
  463. X */
  464. X
  465. Xstatic char *scssid = "5-Feb-86 (Plocher) @(#)glob.c    1.2";
  466. Xstatic char *copyright =
  467. X    "Copyright 1985, 1986 John Plocher.  Non-commercial use approved";
  468. X
  469. X#include    <stdio.h>
  470. X#include    <dos.h>
  471. X#include    <memory.h>
  472. X#include    <direct.h>
  473. X#include    <string.h>
  474. X#include    "glob.h"
  475. X
  476. X/* Change the following if you might have more than this many    */
  477. X/* files returned by glob()                                      */
  478. X
  479. X#define MAXFILES    256    /* max files returned by glob() */
  480. X
  481. Xstatic char *list[MAXFILES];    /* MAXFILES entries per sub-dir */
  482. X
  483. Xextern char *strlwr();
  484. Xextern int getdir();
  485. Xextern char *pos();
  486. X
  487. Xint globerror;            /* PUBLIC - global error number */
  488. X
  489. X/*
  490. X *    glob()
  491. X */
  492. Xchar **
  493. Xglob(proposed)
  494. Xchar *proposed;
  495. X{
  496. X    int i,j,k,needdir,n;
  497. X    char *end, filename[128], newpath[127], tmppath[127];
  498. X    char *f, *p1, *p2;
  499. X    char **names;
  500. X    
  501. X    strcpy(filename, proposed);
  502. X    
  503. X    /* add on current directory if first char is not '/' or '\' */
  504. X    if (*filename != '/' && *filename != '\\') {
  505. X    getcwd(tmppath,128);
  506. X    p2 = strchr(tmppath,'\0');
  507. X    p2--;
  508. X    if (*p2 != '/' && *p2 != '\\')
  509. X        strcat(tmppath,"/");
  510. X    strcat(tmppath,filename);
  511. X    strcpy(filename, tmppath);
  512. X    }
  513. X    for (i=strlen(filename); i; i--)
  514. X    if (filename[i] == '\\')
  515. X        filename[i] = '/';
  516. X    i = 0; j = 0;
  517. X    p2 = strchr(filename,'\0');
  518. X    p2--;
  519. X    if (*p2 == '.')
  520. X    strcat(filename,"/");
  521. X    while ((p1 = pos("/./",filename)) != NULL) {
  522. X    memccpy(p1+1, p1+3, '\0',strlen(p1));
  523. X    }
  524. X    while ((p1 = pos("../",filename)) != NULL) {
  525. X    char tmp;
  526. X    tmp = *(p1 - 1);
  527. X    *(p1 - 1) = '\0';
  528. X    p2 = strrchr(filename,'/');
  529. X    if (p2 == NULL) {
  530. X        globerror = GE_BADFILE;
  531. X        return(NULL);
  532. X    }
  533. X    *(p1 - 1) = tmp;
  534. X    memccpy(p2+1, p1+3, '\0',strlen(p1));
  535. X    }
  536. X    p2 = strchr(filename,'\0');
  537. X    p2--;
  538. X    if (*p2 == '/')
  539. X    *p2 = '\0';
  540. Xloop:
  541. X    while (filename[i]  != 0 &&        /* copy till hit a wildcard */
  542. X       filename[i]  != '*' &&
  543. X       filename[i]  != '?') {
  544. X    tmppath[j++] = filename[i++];
  545. X    }
  546. X    if (filename[i] != 0)    /* wildcard found */
  547. X    while (filename[i]  != 0 &&
  548. X           filename[i]  != '/')
  549. X        tmppath[j++] = filename[i++];
  550. X    if (filename[i] != 0)    /* need directory here */
  551. X    needdir = 1;
  552. X    else            /* any file will do */
  553. X    needdir = 0;
  554. X    tmppath[j] = 0;
  555. X    strcpy(newpath,tmppath);
  556. X    end = strrchr(newpath,'/');
  557. X    if  (end != NULL)
  558. X      *end = '\0';
  559. X      
  560. X    n = getdir(tmppath,needdir);
  561. X
  562. X    if (n == -2) {    /* out of dynamic memory */
  563. X    globerror = GE_NOMEM;
  564. X    return(NULL);
  565. X    }
  566. X    if (n == -1) {    /* exceeded filecount */
  567. X    globerror = GE_MAXFILES;
  568. X    return(NULL);
  569. X    }
  570. X    if (n == 0) { /* file not found */
  571. X    globerror = GE_BADFILE;
  572. X    return(NULL);
  573. X    }
  574. X    if (needdir && n != 1) { /* ambiguous directory reference */
  575. X    for (i = 0; i < n; i++)        /* This is an arbitrary limit */
  576. X        free(list[i]);        /* one could follow all paths */
  577. X    globerror = GE_AMBIGUOUS;    /* and not just the first...  */
  578. X    return(NULL);
  579. X    }
  580. X    if (needdir) {
  581. X    strcpy(tmppath,newpath);
  582. X    strcat(tmppath,"/");
  583. X    strcat(tmppath,list[0]);
  584. X    free(list[0]);
  585. X    j = strlen(tmppath);
  586. X    goto loop;
  587. X    }
  588. X
  589. X    names = (char **)malloc((n+1) * sizeof(char *));
  590. X    for (i = 0; i < n; i++) {
  591. X    sprintf(tmppath,"%s/%s", newpath, list[i]);
  592. X    names[i] = strdup(tmppath);
  593. X    free(list[i]);
  594. X    }
  595. X    names[n] = (char *)0;
  596. X
  597. X    return(names);
  598. X}
  599. X
  600. X/*
  601. X *    pos(target, src)
  602. X *            find target string within src
  603. X */
  604. Xstatic char *pos(s1,s2)
  605. Xchar *s1, *s2;
  606. X{
  607. X    int temploc, dist;
  608. X    char *tp;
  609. X
  610. X    if (*s1) {
  611. X    for (;;) {
  612. X        tp = strchr(s2, *s1);
  613. X        if (tp == NULL) {        /* couldn't even find first char */
  614. X        return(NULL);
  615. X        }
  616. X        if (!strncmp(s1,tp,strlen(s1)))    /* match */ {
  617. X        return(tp);
  618. X        }
  619. X        s2 = tp + 1;
  620. X    }
  621. X    }
  622. X}
  623. X
  624. X/*
  625. X *    File attributes
  626. X */
  627. X
  628. X#define AT_RO        0x01    /* Read Only */
  629. X#define AT_HIDDEN    0x02    /* hidden file */
  630. X#define    AT_SYSTEM    0x04    /* System file */
  631. X#define AT_LABEL    0x08    /* volume label */
  632. X#define AT_DIR        0x10    /* sub directory */
  633. X#define AT_ARCH        0x20    /* archive bit */
  634. X
  635. Xstatic struct REGS rregs;
  636. Xstatic struct SREGS sregs;
  637. X
  638. Xstatic struct DMA {            /* For reading directory entry    */
  639. X    char res[21];
  640. X    char attr;
  641. X    unsigned sec : 5, min : 6, hour : 5;
  642. X    unsigned day : 5, mon : 4, year : 7;
  643. X    long size;
  644. X    char name[13];
  645. X} dma;
  646. X
  647. X/*
  648. X *    getdir        gather all the files found in this directory
  649. X */
  650. Xstatic int 
  651. Xgetdir(path, needdir)    /* return number of 'files' found in this path */
  652. Xchar  *path;        /* this is where to look */
  653. Xint needdir;        /* 1 = we want ONLY AT_DIR type entries */
  654. X            /* 0 = we will take EVERYTHING */
  655. X{
  656. X    int i, j, n;
  657. X    char *entry;
  658. X
  659. X    bdos(0x1a, &dma,0);
  660. X
  661. X    n = 0;
  662. X    rregs.h.ah = 0x4e;
  663. X    rregs.x.cx = AT_RO | AT_HIDDEN | AT_SYSTEM | AT_DIR;
  664. X    rregs.x.dx = (unsigned int) path;
  665. X    j = intdos(&rregs, &rregs);        /* Search for first    */
  666. X    while(j == 0) {
  667. X    strlwr(dma.name);
  668. X    if (needdir && (dma.attr & AT_DIR != AT_DIR)){ /* skip this entry */
  669. X        rregs.h.ah = 0x4f;        /* wes needs dirs, and this ain't one */
  670. X        j = intdos(&rregs, &rregs);/* Search for next    */
  671. X        continue;
  672. X    }
  673. X    entry = strdup(dma.name);
  674. X    if (entry == NULL) {        /* out of memory */
  675. X        for (i = 0; i < n; i++)
  676. X        free(list[i]);
  677. X        return (-2);
  678. X    }
  679. X    if (n >= MAXFILES)        /* too many files found */
  680. X        return(-1);
  681. X    for (i = n++; i > 0; --i) {    /* alphabetize */
  682. X        if (strcmp(entry, list[i - 1]) >= 0)
  683. X        break;
  684. X        list[i] = list[i - 1];
  685. X    }
  686. X    list[i] = entry;
  687. X    rregs.h.ah = 0x4f;
  688. X    j = intdos(&rregs, &rregs);        /* Search for next    */
  689. X    }
  690. X    return(n);
  691. X}
  692. X
  693. !SHAR-EOF!
  694. if [ "`wc -c glob.c`" != "   8494 glob.c" ]
  695. then
  696. echo '   glob.c may be bad'
  697. fi
  698. echo x - glob.h
  699. if [ -s glob.h ]    # exists & size>0
  700. then
  701.     echo "shar: will not overwrite 'glob.h'"
  702. else
  703.     sed "s/^X//" << \!SHAR-EOF! > glob.h
  704. X/*
  705. X *    Header file for wildcard routines 
  706. X */
  707. X
  708. X#define GE_BADPATH     -1    /* invalid path - directory not found    */
  709. X#define GE_AMBIGUOUS     -2    /* ambiguous directory spec        */
  710. X#define GE_MAXFILES     -3    /* too many files found (MAXFILES)    */
  711. X#define GE_NOMEM     -4    /* out of memory            */
  712. X
  713. Xextern int globerror;        /* PUBLIC - global error number */
  714. Xextern char **glob( char * );
  715. X
  716. !SHAR-EOF!
  717. if [ "`wc -c glob.h`" != "    362 glob.h" ]
  718. then
  719. echo '   glob.h may be bad'
  720. fi
  721. echo x - make.bat
  722. if [ -s make.bat ]    # exists & size>0
  723. then
  724.     echo "shar: will not overwrite 'make.bat'"
  725. else
  726.     sed "s/^X//" << \!SHAR-EOF! > make.bat
  727. XREM    makefile for glob routines by John Plocher
  728. XREM    glob is a routine which expands DOS style wildcards into an argv array
  729. X
  730. XREM    Microsoft C 3.0 and 4.0        -Must pack structures in glob.c-
  731. X
  732. Xcl -O -c -Zp glob.c
  733. Xcl -O chd.c glob -o chd
  734. X
  735. !SHAR-EOF!
  736. if [ "`wc -c make.bat`" != "    231 make.bat" ]
  737. then
  738. echo '   make.bat may be bad'
  739. fi
  740. exit
  741.