#!/usr/bin/perl
##---------------------------------------------------------------------------##
## File:
## @(#) man.cgi 1.2 97/08/12 12:58:26 @(#)
## Author:
## Earl Hood ehood@medusa.acs.uci.edu
## Description:
## man.cgi is a CGI program for viewing Unix manpages. The
## program man2html,
## ,
## is used to convert the output from man(1) to html.
##
## If man.cgi is invoked with no input data, it will output a
## form for the user to select a manpage to view.
## man.cgi can handle POST and GET methods.
##
## The code section "Configureable Globals" is designed to
## allow you to modify man.cgi to work with your particular
## system configuration.
##---------------------------------------------------------------------------##
## Copyright (C) 1995-1997, Earl Hood, ehood@medusa.acs.uci.edu
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA
##---------------------------------------------------------------------------##
########################################################################
## Configureable Globals
########################################################################
## Change the value of these variables to reflect your
## system configuration.
########################################################################
## "English" name for program
$ProgName = "Manpage Viewer";
## cgi-bin directory as accessed by a URL.
$CgiBin = "/cgi-bin";
## man program (should be a full pathname)
$ManPrg = '/usr/bin/man';
## man(1) option to specify a section. "-s" is used for Solaris
## systems. If using Tom Christiansen's Perl man program, than
## define use "".
#$SectOpt = "";
$SectOpt = "-s";
## man2html program (needs to be a full pathname)
$ManConvPrg = '/usr/bin/man2html';
## Flag if the -cgiurl option should be used
$DoCgiurl = 1;
## System specific arguments to man2html:
## HP => ("-leftm", "1", "-topm", "8")
## Sun => ("-sun")
## See man2html documentation for more information.
#@ConvArgs = ("-compress");
#@ConvArgs = ("-compress", "-leftm", "1", "-topm", "8");
@ConvArgs = ("-compress", "-sun");
## Keyword search processing arguments for man2html. Normally,
## '-k' is adequate. However, if on a Solaris system, the
## '-solaris' option should be specified with '-k'. See
## man2html documentation on information about the '-solaris' option.
#@KeyWArgs = ("-k"); # Normal
@KeyWArgs = ("-k", "-solaris"); # For Solaris
## Possible manual sections. This array is used to determine the
## the choices available in an option menu.
@Sections = (
'1', '1F', '1M',
'2',
'3', '3C', '3F', '3G', '3I', '3N', '3S', '3X',
'4',
'5',
'6',
'7',
'8',
'9', '9F',
);
## Form method. The value is either 'GET' or 'POST'. 'GET' is
## recommended since the URL sent by the client also contains
## the argument information. This allows a client's "Reload" function
## to reprocess a currently viewed manpage.
$FormMethod = 'GET';
## Argument separator for CGI URL links. As clients become more
## SGML conformant, the simple use of '&' conflicts with
## SGML syntax. You can set this variable to control what is
## used as the separator. Possibilities:
## &
## &
## ;
##
$ArgSep = '&';
## Man directories. Add paths to the list you want man(1) to
## know about
@ManPath = qw(
/usr/man
/usr/openwin/man
/usr/man
);
## PATH setting. Modify as see fit. Once useful modification
## is to have groff utils first in path since its nroff would
## be invoked over the systems nroff when man formats a manpage.
@Path = qw(
/opt/FSFgroff/bin
/bin
/usr/bin
);
########################################################################
## END!!!! Configureable Globals section
########################################################################
########################################################################
## Globals
########################################################################
($PROG = $0) =~ s/.*\///; # Name of program
$VERSION = '2.0.1'; # Version
%FORM = (); # Hash to hold form contents
$Error = ''; # Error string
$ENV{'MANPATH'} = join(":", @ManPath);
$ENV{'PATH'} = join(":", @Path);
########################################################################
## Main block
{
# Set unbuffered I/O. Prevents buffering problems with
# "system()" calls.
select((select(STDOUT), $| = 1)[0]);
# Print content-type header
printouttype("text/html");
# Print man form if called w/no arguments
printform() if noarg();
# If reached here, there is input to process
error("CGI input error") unless parseinput();
printform() unless $FORM{'topic'};
doit();
exit 0;
}
########################################################################
## Subroutines
########################################################################
#-----------------------------------------------------------------------
# printform outputs the man selection form to the client.
#
sub printform {
printhead($ProgName);
print STDOUT <The following form allows you to view a manpage on this system.
Please fill out the following fields and select Submit
to view a manpage.
EndOfForm
printend();
exit 0;
}
#-----------------------------------------------------------------------
# doit does the conversion
#
sub doit {
my($section, $topic, $manexec, $manout, $tmp);
$manout = '';
# Get section and topic from input
#---------------------------------
$section = $FORM{'section'};
$topic = $FORM{'topic'};
error("Questionable characters in topic") if isquestionable($topic);
# Determine command arguments for man and man2html
#-------------------------------------------------
@ARGV = ();
@manargs = ();
$manexec = $ManPrg;
if ($section =~ /keyword/) {
$manexec .= " -k $topic";
push(@manargs, "-k", $topic);
push(@ARGV, @KeyWArgs,
"-title", qq{Keyword search: "$topic"});
} else {
error("No topic entered") unless $topic;
if ($section !~ /all/) {
push(@manargs, $SectOpt) if $SectOpt;
push(@manargs, $section);
}
push(@manargs, $topic);
$manexec .= " $section" if $section !~ /all/;
$manexec .= " $topic";
$tmp = $topic;
$tmp .= "($section)" if $section !~ /all/;
push(@ARGV, @ConvArgs,
"-title", $tmp);
}
# Check if doing man xref detection
#----------------------------------
if ($DoCgiurl) {
push(@ARGV, "-cgiurl",
join('', $CgiBin, '/man.cgi?',
'section=${section}${subsection}',
$ArgSep,
'topic=${title}'));
}
# Convert output from man to html
#--------------------------------
close(STDERR);
open(MANPRG, "-|") or exec($ManPrg, @manargs);
$Man2Html::InFH = \*MANPRG; # set input filehandle
require $ManConvPrg or
error("Problem executing man->HTML converter");
}
########################################################################
## Generic subroutines for CGI use
########################################################################
#-----------------------------------------------------------------------
# noarg returns true if no arguments were passed to script.
#
sub noarg {
$ENV{"REQUEST_METHOD"} eq "GET" && $ENV{"QUERY_STRING"} =~ /^\s*$/;
}
#-----------------------------------------------------------------------
# parseinput converts the input data into the %FORM array
#
sub parseinput {
my($method) = ($ENV{"REQUEST_METHOD"});
my($data);
if ($method eq "GET") {
$data = $ENV{"QUERY_STRING"};
} elsif ($method eq "POST") {
read(STDIN, $data, $ENV{"CONTENT_LENGTH"});
} else {
$Error = "Unrecgonized request method : $method";
return 0;
}
my(@pairs, $name, $value);
if ($data ne '') {
@pairs = split(/&/, $data);
foreach (@pairs) {
($name, $value) = split(/=/);
$name = expandstr($name);
$value = expandstr($value);
$FORM{$name} = $value;
}
}
1;
}
#-----------------------------------------------------------------------
# printouttype prints out specified content-type header back
# to client
#
sub printouttype {
my($type) = shift;
print STDOUT "Content-type: $type\r\n\r\n";
}
#-----------------------------------------------------------------------
# printhead outputs html prematter
#
sub printhead {
my($title, $h1) = @_;
$h1 = $title unless $h1;
print STDOUT <
$title
$h1
ENDOFHEAD
}
#-----------------------------------------------------------------------
# printend outputs html postmatter
#
sub printend {
print STDOUT <
Manpage viewer available with the
man2html
package.
ENDOFEND
}
#-----------------------------------------------------------------------
# error prints an error out to the client.
#
sub error {
my($str) = htmlize(shift);
printhead("$ProgName Error");
$str .= ":" if $Error && $str;
$str .= " $Error";
print STDOUT "$str
";
printend();
exit 0;
}
#-----------------------------------------------------------------------
# htmlize translates special characters to enitity refs.
#
sub htmlize {
my($str) = shift;
$str =~ s/&/\&/g;
$str =~ s/\</g;
$str =~ s/>/\>/g;
$str;
}
#-----------------------------------------------------------------------
# expandstr translates hex codes to characters
#
sub expandstr {
my($str) = shift;
$str =~ tr/+/ /;
$str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ge;
$str;
}
#-----------------------------------------------------------------------
# isquestionable determines if $str contains questionable
# characters if $str is used in a subshell invocation.
#
sub isquestionable {
my($str) = shift;
$str !~ /^[a-zA-Z0-9_\-+ \t\/@%\.]+$/;
}
########################################################################