Add keytab kinit test cases
[krb5.git] / doc / man2html
1 #!/usr/athena/bin/perl
2 #!/usr/local/bin/perl
3 ##---------------------------------------------------------------------------##
4 ##  File:
5 ##      @(#) man2html 1.2 97/08/12 12:57:30 @(#)
6 ##  Author:
7 ##      Earl Hood, ehood@medusa.acs.uci.edu
8 ##  Description:
9 ##      man2html is a Perl program to convert formatted nroff output
10 ##      to HTML.
11 ##      
12 ##      Recommend command-line options based on platform:
13 ##
14 ##      Platform                Options
15 ##      ---------------------------------------------------------------------
16 ##      c2mp                    <None, the defaults should be okay>
17 ##      hp9000s700/800          -leftm 1 -topm 8
18 ##      sun4                    -sun
19 ##      ---------------------------------------------------------------------
20 ##
21 ##---------------------------------------------------------------------------##
22 ##  Copyright (C) 1995-1997     Earl Hood, ehood@medusa.acs.uci.edu
23 ##
24 ##  This program is free software; you can redistribute it and/or modify
25 ##  it under the terms of the GNU General Public License as published by
26 ##  the Free Software Foundation; either version 2 of the License, or
27 ##  (at your option) any later version.
28 ##  
29 ##  This program is distributed in the hope that it will be useful,
30 ##  but WITHOUT ANY WARRANTY; without even the implied warranty of
31 ##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32 ##  GNU General Public License for more details.
33 ##  
34 ##  You should have received a copy of the GNU General Public License
35 ##  along with this program; if not, write to the Free Software
36 ##  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 ##  02111-1307, USA
38 ##---------------------------------------------------------------------------##
39
40 package Man2Html;
41
42 use Getopt::Long;
43
44 ($PROG = $0) =~ s/.*\///;
45 $VERSION = "3.0.1";
46
47 ## Input and outputs filehandles
48 $InFH   = \*STDIN   unless $InFH;
49 $OutFH  = \*STDOUT  unless $OutFH;
50
51 ## Backspace character:  Used in overstriking detection
52 *bs = \"\b";
53
54 ##      Hash of section titles and their HTML tag wrapper.
55 ##      This list allows customization of what HTML tag is used for
56 ##      a given section head.
57 ##
58 ##      The section title can be a regular expression.  Therefore, one must
59 ##      be careful about quoting special characters.
60 ##
61 %SectionHead = (
62
63     '\S.*OPTIONS.*'             => '<H2>',
64     'AUTHORS?'                  => '<H2>',
65     'BUGS'                      => '<H2>',
66     'COMPATIBILITY'             => '<H2>',
67     'DEPENDENCIES'              => '<H2>',
68     'DESCRIPTION'               => '<H2>',
69     'DIAGNOSTICS'               => '<H2>',
70     'ENVIRONMENT'               => '<H2>',
71     'ERRORS'                    => '<H2>',
72     'EXAMPLES'                  => '<H2>',
73     'EXTERNAL INFLUENCES'       => '<H2>',
74     'FILES'                     => '<H2>',
75     'LIMITATIONS'               => '<H2>',
76     'NAME'                      => '<H2>',
77     'NOTES?'                    => '<H2>',
78     'OPTIONS'                   => '<H2>',
79     'REFERENCES'                => '<H2>',
80     'RETURN VALUE'              => '<H2>',
81     'SECTION.*:'                => '<H2>',
82     'SEE ALSO'                  => '<H2>',
83     'STANDARDS CONFORMANCE'     => '<H2>',
84     'STYLE CONVENTION'          => '<H2>',
85     'SYNOPSIS'                  => '<H2>',
86     'SYNTAX'                    => '<H2>',
87     'WARNINGS'                  => '<H2>',
88     '\s+Section.*:'             => '<H3>',
89
90 );
91
92 ## Fallback tag if above is not found
93 $HeadFallback = '<H2>';
94
95 ## Other gobals
96
97 $Bare      = 0;         # Skip printing HTML head/foot flag
98 $BTag      = 'B';       # Overstrike tag
99 $CgiUrl    = '';        # CGI URL expression
100 $Compress  = 0;         # Do blank line compression flag
101 $K         = 0;         # Do keyword search processing flag
102 $NoDepage  = 0;         # Do not strip page information
103 $NoHeads   = 0;         # Do no header detection flag
104 $SeeAlso   = 0;         # Do only SEE ALSO xrefs flag
105 $Solaris   = 0;         # Solaris keyword search processing flag
106 $Sun       = 0;         # Headers not overstriken flag
107 $Title     = '';        # Title
108 $UTag      = 'I';       # Underline tag
109 $ftsz      = 7;         # Bottome margin size
110 $hdsz      = 7;         # Top margin size
111 $leftm     = '';        # Left margin pad
112 $leftmsz   = 0;         # Left margin size
113 $pgsz      = 66;        # Size of page size
114 $txsz      = 52;        # Text body length size
115
116 #############################################################################
117 ##      Main Block
118 #############################################################################
119 {
120     if (get_cli_opts()) {
121         if ($K) {
122             man_k();
123         } else {
124             do_it();
125         }
126     } else {
127         usage();
128     }
129 }
130
131 #############################################################################
132 ##      Subroutines
133 #############################################################################
134
135 sub do_it {
136
137     ##  Define while loop and then eval it when used.  The reason
138     ##  is to avoid the regular expression reevaulation in the
139     ##  section head detection code.
140
141     $doitcode =<<'EndOfDoItCode';
142
143     my($line, $tmp, $i, $head, $preindent, $see_also, $do);
144
145     $see_also = !$SeeAlso;
146     print $OutFH "<!-- Manpage converted by man2html $VERSION -->\n";
147     LOOP: while(!eof($InFH)) {
148         $blank = 0;
149         for ($i=0; $i < $hdsz; $i++) {
150             last LOOP  unless defined($_ = <$InFH>);
151         }
152         for ($i=0; $i < $txsz; $i++) {
153             last LOOP  unless defined($_ = <$InFH>);
154
155             ## Check if compress consecutive blank lines
156             if ($Compress and !/\S/) {
157                 if ($blank) { next; } else { $blank = 1; }
158             } else {
159                 $blank = 0;
160             }
161
162             ## Try to check if line space is needed at page boundaries ##
163             if (!$NoDepage && ($i==0 || $i==($txsz-1)) && !/^\s*$/) {
164                 /^(\s*)/;  $tmp = length($1);
165                 if ($do) {
166                     if ($tmp < $preindent) { print $OutFH "\n"; }
167                 } else {
168                     $do = 1;
169                 }
170                 $preindent = $tmp;
171             } else {
172                 $do = 0;  $preindent = 0;
173             }
174
175             ## Interpret line
176             $line = $_;
177             entitize(\$_);              # Convert [$<>] to entity references
178
179             ## Check for 'SEE ALSO' link only
180             if (!$see_also && $CgiUrl && $SeeAlso) {
181                 ($tmp = $line) =~ s/.\010//go;
182                 if ($tmp =~ /^\s*SEE\s+ALSO\s*$/o) { $see_also = 1; }
183                 else { $see_also = 0; }
184             }
185
186             ## Create anchor links for manpage references
187             s/((((.\010)+)?[\+_\.\w-])+\(((.\010)+)?
188               \d((.\010)+)?\w?\))
189              /make_xref($1)
190              /geox  if $see_also;
191
192             ## Emphasize underlined words
193             # s/((_\010[^_])+[\.\(\)_]?(_\010[^_])+\)?)/emphasize($1)/oge;
194             # s/((_\010[^_])+([\.\(\)_]?(_\010[^_])+)?)/emphasize($1)/oge;
195             #
196             # The previous expressions were trying to be clever about
197             # detecting underlined text which contain non-alphanumeric
198             # characters.  nroff will not underline non-alphanumeric
199             # characters in an underlined phrase, and the above was trying
200             # to detect that.  It does not work all the time, and it
201             # screws up other text, so a simplified expression is used.
202
203             s/((_\010[^_])+)/emphasize($1)/oge;
204
205             $secth = 0;
206             ## Check for strong text and headings
207             if ($Sun || /.\010./o) {
208                 if (!$NoHeads) {
209                     $line =~ s/.\010//go;
210                     $tmp = $HeadFallback;
211 EndOfDoItCode
212
213     ##  Create switch statement for detecting a heading
214     ##
215     $doitcode .= "HEADSW: {\n";
216     foreach $head (keys %SectionHead) {
217         $doitcode .= join("", "\$tmp = '$SectionHead{$head}', ",
218                               "\$secth = 1, last HEADSW  ",
219                               "if \$line =~ /^$leftm$head/o;\n");
220     }
221     $doitcode .= "}\n";
222
223     ##  Rest of routine
224     ##
225     $doitcode .=<<'EndOfDoItCode';
226                     if ($secth || $line =~ /^$leftm\S/o) {
227                         chop $line;
228                         $_ = $tmp . $line . $tmp;
229                         s%<([^>]*)>$%</$1>%;
230                         $_ = "\n</PRE>\n" . $_ . "<PRE>\n";
231                     } else {
232                         s/(((.\010)+.)+)/strongize($1)/oge;
233                     }
234                 } else {
235                     s/(((.\010)+.)+)/strongize($1)/oge;
236                 }
237             }
238             print $OutFH $_;
239         }
240
241         for ($i=0; $i < $ftsz; $i++) {
242             last LOOP  unless defined($_ = <$InFH>);
243         }
244     }
245 EndOfDoItCode
246
247
248     ##  Perform processing.
249
250     printhead()  unless $Bare;
251     print $OutFH "<PRE>\n";
252     eval $doitcode;                     # $doitcode defined above
253     print $OutFH "</PRE>\n";
254     printtail()  unless $Bare;
255 }
256
257 ##---------------------------------------------------------------------------
258 ##
259 sub get_cli_opts {
260     return 0  unless
261     GetOptions(
262         "bare",         # Leave out HTML, HEAD, BODY tags.
263         "belem=s",      # HTML Element for overstriked text (def: "B")
264         "botm=i",       # Number of lines for bottom margin (def: 7)
265         "cgiurl=s",     # CGI URL for linking to other manpages
266         "cgiurlexp=s",  # CGI URL Perl expr for linking to other manpages
267         "compress",     # Compress consecutive blank lines
268         "headmap=s",    # Filename of user section head map file
269         "k",            # Process input from 'man -k' output.
270         "leftm=i",      # Character width of left margin (def: 0)
271         "nodepage",     # Do not remove pagination lines
272         "noheads",      # Do not detect for section heads
273         "pgsize=i",     # Number of lines in a page (def: 66)
274         "seealso",      # Link to other manpages only in the SEE ALSO section
275         "solaris",      # Parse 'man -k' output from a solaris system
276         "sun",          # Section heads are not overstriked in input
277         "title=s",      # Title of manpage (def: Not defined)
278         "topm=i",       # Number of lines for top margin (def: 7)
279         "uelem=s",      # HTML Element for underlined text (def: "I")
280
281         "help"          # Short usage message
282     );
283     return 0  if defined($opt_help);
284
285     $pgsz = $opt_pgsize || $pgsz;
286     if (defined($opt_nodepage)) {
287         $hdsz   = 0;
288         $ftsz   = 0;
289     } else {
290         $hdsz   = $opt_topm  if defined($opt_topm);
291         $ftsz   = $opt_botm  if defined($opt_botm);
292     }
293     $txsz       = $pgsz - ($hdsz + $ftsz);
294     $leftmsz    = $opt_leftm  if defined($opt_leftm);
295     $leftm      = ' ' x $leftmsz;
296
297     $Bare       = defined($opt_bare);
298     $Compress   = defined($opt_compress);
299     $K          = defined($opt_k);
300     $NoDepage   = defined($opt_nodepage);
301     $NoHeads    = defined($opt_noheads);
302     $SeeAlso    = defined($opt_seealso);
303     $Solaris    = defined($opt_solaris);
304     $Sun        = defined($opt_sun);
305
306     $Title      = $opt_title || $Title;
307     $CgiUrl     = $opt_cgiurlexp ||
308                         ($opt_cgiurl ? qq{return "$opt_cgiurl"} : '');
309
310     $BTag       = $opt_belem || $BTag;
311     $UTag       = $opt_uelem || $UTag;
312     $BTag       =~ s/[<>]//g;
313     $UTag       =~ s/[<>]//g;
314
315     if (defined($opt_headmap)) {
316         require $opt_headmap or warn "Unable to read $opt_headmap\n";
317     }
318     1;
319 }
320
321 ##---------------------------------------------------------------------------
322 sub printhead {
323     print $OutFH "<HTML>\n";
324     print $OutFH "<HEAD>\n",
325                  "<TITLE>$Title</TITLE>\n",
326                  "</HEAD>\n"  if $Title;
327     print $OutFH "<BODY>\n";
328     print $OutFH "<H1>$Title</H1>\n",
329                  "<HR>\n"  if $Title;
330 }
331
332 ##---------------------------------------------------------------------------
333 sub printtail {
334     print $OutFH <<EndOfRef;
335 <HR>
336 <ADDRESS>
337 Man(1) output converted with
338 <a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a>
339 </ADDRESS>
340 </BODY>
341 </HTML>
342 EndOfRef
343 }
344
345 ##---------------------------------------------------------------------------
346 sub emphasize {
347     my($txt) = shift;
348     $txt =~ s/.\010//go;
349     $txt = "<$UTag>$txt</$UTag>";
350     $txt;
351 }
352
353 ##---------------------------------------------------------------------------
354 sub strongize {
355     my($txt) = shift;
356     $txt =~ s/.\010//go;
357     $txt = "<$BTag>$txt</$BTag>";
358     $txt;
359 }
360
361 ##---------------------------------------------------------------------------
362 sub entitize {
363     my($txt) = shift;
364
365     ## Check for special characters in overstrike text ##
366     $$txt =~ s/_\010\&/strike('_', '&')/geo;
367     $$txt =~ s/_\010</strike('_', '<')/geo;
368     $$txt =~ s/_\010>/strike('_', '>')/geo;
369
370     $$txt =~ s/(\&\010)+\&/strike('&', '&')/geo;
371     $$txt =~ s/(<\010)+</strike('<', '<')/geo;
372     $$txt =~ s/(>\010)+>/strike('>', '>')/geo;
373
374     ## Check for special characters in regular text.  Must be careful
375     ## to check before/after character in expression because it might be
376     ## a special character.
377     $$txt =~ s/([^\010]\&[^\010])/htmlize2($1)/geo;
378     $$txt =~ s/([^\010]<[^\010])/htmlize2($1)/geo;
379     $$txt =~ s/([^\010]>[^\010])/htmlize2($1)/geo;
380 }
381
382 ##---------------------------------------------------------------------------
383 ##      escape special characters in a string, in-place
384 ##
385 sub htmlize {
386     my($str) = shift;
387     $$str =~ s/&/\&amp;/g;
388     $$str =~ s/</\&lt;/g;
389     $$str =~ s/>/\&gt;/g;
390     $$str;
391 }
392
393 ##---------------------------------------------------------------------------
394 ##      htmlize2() is used by entitize.
395 ##
396 sub htmlize2 {
397     my($str) = shift;
398     $str =~ s/&/\&amp;/g;
399     $str =~ s/</\&lt;/g;
400     $str =~ s/>/\&gt;/g;
401     $str;
402 }
403
404 ##---------------------------------------------------------------------------
405 ##      strike converts HTML special characters in overstriked text
406 ##      into entity references.  The entities are overstriked so
407 ##      strongize() and emphasize() will recognize the entity to be
408 ##      wrapped in tags.
409 ##
410 sub strike {
411     my($w, $char) = @_;
412     my($ret);
413     if ($w eq '_') {
414         if ($char eq '&') {
415             $ret = "_$bs\&_${bs}a_${bs}m_${bs}p_${bs};";
416         } elsif ($char eq '<') {
417             $ret = "_$bs\&_${bs}l_${bs}t_${bs};";
418         } elsif ($char eq '>') {
419             $ret = "_$bs\&_${bs}g_${bs}t_${bs};";
420         } else {
421             warn qq|Unrecognized character, "$char", passed to strike()\n|;
422         }
423     } else {
424         if ($char eq '&') {
425             $ret = "\&$bs\&a${bs}am${bs}mp${bs}p;${bs};";
426         } elsif ($char eq '<') {
427             $ret = "\&$bs\&l${bs}lt${bs}t;${bs};";
428         } elsif ($char eq '>') {
429             $ret = "\&$bs\&g${bs}gt${bs}t;${bs};";
430         } else {
431             warn qq|Unrecognized character, "$char", passed to strike()\n|;
432         }
433     }
434     $ret;
435 }
436
437 ##---------------------------------------------------------------------------
438 ##      make_xref() converts a manpage crossreference into a hyperlink.
439 ##
440 sub make_xref {
441     my $str = shift;
442     $str =~ s/.\010//go;                        # Remove overstriking
443
444     if ($CgiUrl) {
445         my($title,$section,$subsection) =
446             ($str =~ /([\+_\.\w-]+)\((\d)(\w?)\)/);
447
448         $title =~ s/\+/%2B/g;
449         my($href) = (eval $CgiUrl);
450         qq|<B><A HREF="$href">$str</A></B>|;
451     } else {
452         qq|<B>$str</B>|;
453     }
454 }
455
456 ##---------------------------------------------------------------------------
457 ##      man_k() process a keyword search.  The problem we have is there
458 ##      is no standard for keyword search results from man.  Solaris
459 ##      systems have a different enough format to warrent dealing
460 ##      with it as a special case.  For other cases, we try our best.
461 ##      Unfortunately, there are some lines of results that may be
462 ##      skipped.
463 ##
464 sub man_k {
465     my($line,$refs,$section,$subsection,$desc,$i,
466        %Sec1, %Sec1sub, %Sec2, %Sec2sub, %Sec3, %Sec3sub,
467        %Sec4, %Sec4sub, %Sec5, %Sec5sub, %Sec6, %Sec6sub,
468        %Sec7, %Sec7sub, %Sec8, %Sec8sub, %Sec9, %Sec9sub,
469        %SecN, %SecNsub, %SecNsec);
470
471     printhead()  unless $Bare;
472     print $OutFH "<!-- Man keyword results converted by ",
473                       "man2html $VERSION -->\n";
474
475     while ($line = <$InFH>) {
476         next if $line !~ /\(\d\w?\)\s+-\s/; # check if line can be handled
477         ($refs,$section,$subsection,$desc) =
478             $line =~ /^\s*(.*)\((\d)(\w?)\)\s*-\s*(.*)$/;
479
480         if ($Solaris) {
481             $refs =~ s/^\s*([\+_\.\w-]+)\s+([\+_\.\w-]+)\s*$/$1/;
482                                         #  <topic> <manpage>
483         } else {
484             $refs =~ s/\s(and|or)\s/,/gi; # Convert and/or to commas
485             $refs =~ s/^[^:\s]:\s*//;   # Remove prefixed whatis path
486         }
487         $refs =~ s/\s//g;               # Remove all whitespace
488         $refs =~ s/,/, /g;              # Put space after comma
489         htmlize(\$desc);                # Check for special chars in desc
490         $desc =~ s/^(.)/\U$1/;          # Uppercase first letter in desc
491
492         if ($section eq '1') {
493             $Sec1{$refs} = $desc; $Sec1sub{$refs} = $subsection;
494         } elsif ($section eq '2') {
495             $Sec2{$refs} = $desc; $Sec2sub{$refs} = $subsection;
496         } elsif ($section eq '3') {
497             $Sec3{$refs} = $desc; $Sec3sub{$refs} = $subsection;
498         } elsif ($section eq '4') {
499             $Sec4{$refs} = $desc; $Sec4sub{$refs} = $subsection;
500         } elsif ($section eq '5') {
501             $Sec5{$refs} = $desc; $Sec5sub{$refs} = $subsection;
502         } elsif ($section eq '6') {
503             $Sec6{$refs} = $desc; $Sec6sub{$refs} = $subsection;
504         } elsif ($section eq '7') {
505             $Sec7{$refs} = $desc; $Sec7sub{$refs} = $subsection;
506         } elsif ($section eq '8') {
507             $Sec8{$refs} = $desc; $Sec8sub{$refs} = $subsection;
508         } elsif ($section eq '9') {
509             $Sec9{$refs} = $desc; $Sec9sub{$refs} = $subsection;
510         } else {                        # Catch all
511             $SecN{$refs} = $desc; $SecNsec{$refs} = $section;
512             $SecNsub{$refs} = $subsection;
513         }
514     }
515     print_mank_sec(\%Sec1, 1, \%Sec1sub);
516     print_mank_sec(\%Sec2, 2, \%Sec2sub);
517     print_mank_sec(\%Sec3, 3, \%Sec3sub);
518     print_mank_sec(\%Sec4, 4, \%Sec4sub);
519     print_mank_sec(\%Sec5, 5, \%Sec5sub);
520     print_mank_sec(\%Sec6, 6, \%Sec6sub);
521     print_mank_sec(\%Sec7, 7, \%Sec7sub);
522     print_mank_sec(\%Sec8, 8, \%Sec8sub);
523     print_mank_sec(\%Sec9, 9, \%Sec9sub);
524     print_mank_sec(\%SecN, 'N', \%SecNsub, \%SecNsec);
525
526     printtail()  unless $Bare;
527 }
528 ##---------------------------------------------------------------------------
529 ##      print_mank_sec() prints out manpage cross-refs of a specific section.
530 ##
531 sub print_mank_sec {
532     my($sec, $sect, $secsub, $secsec) = @_;
533     my(@array, @refs, $href, $item, $title, $subsection, $i, $section,
534        $xref);
535     $section = $sect;
536
537     @array = sort keys %$sec;
538     if ($#array >= 0) {
539         print $OutFH "<H2>Section $section</H2>\n",
540                      "<DL COMPACT>\n";
541         foreach $item (@array) {
542             @refs = split(/,/, $item);
543             $section = $secsec->{$item}  if $sect eq 'N';
544             $subsection = $secsub->{$item};
545             if ($CgiUrl) {
546                 ($title = $refs[0]) =~ s/\(\)//g;  # watch out for extra ()'s
547                 $xref = eval $CgiUrl;
548             }
549             print $OutFH "<DT>\n";
550             $i = 0;
551             foreach (@refs) {
552                 if ($CgiUrl) {
553                     print $OutFH qq|<B><A HREF="$xref">$_</A></B>|;
554                 } else {
555                     print $OutFH $_;
556                 }
557                 print $OutFH ", "  if $i < $#refs;
558                 $i++;
559             }
560             print $OutFH " ($section$subsection)\n",
561                          "</DT><DD>\n",
562                          $sec->{$item}, "</DD>\n";
563         }
564         print $OutFH "</DL>\n";
565     }
566 }
567
568 ##---------------------------------------------------------------------------
569 ##
570 sub usage {
571     print $OutFH <<EndOfUsage;
572 Usage: $PROG [ options ] < infile > outfile
573 Options:
574   -bare            : Do not put in HTML, HEAD, BODY tags
575   -belem <elem>    : HTML Element for overstriked text (def: "B")
576   -botm <#>        : Number of lines for bottom margin (def: 7)
577   -cgiurl <url>    : URL for linking to other manpages
578   -cgiurlexp <url> : Perl expression URL for linking to other manpages
579   -compress        : Compress consective blank lines
580   -headmap <file>  : Filename of user section head map file
581   -help            : This message
582   -k               : Process a keyword search result
583   -leftm <#>       : Character width of left margin (def: 0)
584   -nodepage        : Do not remove pagination lines
585   -noheads         : Turn off section head detection
586   -pgsize <#>      : Number of lines in a page (def: 66)
587   -seealso         : Link to other manpages only in the SEE ALSO section
588   -solaris         : Process keyword search result in Solaris format
589   -sun             : Section heads are not overstriked in input
590   -title <string>  : Title of manpage (def: Not defined)
591   -topm <#>        : Number of lines for top margin (def: 7)
592   -uelem <elem>    : HTML Element for underlined text (def: "I")
593
594 Description:
595   $PROG takes formatted manpages from STDIN and converts it to HTML sent
596   to STDOUT.  The -topm and -botm arguments are the number of lines to the
597   main body text and NOT to the running headers/footers.
598
599 Version:
600   $VERSION
601   Copyright (C) 1995-1997  Earl Hood, ehood\@medusa.acs.uci.edu
602   $PROG comes with ABSOLUTELY NO WARRANTY and $PROG may be copied only
603   under the terms of the GNU General Public License, which may be found in
604   the $PROG distribution.
605
606 EndOfUsage
607     exit 0;
608 }