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.