#!/usr/local/bin/perl

# ftravel version 1.0
#
#  Travel through a filesystem graph.  Tries to avoid cicles.
#
# usage: ftravel [-t] [-c] [-k killfile] [-p path] [-d depth] host [port]
#
# ftravel travels through a filesystem, starting at the current directory,
# and assumed to be served by a gopher server, and outputs a "travel"
# file.
#   It follows symbolic links, and tries to avoid cycles.
#
#  -t            Uses the current gtime, producing a "gtimes" file instead
#                of the regular "travel" file.
#
#  -c            Disable cycle checking (not recomended).
#
#  -k killfile   Use killfile to prune the graph.
#
#  -p path       Assume that the current directory corresponds to "path"
#                in the gopher server. Subdirectories will be relative to
#                this path.
#
#  -d depth      Assume that the corrent directory is at "depth" in the
#                gopher server.  Used with -p.
#
#  host          Host name of the gopher server (required).
#
#  port          Port number of the gopher server (defaults to 70).

# TODO: rename this thing to travel-file or travel-fs

$0 =~ m:^(.*)/[^/]+$: ;
$1 && push(@INC,$1);
$0 =~ s:^.*/::;
$usage="usage: $0 [-t] [-c] [-k killfile] [-p path] [-d depth] host [port]\n";

$gopherd_conf= "/etc/gopherd.conf";

require "g-expr.pl";
require "g-addgtypes.pl";
require "getopts.pl";

&Getopts("tck:p:d:") || die $usage;
$host = shift || die $usage;
$port = (shift || 70);

$subs= &load_kill_file($opt_k);
eval $subs;

$opt_p =~ s:/$:: ;

chop($cwd_top=`pwd`);
if (@ARGV) {
  $opt_p = "1" unless $opt_p;
  for $dir (@ARGV) {
    $dir =~ s:/$::;
    chdir $dir || die "Can't chdir to $dir: $!\n";
    &not_in_cycle;
    $cwd= (($dir =~ m:^/:) ? $dir : "$cwd_top/$dir" );
    &ftravel($cwd,&time2gtime(time()), $opt_d, "1", "", "$opt_p/$dir");
    &pop_from_cycle;
    chdir $cwd_top;
  }
}
else {
  &not_in_cycle;
  &ftravel($cwd_top,&time2gtime(time()), $opt_d, "1", "", $opt_p);
}
exit 0;

sub ftravel {
  local($cwd0,$gtime0, $depth0, $type0, $name0, $path0)= @_;
  local($gtime, $depth, $type, $name, $path);

  if (! opendir(DIR,".")) { warn "Can't open dir $cwd0: $!\n"; return; }
  local(@dir)= sort readdir(DIR);
  close(DIR);

  $depth= 1+$depth0;
  for $name (@dir) {
    next if substr($name,0,1) eq ".";
    if (!stat($name)) {
      warn "Can't stat ".substr($path0,1)."/$name: $!\n";
      next;
    }
    $path= substr($path0,1). "/". $name;
    if (-d _) {  $type= "1";  $path="1".$path;
    }
    else {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            