/* * TREE command for MS-DOS * * This command is virtually identical to the MS-DOS TREE command, * except that it expands the current directory path instead of * showing '.' in the display. * * Copyright 1995 Dave Dunfield * Freely distributable. */ #include #include #define DIRS 500 /* Depth of directory stacking */ #define DEPTH 50 /* Depth of scanner recursion */ char *parg = 0, /* Path argument */ path[66], /* Final path specification */ full = 0, /* Full listing specified */ dirstack[DIRS][13], /* Stack of directory names */ *actstack[DEPTH]; /* Stack of active levels */ char *Vline = "\xB3\x20\x20", /* Vertical line */ *Vtee = "\xC3\xC4\xC4", /* Vertical/Horizonal tee */ *Corn = "\xC0\xC4\xC4", /* Vertical/Horizontal corner */ *Hline = "\xC4\xC4\xC4"; /* Horisontal line */ unsigned dirptr = 0, /* Directory stacking level */ level = 0; /* Function recursion level */ static char help_text[] = { "\n\ Graphically displays the directory structure of a drive or path.\n\n\ TREE [drive:][path] [/F] [/A]\n\n\ /F Displays the names of the files in each directory.\n\ /A Uses ASCII instead of extended characters.\n\n\ Copyright 1995 Dave Dunfield - Freely distributable.\n" }; /* * Handle a single directory, recurse to do others */ void tree_path(void) { unsigned plen, dirbase, i, j, k, attrs; char name[13], *ptr; /* Get all sibdirectory names in this dir */ dirbase = dirptr; plen = strlen(path); strcpy(path+plen, "*.*"); if(!find_first(path, -1, name, &k, &k, &attrs, &k, &k)) do { if((attrs & DIRECTORY) && (*name != '.')) { strcpy(dirstack[dirptr++], name); continue; } } while(!find_next(name, &k, &k, &attrs, &k, &k)); /* Display files in this dir if required */ actstack[level++] = (dirbase == dirptr) ? " " : Vline; if(full) { i = 0; if(!find_first(path, -1, name, &k, &k, &attrs, &k, &k)) do { if(attrs & (DIRECTORY|VOLUME)) continue; for(j=0; j < level; ++j) fputs(actstack[j], stdout); i = -1; printf("%s\n", name); } while(!find_next(name, &k, &k, &attrs, &k, &k)); if(i) { for(j=0; j < level; ++j) fputs(actstack[j], stdout); putc('\n', stdout); } } /* Report of no subdirectories exist */ if((dirbase == dirptr) && (level == 1)) printf("No sub-directories exist\n"); /* Recurse into subdirectories */ for(i=dirbase; i < dirptr; ++i) { actstack[level-1] = ((i+1) != dirptr) ? Vtee : Corn; for(j=0; j < level; ++j) fputs(actstack[j], stdout); actstack[level-1] = ((i+1) != dirptr) ? Vline : " "; printf("%s\n", ptr = dirstack[i]); strcpy(path+plen, ptr); strcat(path, "\\"); tree_path(); } /* Restore entry conditions and exit */ path[plen] = 0; dirptr = dirbase; --level; } /* * Main program - parse arguments & start recursive procedure */ main(int argc, char *argv[]) { int i; char *ptr, c; for(i=1; i < argc; ++i) { ptr = argv[i]; while(*ptr) switch (c = *ptr++) { case '/' : /* Option switch */ switch(c = toupper(*ptr++)) { case 'A' : /* Ascii - switch BOX characters */ Vline = "| "; Vtee = "+--"; Corn = "\\--"; Hline = "---"; continue; case 'F' : /* Select FULL mode */ full = -1; continue; case '?' : /* Help request */ fputs(help_text, stdout); exit(0); } printf("Invalid switch - /%c\n", c); exit(-1); default: /* Pathname */ if(parg) { printf("Too many parameters - %s\n", argv[i]); exit(-1); } parg = argv[i]; ptr = ""; } } /* If no path specified, default to current */ if(!parg) { *(parg = help_text) = '\\'; getdir(help_text+1); } /* If no drive name specified, obtain current drive */ if(parg[1] == ':') strcpy(path, parg); else { *path = get_drive() + 'A'; path[1] = ':'; strcpy(path+2, parg); } /* Display volume label of disk */ printf("Directory PATH listing"); *help_text = *path; strcpy(help_text+1, ":\\*.*"); if(!find_first(help_text, VOLUME, ptr = help_text, &i, &i, &i, &i, &i)) { printf(" for volume "); while(c = *ptr++) if(c != '.') putc(c, stdout); } /* Display path and append backslash if not given */ printf("\n%s\n", path); switch(path[strlen(path)-1]) { default: strcat(path, "\\"); case ':' : case '\\' : } /* Perform recursive function */ tree_path(); }