#!/usr/bin/perl # # # Copyright (c) 1996-2011 Wolfram Schneider # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # man.cgi - HTML hypertext FreeBSD man page interface # # based on bsdi-man.pl,v 2.17 1995/10/05 16:48:58 sanders Exp # bsdi-man -- HTML hypertext BSDI man page interface # based on bsdi-man.pl,v 2.10 1993/10/02 06:13:23 sanders Exp # by polk@BSDI.COM 1/10/95 # BSDI Id: bsdi-man,v 1.2 1995/01/11 02:30:01 polk Exp # Dual CGI/Plexus mode and new interface by sanders@bsdi.com 9/22/1995 # # $FreeBSD: head/en_US.ISO8859-1/htdocs/cgi/man.cgi 46495 2015-04-06 17:47:33Z wosch $ ############################################################################ # !!! man.cgi is stale perl4 code !!! ############################################################################ # run `perltidy -b man.cgi' to indent the code # Use standard FreeBSD CGI Style if available. # Otherwise print simple HTML design. package cgi_style; use constant HAS_FREEBSD_CGI_STYLE => eval { require "./cgi-style.pl"; }; package main; alarm(10); $debug = 3; $www{'title'} = 'Minix Man Pages'; $www{'home'} = 'https://www.minix3.org'; $www{'head'} = $www{'title'}; $command{'man'} = '/usr/bin/man'; # 8Bit clean man #$command{'man'} = '/usr/local/www/bin/man.wrapper'; # set CPU limits # Config Options # map sections to their man command argument(s) %sections = ( '', '', 'All', '', '0', '', '1', '-S1', '1c', '-S1', '1C', '-S1', '1g', '-S1', '1m', '-S1', '2', '-S2', '2j', '-S2', '3', '-S3', '3S', '-S3', '3f', '-S3', '3j', '-S3', '3m', '-S3', '3n', '-S3', '3p', '-S3', '3pm', '-S3', '3r', '-S3', '3s', '-S3', '3x', '-S3', '4', '-S4', '5', '-S5', '6', '-S6', '7', '-S7', '8', '-S8', '8c', '-S8', '9', '-S9', 'l', '-Sl', 'n', '-Sn', ); $sectionpath = { }; foreach my $os ( keys %$sectionpath ) { foreach my $section ( split( /:/, $sectionpath->{$os}{'path'} ) ) { $section =~ /(.)(.*)/; $sectionpath->{$os}{$1} .= ( $sectionpath->{$os}{$1} ? ':' : '' ) . $section; } } %sectionName = ( '0', 'All Sections', '1', '1 - General Commands', '2', '2 - System Calls', '3', '3 - Subroutines', '4', '4 - Special Files', '5', '5 - File Formats', '6', '6 - Games', '7', '7 - Macros and Conventions', '8', '8 - Maintenance Commands', '9', '9 - Kernel Interface', 'n', 'n - New Commands', ); $manLocalDir = '/home/minix/man.minix3.org/man'; $manPathDefault = 'minix'; %manPath = ( 'X11R7', "$manLocalDir/X11R7-current", 'Minix 2.0.0', "$manLocalDir/Minix-2.0.0", 'Minix 3.1.5', "$manLocalDir/Minix-3.1.5", 'Minix 3.1.6', "$manLocalDir/Minix-3.1.6", 'Minix 3.1.7', "$manLocalDir/Minix-3.1.7", 'Minix 3.1.8', "$manLocalDir/Minix-3.1.8", 'Minix 3.2.0', "$manLocalDir/Minix-3.2.0", 'Minix 3.2.1', "$manLocalDir/Minix-3.2.1", 'Minix 3.3.0', "$manLocalDir/Minix-3.3.0", 'Minix', "$manLocalDir/Minix", #'Minix current', "$manLocalDir/Minix-current", ); my @no_pdf_output = ( ); my %no_pdf_output = map { $_ => 1 } @no_pdf_output; my %valid_arch = map { $_ => 1 } qw/acorn26 acorn32 algor alpha amd64 amiga arc arm arm26 arm32 armish atari aviion bebox cats cesfic cobalt dreamcast evbarm evbmips evbppc evbsh3 evbsh5 hp300 hp700 hpcarm hpcmips hpcsh hppa hppa64 i386 ibmnws landisk loongson luna68k luna88k mac68k macppc mipsco mmeye mvme68k mvme88k mvmeppc netwinder news68k newsmips next68k ofppc palm pc532 pegasos playstation2 pmax pmppc powerpc prep sandpoint sbmips sgi sgimips shark socppc sparc sparc64 sun2 sun3 sun3x tahoe vax walnut wgrisc x68k zaurus/; my $default_arch = 'i386'; my %arch = ( #'Minix 2.0.0' => { 'arch' => [qw/i386 sparc/] } , #'Minix 3.1.5' => { 'arch' => [qw/i386/] } , #'Minix 3.1.6' => { 'arch' => [qw/i386/] } , #'Minix 3.1.7' => { 'arch' => [qw/i386/] } , #'Minix 3.1.8' => { 'arch' => [qw/i386/] } , #'Minix 3.2.0' => { 'arch' => [qw/i386/] } , #'Minix 3.2.1' => { 'arch' => [qw/evbarm i386/] } , #'Minix 3.3.0' => { 'arch' => [qw/evbarm i386/] } , ); # delete not existing releases while ( ( $key, $val ) = each %manPath ) { my $counter = 0; # if the manpath contains colons, at least one directory must exists foreach ( split( /:/, $val ) ) { $counter++ if -d; } # give up and delete release if ( !$counter && $key ne $manPathDefault ) { delete $manPath{"$key"}; warn qq{man.cgi Remove release "$key"\n} if $debug >= 2; } } # keywords must be in lower cases. %manPathAliases = ( 'minix', 'Minix', 'current', 'Minix-current', 'X11', 'X11R7', ); # # sort by OS release number # # e.g.: # # XFree86 2.1 # XFree86 3.3 # XFree86 3.3.6 # XFree86 4.0 # ... # XFree86 10.0 # XFree86 10.0.1 # XFree86 11 # sub sort_versions { my @a = ( lc($a) =~ /(\d+|\D+)/g ); my @b = ( lc($b) =~ /(\d+|\D+)/g ); my $flag = 0; while ( @a and @b ) { my $a1 = shift @a; my $b1 = shift @b; # sort numerically if possible if ( $a1 =~ /^\d+$/ && $b1 =~ /^\d+$/ ) { return $a1 <=> $b1 if $a1 <=> $b1; $flag++; } # sort by characters else { # minor number and characters # 4.1 RELEASE <=> 4.1.1 RELEASE if ( $flag && ( $a1 =~ /^\d+$/ || $b1 =~ /^\d+$/ ) ) { return $a1 =~ /^\d+$/ ? 1 : -1; } # characters only return $a1 cmp $b1 if $a1 cmp $b1; $flag = 0; } } # longest version string wins return @a <=> @b; } foreach ( sort { &sort_versions } keys %manPathAliases ) { # delete non-existing aliases if ( !defined( $manPath{ $manPathAliases{$_} } ) ) { undef $manPathAliases{$_}; next; } # add aliases, replases spaces with dashes if (/\s/) { local ($key) = $_; $key =~ s/\s+/-/g; $manPathAliases{$key} = $manPathAliases{$_}; } } @sections = keys %sections; shift @sections; # all but the "" entry $sections = join( "|", @sections ); # sections regexp # mailto - Author # webmaster - who run this service $mailto = 'info@minix3.org'; $mailtoURL = 'http://wolfram.schneider.org'; $mailtoURL = "mailto:$mailto" if !$mailtoURL; $full_url = 'https://man.minix3.org/'; $want_to_link_to_this_page = 1; &secure_env; # CGI Interface -- runs at load time &do_man( &env('SCRIPT_NAME'), &env('PATH_INFO'), &env('QUERY_STRING') ) unless defined($main'plexus_configured); $enable_include_links = 0; $enable_mailto_links = 0; # # end of config ####################################################################################### sub html_footer { my %args = @_; my $footer = q#   #; # print #qq{home | help \n} # if !$args{'no_home_link'}; if (cgi_style::HAS_FREEBSD_CGI_STYLE) { print q{
}; print &cgi_style::html_footer; } else { print $footer; print "\n\n"; } } sub html_header { my ( $title, $base ) = @_; my $html_meta = q| |; my $banner = q|
|; return &html_header2( $title, $html_meta, $banner ) if !cgi_style::HAS_FREEBSD_CGI_STYLE; ( my $header = &cgi_style::short_html_header( $title, 1 ) ) =~ s,,\n$html_meta,s; $header =~ s,^Content-type:\s+\S+\s+,,s; $header =~ s,,\n,s if $base; $header = $header.$banner; return $header; } # Plexus Native Interface sub do_man { local ( $BASE, $path, $form ) = @_; local ( $_, %form, $query, $name, $section, $apropos ); local ($u) = $BASE; return &faq_output($u) if ( $path =~ /\/(faq|help)\.html$/ ); return &get_the_sources if ( $path =~ /source$/ ); return &include_output($path) if ( $enable_include_links && $path =~ m%^/usr/include/% && -f $path ); return &indexpage if ( $form eq "" ); &decode_form( $form, *form, 0 ); $format = $form{'format'}; $format = 'html' if $format !~ /^(ps|pdf|ascii|latin1)$/; $arch = $form{'arch'} || ""; $arch = '' if $arch eq 'none' || $arch eq 'default'; if ( $arch =~ /^([a-zA-Z0-9]+)$/ && $valid_arch{$arch} ) { $arch = $1; } elsif ($arch) { warn "Unknown arch: '$arch', ignored\n"; $arch = ""; } else { $arch = ""; } # remove trailing spaces for dumb users $form{'query'} =~ s/\s+$//; $form{'query'} =~ s/^\s+//; $name = $query = $form{'query'}; $section = $form{'sektion'}; $apropos = $form{'apropos'}; $alttitle = $form{'title'}; $manpath = $form{'manpath'}; if ( $manpath =~ /^([0-9A-Za-z \.\-\/]+)$/ ) { $manpath = $1; } else { $manpath = ''; } if ( !$manpath ) { $manpath = $manPathDefault; } elsif ( !$manPath{$manpath} ) { local ($m) = ( $manpath =~ y/A-Z/a-z/ ); if ( $manPath{ $manPathAliases{$manpath} } ) { $manpath = $manPathAliases{$manpath}; } else { $manpath = $manPathDefault; } } $format = 'html' if $no_pdf_output{$manpath} && $format =~ /^(ps|pdf)$/; local ($fform) = &dec($form); if ( $fform =~ m%^([a-zA-Z_\-\.:]+)$% ) { return &man( $1, '' ); } elsif ( $fform =~ m%^([a-zA-Z_\-\.:]+)\(([0-9a-zA-Z]+)\)$% ) { return &man( $1, $2 ); } # download a man hierarchy as gzip'd tar file return &download if ( $apropos > 1 ); # empty query return &indexpage if ( $manpath && $form !~ /query=/ ); $section = "" if $section eq "ALL" || $section eq ''; if ( !$apropos && $query =~ m/^(.*)\(([^\)]*)\)/ ) { $name = $1; $section = $2; } if ( $name =~ /^([\w\-:\.]+)$/ ) { $name = $1; } else { $name = ''; } if ( $section =~ /^([\w\-\.]+)$/ ) { $section = $1; } else { $section = ''; } $apropos ? &apropos($query) : &man( $name, $section, $arch ); } # --------------------- support routines ------------------------ sub debug { &http_header("text/plain"); print @_, "\n----------\n\n\n"; } sub get_the_sources { local ($file) = $0; open( R, $file ) || &mydie("open $file: $!\n"); print "Content-type: text/plain\n\n"; while () { print } close R; exit; } # download a manual directory as gzip'd tar archive sub download { $| = 1; my $filename = $manpath; $filename =~ s/\s+/_/; $filename = &encode_url($filename); $filename .= '.tgz'; print qq{Content-type: application/x-tgz\n} . qq{Content-disposition: attachment; filename="$filename"\n} . "\n"; local (@m); local ($m) = $manPath{"$manpath"}; foreach ( split( /:/, $m ) ) { push( @m, $_ . '/' ) if s%^$manLocalDir/?%%; } chdir($manLocalDir) || do { print "chdir: $!\n"; exit(0); }; $m = join( " ", @m ); sleep 1; system("find $m -print | cpio -o --format ustar 2>/dev/null | gzip -cqf"); exit(0); } sub http_header { local ( $content_type, $filename ) = @_; print qq{Content-disposition: inline; filename="$filename"\n} if $filename; if ( defined($main'plexus_configured) ) { &main'MIME_header( 'ok', $content_type ); } else { print "Content-type: $content_type\n\n"; } } sub env { defined( $main'ENV{ $_[0] } ) ? $main'ENV{ $_[0] } : undef; } sub apropos { local ($query) = @_; local ( $_, $title, $head, *APROPOS ); local ( $names, $section, $msg, $key ); local ($prefix); $prefix = "Apropos "; if ($alttitle) { $prefix = ""; $title = &encode_title($alttitle); $head = &encode_data($alttitle); } else { $title = &encode_title($query); $head = &encode_data($query); } &http_header("text/html"); print &html_header("Apropos $title"); print "

", $www{'head'}, "

\n\n"; &formquery; local ($mpath) = $manPath{$manpath}; if ( $debug >= 2 ) { foreach my $dir ( split( /:/, $mpath ) ) { my $whatis = $dir . '/whatis'; warn "$manpath: no whatis file found: $whatis\n" if !-f $whatis; } } open( APROPOS, "env MANPATH=$mpath $command{'man'} -k . |" ) || do { warn "$0: Cannot open whatis database for `$mpath'\n"; print "Cannot open whatis database for `$mpath'\n"; print "\n\n\n"; return; }; local ($q) = $query; $q =~ s/(\W)/\\W/g; local ($acounter) = 0; print qq{
\n}; while () { next if !/$q/oi; $acounter++; # matches whatis.db lines: name[, name ...] (sect) - msg $names = $section = $msg = $key = undef; ( $key, $section ) = m/^([^()]+)\(([^)]*)\)/; $key =~ s/\s+$//; $key =~ s/.*\s+//; ( $names, $msg ) = m/^(.*\))\s+-\s+(.*)/; print "
", &encode_data("$names"), "\n
\n
", &encode_data($msg), "
\n"; } print qq{
\n}; close(APROPOS); if ( !$acounter ) { print "Sorry, no data found for `$query'.\n"; print qq{You may look for other } . qq{FreeBSD Search Services.\n}; } &html_footer; } sub to_filename { my %args = @_; my $name = exists $args{'name'} ? $args{'name'} : 'manpage'; my $section = exists $args{'section'} && $args{'section'} ne "" ? $args{'section'} : '0'; my $format = exists $args{'format'} ? $args{'format'} : 'unkown'; my $filename = qq{$name.$section.$format}; $filename =~ s/[^\w\-\.]/_/g; $filename =~ s/_+/_/g; return $filename; } sub man { local ( $name, $section, $arch ) = @_; local ( $_, $title, $head, *MAN ); local ( $html_name, $html_section, $prefix ); local (@manargs); local ($query) = $name; # $section =~ s/^([0-9ln]).*$/$1/; $section =~ tr/A-Z/a-z/; $prefix = "Man "; if ($alttitle) { $prefix = ""; $title = &encode_title($alttitle); $head = &encode_data($alttitle); } elsif ($section) { $title = &encode_title("${name}($section)"); $head = &encode_data("${name}($section)"); } else { $title = &encode_title("${name}"); $head = &encode_data("${name}"); } if ( $format eq "html" ) { &http_header("text/html"); print &html_header("$title"); print "

", $www{'head'}, "

\n\n"; &formquery; print "
\n";
    }
    else {

        #$format =~ /^(ps|ascii|latin1)$/')
        $ENV{'NROFF_FORMAT'} = $format;

        # Content-encoding: x-gzip
        if ( $format eq "ps" ) {
            &http_header(
                "application/postscript",
                &to_filename(
                    'name'    => $name,
                    'section' => $section,
                    'format'  => 'ps'
                )
            );
        }
        elsif ( $format eq "pdf" ) {
            &http_header(
                "application/pdf",
                &to_filename(
                    'name'    => $name,
                    'section' => $section,
                    'format'  => 'pdf'
                )
            );
        }
        else {
            &http_header("text/plain");
        }
    }

    $html_name    = &encode_data($name);
    $html_section = &encode_data($section);

    #print Dumper($sectionpath);
    #print "yy $section yy $manpath\n";
    if ( $name =~ /^\s*$/ ) {
        print "Empty input, no man page given.\n";
        return;
    }

    if ( index( $name, '*' ) != -1 ) {
        print "Invalid character input '*': $name\n";
        return;
    }

    if ( $section !~ /^[0-9ln]\w*$/ && $section ne '' ) {
        print "Sorry, section `$section' is not valid\n";
        return;
    }

    if ( !$section ) {
        if ( $sectionpath->{$manpath} ) {
            $section = "-S " . $sectionpath->{$manpath}{'path'};
        }
        else {
            $section = '';
        }
    }
    else {
        if ( $sectionpath->{$manpath}{$section} ) {
            $section = "-S " . $sectionpath->{$manpath}{$section};
        }
        else {
            my $s = substr( $section, 0, 1 );

            # create a colon separated list of sections
            $section = "-S $section" . ( $s ne $section ? ":$s" : '' );
        }
    }

    @manargs = split( / /, $section );
    if ($manpath) {
        if ( $manPath{$manpath} ) {
            unshift( @manargs, ( '-M', $manPath{$manpath} ) );
            &groff_path( $manPath{$manpath} );
        }
        elsif ( $manpath{ &dec($manpath) } ) {
            unshift( @manargs, ( '-M', $manPath{ &dec($manpath) } ) );
            &groff_path( $manPath{ &dec($manpath) } );
        }
        else {

            # unset invalid manpath
            print "x $manpath x\n";
            print "x " . &dec($manpath) . "x\n";
            undef $manpath;
        }
    }

    if ( $format =~ /^(ps|pdf)$/ ) {
        push( @manargs, '-t' );
    }

    warn "X $command{'man'} @manargs -- x $name x\n" if $debug >= 3;

    push( @manargs, ( "-m", $arch ) ) if $arch;

    &proc( *MAN, $command{'man'}, @manargs, "--", $name )
      || &mydie("$0: open of $command{'man'} command failed: $!\n");
    if ( eof(MAN) ) {

        # print "X $command{'man'} @manargs -- x $name x\n";
        print qq{
\n}; print "Sorry, no data found for `$html_name" . ( $html_section ? "($html_section)" : '' ) . "'.\n"; print qq{Please try a keyword search.\n}; print qq{

You may look for other } . qq{FreeBSD Search Services.

\n}; &html_footer; return; } if ( $format ne "html" ) { if ( $format eq "latin1" || $format eq "ascii" ) { while () { s/.//g; print; } } elsif ( $format eq "pdf" ) { # # run a PostScript to PDF converter # local (@args) = ( 'mktemp', '/tmp/_man.cgi-ps2pdf-XXXXXXXXXXXX' ); open( TMP, "-|" ) or exec(@args) or die "open @args: $!\n"; local ($tempfile) = ; close TMP; # chomp, avoid security warnings using -T switch #chop($tempfile); if ( $tempfile =~ /(\S+)/ ) { $tempfile = $1; } if ( !$tempfile || !-f $tempfile ) { die "Cannot create tempfile: $tempfile\n"; } #warn $tempfile; #$tempfile = '/tmp/bla2'; open( TMP, "> $tempfile" ) or die "open $tempfile: $!\n"; while () { print TMP $_; } close TMP; local ( $ENV{'PATH'} ) = '/bin:/usr/bin:/usr/local/bin'; open( PDF, "-|" ) or exec( '/usr/bin/ps2pdf', $tempfile, '/dev/stdout' ) or die "open ps2pdf: $!\n"; # sleep and delete the temp file #select(undef, undef, undef, 0.8); #unlink($tempfile); while () { print; } close PDF; unlink($tempfile); } else { while () { print; } } close(MAN); exit(0); } local ($space) = 1; local (@sect); local ( $i, $j ); while () { # remove tailing white space if (/^\s+$/) { next if $space; $space = 1; } else { $space = 0; } $_ = &encode_data($_); if ( $enable_include_links && m,()?\#include()?\s+()?\<\;(.*\.h)\>\;()?, ) { $match = $4; ( $regexp = $match ) =~ s/\./\\\./; s,$regexp,\$match\,; } /^\s/ && # skip headers s,((<[IB]>)?[\w\_\.\-]+\s*()?\s*\(([1-9ln][a-zA-Z]*)\)),&mlnk($1),oige; # detect E-Mail Addreses in manpages if ( $enable_mailto_links && /\@/ ) { s/([a-z0-9_\-\.]+\@[a-z0-9\-\.]+\.[a-z]+)/$1<\/A>/gi; } # detect URLs in manpages if (m%tp://%) { s,((ftp|http)://[^\s<>\)]+),$1,gi; } if (s%^(.*?)+\n?$% ($str = $1) =~ s,(|),,g; $str%ge) { $i = $_; $j = &encode_url($i); $j =~ s/\+/_/g; $_ = qq{$i\n}; push( @sect, $i ); } print; } close(MAN); print qq{\n\n
\n}; for ( $i = 0 ; $i <= $#sect ; $i++ ) { $j = &encode_url( $sect[$i] ); $j =~ s/\+/_/g; print qq{
$sect[$i]} . ( $i < $#sect ? " |\n" : "\n" ); } print qq{
}; print qq{