home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************/
- /***************************************************************************/
- /** QuickC source for TRUNK **/
- /** command line--> QCL /c /AS /Gs /Ox TRUNK.C **/
- /** --> LINK TRUNK.OBJ,TRUNK.EXE,,c:...\SLIBCE.LIB /ST:0x1000 **/
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** TRUNK -- a replacement for the MS-DOS 'TREE' command. TREE allows only
- *** one option ('/f'--similar to the one implemented in TRUNK), and its output
- *** is verbose and completely unsuited for passing to other programs. TRUNK
- *** is fully redirectable using MS-DOS redirection and pipes.
- ***
- *** Command line option flags are evaluated in left-to-right order.
- *** Flags may conflict with each other, and the flag to the right takes
- *** precedence--e.g. the command line 'TRUNK /f /o' will print only a
- *** summary, no file names.
- ***
- *** One significant departure from DOS is that TRUNK considers the root to be
- *** a directory like any other when summarizing directory structure (obeying
- *** the /s or /o flag). CHKDSK, on the other hand, reports the number of
- *** *subdirectories* and leaves the existence of the root directory implied.
- *** This difference (more semantic than functional) means that when TRUNK is
- *** applied to an entire disk, the number of directories reported found will
- *** be one greater than the number of subdirectories reported by CHKDSK.
- ***
- *** Official TRUNK soundtrack:
- *** "Fleetwood Mac in Chicago" Sire: SASH 3175-2 (C) 1975, or
- *** Blue Horizon: BH 3801 (C) 1969
- ***
- *** Enjoy.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <errno.h>
- #include <string.h>
- #include <direct.h>
- #include <conio.h>
-
- #include "trunk.h"
-
- int dirs_found=0;
- int files_found=0;
- unsigned srch_attrib=_A_NORMAL | _A_RDONLY | _A_SUBDIR;
- int summary=0;
- int print_dirs=1;
- int print_files=0;
- int print_drive=0;
- int print_path=1;
- int force_lower=0;
- int screenfull_pause=0;
- int screen_lines;
- int help=0;
- int info=0;
- unsigned search_drive;
- unsigned home_drive;
- char dflt_match[]="*.*";
- char *match_ptr=dflt_match;
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** main
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- void main(int argc, char *argv[])
-
- {
- path current_dir;
- char *home_cwd_ptr=current_dir;
- char *alt_cwd_ptr=current_dir;
- path search_dir;
- char *search_ptr=search_dir;
- int n;
- char summary_buf[55];
-
-
-
- /**
- *** Process any command line arguments that are flags. The last argument
- *** is assumed to be the pathname. Since the pathname is not required, the
- *** last argument may be a flag as well. If the last argument is a flag, it
- *** is assumed that there is no pathname.
- **/
- if (argc > 1) {
- for (n=1; n < argc; n++) /* argv[0] always == TRUNK */
- {
- if (argv[n][0] == '/')
- switch ( locase(argv[n][1]) ) {
- case 'y': srch_attrib |= _A_SYSTEM;
- case 'h': srch_attrib |= _A_HIDDEN;
- break;
- case 'n': if (argv[n][2] == 'd')
- print_drive=2;
- if (argv[n][2] == 'p')
- print_path=0;
- break;
- case 'o': print_dirs=0;
- print_files=0;
- case 's': summary=1;
- break;
- case 'f': print_dirs=0;
- print_files=1;
- break;
- case 'm': if (argv[n][2])
- match_ptr=&argv[n][2];
- break;
- case 'l': force_lower=1; break;
- case 'p': screenfull_pause=atoi(&argv[n][2]);
- if (screenfull_pause < 1)
- screenfull_pause=DEFLT_SCRFULL;
- screen_lines=0;
- break;
- case 'v': display_line(version);
- return;
- case '?': help=1; break;
- case '$': info=1; break;
- }
- } /* for (n=1; n < argc-1; n++) */
- }
-
- /**
- *** If help was requested (through the /? flag or by TRUNK ?), print a help
- *** message and quit. Ditto for TRUNK information (/$). Both of these
- *** options terminate TRUNK before anything interesting happens.
- **/
- if ( (help) || (argv[1][0] == '?') ) {
- display_strings(help_msg);
- return;
- }
- if (info) {
- display_strings(info_msg);
- return;
- }
-
- /**
- *** If there are command line arguments, then the last one may be the
- *** path to search on. If the last argument (argv[argc-1]) is not a flag,
- *** then it is assumed to be the search path.
- ***
- *** If there is a drive specified in the pathname which is not the current
- *** drive, then the current drive is switched to that drive, the current
- *** working directory of that drive is retrieved, and the current drive is
- *** reset to its original state.
- ***
- *** If there is no search path in the command line, then the current
- *** working directory is used as the search path.
- **/
-
- /* Get the current working directory for later */
- getcwd(home_cwd_ptr, sizeof(path));
-
- if ( (argc == 1) || (argv[argc-1][0] == '/') )
- search_ptr=home_cwd_ptr;
- else {
- strcpy(search_ptr, argv[argc-1]);
- if ( (search_ptr[0] == home_cwd_ptr[0]) && (search_ptr[1] == ':') )
- search_ptr+=2;
- if (search_ptr[1] != ':')
- get_targetdir(search_ptr, home_cwd_ptr);
- else {
- home_drive=locase(home_cwd_ptr[0])-'a'+1;
- search_drive=locase(search_ptr[0])-'a'+1;
- if(change_drive(search_drive) != 0) {
- puts(sys_errlist[EINVAL]);
- return;
- }
- getcwd(alt_cwd_ptr, sizeof(path));
- if (search_ptr[2] == '\0')
- search_ptr=alt_cwd_ptr;
- get_targetdir(search_ptr, alt_cwd_ptr);
- change_drive(home_drive);
- }
- }
-
- /**
- *** go for it
- **/
- if (force_lower)
- strlwr(search_ptr);
- if (search_ptr[0])
- delve(search_ptr);
- if (summary) {
- summary_buf[0]=' '; summary_buf[1]=' '; summary_buf[2]=' ';
- itoa(dirs_found, &summary_buf[3], 10);
- strcat(&summary_buf[3], " directories found, containing ");
- itoa(files_found, strchr(&summary_buf[3], '\0'), 10);
- strcat(&summary_buf[3], " files");
- display_line(summary_buf);
- }
- return;
- }
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** delve -- function that recursively steps down the directory structure
- *** of a disk, either printing directories/files or just watching them
- *** go by, according to the command line flags.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- int delve( char *parent_ptr )
-
- {
- struct find_t my_dta;
- unsigned int find_result;
- path current_path;
- char *current_end;
-
-
- /**
- *** delve is only called on an existing directory, so this here is a valid
- *** directory we're in. If appropriate, print said fact.
- **/
- ++dirs_found;
- if (print_dirs)
- display_line( (print_path) ? parent_ptr+print_drive
- : strrchr(parent_ptr,'\\')+1);
-
- /**
- *** Copy the path passed from above, and stick a backslash at the end of it.
- *** current_end ends up pointing to the 1st char after this backslash, which
- *** is the place to put file matching mask and the name of the next
- *** subdirectory down the chain.
- **/
- strcpy(current_path, parent_ptr);
- current_end=strchr(current_path,'\0');
- if ( *(current_end-1) != '\\')
- *current_end++='\\';
-
- /**
- *** First, find all the files that match the mask pointed to by match_ptr,
- *** and print them if appropriate. If the /m flag has not been used by the
- *** user, then *match_ptr == "*.*" and all files in the subdirectory will be
- *** found.
- **/
- strcpy(current_end, match_ptr);
- find_result=_dos_findfirst(current_path, srch_attrib & ~_A_SUBDIR, &my_dta);
- while (find_result == 0) {
- ++files_found;
- if (print_files) {
- strcpy(current_end, my_dta.name);
- if (force_lower)
- strlwr(current_end);
- display_line( (print_path) ? current_path+print_drive
- : current_end);
- }
- find_result=_dos_findnext(&my_dta);
- }
-
- /**
- *** Now go through the subdirectory looking for other directories. If a
- *** subdirectory is found, call delve on it
- **/
- strcpy(current_end, dflt_match);
- find_result=_dos_findfirst(current_path, srch_attrib, &my_dta);
- while (find_result == 0) {
- if ( (my_dta.attrib & _A_SUBDIR) && (my_dta.name[0] != '.') ) {
- strcpy(current_end, my_dta.name);
- if (force_lower)
- strlwr(current_end);
- delve(current_path);
- }
- find_result=_dos_findnext(&my_dta);
- }
-
- return(0);
- }
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** get_targetdir -- TRUNK has to find the target directory in more than
- *** one place in the code, so this function consolidates them. The target
- *** directory passed to this function can be relative to the current
- *** directory (such as '..'), so we chdir to that directory, ask DOS what the
- *** current pathname is, and place that in *target. Finally we change back
- *** to the directroy whence we came. If the target directory does not exist,
- *** *target is set to a null string.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- char *get_targetdir( char *target, /* place to put target pathname */
- char *home /* directory we just came from */
- )
-
- {
- if (chdir(target) != 0)
- target[0]='\0';
- else {
- getcwd(target, sizeof(path));
- chdir(home);
- }
- return(target);
- }
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** change_drive -- take advantage of some quick-and-dirty method of changing
- *** the current logged drive. _dos_settdrive is void(), so we have to use
- *** _dos_getdrive to see if the change actually took place.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- int change_drive( unsigned new_drive )
-
- {
- unsigned avail_drives;
- unsigned drive_now;
-
-
- _dos_setdrive(new_drive, &avail_drives);
- _dos_getdrive(&drive_now);
- return( (new_drive == drive_now) ? 0 : -1 );
- }
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** display_line -- print strings to the screen, pausing every screenful if
- *** the /p flag is on.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- void display_line( char *out_line )
-
- {
- int n=0;
- char ch;
-
-
- puts(out_line);
- ++screen_lines;
- if ( (screenfull_pause) && (screenfull_pause == screen_lines) ) {
- while( kbhit() )
- getch();
- while( (ch=" Strike any key to continue==>"[++n]) )
- fputchar(ch);
- while( !kbhit() );
- while( kbhit() )
- getch();
- fputchar('\n');
- screen_lines=0;
- }
- return;
- }
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** display_strings -- use puts to print a series of strings to stdout until
- *** a null string is encountered.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- void display_strings( char *msgs[] )
- {
-
- while ( msgs[0][0] )
- display_line( msgs++[0] );
- return;
- }
-
-
-
- /***************************************************************************/
- /***************************************************************************/
- /**
- *** locase -- convert passed character to lower case. made this a function
- *** to save a few bytes in code space.
- **/
- /***************************************************************************/
- /***************************************************************************/
-
- char locase( char ch )
-
- {
-
- return( ((ch >= 'A') && (ch <='Z')) ? (ch+32) : ch );
- }
-