From cameron@cse.unsw.edu.au Tue Feb 15 13:48:08 1994 Article: 7916 of comp.infosystems.www From: cameron@cse.unsw.edu.au Subject: Re: man to html? Organization: Computing Facility, CS&E, Uni Of NSW, Oz Date: Fri, 11 Feb 94 07:17:47 MET I use the following to provide a web manual browser for our students. It may not be what you want, but the "man2html" subroutine should readily adapt to your needs. Please put my name and email address on it if you use it. You can try it out at http://www.cse.unsw.edu.au/scripts/man. You'll get our SGI machine; the students get their local architecture by redirecting through http://localhost. - Cameron Simpson cameron@cse.unsw.edu.au, DoD#743 -- Ignorance is preferable to error; and he is less remote from the truth who believes nothing, than he who believes what is wrong. - Thomas Jefferson #!/bin/sh # sed 's/^X//' > man.pl <<'EOF-/home/cs/orchestra/crwth/1/cameron/etc/web/../scripts/man' X#!/usr/local/bin/perl X# X# Script to produce manual entries. X# - Cameron Simpson, 05jan94 X# X Xif ($#ARGV >= $[ && $ARGV[$[] eq '-q') X { shift; X $ENV{QUERY_STRING}=shift; X } Xelse X{ open(STDERR,'>/dev/null'); X} X Xprint "Content-Type: text/html\n\n"; X X@manpath=('/usr/local/man', X '/usr/local/gnu/man', X '/usr/local/lib/elm/man', X '/usr/local/lib/tcl', X '/usr/local/share/man', X '/usr/man', X '/usr/catman/local', X '/usr/catman/a_man', X '/usr/catman/g_man', X '/usr/catman/p_man', X '/usr/catman/u_man', X '/usr/local/X11/man', X '/usr/X11/man'); X@mansubdirs=('ftn','pas','standard','X','Xt','libmalloc','audio','X11'); X Xif (length($ENV{PATH_INFO})) X { $ENV{PATH_INFO}=&clean_path($ENV{PATH_INFO}); X } X Xif (length($ENV{QUERY_STRING})) X { $title="UNSW CSE Manual Lookup for $ENV{QUERY_STRING}"; X } Xelsif (length($ENV{PATH_INFO})) X { $title="UNSW CSE Manual Entry for $ENV{PATH_INFO}"; X } Xelse { $title="UNSW CSE Manual Lookup"; X } X Xprint "$title \n"; Xprint "

$title

\n"; X Xif (length($ENV{QUERY_STRING})) X { $opendirs=0; X $start=time; X @manuals=&searchfor($ENV{QUERY_STRING}); X $end=time; X print "[ Searched ",$opendirs," directories in ",$end-$start," seconds. ]

\n"; X if ($#manuals < $[) X # no matches X { print "Sorry, no match for \"$ENV{QUERY_STRING}\".\n"; X } X elsif ($#manuals == $[) X # exactly one match X { &showman(shift @manuals); X } X else X { print "\"^$ENV{QUERY_STRING}\" matches ", X $#manuals-$[+1, X " manual entries:\n

\n"; X } X } Xelsif (length($ENV{PATH_INFO})) X { &showman($ENV{PATH_INFO}); X } Xelse X{ print <<'BLURB' X Enter a command name to retrieve its manual entry. X

X

Other Manual Entry Collections

X The searchable index (above) consults the local manuals X (the ones for the School's computers). X Occasionally it can be useful to X check out the corresponding entry for another platform. X Therefore feel free to also look at the following set of manuals. X Naturally, they don't necessarily describe the environment here at CSE. X With that in mind, the following categories are mostly sourced from X www.cis.ohio-state.edu. X In particular, the /usr/local and /usr/unsup pages are from there. X XBLURB X ; X X} X Xexit 0; X Xsub showman # path -> ok X { local($path)=@_; X local($ok,$mandir,$_); X X $ok=0; X MANCHECK: X for $mandir (@manpath) X { $chkpath=substr($path,$[,length($mandir)+1); X if ($chkpath eq "$mandir/") { $ok=1; last MANCHECK; } X } X X if (!$ok) X { print "Sorry, you can't look up the file $path.\n"; X return 0; X } X X local($needroff,$packed,$roffdir,$manopen); X X $needroff=($path =~ m:/man\d+[^/.]*/:); X $packed=($path =~ /\.z$/i); X ($roffdir=$path) =~ s:/+[^/]+/+[^/]+/*$::; X $manopen=($needroff X ? $packed X ? "cd '$roffdir'; gunzip < '$path'|tbl|neqn|nroff -man|col|" X : "cd '$roffdir'; tbl < '$path'|neqn|nroff -man|col|" X : $packed X ? "gunzip < '$path'|" X : "< $path\0"); X if (!open(MAN,$manopen)) X { print "Sorry, can't open $path: $!\n"; X return 0; X } X X print "[ $path ]

\n"; X print "

\n";
X
X	  local($hadblank)=1;
X
X	  while ()
X		{ $_=join('',&man2html($_));
X		  s/\s+$//;
X		  if (length)
X			{ print $_, "\n";
X			  $hadblank=0;
X			}
X		  else
X		  { if (!$hadblank)
X			{ print $_, "\n";
X			}
X		    
X		    $hadblank=1;
X		  }
X		}
X
X	  close(MAN);
X
X	  print "

\n"; X X if ($queries > 1) X { local($query); X X print "[ ", $queries, " queries (", X $newqueries, " distinct) in ", X $querytime, " seconds. ]
\n"; X X for (sort keys %querytime) X { print "[ query: $_, time=$querytime{$_} ]
\n"; X } X } X X 1; X } X Xsub man2html X { local(@lines)=@_; X local($_); X X for (@lines) X { # convert special characters X s:()+([<>&]):$2:g; # clear underlines from specials X s:(([<>&])+\2:$2:g;# clear bold from specials X s:&:&:g; # replace with SGML escapes X s:<:<:g; X s:>:>:g; X X # recognise bold (accomodating underlined bold!) X s:(()*(.)\3)+)+:$&:g; X s:(.)\1)+:$1:g; X X # recognise italics X s:(()+.)+:$&:g; X s:()+(.):$2:g; X X # recognise references X # all upper MLALIAS(8L) X s:(<[bi]>)?\b([A-Z_\d]+)()?\((\d)\w*\):&manhref($&,"\L$2\E.$4"):eg; X # mixed X s:(<[bi]>)?\b(\w*[a-z]\w*)()?\((\d)\w*\):&manhref($&,"$2.$4"):eg; X } X X @lines; X } X Xsub manhref # (label,query) -> href X { local($label,$query)=@_; X X # doing the search now is a waste of time as it turns out X return "$label"; X X local(@matches)=&searchfor($query); X local($ref); X X if (@matches < 1) X { $label; X } X else X { if (@matches == 1) X { $ref="http:$ENV{SCRIPT_NAME}$matches[$[]"; X } X else X { $ref="http:$ENV{SCRIPT_NAME}?$query"; X } X X "$label"; X } X } X X# strip . and .. from path Xsub clean_path X { local($path)=@_; X local(@path,$_); X X @path=(); X for (grep(length,split(m:/+:,$path))) X { if ($_ eq '.') {} X elsif ($_ eq '..') { pop @path; } X else { push(@path,$_); } X } X '/'.join('/',@path); X } X Xsub dirents # dir -> @entries X { local($dir)=@_; X local(@dirents); X X if (!defined($dirents{$dir})) X { local($dstart,$dend); X X if (-d "$dir/." && opendir(DIRENTS,$dir)) X { $opendirs++; X print STDERR "opendir($dir)\n"; X @dirents=readdir(DIRENTS); X closedir(DIRENTS); X } X X $dirents{$dir}=join("\0",@dirents); X } X else X { @dirents=split(/\0/,$dirents{$dir}); X } X X @dirents; X } X Xsub searchfor X { local($QUERY)=@_; X local(@matched,$sectnum); X local($qstart,$qend); X X $queries++; X if (defined($searchfor{$QUERY})) X { @matched=split(/\0/,$searchfor{$QUERY}); X } X else X { local($mandir,%notneeded,@cats,$cat,$sub,$glob,$globbed,$path); X X if ($QUERY =~ /\.(\d)/) { $sectnum=$1; } X X $newqueries++; X $qstart=time; X MANDIR: X for $mandir (@manpath) X { undef %notneeded; # used to mark catX as seen so manX can be ignored X # sort so that we consider cat before man X @cats=sort grep(/^(man|cat)/,&dirents($mandir)); X @cats=grep(!/^(man|cat)(\d)/ || $2 eq $sectnum,@cats) if length($sectnum); X next MANDIR unless @cats; X for $cat (@cats) X { SUBDIR: X for $sub ('',@mansubdirs) X { $glob="$mandir/$cat/"; X $glob.="$sub/" if length($sub); X @globbed=sort &dirents($glob); X last SUBDIR if !@globbed && !length($sub); X next SUBDIR if !@globbed; X @globbed=grep(/^$QUERY/,@globbed); X PATH: X for $globbed (@globbed) X { $path=$glob.$globbed; X next PATH if $notneeded{$path}; X push(@matched,$path) if -r $path; X if ($path =~ m:/cat(\d+[^/.]*)/:) X { $notneeded{"$`/man$1/$'"}=1; X } X } X } X } X } X X $searchfor{$QUERY}=join("\0",@matched); X X $qend=time; X $querytime+=$qend-$qstart; X $querytime{$QUERY}=$qend-$qstart; X } X X @matched; X } EOF-/home/cs/orchestra/crwth/1/cameron/etc/web/../scripts/man exit 0