lee@minnow.UUCP (Gene Lee ) (07/30/87)
[MUNCH] ----------------------------- cut here ---------------------------------- /* VTREE "vtree path" draws the directory tree structure starting at the path given as the parameter. Gene Lee UUCP: ...ihnp4!{meccts,dayton,rosevax}!ems!minnow!lee UNISYS Corporation ATT: (612) 635-6334 */ #include <stdio.h> #include <ftw.h> #include <sys/types.h> /* included because <sys/stat.h> needs it */ #include <sys/stat.h> /* included to use STAT(2) structure in fn() */ #include <errno.h> /* included to pick up error number */ #include <string.h> /* included to use string functions */ int fn(); char *tail(); #define MAXDEPTH 100 /* maximum directory depth allowed */ #define DIRNAME_LENGTH 15 /* maximum number of chars in a directory name */ #define LEADGAP 5 /* number of spaces in to start drawing first col */ #define CONNECT_CHAR "_" /* char used to connect node names in drawing */ #define BLANK_CHAR " " /* char used to draw blanks when drawing */ #define BRANCH_CHAR "L" /* char used to draw branch from parent node */ #define NEWLINE_CHAR "\n" /* char used to perform a line feed-carriage ret */ #define VERT_CONNECT "|" /* char used to draw vertical lines */ main(argc,argv) int argc; char *argv[]; { int ftw_stat; int i; if (argc != 2) { fprintf(stderr, "Call: vtree path\n"); exit(-1); } fprintf(stdout, "VTREE\n\n\n%s\n", argv[1]); for (i=0; i < strlen(argv[1]); i++) fprintf(stdout, "_"); fprintf(stdout, "\n%s\n%s", VERT_CONNECT, VERT_CONNECT); ftw_stat = ftw(argv[1], fn, 10); fprintf(stdout, "%s%s", NEWLINE_CHAR, NEWLINE_CHAR); if (ftw_stat != 0) printf("FTW error = %d\n",errno); } /*_________________________________________________________________________*/ int fn(name,ptr,type) char *name; /* name of the directory entity */ struct stat *ptr; /* pointer to a STAT(2) structure */ int type; /* entity type according to <ftw.h> */ { static char table[MAXDEPTH][DIRNAME_LENGTH]; static int tablecount=0; /* count of how many entries in the table are currently valid */ static int column=0; /* what column are we printing output in */ static match_found; /* has a match been found yet */ static firsttime=1; /* the first time this routine is called */ switch (type) { case FTW_D: /* printf("%s\n",name); */ break; case FTW_DNR: /* printf("%s",name); printf(" directory that can't be read\n"); */ break; default: return(0); /* other types of entity need no processing */ } if (firsttime) { loadtable(table, &tablecount, name); firsttime =0; return(0); } match_found=0; do { /* if this path is a extension of the last path */ if (tablecount == 0 || match(table,tablecount, name) ==0) { strcpy(table[tablecount++], tail(name)); /* add last node to table */ column++; /* were going to print new name in next column */ drawlevel(column, tail(name)); match_found =1; /* we just found a new directory level */ } else { tablecount--; /* back up one node level and try again */ column--; /* printout column goes back with dir level */ } if (tablecount < 0) { fprintf(stderr, "Internal Program Error\n"); exit(-1); } } while (!match_found); return(0); } /* _________________________________________________________________________ */ /* This function returns a pointer into path of the last node in the path */ char *tail(path) char *path; { char *ptr; if ((ptr =strrchr(path,'/')) == NULL) return(path); /* it didn't have a path seperator */ else return(ptr +1); /* return pointer to last node in path */ } /* _________________________________________________________________________ */ /* match checks to see if the first nodes in the path name match to node names in the table */ int match(table,tablecount,name) char table[MAXDEPTH][DIRNAME_LENGTH]; int tablecount; /* how many entries in the table are valid and need to be checked */ char *name; /* the directory path of node names */ { int i; char *ptr; char path[200]; /* make a copy of their pathname to strtok on */ strcpy(path, name); /* check first node name against first table entry */ if (strcmp(table[0], (ptr =strtok(path,"/"))) != 0) { return(-1); /* return no match */ } /* check the rest of the table up to the last valid entry against each node name in the path */ for (i=1; i < tablecount; i++) if (strcmp(table[i], strtok(NULL, "/")) != 0) return(-1); /* return no match */ return(0); } /* ______________________________________________________________________ */ loadtable(table, tablecount, name) char table[MAXDEPTH][DIRNAME_LENGTH]; int *tablecount; char *name; { char path[160]; /* make a copy of the path so as not to chg it */ char *ptr; strcpy(path, name); *tablecount =0; /* nothing in the table yet */ if ((ptr = strtok(path, "/")) == NULL) /* if only a '/' for ex */ return; else { strcpy(table[*tablecount], ptr); /* load table entry */ (*tablecount)++; /* add the node name found to the count */ } while ((ptr = strtok(NULL, "/")) != NULL) { /* while a node name is found */ strcpy(table[*tablecount], ptr); (*tablecount)++; } } /* ______________________________________________________________________ */ drawlevel(column,name) int column; /* column to print nodename in */ char *name; /* nodename to print */ { static int lastcolumn=MAXDEPTH; /* last column a name was printed in */ static int lastlength; /* length of last nodename printed */ if (column <= lastcolumn) /* this means we need to start a new row */ startnewrow(column, name); else /* add name to end of last row */ addtorow(lastlength, name); lastcolumn =column; /* remember the last column printed in */ lastlength =strlen(name); /* remember length of last name printed */ } /*_________________________________________________________________________*/ addtorow(lastlength, name) int lastlength; /* length of the previously printed name */ char *name; /* name to be printed */ { int i; /* move over and print it */ for (i=0; i < DIRNAME_LENGTH +1 -lastlength; i++) fprintf(stdout, CONNECT_CHAR); fprintf(stdout, name); /* print the node name */ } /*_________________________________________________________________________*/ startnewrow(column, name) int column; /* column to print nodename in */ char *name; /* nodename to print */ { int i,j; fprintf(stdout, NEWLINE_CHAR); /* start the new line */ /* move away from left edge */ if (column ==1) { /* if printing in first column */ fprintf(stdout, BRANCH_CHAR); /* char along left edge */ for (i=0; i < LEADGAP -1; i++) fprintf(stdout, CONNECT_CHAR); } else { fprintf(stdout, VERT_CONNECT); /* char along left edge */ for (i=0; i < LEADGAP -1; i++) fprintf(stdout, BLANK_CHAR); } /* move over to its parents column in above row */ for (i=0; i < (column -2); i++) for (j=0; j < DIRNAME_LENGTH +1; j++) fprintf(stdout, BLANK_CHAR); if (column > 1) { /* LEADGAP did this already for column ones */ fprintf(stdout, BRANCH_CHAR); /* branch down from prev row */ for (i=0; i < DIRNAME_LENGTH; i++) fprintf(stdout, CONNECT_CHAR); } fprintf(stdout, name); /* print the node name */ } /* ----------------- end of source ------------------------------------ */ -- Gene Lee UUCP: ...ihnp4!{meccts,dayton,rosevax}!ems!minnow!lee UNISYS Corporation ATT: (612) 635-6334 If not for the courage of the fearless crew, the minnow would be lost.