From: boone@convex.cl.msu.edu (Dennis Boone)
Newsgroups: alt.gopher
Subject: Gopher Road Map tool "gophertree"
Keywords: tree listing road map gopher gophertree
Date: 21 Jul 92 20:53:27 GMT
Organization: Michigan State University, East Lansing

This tool creates an indented listing of the files in a Gopher server.
We feel that a listing like the one created by gophertree will be helpful
to new users as they begin using Gopher.  Later, as they develop confidence,
it becomes a useful index.  By default, the listing is set up for printing
on standard letter paper, but the program is configurable.  A sample listing
appears below.

Gophertree is a major modification of the gopherls tool found in the Gopher
distribution.

Example output:

MSU Gopher Road Map                      Host: gopher.msu.edu
Last Update: 7/21/92                                                Page:   1

Name					Type	Destination
--------------------------------------	-------	------------------------------
About Gopher                            Dir     serv2.cl.msu.edu
  What is it? (under construction)      File    serv2.cl.msu.edu
  Why do I need it? (under constructio  File    serv2.cl.msu.edu
  Where can I get it? (under construct  File    serv2.cl.msu.edu
  How do I use it? (under construction  File    serv2.cl.msu.edu
  Who can I contact?                    File    serv2.cl.msu.edu
  When was the last update?             File    serv2.cl.msu.edu
  About MSU's Gopher                    File    serv2.cl.msu.edu
Michigan State University               Dir     serv2.cl.msu.edu
  Alumni Association                    Dir     serv2.cl.msu.edu
    Up Front: MSU Trustees Help Direct  File    serv2.cl.msu.edu
    In-Basket                           File    serv2.cl.msu.edu
    National Alumni Board Officers 199  File    serv2.cl.msu.edu
    MSU Alumni Magazine (Table of Cont  File    serv2.cl.msu.edu
    Around Circle Drive                 File    serv2.cl.msu.edu
    People/John Mueller: Oldies But Go  File    serv2.cl.msu.edu
    People/Arthur Hills: Golf's Hottes  File    serv2.cl.msu.edu
    People/Ingrid Jones: Can't Beat He  File    serv2.cl.msu.edu
    People/Ivan Lahaie: In the Realm o  File    serv2.cl.msu.edu
    People/Joan Sills: The World's Top  File    serv2.cl.msu.edu
    People/Julie Dixon: Medicine Woman  File    serv2.cl.msu.edu
    People/Wayne Fontes: NFL Coach of   File    serv2.cl.msu.edu
    People/Harriette McAdoo: Defining   File    serv2.cl.msu.edu
    Dow Gift Will Accelerate Composite  File    serv2.cl.msu.edu
    Meet Merrily Dean Baker, MSU's A.D  File    serv2.cl.msu.edu
    . . .
  Campus Events & Sights                Dir     serv2.cl.msu.edu
    About Campus Events & Sights        File    serv2.cl.msu.edu
    Bulletins                           File    serv2.cl.msu.edu
    Events                              Dir     serv2.cl.msu.edu
      Search Everything                 Index   netsun.cl.msu.edu
      Search May                        Index   netsun.cl.msu.edu
      May                               Dir     serv2.cl.msu.edu
      Search June                       Index   netsun.cl.msu.edu
      June                              Dir     serv2.cl.msu.edu


The program:
---------------------------------snip-------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	gophertree
# This archive created: Tue Jul 21 16:49:49 1992
export PATH; PATH=/bin:$PATH
if test -f 'gophertree'
then
	echo shar: will not over-write existing file "'gophertree'"
else
cat << \SHAR_EOF > 'gophertree'
#!/usr/local/bin/perl
# gophertree
# Prints pretty indented listings of a Gopher menu tree
# Copyright (C) 1992, Trustees of Michigan State University
# 
# Modifications:
# Original author unknown
# 07/07/92 Boone      Major conversion from gopherls
# End Modifications

sub dokill
{
    kill 9,$child if $child;
}

sub Opengopher
{
    $sockaddr++;
    local($them,$port) = @_;	
    $them = 'localhost' unless $them;

    $AF_INET = 2;
    $SOCK_STREAM = 1;

    $SIG{'INT'} = 'dokill';

    $sockaddr = 'S n a4 x8';

    chop($hostname = `hostname`);

    ($name,$aliases,$proto) = getprotobyname('tcp');
    ($name,$aliases,$port) = getservbyname($port,'tcp')
	unless $port =~ /^\d+$/;;
    ($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
    ($name,$aliases,$type,$len,$thataddr) = gethostbyname($them);

    $this = pack($sockaddr, $AF_INET, $sockaddr, $thisaddr);
    $that = pack($sockaddr, $AF_INET, $port, $thataddr);

    # Make the socket filehandle.
    socket(S, $AF_INET, $SOCK_STREAM, $proto) || die $!;

    # Give the socket an address.
    bind(S, $this) || die $!;

    # Call up the server.
    connect(S,$that) || die $!;

    # Set socket to be command buffered.
    select(S); $| = 1; select(STDOUT);

}

sub GetList 
{
	local($CurrentHost, $Port, $Path, $indent) = @_;
	local(@dirx, $Name, $Obj, $fname, $ftype, $fhost, $i);
	&Opengopher($CurrentHost, $Port);
	print S "$Path\n";
	@dirx = <S>;
	close(S);
	$i = 0;
	foreach (@dirx) 
	{
		last if /^\./;
		chop; chop;
		($ObjName, $Path, $CurrentHost, $Port) = split('\t', $_);
		$Name = substr($ObjName, 1);
		$Obj = substr($ObjName, 0, 1);
		$fname = $indent . $Name;
		$ftype = "";
		$ftype = "File" if ($Obj eq "0");
		$ftype = "Dir" if ($Obj eq "1");
		$ftype = "Phone" if ($Obj eq "2");
		$ftype = "Error" if ($Obj eq "3");
		$ftype = "MacHqx" if ($Obj eq "4");
		$ftype = "PcHqx" if ($Obj eq "5");
		$ftype = "Uue" if ($Obj eq "6");
		$ftype = "Index" if ($Obj eq "7");
		$ftype = "Telnet" if ($Obj eq "8");
		$ftype = "Binary" if ($Obj eq "9");
		$ftype = "File" if ($Obj eq "R");
		$ftype = "TN3270" if ($Obj eq "T");
		$ftype = "File" if ($Obj eq "e");
		$ftype = "Ftp" if ($Obj eq "f");
		$ftype = "HTML" if ($Obj eq "h");
		$ftype = "Info" if ($Obj eq "i");
		$ftype = "Mail" if ($Obj eq "m");
		$ftype = "Sound" if ($Obj eq "s");
		$ftype = "Index" if ($Obj eq "w");
		$fhost = $CurrentHost;

		write if (($i < $breaklong) && ($Obj ne "i"));

		if (($Obj eq "1") && ($CurrentHost eq $firsthost) && 
			(($Port != $firstport) || ($Path != ""))) 
		{
			&GetList($CurrentHost, $Port, $Path, $indent . $iadd);
		}

		$i++ if ($Obj eq "0");
		if ($i == 15) 
		{
			print("$indent. . .\n");
			--$-;
		}
	}
}

# **************************************************************************
# * Main
# **************************************************************************

# Parse command line

	if ($#ARGV < 1) 
	{
		print "Usage:  gophertree  host  port  path\n";
		exit(1);
	}

	$firsthost = $CurrentHost = $ARGV[0];
	$firstport = $Port = $ARGV[1];
	$Path = "";
	if ($#ARGV == 2) 
	{
		$Path = $ARGV[2];
	}

# Initialize some variables

	($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
	$today = $mon+1 . "/" . $mday . "/" . $year;

	$^ = 'TOP';         # Report header format
	$~ = 'STDOUT';      # Report body format
	$indent = "";       # Goes in front of description to indicate treeness

# CHANGE--User-configurable defaults

	$breaklong = 15;    # CHANGE--Where to break long lists, place ". . ."
	$= = 55;            # CHANGE--Lines per page
	$iadd = "  ";       # CHANGE--Amount to indent each new level

# Real work

	&GetList($CurrentHost, $Port, $Path, $indent);
	exit(0);

#
# Formats
#

format TOP =

MSU Gopher Road Map                      Host: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$firsthost
Last Update: @<<<<<<<                                               Page: @>>
$today $%

Name					Type	Destination
--------------------------------------	-------	------------------------------
.

format STDOUT =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$fname $ftype $fhost
.
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0

---------------------------------snip-------------------------------
--
 == Frustration is portable. ==
Newsgroups: alt.gopher