Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!seismo!ll-xn!ames!necntc!ncoast!allbery
From: mikep@ism780c.UUCP (Michael A. Petonic)
Newsgroups: comp.sources.misc
Subject: Display Tree for 4.3bsd (source)
Message-ID: <2708@ncoast.UUCP>
Date: Tue, 23-Jun-87 21:15:25 EDT
Article-I.D.: ncoast.2708
Posted: Tue Jun 23 21:15:25 1987
Date-Received: Thu, 25-Jun-87 04:24:43 EDT
Sender: allbery@ncoast.UUCP
Lines: 243
Keywords: YARU (Yet Another Recursive Utility)
Approved: allbery@ncoast.UUCP
X-Archive: comp.sources.misc/8706/3
I spent an hour hacking this utility out because I was looking
for something like it but couldn't find one. I guess you could
put together something in shell-script that does something similar,
but I don't like waiting that long for code to run. Also could
use find, I guess.....
This utility recursively descends a directory tree and prints
the structure of it. I know that "ls -R" will do something
similar, but it doesn't leave out normal files. This is a
heck of a lot more flexible in what it does, anyway.
The *real* reason that I wrote this was because I wanted to
learn more about the 4.3bsd file system (like symbolic links)
and also the directory reading calls. I've been modifying
programs that use the directory reading calls, and I wanted
to write something original.
Took more time to figure out how to write a manual entry than
it did to code....
:
# This is a shar file. Delete everything above the line with ":" and
# run it through the shell like this:
# $ sh file
# This will extract the following files
# dt.1 - manual entry for dt
# dt.c - source code for 4.3bsd display tree program
#
# Send any comments to {seismo|sdcrdcf}!ism780c!mikep
#
# Author : Michael A. Petonic
#
# NOTE: The source was written with ":set ts=3" and ":set sw=3" in vi.
# For the benefit of most people, I have expanded the tabs to 3 spaces
# each so that it looks semi decent.
#
#
echo x - dt.1
sed 's/^X//' >dt.1 <<'*-*-END-of-dt.1-*-*'
X'\" %W% - %E%
X.TH DS 1 %I% %P%
X.SH NAME
Xdt \- display tree
X.SH SYNOPSIS
X.B dt
X[
X.B -vs
X]
X[
X.B -i n
X] dir ...
X.SH DESCRIPTION
X\fIDt\fR recursively descends a directory tree printing out only the
Xsubdirectories. If no directories are specified, then the current
Xworking directory is taken as a default.
X.P
XThe \fB-v\fR switch is used to specify verbose output (can't open a
Xdirectory, etc.). Directories that are actually symbolic links are
Xnot descended and marked by an "(s)" after their name
Xunless the \fB-s\fR switch is specifed.
X.P
XEach level in the tree is separated with tabs unless \fB-i\fR is specified,
Xthen \fBn\fR spaces are output instead.
X.SH SEE ALSO
Xls(1),du(1)
X.SH BUGS
XCurrently, \fIDt\fR lists the directories in the order that they are
Xstored, not alphabetical.
*-*-END-of-dt.1-*-*
echo x - dt.c
sed 's/^X//' >dt.c <<'*-*-END-of-dt.c-*-*'
X#include
X#include
X#include
X#include
X
X#define INDENT_STR 3
X#define MAXFILES 20
Xextern int errno;
X
Xchar *pn; /* program name */
X
Xint vflag = 0; /* verbose flag */
Xint sflag = 0; /* include symbolic links? */
Xint tflag = 1; /* use tabs instead of spaces???? */
Xint in_size = 0; /* indent size */
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X char *dir;
X struct stat sb;
X register char c;
X int errflag = 0;
X extern char *optarg;
X extern int optind;
X
X pn = argv[0];
X
X
X while((c = getopt(argc,argv,"vi:s")) != EOF)
X switch(c) {
X case 'v':
X vflag = 1;
X break;
X case 's':
X sflag = 1;
X break;
X case 'i':
X if(!(in_size = atoi(optarg))) {
X fprintf(stderr,"%s: invalid indent size \"%s\"\n",pn,optarg);
X ++errflag;
X }
X tflag = 0;
X break;
X case '?':
X default:
X ++errflag;
X }
X
X if(errflag || (tflag && in_size)) {
X fprintf(stderr,"Usage: %s [-vs] [-i n] [...]\n",pn);
X exit(99);
X }
X
X if(optind == argc) {
X dir = ".";
X descend(dir,0);
X exit(0);
X }
X
X
X for(;optind!cd\n",path);
X pout(ts,level);
X }
X return;
X }
X pout(path,level);
X
X if((dirp = opendir(".")) == NULL) {
X fprintf(stderr,"%s: can't open \".\"\n",pn);
X exit(2);
X }
X
X errno = 0;
X while(dent=readdir(dirp)) {
X if(!strcmp(dent->d_name,".") || !strcmp(dent->d_name,".."))
X continue;
X if(stat(dent->d_name,&sb) < 0) {
X if(vflag) {
X sprintf(ts,"<%s>!stat",dent->d_name);
X pout(ts,level);
X }
X continue;
X }
X if((sb.st_mode&S_IFMT) != S_IFDIR)
X continue;
X
X /* check for symbolic link */
X if(lstat(dent->d_name,&sb) < 0) {
X if(vflag) {
X sprintf(ts,"<%s>!lstat",dent->d_name);
X pout(ts,level);
X }
X continue;
X }
X if(((sb.st_mode&S_IFMT) == S_IFLNK) && (!sflag)) {
X sprintf(ts,"%s(s)",dent->d_name);
X pout(ts,level+1);
X continue;
X }
X if(dirp->dd_fd >= MAXFILES-1) {
X offset = telldir(dirp);
X closedir(dirp);
X dirp = NULL;
X }
X descend(dent->d_name,level+1);
X if(!dirp) {
X if((dirp = opendir(".")) == NULL) {
X fprintf(stderr,"%s: can't reopen \".\"\n",pn);
X exit(9);
X }
X seekdir(offset);
X }
X }
X
X closedir(dirp);
X if(chdir("..") < 0) {
X fprintf(stderr,"%s: can't change to \"..\"\n",pn);
X exit(99);
X }
X return;
X}
X
X
X
Xpout(name,indent)
Xchar *name;
Xint indent;
X{
X int i;
X
X if(tflag) {
X for(i=0;i