home *** CD-ROM | disk | FTP | other *** search
- /* C.Dirscan: Get filenames for a wildcarded value */
-
- /* Use as:
- *
- * for (file = dirscan(wild); file; file = dirscan(0))
- * ...
- *
- * Specifying an argument other than 0 restarts the scan with the
- * new wildcard value.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "kernel.h"
- #include "swis.h"
-
- /* Constants. The function assumes that a directory can hold no more than
- * MAX_DIR entries, and a filename can be no longer than NAME_LEN characters.
- * It also assumes that OS_GBPB 9 will only ever fail to return all possible
- * filenames on the first call if the supplied buffer becomes full. In this
- * case, dirscan() will ignore any omitted entries. This behaviour is not
- * ideal, but gains significantly in efficiency. (The given buffer size
- * should be easily enough for all normal cases).
- */
- #define MAX_DIR 255
- #define NAME_LEN 10
- #define BUFFER_SIZE (MAX_DIR * (NAME_LEN + 1))
-
- char *dirscan (const char *f)
- {
- int len;
- int dot_stripped = 0;
- const char *file;
- _kernel_swi_regs regs;
-
- static char *ptr = NULL;
- static int num_left = 0;
- static char *buffer = NULL;
- static char *name;
- static char res[255];
-
- if (f && *f)
- {
- /* Delete any old buffer */
- if (buffer)
- {
- free (buffer);
- buffer = NULL;
- }
-
- /* Try for a directory prefix */
- file = strrchr (f, '.');
-
- /* If not, try for a filing system prefix */
- if (file == NULL)
- {
- if (*f == '-')
- file = strchr (f + 1, '-');
- else
- file = strchr (f, ':');
- }
-
- if (file == NULL)
- {
- /* We have a simple file name, with no directory. So
- * we set name to point to the place to store the
- * file name (ie, res), and we temporarily set res
- * to hold the directory name (ie, ""). We also set
- * file to the file name f.
- */
- name = res;
- file = f;
- name[0] = '\0';
- }
- else
- {
- /* More work to do. Set res up with the directory,
- * as above, and point name to the place to put the
- * file name(s). And set file to the file name.
- */
-
- len = file - f + 1;
-
- /* Do not allow file names over 255 characters
- * (ie, 245 for the directory, and 10 for the
- * base name).
- */
- if (len > 245)
- return 0;
-
- /* Build the start of the file name to be returned */
- strncpy (res, f, len);
- name = &res[len];
-
- /* Temporarily, put the name of the directory to scan
- * into res. At the moment, res holds "dir." or "FS:"
- * without a NULL terminator. If the former, we must
- * temporarily remove the dot and add a NULL, but if
- * the latter, we must add the current directory
- * name "@".
- */
- if (*file == '.')
- {
- dot_stripped = name[-1];
- name[-1] = '\0';
- }
- else
- {
- name[0] = '@';
- name[1] = '\0';
- }
-
- /* Now, set file to the base file name */
- ++file;
- }
-
- /* Is the file name wildcarded? */
- if (!strchr (file, '*') && !strchr (file, '#'))
- {
- /* If not, we return the name we were handed,
- * and remember not to return any more later.
- */
-
- /* First restore the proper prefix */
- if (dot_stripped)
- name[-1] = dot_stripped;
-
- strcpy (name, file);
- num_left = 0;
- return res;
- }
- else
- {
- /* OK, this is the big one. We set up a buffer, and
- * read all the names from the selected directory
- * which match the pattern into it.
- */
-
- buffer = malloc (BUFFER_SIZE) ;
- if (buffer == NULL)
- return 0;
-
- regs.r[0] = 9;
- regs.r[1] = (int) res;
- regs.r[2] = (int) buffer;
- regs.r[3] = BUFFER_SIZE;
- regs.r[4] = 0;
- regs.r[5] = BUFFER_SIZE;
- regs.r[6] = (int) file;
-
- if (_kernel_swi (OS_GBPB, ®s, ®s))
- return 0;
-
- /* Now restore the proper prefix */
- if (dot_stripped)
- name[-1] = dot_stripped;
-
- /* If there were no entries to find, say so */
- if (regs.r[3] == 0)
- {
- num_left = 0;
- free (buffer);
- buffer = NULL;
- return 0;
- }
-
- /* Remember how many more to return and set ptr
- * ready to return the next one.
- */
- num_left = regs.r[3] - 1;
- ptr = buffer + strlen (buffer) + 1;
-
- /* Return the first one */
- strcpy (name, buffer);
- return res;
- }
- }
-
- /* If we've run out of names to return, free the buffer and stop */
- if (num_left == 0)
- {
- if (buffer)
- {
- free (buffer);
- buffer = NULL;
- }
- return 0;
- }
-
-
- /* Return the next entry in the buffer, and move on in the buffer */
- strcpy (name, ptr);
- ptr += strlen(ptr) + 1;
- --num_left;
-
- return res;
- }
-
- #ifdef TEST
- #include <stdio.h>
-
- int main (int argc, char *argv[])
- {
- char *name;
-
- while (--argc > 0)
- {
- printf("Scanning %s\n", *++argv);
- for (name = dirscan(*argv); name; name = dirscan(0))
- printf("%s\n", name);
- }
-
- return 0;
- }
- #endif
-