#!/usr/bin/env python #================================================================ # manweb.cgi: Display a man page in HTML. For documentation, see: # http://www.nmt.edu/tcc/help/lang/python/examples/manweb/ #---------------------------------------------------------------- #================================================================ # Imports #---------------------------------------------------------------- import sys, os import cgi import re #================================================================ # Manifest constants #---------------------------------------------------------------- MAN_BASE = "/usr/share/man/man" PAGENAME_RE = re.compile ( r'[_a-zA-Z]' # Starts with letter or underbar r'[-+.:_a-zA-Z0-9]*' # Zero or more: + - . : _ letter digit r'$' ) # Match the entire string SECTION_RE = re.compile ( r'[0-9ln]' # Starts with one digit, letter l, or n r'[px]?' # Optional suffix r'$' ) # Match the entire string SUFFIX_RE = re.compile ( r'[a-z]+' # One or more letters r'$' ) # Match the entire string GATEWAY = "GATEWAY_INTERFACE" CGI_VERSION = "CGI/1.1" PAGE_NAME_ARG = "p" SECTION_ARG = "s" DEFAULT_SECTION = "1" SUFFIX_ARG = "x" # - - - m a i n def main(): """Main program: display a man page in HTML. [ if (this script is being executed by the CGI protocol) and (its arguments are valid) and (the arguments described an existing man page -> sys.stdout +:= the output of man2html reformatting that page else -> sys.stdout +:= an error message as HTML ] """ #-- 1 -- # [ if (this script is being executed by the CGI protocol) and # (its arguments are valid) -> # pageName := the page name argument # section := the section number argument, defaulting to "1" # else -> # sys.stdout +:= an error message as HTML # stop execution ] pageName, section, suffix = processArguments() #-- 3 -- # [ if the man file specified by pagename and section exists -> # manPath := the absolute pathname to that file # else -> # sys.stdout +:= an error message as HTML # stop execution ] manPath = findManFile ( pageName, section, suffix ) #-- 4 -- # [ if manPath specifies a readable, valid man file -> # sys.stdout +:= the output of man2html operating on # that file # else -> # sys.stdout +:= an error message as HTML ] convert ( manPath ) # - - - p r o c e s s A r g u m e n t s def processArguments(): """Retrieve and validate the arguments. [ if (this script is being executed by the CGI protocol) and (its arguments are valid) -> return (page name argument, section number argument defaulting to "1", suffix defaulting to "") else -> sys.stdout +:= an error message as HTML stop execution ] """ #-- 1 -- # [ if environmental variable GATEWAY is defined has the value # CGI_VERSION -> # I # else -> # sys.stdout +:= an HTML error message # stop execution ] try: gateway = os.environ [ GATEWAY ] if gateway != CGI_VERSION: errorPage ( "Incorrect CGI protocol version." ) except KeyError: errorPage ( "This script must be executed using the CGI " "protocol." ) #-- 2 -- # [ form := a cgi.FieldStorage instance representing the # arguments from the URL used to invoke this script ] form = cgi.FieldStorage() #-- 3 -- # [ if (form[PAGE_NAME_ARG] does not exist) or # (it exists but is not valid) -> # sys.stdout +:= an error message as HTML # stop execution # else -> # pageName := the corresponding value try: pageName = form[PAGE_NAME_ARG].value except KeyError: errorPage ( "The 'p=PAGENAME' argument is required." ) #-- 4 -- # [ if pageName matches PAGENAME_RE -> # I # else -> # sys.stdout +:= an error message as HTML # stop execution ] m = PAGENAME_RE.match ( pageName ) if m is None: errorPage ( "The 'p=PAGENAME' argument is not valid." ) #-- 5 -- # [ if form[SECTION_ARG] does not exist -> # sectionName := DEFAULT_SECTION # else if it exists and is valid -> # sectionName := the corresponding value # else -> # sys.stdout +:= an error message as HTML # stop execution try: section = form[SECTION_ARG].value m = SECTION_RE.match ( section ) if m is None: errorPage ( "The 's=SECTION' argument is not valid." ) except KeyError: section = DEFAULT_SECTION #-- 7 -- # [ if form[SUFFIX_ARG] does not exist -> # suffix := "" # else if form[SUFFIX_ARG] exists and is valid -> # suffix := the corresponding value # else -> # sys.stdout +:= an error message as HTML # stop execution try: suffix = form[SUFFIX_ARG].value m = SUFFIX_RE.match ( suffix ) if m is None: errorPage ( "The 'x=SUFFIX' argument is not valid." ) except KeyError: suffix = "" #-- 8 -- return (pageName, section, suffix) # - - - f i n d M a n F i l e def findManFile ( pageName, section, suffix ): """Locate the man page and verify its existence. [ (pageName is a page name as a string) and (section is a section number as a string) and (suffix is a suffix string) -> if that man page exists in that section -> return the absolute path to the page else -> sys.stdout +:= an error message as HTML stop execution ] """ #-- 1 -- # [ manPath := path to the man file for page name # (pageName), section (section), and suffix (suffix) ] manPath = ( "%s%s/%s.%s%s.gz" % (MAN_BASE, section, pageName, section, suffix) ) #-- 2 -- # [ if manPath names an existing file -> # I # else -> # sys.stdout +:= an error message in HTML # stop execution ] if not os.path.exists ( manPath ): errorPage ( "No such man page: %s" % manPath ) #-- 3 -- return manPath # - - - c o n v e r t def convert ( manPath ): """Convert a man page to HTML and display it. [ manPath is a string -> if manPath specifies a readable, valid man file -> sys.stdout +:= the output of man2html operating on that file else -> sys.stdout +:= an error message as HTML ] """ #-- 1 -- command = "zcat %s|man2html" % manPath #-- 2 -- # [ pipe := an open file handle for reading the output of # command ] pipe = os.popen ( command ) #-- 3 -- # [ sys.stdout +:= contents of pipe ] sys.stdout.write ( pipe.read() ) #-- 4 -- # [ if pipe.close returns a false value -> # I # else -> # sys.stdout +:= an error message in HTML ] status = pipe.close() if status: errorPage ( "The man2html conversion step for file '%s' " "failed." % manPath ) # - - - e r r o r P a g e def errorPage ( text ): """Write an HTML error message page. [ text is a string -> sys.stdout +:= an HTML error message page containing text stop execution ] """ #-- 1 -- # [ sys.stdout +:= CGI headers for generating HTML ] print "Content-type: text/html" print print "" print "
" print "We were unable to process your request: %s" % text print "
" print "" print "" sys.exit(1) if __name__ == "__main__": main()