home *** CD-ROM | disk | FTP | other *** search
- /* ------------------------------------------------------------ *
- * This is 'glob ()' version 1.04 (11/27/87) by Bob Kamins. *
- * ------------------------------------------------------------ *
- * int glob (argc, argv, attr) *
- * int *argc; <- pointer to argument count *
- * char **argv []; <- pointer to argument array pointer *
- * char attribute; <- file search attribute *
- * ----------------------------------------------------------- *
- * 'glob ()' will expand ambiguous file name arguments (using *
- * wildcards) into unambiguous file names that can be used by *
- * an application program. The expanded arguments and count *
- * replace the old 'argc' and 'argv', so that an existing *
- * application program will require minimal changes. *
- * *
- * 'glob ()' uses ms-dos functions 0x4e and 0x4f ('findfirst' *
- * and 'findnext') to find each expanded name, which is then *
- * installed in a newly allocated memory space. When all of *
- * the names have been found, a new 'argv' array is allocated *
- * and the old 'argv' and 'argc' are overwritten. The memory *
- * used by the old 'argv' array and its associated elements *
- * is lost (except for 'argv [0]'.) *
- * *
- * I decided to sort all of the names except 'argv [0]' (with *
- * 'qsort ()') after the new 'argv' array is made. This is *
- * not entirely compatible with most Unix shells: they will *
- * return the new arguments sorted within the original ufn's. *
- * We can easily do that, but I'm not sure that there is any *
- * tremendous advantage to it. *
- * ------------------------------------------------------------ *
- * Usage: *
- * *
- * main (int argc, char *argv []) /* usual invocation *
- * { *
- * int i; *
- * glob (&argc, &argv, attr); /* pass the addresses *
- * for (i = 0; i < argc; i++) /* just like before *
- * { *
- * ...blah - blah - blah *
- * ------------------------------------------------------------ *
- * 'glob ()' returns a negative value if any error occurs and *
- * zero otherwise. *
- * ============================================================ *
- * 11/28/87 (1.06): If an argument is enclosed in single *
- * quotes, it is considered not to be *
- * globbable. The quotes should be *
- * removed and the argument should not *
- * be expanded (see 'expand ()'.) *
- * ------------------------------------------------------------ *
- */
-
- #include <stdio.h>
- #include <dir.h>
-
- static char *first; /* first element of expanded argument list */
- static int newc; /* new argc */
-
- /* ------------------------------------------------------------- *
- * 'insert ()' puts a (possibly) expanded file name in the next *
- * position in the list and updates the count in 'newc'. *
- * ------------------------------------------------------------- *
- * The function will return zero if no error occurred or -1 if *
- * the 'sbrk ()' fails. *
- * ------------------------------------------------------------- */
-
- static int insert (char *newname)
- {
- char *p;
-
- if (((int) (p = (char *) sbrk (strlen (newname) + 1))) == -1)
- return (-2); /* 'sbrk ()' failed */
- if (first == NULL)
- first = p;
- while ((*p++ = *newname++) != 0) /* copy newname */
- ;
- newc++; /* bump the argument counter */
- return (0); /* normal return */
- }
-
- /* ------------------------------------------------------------- *
- * 'fullname ()' returns a pointer to the drive/path/file name *
- * if one was used in the original argument. Note that the *
- * abbreviation '..' is not translated to a to a full drive/- *
- * path/name specification (although this could be done) but *
- * returned as '..', which is sufficient to perform most types *
- * of operations (open/read/write/close) on the file. *
- * ------------------------------------------------------------- */
-
- static char *fullname (char *argv, char *name)
- {
- int res;
- char path [MAXDIR]; /* holds the path temporarily */
- static char fullpath [MAXPATH]; /* holds the drive at first */
-
- res = fnsplit (argv, &fullpath, &path, NULL, NULL);
- if ((res & DIRECTORY) > 0) /* add path name */
- strcat (fullpath, path);
- strcat (fullpath, name); /* add file name */
- strupr (fullpath); /* everything in upper case */
- return (fullpath);
- }
-
- /* ------------------------------------------------------------- *
- * 'expand ()' checks an argument for wildcards, expands it if *
- * neccessary, and saves the expansion (or original, if no *
- * wildcards were found) in a list. *
- * ------------------------------------------------------------- *
- * If errors are detected (during 'insert ()'), 'expand ()' is *
- * terminated and the error is returned to the caller. *
- * ------------------------------------------------------------- */
-
- static int expand (char *argv, unsigned char attr)
- {
- int ret, /* stores 'insert ()' return code */
- done; /* controls 'findnext ()' loop */
- struct ffblk ffblk; /* used by 'findfirst ()' & 'findnext ()' */
-
- if ((strpbrk (argv, "*?")) == NULL)
- { /* no wildcards in this argument */
- if ((ret = insert (argv)) < 0)
- return (ret); /* 'insert ()' returned error */
- }
-
- else /* this argument has wildcards -- expand it... */
- {
- done = findfirst (argv, &ffblk, attr);
- while (!done)
- {
- if ((ret = insert (fullname (argv, ffblk.ff_name))) < 0)
- return (ret); /* function returned error */
- done = findnext (&ffblk);
- }
- }
- return (0); /* normal return */
- }
-
- /* ------------------------------------------------------------- *
- * 'makearray ()' traverses the argument list and creates the *
- * new 'argv' pointer array. Zero is returned if no error or *
- * -2 if a memory allocation error occurs. *
- * ------------------------------------------------------------- */
-
- static int makearray ()
- {
- int i; /* loop index counter */
- char **p; /* pointer to array element */
-
- p = (char **) sbrk (newc * sizeof (char *));
- if ((int) p == -1) /* 'sbrk ()' failed */
- return (-3);
-
- for (i = 0; i < newc; i++) /* for each new argument */
- {
- *p++ = first++; /* set array element to address of string */
- while (*first++ != 0) /* look for end of string */
- ;
- }
- return (0);
- }
-
- /* ---------------------------------------------------------- *
- * 'fcmp ()' is the comparison function for 'qsort' below. *
- * ---------------------------------------------------------- */
-
- static int fcmp (char **a, char **b)
- {
- return (strcmp (*a, *b));
- }
-
- /* ---------------------------------------------------------- *
- * The main 'glob ()' function expands wildcarded arguments *
- * passed in 'argv' and plugs new values into 'argv' and *
- * 'argc'. Zero is returned if no errors occur, or else a *
- * negative number indicating the type of error is returned: *
- * -1: 'sbrk ()' in 'glob ()' failed. *
- * -2: 'sbrk ()' in 'insert ()' failed. *
- * -3: 'sbrk ()' in 'makearray ()' failed. *
- * ---------------------------------------------------------- */
-
- int glob (int *argc, char **argv [], unsigned char attr)
- {
- int i,
- ret; /* holds function return values */
- char **p; /* pointer to 'argv [0]' */
-
- /*
- * save each argument or expansion in a list:
- */
- newc = 0;
- first = NULL;
- for (i = 1; i < *argc; i++)
- {
- if ((ret = expand ((*argv) [i], attr)) < 0)
- return (ret); /* 'expand ()' returned error */
- }
-
- /*
- * save old 'argv [0]' (program name) in new 'argv' array:
- */
- p = (char **) sbrk (sizeof (char *));
- if ((int) p == -1)
- return (-1); /* 'sbrk ()' failed */
- *p = *argv [0]; /* save address of old 'argv [0]' */
- *argv = p; /* point to second element in new array */
- *argc = newc + 1;
- if ((ret = makearray ()) < 0)
- return (ret);
- qsort (&((*argv) [1]), newc, sizeof (char **), fcmp);
- return (0);
- }
-