3 use 5.006; # we use some open(X, "<", $y) syntax
9 use Fcntl; # for sysopen
10 use File::Spec::Functions qw(catfile catdir splitdir);
12 use vars qw($VERSION @Pagers $Bindir $Pod2man
13 $Temp_Files_Created $Temp_File_Lifetime
16 #..........................................................................
18 BEGIN { # Make a DEBUG constant very first thing...
19 unless(defined &DEBUG) {
20 if(($ENV{'PERLDOCDEBUG'} || '') =~ m/^(\d+)/) { # untaint
21 eval("sub DEBUG () {$1}");
22 die "WHAT? Couldn't eval-up a DEBUG constant!? $@" if $@;
29 use Pod::Perldoc::GetOptsOO; # uses the DEBUG.
31 #..........................................................................
38 *IS_VMS = $^O eq 'VMS' ? \&TRUE : \&FALSE unless defined &IS_VMS;
39 *IS_MSWin32 = $^O eq 'MSWin32' ? \&TRUE : \&FALSE unless defined &IS_MSWin32;
40 *IS_Dos = $^O eq 'dos' ? \&TRUE : \&FALSE unless defined &IS_Dos;
41 *IS_OS2 = $^O eq 'os2' ? \&TRUE : \&FALSE unless defined &IS_OS2;
42 *IS_Cygwin = $^O eq 'cygwin' ? \&TRUE : \&FALSE unless defined &IS_Cygwin;
43 *IS_Linux = $^O eq 'linux' ? \&TRUE : \&FALSE unless defined &IS_Linux;
44 *IS_HPUX = $^O =~ m/hpux/ ? \&TRUE : \&FALSE unless defined &IS_HPUX;
47 $Temp_File_Lifetime ||= 60 * 60 * 24 * 5;
48 # If it's older than five days, it's quite unlikely
49 # that anyone's still looking at it!!
50 # (Currently used only by the MSWin cleanup routine)
53 #..........................................................................
54 { my $pager = $Config{'pager'};
55 push @Pagers, $pager if -x (split /\s+/, $pager)[0] or IS_VMS;
57 $Bindir = $Config{'scriptdirexp'};
58 $Pod2man = "pod2man" . ( $Config{'versiononly'} ? $Config{'version'} : '' );
60 # End of class-init stuff
62 ###########################################################################
66 foreach my $subname (map "opt_$_", split '', q{mhlDriFfXqnTdULv}) {
68 *$subname = do{ use strict 'refs'; sub () { shift->_elem($subname, @_) } };
71 # And these are so that GetOptsOO knows they take options:
72 sub opt_f_with { shift->_elem('opt_f', @_) }
73 sub opt_q_with { shift->_elem('opt_q', @_) }
74 sub opt_d_with { shift->_elem('opt_d', @_) }
75 sub opt_L_with { shift->_elem('opt_L', @_) }
76 sub opt_v_with { shift->_elem('opt_v', @_) }
78 sub opt_w_with { # Specify an option for the formatter subclass
79 my($self, $value) = @_;
80 if($value =~ m/^([-_a-zA-Z][-_a-zA-Z0-9]*)(?:[=\:](.*?))?$/s) {
82 my $option_value = defined($2) ? $2 : "TRUE";
83 $option =~ tr/\-/_/s; # tolerate "foo-bar" for "foo_bar"
84 $self->add_formatter_option( $option, $option_value );
86 warn "\"$value\" isn't a good formatter option name. I'm ignoring it!\n";
91 sub opt_M_with { # specify formatter class name(s)
92 my($self, $classes) = @_;
93 return unless defined $classes and length $classes;
94 DEBUG > 4 and print "Considering new formatter classes -M$classes\n";
96 foreach my $classname (split m/[,;]+/s, $classes) {
97 next unless $classname =~ m/\S/;
98 if( $classname =~ m/^(\w+(::\w+)+)$/s ) {
99 # A mildly restrictive concept of what modulenames are valid.
100 push @classes_to_add, $1; # untaint
102 warn "\"$classname\" isn't a valid classname. Ignoring.\n";
106 unshift @{ $self->{'formatter_classes'} }, @classes_to_add;
109 "Adding @classes_to_add to the list of formatter classes, "
110 . "making them @{ $self->{'formatter_classes'} }.\n"
116 sub opt_V { # report version and exit
118 "Perldoc v$VERSION, under perl v$] for $^O",
120 (defined(&Win32::BuildNumber) and defined &Win32::BuildNumber())
121 ? (" (win32 build ", &Win32::BuildNumber(), ")") : (),
123 (chr(65) eq 'A') ? () : " (non-ASCII)",
130 sub opt_t { # choose plaintext as output format
132 $self->opt_o_with('text') if @_ and $_[0];
133 return $self->_elem('opt_t', @_);
136 sub opt_u { # choose raw pod as output format
138 $self->opt_o_with('pod') if @_ and $_[0];
139 return $self->_elem('opt_u', @_);
143 # choose man as the output format, and specify the proggy to run
145 $self->opt_o_with('man') if @_ and $_[0];
146 $self->_elem('opt_n', @_);
149 sub opt_o_with { # "o" for output format
150 my($self, $rest) = @_;
151 return unless defined $rest and length $rest;
152 if($rest =~ m/^(\w+)$/s) {
155 warn "\"$rest\" isn't a valid output format. Skipping.\n";
159 $self->aside("Noting \"$rest\" as desired output format...\n");
161 # Figure out what class(es) that could actually mean...
164 foreach my $prefix ("Pod::Perldoc::To", "Pod::Simple::", "Pod::") {
167 $rest, # Yes, try it first with the given capitalization
168 "\L$rest", "\L\u$rest", "\U$rest" # And then try variations
171 push @classes, $prefix . $stem;
172 #print "Considering $prefix$stem\n";
175 # Tidier, but misses too much:
176 #push @classes, $prefix . ucfirst(lc($rest));
178 $self->opt_M_with( join ";", @classes );
182 ###########################################################################
183 # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
185 sub run { # to be called by the "perldoc" executable
188 print "Parameters to $class\->run:\n";
191 $x[1] = '<undef>' unless defined $x[1];
192 $x[1] = "@{$x[1]}" if ref( $x[1] ) eq 'ARRAY';
193 print " [$x[0]] => [$x[1]]\n";
198 return $class -> new(@_) -> process() || 0;
201 # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
202 ###########################################################################
204 sub new { # yeah, nothing fancy
206 my $new = bless {@_}, (ref($class) || $class);
207 DEBUG > 1 and print "New $class object $new\n";
212 #..........................................................................
214 sub aside { # If we're in -D or DEBUG mode, say this.
216 if( DEBUG or $self->opt_D ) {
219 my $callsub = (caller(1))[3];
220 my $package = quotemeta(__PACKAGE__ . '::');
221 $callsub =~ s/^$package/'/os;
222 # the o is justified, as $package really won't change.
227 if(DEBUG) { print $out } else { print STDERR $out }
232 #..........................................................................
238 # Erase evidence of previous errors (if any), so exit status is simple.
242 perldoc [options] PageName|ModuleName|ProgramName|URL...
243 perldoc [options] -f BuiltinFunction
244 perldoc [options] -q FAQRegex
245 perldoc [options] -v PerlVariable
248 -h Display this help message
250 -r Recursive search (slow)
252 -t Display pod using pod2text instead of pod2man and nroff
253 (-t is the default on win32 unless -n is specified)
254 -u Display unformatted pod text
255 -m Display module's file in its entirety
256 -n Specify replacement for nroff
257 -l Display the module's file name
258 -F Arguments are file names, not modules
259 -D Verbosely describe what's going on
260 -T Send output to STDOUT without any pager
261 -d output_filename_to_send_to
262 -o output_format_name
263 -M FormatterModuleNameToUse
264 -w formatter_option:option_value
265 -L translation_code Choose doc translation (if any)
266 -X Use index if present (looks for pod.idx at $Config{archlib})
267 -q Search the text of questions (not answers) in perlfaq[1-9]
268 -f Search Perl built-in functions
269 -v Search predefined Perl variables
271 PageName|ModuleName|ProgramName|URL...
272 is the name of a piece of documentation that you want to look at. You
273 may either give a descriptive name of the page (as in the case of
274 `perlfunc') the name of a module, either like `Term::Info' or like
275 `Term/Info', or the name of a program, like `perldoc', or a URL
276 starting with http(s).
279 is the name of a perl function. Will extract documentation from
283 is a regex. Will search perlfaq[1-9] for and extract any
284 questions that match.
286 Any switches in the PERLDOC environment variable will be used before the
287 command line arguments. The optional pod index file contains a list of
288 filenames, one per line.
294 #..........................................................................
297 my $me = $0; # Editing $0 is unportable
299 $me =~ s,.*[/\\],,; # get basename
304 #..........................................................................
308 my $me = $self->program_name;
311 Usage: $me [-h] [-V] [-r] [-i] [-D] [-t] [-u] [-m] [-n nroffer_program] [-l] [-T] [-d output_filename] [-o output_format] [-M FormatterModuleNameToUse] [-w formatter_option:option_value] [-L translation_code] [-F] [-X] PageName|ModuleName|ProgramName
316 The -h option prints more help. Also try "$me perldoc" to get
317 acquainted with the system. [Perldoc v$VERSION]
322 #..........................................................................
324 sub pagers { @{ shift->{'pagers'} } }
326 #..........................................................................
328 sub _elem { # handy scalar meta-accessor: shift->_elem("foo", @_)
329 if(@_ > 2) { return $_[0]{ $_[1] } = $_[2] }
330 else { return $_[0]{ $_[1] } }
332 #..........................................................................
333 ###########################################################################
335 # Init formatter switches, and start it off with __bindir and all that
336 # other stuff that ToMan.pm needs.
342 # Make sure creat()s are neither too much nor too little
343 eval { umask(0077) }; # doubtless someone has no mask
345 $self->{'args'} ||= \@ARGV;
346 $self->{'found'} ||= [];
347 $self->{'temp_file_list'} ||= [];
350 $self->{'target'} = undef;
352 $self->init_formatter_class_list;
354 $self->{'pagers' } = [@Pagers] unless exists $self->{'pagers'};
355 $self->{'bindir' } = $Bindir unless exists $self->{'bindir'};
356 $self->{'pod2man'} = $Pod2man unless exists $self->{'pod2man'};
358 push @{ $self->{'formatter_switches'} = [] }, (
359 # Yeah, we could use a hashref, but maybe there's some class where options
360 # have to be ordered; so we'll use an arrayref.
362 [ '__bindir' => $self->{'bindir' } ],
363 [ '__pod2man' => $self->{'pod2man'} ],
366 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
367 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
369 $self->{'translators'} = [];
370 $self->{'extra_search_dirs'} = [];
375 #..........................................................................
377 sub init_formatter_class_list {
379 $self->{'formatter_classes'} ||= [];
381 # Remember, no switches have been read yet, when
382 # we've started this routine.
384 $self->opt_M_with('Pod::Perldoc::ToPod'); # the always-there fallthru
385 $self->opt_o_with('text');
386 $self->opt_o_with('man') unless IS_MSWin32 || IS_Dos
388 ($ENV{TERM} || '') !~ /dumb|emacs|none|unknown/i
394 #..........................................................................
397 # if this ever returns, its retval will be used for exit(RETVAL)
400 DEBUG > 1 and print " Beginning process.\n";
401 DEBUG > 1 and print " Args: @{$self->{'args'}}\n\n";
403 print "Object contents:\n";
406 $x[1] = '<undef>' unless defined $x[1];
407 $x[1] = "@{$x[1]}" if ref( $x[1] ) eq 'ARRAY';
408 print " [$x[0]] => [$x[1]]\n";
414 # TODO: make it deal with being invoked as various different things
417 return $self->usage_brief unless @{ $self->{'args'} };
418 $self->pagers_guessing;
419 $self->options_reading;
420 $self->aside(sprintf "$0 => %s v%s\n", ref($self), $self->VERSION);
421 $self->drop_privs_maybe;
422 $self->options_processing;
424 # Hm, we have @pages and @found, but we only really act on one
425 # file per call, with the exception of the opt_q hack, and with
431 $self->{'pages'} = \@pages;
432 if( $self->opt_f) { @pages = ("perlfunc") }
433 elsif( $self->opt_q) { @pages = ("perlfaq1" .. "perlfaq9") }
434 elsif( $self->opt_v) { @pages = ("perlvar") }
435 else { @pages = @{$self->{'args'}};
437 # if @pages == 1 and $pages[0] eq 'perldoc';
440 return $self->usage_brief unless @pages;
442 $self->find_good_formatter_class();
443 $self->formatter_sanity_check();
445 $self->maybe_diddle_INC();
446 # for when we're apparently in a module or extension directory
448 my @found = $self->grand_search_init(\@pages);
449 exit (IS_VMS ? 98962 : 1) unless @found;
452 DEBUG and print "We're in -l mode, so byebye after this:\n";
453 print join("\n", @found), "\n";
457 $self->tweak_found_pathnames(\@found);
458 $self->assert_closing_stdout;
459 return $self->page_module_file(@found) if $self->opt_m;
460 DEBUG > 2 and print "Found: [@found]\n";
462 return $self->render_and_page(\@found);
465 #..........................................................................
468 my( %class_seen, %class_loaded );
469 sub find_good_formatter_class {
471 my @class_list = @{ $self->{'formatter_classes'} || [] };
472 die "WHAT? Nothing in the formatter class list!?" unless @class_list;
474 my $good_class_found;
475 foreach my $c (@class_list) {
476 DEBUG > 4 and print "Trying to load $c...\n";
477 if($class_loaded{$c}) {
478 DEBUG > 4 and print "OK, the already-loaded $c it is!\n";
479 $good_class_found = $c;
483 if($class_seen{$c}) {
485 "I've tried $c before, and it's no good. Skipping.\n";
491 if( $c->can('parse_from_file') ) {
493 "Interesting, the formatter class $c is already loaded!\n";
496 (IS_VMS or IS_MSWin32 or IS_Dos or IS_OS2)
497 # the always case-insensitive filesystems
498 and $class_seen{lc("~$c")}++
501 "We already used something quite like \"\L$c\E\", so no point using $c\n";
502 # This avoids redefining the package.
504 DEBUG > 4 and print "Trying to eval 'require $c'...\n";
507 if(DEBUG() or $self->opt_D) {
508 # feh, let 'em see it
511 # The average user just has no reason to be seeing
512 # $^W-suppressible warnings from the the require!
517 DEBUG > 4 and print "Couldn't load $c: $!\n";
522 if( $c->can('parse_from_file') ) {
523 DEBUG > 4 and print "Settling on $c\n";
525 $v = ( defined $v and length $v ) ? " version $v" : '';
526 $self->aside("Formatter class $c$v successfully loaded!\n");
527 $good_class_found = $c;
530 DEBUG > 4 and print "Class $c isn't a formatter?! Skipping.\n";
534 die "Can't find any loadable formatter class in @class_list?!\nAborting"
535 unless $good_class_found;
537 $self->{'formatter_class'} = $good_class_found;
538 $self->aside("Will format with the class $good_class_found\n");
544 #..........................................................................
546 sub formatter_sanity_check {
548 my $formatter_class = $self->{'formatter_class'}
549 || die "NO FORMATTER CLASS YET!?";
551 if(!$self->opt_T # so -T can FORCE sending to STDOUT
552 and $formatter_class->can('is_pageable')
553 and !$formatter_class->is_pageable
554 and !$formatter_class->can('page_for_perldoc')
557 ($formatter_class->can('output_extension')
558 && $formatter_class->output_extension
560 $ext = ".$ext" if length $ext;
562 my $me = $self->program_name;
564 "When using Perldoc to format with $formatter_class, you have to\n"
565 . "specify -T or -dsomefile$ext\n"
566 . "See `$me perldoc' for more information on those switches.\n"
571 #..........................................................................
573 sub render_and_page {
574 my($self, $found_list) = @_;
576 $self->maybe_generate_dynamic_pod($found_list);
578 my($out, $formatter) = $self->render_findings($found_list);
581 printf "Perldoc (%s) output saved to %s\n",
582 $self->{'formatter_class'} || ref($self),
584 print "But notice that it's 0 bytes long!\n" unless -s $out;
587 } elsif( # Allow the formatter to "page" itself, if it wants.
588 $formatter->can('page_for_perldoc')
590 $self->aside("Going to call $formatter\->page_for_perldoc(\"$out\")\n");
591 if( $formatter->page_for_perldoc($out, $self) ) {
592 $self->aside("page_for_perldoc returned true, so NOT paging with $self.\n");
595 $self->aside("page_for_perldoc returned false, so paging with $self instead.\n");
600 # Do nothing, since the formatter has "paged" it for itself.
603 # Page it normally (internally)
605 if( -s $out ) { # Usual case:
606 $self->page($out, $self->{'output_to_stdout'}, $self->pagers);
610 $self->aside("Skipping $out (from $$found_list[0] "
611 . "via $$self{'formatter_class'}) as it is 0-length.\n");
613 push @{ $self->{'temp_file_list'} }, $out;
614 $self->unlink_if_temp_file($out);
618 $self->after_rendering(); # any extra cleanup or whatever
623 #..........................................................................
625 sub options_reading {
628 if( defined $ENV{"PERLDOC"} and length $ENV{"PERLDOC"} ) {
629 require Text::ParseWords;
630 $self->aside("Noting env PERLDOC setting of $ENV{'PERLDOC'}\n");
631 # Yes, appends to the beginning
632 unshift @{ $self->{'args'} },
633 Text::ParseWords::shellwords( $ENV{"PERLDOC"} )
635 DEBUG > 1 and print " Args now: @{$self->{'args'}}\n\n";
637 DEBUG > 1 and print " Okay, no PERLDOC setting in ENV.\n";
641 and print " Args right before switch processing: @{$self->{'args'}}\n";
643 Pod::Perldoc::GetOptsOO::getopts( $self, $self->{'args'}, 'YES' )
644 or return $self->usage;
647 and print " Args after switch processing: @{$self->{'args'}}\n";
649 return $self->usage if $self->opt_h;
654 #..........................................................................
656 sub options_processing {
660 my $podidx = "$Config{'archlib'}/pod.idx";
661 $podidx = "" unless -f $podidx && -r _ && -M _ <= 7;
662 $self->{'podidx'} = $podidx;
665 $self->{'output_to_stdout'} = 1 if $self->opt_T or ! -t STDOUT;
667 $self->options_sanity;
669 $self->opt_n("nroff") unless $self->opt_n;
670 $self->add_formatter_option( '__nroffer' => $self->opt_n );
672 # Get language from PERLDOC_POD2 environment variable
673 if ( ! $self->opt_L && $ENV{PERLDOC_POD2} ) {
674 if ( $ENV{PERLDOC_POD2} eq '1' ) {
675 $self->_elem('opt_L',(split(/\_/, $ENV{LC_ALL} || $ENV{LC_LANG} || $ENV{LANG}))[0] );
678 $self->_elem('opt_L', $ENV{PERLDOC_POD2});
682 # Adjust for using translation packages
683 $self->add_translator(split(/\s+/,$self->opt_L)) if $self->opt_L;
688 #..........................................................................
693 # The opts-counting stuff interacts quite badly with
694 # the $ENV{"PERLDOC"} stuff. I.e., if I have $ENV{"PERLDOC"}
695 # set to -t, and I specify -u on the command line, I don't want
696 # to be hectored at that -u and -t don't make sense together.
698 #my $opts = grep $_ && 1, # yes, the count of the set ones
699 # $self->opt_t, $self->opt_u, $self->opt_m, $self->opt_l
702 #$self->usage("only one of -t, -u, -m or -l") if $opts > 1;
705 # Any sanity-checking need doing here?
707 # But does not make sense to set either -f or -q in $ENV{"PERLDOC"}
708 if( $self->opt_f or $self->opt_q ) {
709 $self->usage("Only one of -f -or -q") if $self->opt_f and $self->opt_q;
711 "Perldoc is only really meant for reading one word at a time.\n",
712 "So these parameters are being ignored: ",
713 join(' ', @{$self->{'args'}}),
715 if @{$self->{'args'}}
720 #..........................................................................
722 sub grand_search_init {
723 my($self, $pages, @found) = @_;
726 if (/^http(s)?:\/\//) {
729 my $response = HTTP::Tiny->new->get($_);
730 if ($response->{success}) {
731 my ($fh, $filename) = File::Temp::tempfile(UNLINK => 1);
732 $fh->print($response->{content});
733 push @found, $filename;
734 ($self->{podnames}{$filename} =
735 m{.*/([^/#?]+)} ? uc $1 : "UNKNOWN")
736 =~ s/\.P(?:[ML]|OD)\z//;
740 ($self->opt_m ? "module" : "documentation") . " found for \"$_\".\n";
744 if ($self->{'podidx'} && open(PODIDX, $self->{'podidx'})) {
745 my $searchfor = catfile split '::', $_;
746 $self->aside( "Searching for '$searchfor' in $self->{'podidx'}\n" );
750 push(@found, $_) if m,/$searchfor(?:\.(?:pod|pm))?\z,i;
752 close(PODIDX) or die "Can't close $$self{'podidx'}: $!";
756 $self->aside( "Searching for $_\n" );
760 push @found, $_ if $self->opt_m or $self->containspod($_);
766 # prepend extra search directories (including language specific)
767 push @searchdirs, @{ $self->{'extra_search_dirs'} };
769 # We must look both in @INC for library modules and in $bindir
770 # for executables, like h2xs or perldoc itself.
771 push @searchdirs, ($self->{'bindir'}, @INC);
772 unless ($self->opt_m) {
775 for ($i = 0; $trn = $ENV{'DCL$PATH;'.$i}; $i++) {
776 push(@searchdirs,$trn);
778 push(@searchdirs,'perl_root:[lib.pods]') # installed pods
781 push(@searchdirs, grep(-d, split($Config{path_sep},
785 my @files = $self->searchfor(0,$_,@searchdirs);
787 $self->aside( "Found as @files\n" );
789 # add "perl" prefix, so "perldoc foo" may find perlfoo.pod
790 elsif (BE_LENIENT and !/\W/ and @files = $self->searchfor(0, "perl$_", @searchdirs)) {
791 $self->aside( "Loosely found as @files\n" );
794 # no match, try recursive search
795 @searchdirs = grep(!/^\.\z/s,@INC);
796 @files= $self->searchfor(1,$_,@searchdirs) if $self->opt_r;
798 $self->aside( "Loosely found as @files\n" );
802 ($self->opt_m ? "module" : "documentation") . " found for \"$_\".\n";
803 if ( @{ $self->{'found'} } ) {
804 print STDERR "However, try\n";
805 my $me = $self->program_name;
806 for my $dir (@{ $self->{'found'} }) {
807 opendir(DIR, $dir) or die "opendir $dir: $!";
808 while (my $file = readdir(DIR)) {
809 next if ($file =~ /^\./s);
810 $file =~ s/\.(pm|pod)\z//; # XXX: badfs
811 print STDERR "\t$me $_\::$file\n";
813 closedir(DIR) or die "closedir $dir: $!";
823 #..........................................................................
825 sub maybe_generate_dynamic_pod {
826 my($self, $found_things) = @_;
829 $self->search_perlfunc($found_things, \@dynamic_pod) if $self->opt_f;
831 $self->search_perlvar($found_things, \@dynamic_pod) if $self->opt_v;
833 $self->search_perlfaqs($found_things, \@dynamic_pod) if $self->opt_q;
835 if( ! $self->opt_f and ! $self->opt_q and ! $self->opt_v ) {
836 DEBUG > 4 and print "That's a non-dynamic pod search.\n";
837 } elsif ( @dynamic_pod ) {
838 $self->aside("Hm, I found some Pod from that search!\n");
839 my ($buffd, $buffer) = $self->new_tempfile('pod', 'dyn');
841 push @{ $self->{'temp_file_list'} }, $buffer;
842 # I.e., it MIGHT be deleted at the end.
844 my $in_list = $self->opt_f || $self->opt_v;
846 print $buffd "=over 8\n\n" if $in_list;
847 print $buffd @dynamic_pod or die "Can't print $buffer: $!";
848 print $buffd "=back\n" if $in_list;
850 close $buffd or die "Can't close $buffer: $!";
852 @$found_things = $buffer;
853 # Yes, so found_things never has more than one thing in
854 # it, by time we leave here
856 $self->add_formatter_option('__filter_nroff' => 1);
860 $self->aside("I found no Pod from that search!\n");
866 #..........................................................................
868 sub add_formatter_option { # $self->add_formatter_option('key' => 'value');
870 push @{ $self->{'formatter_switches'} }, [ @_ ] if @_;
872 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
873 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
878 #.........................................................................
880 sub new_translator { # $tr = $self->new_translator($lang);
884 my $pack = 'POD2::' . uc($lang);
885 eval "require $pack";
886 if ( !$@ && $pack->can('new') ) {
890 eval { require POD2::Base };
893 return POD2::Base->new({ lang => $lang });
896 #.........................................................................
898 sub add_translator { # $self->add_translator($lang);
901 my $tr = $self->new_translator($lang);
903 push @{ $self->{'translators'} }, $tr;
904 push @{ $self->{'extra_search_dirs'} }, $tr->pod_dirs;
906 $self->aside( "translator for '$lang' loaded\n" );
908 # non-installed or bad translator package
909 warn "Perldoc cannot load translator package for '$lang': ignored\n";
916 #..........................................................................
919 my($self, $found_things, $pod) = @_;
921 my $opt = $self->opt_v;
923 if ( $opt !~ /^ (?: [\@\%\$]\S+ | [A-Z]\w* ) $/x ) {
924 die "'$opt' does not look like a Perl variable\n";
927 DEBUG > 2 and print "Search: @$found_things\n";
929 my $perlvar = shift @$found_things;
930 open(PVAR, "<", $perlvar) # "Funk is its own reward"
931 or die("Can't open $perlvar: $!");
933 if ( $opt ne '$0' && $opt =~ /^\$\d+$/ ) { # handle $1, $2, ...
934 $opt = '$<I<digits>>';
936 my $search_re = quotemeta($opt);
939 print "Going to perlvar-scan for $search_re in $perlvar\n";
947 # Look for our variable
951 while (<PVAR>) { # "The Mothership Connection is here!"
952 last if /^=head2 Error Indicators/;
953 # \b at the end of $` and friends borks things!
954 if ( m/^=item\s+$search_re\s/ ) {
958 last if $found && !$inheader && !$inlist;
960 elsif (!/^\s+$/) { # not a blank line
962 $inheader = 0; # don't accept more =item (unless inlist)
966 $inheader = 1; # start over
975 last if $found && !$inheader && !$inlist;
979 # ++$found if /^\w/; # found descriptive text
981 @$pod = () unless $found;
983 die "No documentation for perl variable '$opt' found\n";
985 close PVAR or die "Can't open $perlvar: $!";
990 #..........................................................................
992 sub search_perlfunc {
993 my($self, $found_things, $pod) = @_;
995 DEBUG > 2 and print "Search: @$found_things\n";
997 my $perlfunc = shift @$found_things;
998 open(PFUNC, "<", $perlfunc) # "Funk is its own reward"
999 or die("Can't open $perlfunc: $!");
1001 # Functions like -r, -e, etc. are listed under `-X'.
1002 my $search_re = ($self->opt_f =~ /^-[rwxoRWXOeszfdlpSbctugkTBMAC]$/)
1003 ? '(?:I<)?-X' : quotemeta($self->opt_f) ;
1006 print "Going to perlfunc-scan for $search_re in $perlfunc\n";
1008 my $re = 'Alphabetical Listing of Perl Functions';
1010 # Check available translator or backup to default (english)
1011 if ( $self->opt_L && defined $self->{'translators'}->[0] ) {
1012 my $tr = $self->{'translators'}->[0];
1013 $re = $tr->search_perlfunc_re if $tr->can('search_perlfunc_re');
1019 last if /^=head2 $re/;
1022 # Look for our function
1025 while (<PFUNC>) { # "The Mothership Connection is here!"
1026 if ( m/^=item\s+$search_re\b/ ) {
1030 last if $found > 1 and not $inlist;
1037 last if $found > 1 and not $inlist;
1041 ++$found if /^\w/; # found descriptive text
1045 "No documentation for perl function `%s' found\n",
1049 close PFUNC or die "Can't open $perlfunc: $!";
1054 #..........................................................................
1056 sub search_perlfaqs {
1057 my( $self, $found_things, $pod) = @_;
1061 my $search_key = $self->opt_q;
1063 my $rx = eval { qr/$search_key/ }
1065 Invalid regular expression '$search_key' given as -q pattern:
1067 Did you mean \\Q$search_key ?
1072 foreach my $file (@$found_things) {
1073 die "invalid file spec: $!" if $file =~ /[<>|]/;
1074 open(INFAQ, "<", $file) # XXX 5.6ism
1075 or die "Can't read-open $file: $!\nAborting";
1077 if ( m/^=head2\s+.*(?:$search_key)/i ) {
1079 push @$pod, "=head1 Found in $file\n\n" unless $found_in{$file}++;
1081 elsif (/^=head[12]/) {
1089 die("No documentation for perl FAQ keyword `$search_key' found\n")
1096 #..........................................................................
1098 sub render_findings {
1099 # Return the filename to open
1101 my($self, $found_things) = @_;
1103 my $formatter_class = $self->{'formatter_class'}
1104 || die "No formatter class set!?";
1105 my $formatter = $formatter_class->can('new')
1106 ? $formatter_class->new
1110 if(! @$found_things) {
1111 die "Nothing found?!";
1112 # should have been caught before here
1113 } elsif(@$found_things > 1) {
1115 "Perldoc is only really meant for reading one document at a time.\n",
1116 "So these parameters are being ignored: ",
1117 join(' ', @$found_things[1 .. $#$found_things] ),
1121 my $file = $found_things->[0];
1123 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
1124 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
1126 # Set formatter options:
1127 if( ref $formatter ) {
1128 foreach my $f (@{ $self->{'formatter_switches'} || [] }) {
1129 my($switch, $value, $silent_fail) = @$f;
1130 if( $formatter->can($switch) ) {
1131 eval { $formatter->$switch( defined($value) ? $value : () ) };
1132 warn "Got an error when setting $formatter_class\->$switch:\n$@\n"
1135 if( $silent_fail or $switch =~ m/^__/s ) {
1136 DEBUG > 2 and print "Formatter $formatter_class doesn't support $switch\n";
1138 warn "$formatter_class doesn't recognize the $switch switch.\n";
1144 $self->{'output_is_binary'} =
1145 $formatter->can('write_with_binmode') && $formatter->write_with_binmode;
1147 if( $self->{podnames} and exists $self->{podnames}{$file} and
1148 $formatter->can('name') ) {
1149 $formatter->name($self->{podnames}{$file});
1152 my ($out_fh, $out) = $self->new_output_file(
1153 ( $formatter->can('output_extension') && $formatter->output_extension )
1155 $self->useful_filename_bit,
1158 # Now, finally, do the formatting!
1161 if(DEBUG() or $self->opt_D) {
1162 # feh, let 'em see it
1165 # The average user just has no reason to be seeing
1166 # $^W-suppressible warnings from the formatting!
1169 eval { $formatter->parse_from_file( $file, $out_fh ) };
1172 warn "Error while formatting with $formatter_class:\n $@\n" if $@;
1173 DEBUG > 2 and print "Back from formatting with $formatter_class\n";
1176 or warn "Can't close $out: $!\n(Did $formatter already close it?)";
1177 sleep 0; sleep 0; sleep 0;
1178 # Give the system a few timeslices to meditate on the fact
1179 # that the output file does in fact exist and is closed.
1181 $self->unlink_if_temp_file($file);
1184 if( $formatter->can( 'if_zero_length' ) ) {
1185 # Basically this is just a hook for Pod::Simple::Checker; since
1186 # what other class could /happily/ format an input file with Pod
1187 # as a 0-length output file?
1188 $formatter->if_zero_length( $file, $out, $out_fh );
1190 warn "Got a 0-length file from $$found_things[0] via $formatter_class!?\n"
1194 DEBUG and print "Finished writing to $out.\n";
1195 return($out, $formatter) if wantarray;
1199 #..........................................................................
1201 sub unlink_if_temp_file {
1202 # Unlink the specified file IFF it's in the list of temp files.
1203 # Really only used in the case of -f / -q things when we can
1204 # throw away the dynamically generated source pod file once
1205 # we've formatted it.
1207 my($self, $file) = @_;
1208 return unless defined $file and length $file;
1210 my $temp_file_list = $self->{'temp_file_list'} || return;
1211 if(grep $_ eq $file, @$temp_file_list) {
1212 $self->aside("Unlinking $file\n");
1213 unlink($file) or warn "Odd, couldn't unlink $file: $!";
1215 DEBUG > 1 and print "$file isn't a temp file, so not unlinking.\n";
1220 #..........................................................................
1222 sub MSWin_temp_cleanup {
1224 # Nothing particularly MSWin-specific in here, but I don't know if any
1225 # other OS needs its temp dir policed like MSWin does!
1229 my $tempdir = $ENV{'TEMP'};
1230 return unless defined $tempdir and length $tempdir
1231 and -e $tempdir and -d _ and -w _;
1234 "Considering whether any old files of mine in $tempdir need unlinking.\n"
1237 opendir(TMPDIR, $tempdir) || return;
1240 my $limit = time() - $Temp_File_Lifetime;
1242 DEBUG > 5 and printf "Looking for things pre-dating %s (%x)\n",
1247 while(defined($filespec = readdir(TMPDIR))) {
1249 $filespec =~ m{^perldoc_[a-zA-Z0-9]+_T([a-fA-F0-9]{7,})_[a-fA-F0-9]{3,}}s
1251 if( hex($1) < $limit ) {
1252 push @to_unlink, "$tempdir/$filespec";
1253 $self->aside( "Will unlink my old temp file $to_unlink[-1]\n" );
1256 printf " $tempdir/$filespec is too recent (after %x)\n", $limit;
1260 print " $tempdir/$filespec doesn't look like a perldoc temp file.\n";
1264 $self->aside(sprintf "Unlinked %s items of mine in %s\n",
1265 scalar(unlink(@to_unlink)),
1271 # . . . . . . . . . . . . . . . . . . . . . . . . .
1273 sub MSWin_perldoc_tempfile {
1274 my($self, $suffix, $infix) = @_;
1276 my $tempdir = $ENV{'TEMP'};
1277 return unless defined $tempdir and length $tempdir
1278 and -e $tempdir and -d _ and -w _;
1283 $spec = sprintf "%s\\perldoc_%s_T%x_%x%02x.%s", # used also in MSWin_temp_cleanup
1284 # Yes, we embed the create-time in the filename!
1289 defined( &Win32::GetTickCount )
1290 ? (Win32::GetTickCount() & 0xff)
1292 # Under MSWin, $$ values get reused quickly! So if we ran
1293 # perldoc foo and then perldoc bar before there was time for
1294 # time() to increment time."_$$" would likely be the same
1295 # for each process! So we tack on the tick count's lower
1296 # bits (or, in a pinch, rand)
1300 } while( -e $spec );
1304 while($counter < 50) {
1306 # If we are running before perl5.6.0, we can't autovivify
1309 $fh = Symbol::gensym();
1311 DEBUG > 3 and print "About to try making temp file $spec\n";
1312 return($fh, $spec) if open($fh, ">", $spec); # XXX 5.6ism
1313 $self->aside("Can't create temp file $spec: $!\n");
1316 $self->aside("Giving up on making a temp file!\n");
1317 die "Can't make a tempfile!?";
1320 #..........................................................................
1323 sub after_rendering {
1325 $self->after_rendering_VMS if IS_VMS;
1326 $self->after_rendering_MSWin32 if IS_MSWin32;
1327 $self->after_rendering_Dos if IS_Dos;
1328 $self->after_rendering_OS2 if IS_OS2;
1332 sub after_rendering_VMS { return }
1333 sub after_rendering_Dos { return }
1334 sub after_rendering_OS2 { return }
1336 sub after_rendering_MSWin32 {
1337 shift->MSWin_temp_cleanup() if $Temp_Files_Created;
1340 #..........................................................................
1342 #..........................................................................
1345 sub minus_f_nocase { # i.e., do like -f, but without regard to case
1347 my($self, $dir, $file) = @_;
1348 my $path = catfile($dir,$file);
1349 return $path if -f $path and -r _;
1352 or IS_VMS or IS_MSWin32
1355 # On a case-forgiving file system, or if case is important,
1356 # that is it, all we can do.
1357 warn "Ignored $path: unreadable\n" if -f _;
1364 foreach $p (splitdir $file){
1365 my $try = catfile @p, $p;
1366 $self->aside("Scrutinizing $try...\n");
1370 if ( $p eq $self->{'target'} ) {
1371 my $tmp_path = catfile @p;
1373 for (@{ $self->{'found'} }) {
1374 $path_f = 1 if $_ eq $tmp_path;
1376 push (@{ $self->{'found'} }, $tmp_path) unless $path_f;
1377 $self->aside( "Found as $tmp_path but directory\n" );
1380 elsif (-f _ && -r _) {
1384 warn "Ignored $try: unreadable\n";
1386 elsif (-d catdir(@p)) { # at least we see the containing directory!
1389 my $p_dirspec = catdir(@p);
1390 opendir DIR, $p_dirspec or die "opendir $p_dirspec: $!";
1391 while(defined( $cip = readdir(DIR) )) {
1392 if (lc $cip eq $lcp){
1394 last; # XXX stop at the first? what if there's others?
1397 closedir DIR or die "closedir $p_dirspec: $!";
1398 return "" unless $found;
1401 my $p_filespec = catfile(@p);
1402 return $p_filespec if -f $p_filespec and -r _;
1403 warn "Ignored $p_filespec: unreadable\n" if -f _;
1409 #..........................................................................
1411 sub pagers_guessing {
1415 push @pagers, $self->pagers;
1416 $self->{'pagers'} = \@pagers;
1419 push @pagers, qw( more< less notepad );
1420 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1423 push @pagers, qw( most more less type/page );
1426 push @pagers, qw( less.exe more.com< );
1427 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1431 unshift @pagers, 'less', 'cmd /c more <';
1433 push @pagers, qw( more less pg view cat );
1434 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1438 if (($pagers[0] eq 'less') || ($pagers[0] eq '/usr/bin/less')) {
1439 unshift @pagers, '/usr/bin/less -isrR';
1443 unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER};
1448 #..........................................................................
1450 sub page_module_file {
1451 my($self, @found) = @_;
1454 # Don't ever just pass this off to anything like MSWin's "start.exe",
1455 # since we might be calling on a .pl file, and we wouldn't want that
1456 # to actually /execute/ the file that we just want to page thru!
1457 # Also a consideration if one were to use a web browser as a pager;
1458 # doing so could trigger the browser's MIME mapping for whatever
1459 # it thinks .pm/.pl/whatever is. Probably just a (useless and
1460 # annoying) "Save as..." dialog, but potentially executing the file
1461 # in question -- particularly in the case of MSIE and it's, ahem,
1462 # occasionally hazy distinction between OS-local extension
1463 # associations, and browser-specific MIME mappings.
1465 if ($self->{'output_to_stdout'}) {
1466 $self->aside("Sending unpaged output to STDOUT.\n");
1469 foreach my $output (@found) {
1470 unless( open(TMP, "<", $output) ) { # XXX 5.6ism
1471 warn("Can't open $output: $!");
1476 print or die "Can't print to stdout: $!";
1478 close TMP or die "Can't close while $output: $!";
1479 $self->unlink_if_temp_file($output);
1481 return $any_error; # successful
1484 foreach my $pager ( $self->pagers ) {
1485 $self->aside("About to try calling $pager @found\n");
1486 if (system($pager, @found) == 0) {
1487 $self->aside("Yay, it worked.\n");
1490 $self->aside("That didn't work.\n");
1492 # Odd -- when it fails, under Win32, this seems to neither
1493 # return with a fail nor return with a success!!
1494 # That's discouraging!
1498 sprintf "Can't manage to find a way to page [%s] via pagers [%s]\n",
1500 join(' ', $self->pagers),
1504 DEBUG > 1 and print "Bailing out in a VMSish way.\n";
1506 use vmsish qw(status exit);
1513 # i.e., an UNSUCCESSFUL return value!
1516 #..........................................................................
1519 my($self, $dir, $file) = @_;
1521 unless( ref $self ) {
1522 # Should never get called:
1525 Carp::croak( join '',
1526 "Crazy ", __PACKAGE__, " error:\n",
1527 "check_file must be an object_method!\n",
1532 if(length $dir and not -d $dir) {
1533 DEBUG > 3 and print " No dir $dir -- skipping.\n";
1538 return $self->minus_f_nocase($dir,$file);
1542 my $path = $self->minus_f_nocase($dir,$file);
1543 if( length $path and $self->containspod($path) ) {
1545 " The file $path indeed looks promising!\n";
1549 DEBUG > 3 and print " No good: $file in $dir\n";
1554 #..........................................................................
1557 my($self, $file, $readit) = @_;
1558 return 1 if !$readit && $file =~ /\.pod\z/i;
1561 # Under cygwin the /usr/bin/perl is legal executable, but
1562 # you cannot open a file with that name. It must be spelled
1563 # out as "/usr/bin/perl.exe".
1565 # The following if-case under cygwin prevents error
1568 # Cannot open /usr/bin/perl: no such file or directory
1570 # This would work though
1572 # $ perldoc perl.pod
1574 if ( IS_Cygwin and -x $file and -f "$file.exe" )
1576 warn "Cygwin $file.exe search skipped\n" if DEBUG or $self->opt_D;
1581 open(TEST,"<", $file) or die "Can't open $file: $!"; # XXX 5.6ism
1584 close(TEST) or die "Can't close $file: $!";
1588 close(TEST) or die "Can't close $file: $!";
1592 #..........................................................................
1594 sub maybe_diddle_INC {
1597 # Does this look like a module or extension directory?
1599 if (-f "Makefile.PL" || -f "Build.PL") {
1601 # Add "." and "lib" to @INC (if they exist)
1602 eval q{ use lib qw(. lib); 1; } or die;
1604 # don't add if superuser
1605 if ($< && $> && -d "blib") { # don't be looking too hard now!
1606 eval q{ use blib; 1 };
1607 warn $@ if $@ && $self->opt_D;
1614 #..........................................................................
1616 sub new_output_file {
1618 my $outspec = $self->opt_d; # Yes, -d overrides all else!
1619 # So don't call this twice per format-job!
1621 return $self->new_tempfile(@_) unless defined $outspec and length $outspec;
1623 # Otherwise open a write-handle on opt_d!f
1626 # If we are running before perl5.6.0, we can't autovivify
1629 $fh = Symbol::gensym();
1631 DEBUG > 3 and print "About to try writing to specified output file $outspec\n";
1632 die "Can't write-open $outspec: $!"
1633 unless open($fh, ">", $outspec); # XXX 5.6ism
1635 DEBUG > 3 and print "Successfully opened $outspec\n";
1636 binmode($fh) if $self->{'output_is_binary'};
1637 return($fh, $outspec);
1640 #..........................................................................
1642 sub useful_filename_bit {
1643 # This tries to provide a meaningful bit of text to do with the query,
1644 # such as can be used in naming the file -- since if we're going to be
1645 # opening windows on temp files (as a "pager" may well do!) then it's
1646 # better if the temp file's name (which may well be used as the window
1647 # title) isn't ALL just random garbage!
1648 # In other words "perldoc_LWPSimple_2371981429" is a better temp file
1649 # name than "perldoc_2371981429". So this routine is what tries to
1650 # provide the "LWPSimple" bit.
1653 my $pages = $self->{'pages'} || return undef;
1654 return undef unless @$pages;
1656 my $chunk = $pages->[0];
1657 return undef unless defined $chunk;
1659 $chunk =~ s/\.\w+$//g; # strip any extension
1660 if( $chunk =~ m/([^\#\\:\/\$]+)$/s ) { # get basename, if it's a file
1665 $chunk =~ s/[^a-zA-Z0-9]+//g; # leave ONLY a-zA-Z0-9 things!
1666 $chunk = substr($chunk, -10) if length($chunk) > 10;
1670 #..........................................................................
1672 sub new_tempfile { # $self->new_tempfile( [$suffix, [$infix] ] )
1675 ++$Temp_Files_Created;
1678 my @out = $self->MSWin_perldoc_tempfile(@_);
1679 return @out if @out;
1680 # otherwise fall thru to the normal stuff below...
1684 return File::Temp::tempfile(UNLINK => 1);
1687 #..........................................................................
1689 sub page { # apply a pager to the output file
1690 my ($self, $output, $output_to_stdout, @pagers) = @_;
1691 if ($output_to_stdout) {
1692 $self->aside("Sending unpaged output to STDOUT.\n");
1693 open(TMP, "<", $output) or die "Can't open $output: $!"; # XXX 5.6ism
1696 print or die "Can't print to stdout: $!";
1698 close TMP or die "Can't close while $output: $!";
1699 $self->unlink_if_temp_file($output);
1701 # On VMS, quoting prevents logical expansion, and temp files with no
1702 # extension get the wrong default extension (such as .LIS for TYPE)
1704 $output = VMS::Filespec::rmsexpand($output, '.') if IS_VMS;
1706 $output =~ s{/}{\\}g if IS_MSWin32 || IS_Dos;
1707 # Altho "/" under MSWin is in theory good as a pathsep,
1708 # many many corners of the OS don't like it. So we
1709 # have to force it to be "\" to make everyone happy.
1711 foreach my $pager (@pagers) {
1712 $self->aside("About to try calling $pager $output\n");
1714 last if system("$pager $output") == 0;
1716 last if system("$pager \"$output\"") == 0;
1723 #..........................................................................
1726 my($self, $recurse,$s,@dirs) = @_;
1728 $s = VMS::Filespec::unixify($s) if IS_VMS;
1729 return $s if -f $s && $self->containspod($s);
1730 $self->aside( "Looking for $s in @dirs\n" );
1734 $self->{'target'} = (splitdir $s)[-1]; # XXX: why not use File::Basename?
1735 for ($i=0; $i<@dirs; $i++) {
1737 next unless -d $dir;
1738 ($dir = VMS::Filespec::unixpath($dir)) =~ s!/\z!! if IS_VMS;
1739 if ( (! $self->opt_m && ( $ret = $self->check_file($dir,"$s.pod")))
1740 or ( $ret = $self->check_file($dir,"$s.pm"))
1741 or ( $ret = $self->check_file($dir,$s))
1743 $ret = $self->check_file($dir,"$s.com"))
1745 $ret = $self->check_file($dir,"$s.cmd"))
1746 or ( (IS_MSWin32 or IS_Dos or IS_OS2) and
1747 $ret = $self->check_file($dir,"$s.bat"))
1748 or ( $ret = $self->check_file("$dir/pod","$s.pod"))
1749 or ( $ret = $self->check_file("$dir/pod",$s))
1750 or ( $ret = $self->check_file("$dir/pods","$s.pod"))
1751 or ( $ret = $self->check_file("$dir/pods",$s))
1753 DEBUG > 1 and print " Found $ret\n";
1758 opendir(D,$dir) or die "Can't opendir $dir: $!";
1759 my @newdirs = map catfile($dir, $_), grep {
1761 not /^auto\z/s and # save time! don't search auto dirs
1762 -d catfile($dir, $_)
1764 closedir(D) or die "Can't closedir $dir: $!";
1765 next unless @newdirs;
1766 # what a wicked map!
1767 @newdirs = map((s/\.dir\z//,$_)[1],@newdirs) if IS_VMS;
1768 $self->aside( "Also looking in @newdirs\n" );
1769 push(@dirs,@newdirs);
1775 #..........................................................................
1777 my $already_asserted;
1778 sub assert_closing_stdout {
1781 return if $already_asserted;
1783 eval q~ END { close(STDOUT) || die "Can't close STDOUT: $!" } ~;
1784 # What for? to let the pager know that nothing more will come?
1787 $already_asserted = 1;
1792 #..........................................................................
1794 sub tweak_found_pathnames {
1795 my($self, $found) = @_;
1797 foreach (@$found) { s,/,\\,g }
1802 #..........................................................................
1804 #..........................................................................
1806 sub am_taint_checking {
1808 die "NO ENVIRONMENT?!?!" unless keys %ENV; # reset iterator along the way
1809 my($k,$v) = each %ENV;
1810 return is_tainted($v);
1813 #..........................................................................
1815 sub is_tainted { # just a function
1817 my $nada = substr($arg, 0, 0); # zero-length!
1818 local $@; # preserve the caller's version of $@
1819 eval { eval "# $nada" };
1820 return length($@) != 0;
1823 #..........................................................................
1825 sub drop_privs_maybe {
1828 # Attempt to drop privs if we should be tainting and aren't
1829 if (!(IS_VMS || IS_MSWin32 || IS_Dos
1832 && ($> == 0 || $< == 0)
1833 && !$self->am_taint_checking()
1835 my $id = eval { getpwnam("nobody") };
1836 $id = eval { getpwnam("nouser") } unless defined $id;
1837 $id = -2 unless defined $id;
1839 # According to Stevens' APUE and various
1840 # (BSD, Solaris, HP-UX) man pages, setting
1841 # the real uid first and effective uid second
1842 # is the way to go if one wants to drop privileges,
1843 # because if one changes into an effective uid of
1844 # non-zero, one cannot change the real uid any more.
1846 # Actually, it gets even messier. There is
1847 # a third uid, called the saved uid, and as
1848 # long as that is zero, one can get back to
1849 # uid of zero. Setting the real-effective *twice*
1850 # helps in *most* systems (FreeBSD and Solaris)
1851 # but apparently in HP-UX even this doesn't help:
1852 # the saved uid stays zero (apparently the only way
1853 # in HP-UX to change saved uid is to call setuid()
1854 # when the effective uid is zero).
1857 $< = $id; # real uid
1858 $> = $id; # effective uid
1859 $< = $id; # real uid
1860 $> = $id; # effective uid
1862 if( !$@ && $< && $> ) {
1863 DEBUG and print "OK, I dropped privileges.\n";
1864 } elsif( $self->opt_U ) {
1865 DEBUG and print "Couldn't drop privileges, but in -U mode, so feh."
1867 DEBUG and print "Hm, couldn't drop privileges. Ah well.\n";
1868 # We used to die here; but that seemed pointless.
1874 #..........................................................................
1882 Pod::Perldoc - Look up Perl documentation in Pod format.
1886 use Pod::Perldoc ();
1888 Pod::Perldoc->run();
1892 The guts of L<perldoc> utility.
1898 =head1 COPYRIGHT AND DISCLAIMERS
1900 Copyright (c) 2002-2007 Sean M. Burke.
1902 This library is free software; you can redistribute it and/or modify it
1903 under the same terms as Perl itself.
1905 This program is distributed in the hope that it will be useful, but
1906 without any warranty; without even the implied warranty of
1907 merchantability or fitness for a particular purpose.
1911 Current maintainer: Adriano R. Ferreira <ferreira@cpan.org>
1913 Past contributions from:
1914 Sean M. Burke <sburke@cpan.org>
1920 # Perldoc -- look up a piece of documentation in .pod format that
1921 # is embedded in the perl installation tree.
1925 # See ChangeLog in CPAN dist for Pod::Perldoc for later notes.
1927 # Version 3.01: Sun Nov 10 21:38:09 MST 2002
1928 # Sean M. Burke <sburke@cpan.org>
1929 # Massive refactoring and code-tidying.
1930 # Now it's a module(-family)!
1931 # Formatter-specific stuff pulled out into Pod::Perldoc::To(Whatever).pm
1932 # Added -T, -d, -o, -M, -w.
1933 # Added some improved MSWin funk.
1937 # Version 2.05: Sat Oct 12 16:09:00 CEST 2002
1938 # Hugo van der Sanden <hv@crypt.org>
1939 # Made -U the default, based on patch from Simon Cozens
1940 # Version 2.04: Sun Aug 18 13:27:12 BST 2002
1941 # Randy W. Sims <RandyS@ThePierianSpring.org>
1942 # allow -n to enable nroff under Win32
1943 # Version 2.03: Sun Apr 23 16:56:34 BST 2000
1944 # Hugo van der Sanden <hv@crypt.org>
1945 # don't die when 'use blib' fails
1946 # Version 2.02: Mon Mar 13 18:03:04 MST 2000
1947 # Tom Christiansen <tchrist@perl.com>
1948 # Added -U insecurity option
1949 # Version 2.01: Sat Mar 11 15:22:33 MST 2000
1950 # Tom Christiansen <tchrist@perl.com>, querulously.
1951 # Security and correctness patches.
1952 # What a twisted bit of distasteful spaghetti code.
1957 # Version 1.15: Tue Aug 24 01:50:20 EST 1999
1958 # Charles Wilson <cwilson@ece.gatech.edu>
1959 # changed /pod/ directory to /pods/ for cygwin
1960 # to support cygwin/win32
1961 # Version 1.14: Wed Jul 15 01:50:20 EST 1998
1962 # Robin Barker <rmb1@cise.npl.co.uk>
1963 # -strict, -w cleanups
1964 # Version 1.13: Fri Feb 27 16:20:50 EST 1997
1965 # Gurusamy Sarathy <gsar@activestate.com>
1966 # -doc tweaks for -F and -X options
1967 # Version 1.12: Sat Apr 12 22:41:09 EST 1997
1968 # Gurusamy Sarathy <gsar@activestate.com>
1969 # -various fixes for win32
1970 # Version 1.11: Tue Dec 26 09:54:33 EST 1995
1971 # Kenneth Albanowski <kjahds@kjahds.com>
1972 # -added Charles Bailey's further VMS patches, and -u switch
1973 # -added -t switch, with pod2text support
1975 # Version 1.10: Thu Nov 9 07:23:47 EST 1995
1976 # Kenneth Albanowski <kjahds@kjahds.com>
1977 # -added VMS support
1978 # -added better error recognition (on no found pages, just exit. On
1979 # missing nroff/pod2man, just display raw pod.)
1980 # -added recursive/case-insensitive matching (thanks, Andreas). This
1981 # slows things down a bit, unfortunately. Give a precise name, and
1984 # Version 1.01: Tue May 30 14:47:34 EDT 1995
1985 # Andy Dougherty <doughera@lafcol.lafayette.edu>
1986 # -added pod documentation.
1987 # -added PATH searching.
1988 # -added searching pod/ subdirectory (mainly to pick up perlfunc.pod
1995 # Cache the directories read during sloppy match
1996 # (To disk, or just in-memory?)
1998 # Backport this to perl 5.005?
2000 # Implement at least part of the "perlman" interface described
2001 # in Programming Perl 3e?