home *** CD-ROM | disk | FTP | other *** search
- /*
- *==========================================================================
- * rm - lists all matching directory entries in a path. wildcards are
- * allowed in the pattern. user chooses whether to delete the files.
- * a recursive search of sub-directories is supported.
- *
- * usage: rm [-r] [drive:][path]filespec
- * r = recursively search sub-directories below path
- *
- * compile: msc rm; [Microsoft C version 3.0 ]
- * link : link rm; [Microsoft Link ver. 3.01]
- *
- * note : the stack may be adjusted if necessary
- *==========================================================================
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <dos.h>
-
- #define DRIVE 0x0E /* select default drive */
- #define FINDFIRST 0x4E /* find first matching file */
- #define FINDNEXT 0x4F /* find next matching entry */
- #define SETDTA 0x1A /* set disk transfer address */
-
- #define SUBDIR 0x10 /* file attribute: sub-direct */
- #define FILES 0x00 /* file attribute: reg-files */
-
- #define INVALID 0x12 /* invalid search parameter */
- #define NOTFOUND 0x02 /* pattern not matched */
-
- #define FALSE 0
- #define TRUE 1
-
- #define PATHLEN 256 /* maximum length of path */
- #define NAMELEN 13 /* maximum length of filename */
-
- typedef struct /* MS-DOS disk transfer block */
- {
- char sysinfo[21]; /* system information */
- char attrib; /* file attributes */
- int filtime; /* time of file */
- int fildate; /* date of file */
- long filsize; /* size of file in bytes */
- char fname[NAMELEN]; /* filename and extension */
- } DIR;
-
- DIR dtawrk; /* working DTA block */
-
- char basepath[PATHLEN]; /* search path if given */
- char cur_path[PATHLEN]; /* current path at beginning */
- char loc_path[PATHLEN]; /* local directory path */
-
- int basedir; /* recursive search counter */
- int found; /* number of matching entries */
- int deleted; /* number of deleted matches */
-
- struct SREGS segregs; /* segment registers */
- union REGS regs; /* union for registers */
-
- void abend(), usage(), s_dta(),
- s_drive(), restore(), pg_files();
-
- /*
- *=================================================================
- * abnormal termination routine
- * this function is called for the following reasons:
- * 1. the filespec is too long [13 characters max.].
- * 2. the pathlength exceeds buffer space allocated [256].
- * 3. the drivespec does not exist, or is not in proper format.
- *=================================================================
- */
- void abend(msg)
- char *msg; /* termination error message */
- {
- restore();
- fputs(msg, stderr);
- exit(1);
- }
-
- /*
- *=======================================================
- * explain usage of utility
- * called if invalid number of parameters in command
- * line, or option parameter is invalid.
- *=======================================================
- */
- void usage()
- {
- fputs("usage: rm [-r] [drive:][path]filespec...\n", stderr);
- exit(1);
- }
-
- /*
- *=================================================
- * set the Disk Transfer Address to our buffer area
- * using segment register for full address.
- *=================================================
- */
- void s_dta()
- {
- segread(&segregs);
- regs.h.ah = SETDTA;
- regs.x.dx = &dtawrk;
- intdosx(®s, ®s, &segregs);
- }
-
- /*
- *=======================================================
- * select chosen drive
- * this DOS call does not return an error value in
- * the normal way. it returns the number of drives
- * currently available. if the chosen drive was
- * out of this range, no drive-change was done.
- *=======================================================
- */
- void s_drive(d)
- char *d; /* drive string */
- {
- unsigned drv;
-
- drv = toupper(*d) - 'A';
- regs.h.ah = DRIVE;
- regs.h.dl = drv;
- intdos(®s, ®s);
-
- if (regs.h.al < drv)
- abend("\ninvalid drive...\n");
- }
-
- /*
- *===============================================================
- * restore drive and directory to original values
- * of course, if original working drivespec was not changed,
- * no drive-change is needed, but why add the test logic?
- *===============================================================
- */
- void restore()
- {
- char dr[3]; /* drive */
-
- strncpy(dr, cur_path, 2);
- s_drive(dr);
- chdir(cur_path);
- }
-
- /*
- *==============================================================
- * search directory(s), print all matches and query for deletion
- *==============================================================
- */
- void pg_files(xtn, str)
- int xtn; /* extended search flag */
- char *str; /* pattern search template */
- {
- char dta_buf[21]; /* system info for search */
- char query; /* user response to match */
-
- /*
- * recursive search through sub-directories if requested
- */
-
- if (xtn)
- {
- regs.h.ah = FINDFIRST;
- regs.x.cx = SUBDIR; /* look for directory */
- regs.x.dx = "*."; /* wild card for directories */
- intdos(®s, ®s);
-
- /*
- * if we fail here, something is wrong.
- * all directories have "." and ".." .
- */
-
- if (regs.x.ax == NOTFOUND || regs.x.ax == INVALID)
- {
- if (basedir)
- {
- chdir("..");
- basedir--;
- }
- return; /* invalid path, or no match */
- }
-
- /*
- * as long as we keep finding subdirectories
- * skip past "." and ".."
- */
-
- while (regs.x.ax != INVALID)
- {
- if ((dtawrk.attrib & SUBDIR) && (dtawrk.fname[0] != '.'))
- {
-
- /*
- * save our place and recurse (??)
- */
-
- memcpy(dta_buf, dtawrk.sysinfo, 21);
- chdir(dtawrk.fname);
- ++basedir;
- pg_files(xtn, str);
-
- /*
- * restore our search position and
- * continue the search.
- */
-
- memcpy(dtawrk.sysinfo, dta_buf, 21);
- }
- regs.h.ah = FINDNEXT;
- intdos(®s, ®s);
- }
- }
-
- /*
- * at this point, we are either in the current directory, or
- * somewhere in a subdirectory in an extended search. the
- * function getcwd() tells us where we are and we print it.
- */
-
- if (getcwd(loc_path, PATHLEN) == NULL)
- abend("\ncurrent pathname exceeds buffer space...\n");
-
- printf("\ncurrently looking in: %s\n", loc_path);
-
- /*
- * now we look for the pattern and print out any matches found
- */
-
- regs.h.ah = FINDFIRST;
- regs.x.cx = FILES;
- regs.x.dx = str;
- intdos(®s, ®s);
-
- if (regs.x.ax != NOTFOUND && regs.x.ax != INVALID)
- {
- while (regs.x.ax != INVALID)
- {
- printf("delete: %-15s [y/n] ", dtawrk.fname);
-
- if (query = getche() == 'y' || query == 'Y')
- {
- unlink(dtawrk.fname);
- ++deleted;
- }
-
- putchar('\n');
- ++found;
- regs.h.ah = FINDNEXT;
- intdos(®s, ®s);
- }
- }
-
- /*
- * if we were in a subdirectory, back up one
- */
-
- if (basedir)
- {
- basedir--;
- chdir("..");
- }
-
- return;
- }
-
- /*
- *===========================================================
- * main: test parameter count, find out where we are, do some
- * rudimentary validity checking and parsing of the
- * command line parameter(s), call the search routine,
- * and print total matches found, files deleted.
- *===========================================================
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char drive[3]; /* drivespec */
- char pattern[NAMELEN]; /* search pattern */
- char *baseptr, *patptr; /* parse pointers */
- int recurse; /* scope of search */
-
- if (argc < 2 || argc > 3)
- usage(); /* test parameter count */
-
- /*
- * find out where we are and store it
- */
-
- if (getcwd(cur_path, PATHLEN) == NULL)
- {
- fputs("\nlarger pathname buffer needed\n", stderr);
- exit(1);
- }
-
- /*
- * establish a working DTA and initialize variables
- */
-
- s_dta();
- found = 0;
- basedir = 0;
- *basepath = NULL;
- drive[0] = NULL;
- pattern[0] = NULL;
- baseptr = NULL;
- patptr = NULL;
- recurse = FALSE;
-
- /*
- * check for recursion flag
- */
-
- if (argc == 3)
- if (strcmp(*++argv, "-r") && strcmp(*argv, "-R"))
- usage();
- else
- recurse = TRUE;
-
- /*
- * parse search template. check for drive, path, and filespec.
- */
-
- patptr = strrchr(*++argv, '\\'); /* look for last backslash */
-
- if (patptr == NULL)
- {
- patptr = strrchr(*argv, ':'); /* check for drivespec */
-
- if (patptr == NULL)
- patptr = *argv;
- else
- ++patptr;
- }
- else
- ++patptr;
-
- if (strlen(patptr) >= NAMELEN)
- abend("\nsearch template too long...\n");
- else
- {
- strcpy(pattern, patptr);
- *patptr = NULL;
- }
-
- /*
- * the filespec pattern has been found, and argv
- * has been shortened. if anything is left, it
- * must be a drivespec and/or pathname.
- */
-
- if (**argv)
- {
- baseptr = strrchr(*argv, ':');
-
- if (baseptr == NULL)
- baseptr = *argv;
- else
- ++baseptr;
- }
-
- /*
- * if we have a pathname, we must see if more than
- * one backslash occurs. if we started with a
- * string like "\*.h", the correct path is "\".
- * if the string was "\c\*.h", the correct path is
- * "\c", not "\c\".
- */
-
- if (baseptr)
- {
- if (strchr(baseptr, '\\') != strrchr(baseptr, '\\'))
- *(baseptr + strlen(baseptr) - 1) = NULL;
-
- if (strlen(baseptr) >= PATHLEN)
- abend("\nsearch path too long...\n");
- else
- {
- strcpy(basepath, baseptr);
- *baseptr = NULL;
- }
- }
-
- /*
- * anything left over must be a drivespec, and
- * must be two characters, the first being an
- * alphabetic and the second being ":".
- */
-
- if (**argv)
- if (strlen(*argv) == 2 && isalpha(**argv) && *(*argv + 1) == ':')
- strcpy(drive, *argv);
- else
- abend("\ninvalid drive...\n");
-
- /*
- * make the search here
- */
-
- if (drive[0])
- s_drive(drive);
-
- if (*basepath)
- if (chdir(basepath))
- abend("\ncould not access specified directory...\n");
-
- pg_files(recurse, pattern);
-
- restore();
-
- /*
- * display the results
- */
-
- printf("\n\nTOTAL MATCHES FOUND: %d\n", found);
- printf("TOTAL FILES DELETED: %d\n", deleted);
- exit(0);
- }