1 use 5.006; # we use some open(X, "<", $y) syntax
8 use Fcntl; # for sysopen
9 use File::Basename qw(basename);
10 use File::Spec::Functions qw(catfile catdir splitdir);
12 use vars qw($VERSION @Pagers $Bindir $Pod2man
13 $Temp_Files_Created $Temp_File_Lifetime
17 #..........................................................................
19 BEGIN { # Make a DEBUG constant very first thing...
20 unless(defined &DEBUG) {
21 if(($ENV{'PERLDOCDEBUG'} || '') =~ m/^(\d+)/) { # untaint
22 eval("sub DEBUG () {$1}");
23 die "WHAT? Couldn't eval-up a DEBUG constant!? $@" if $@;
30 use Pod::Perldoc::GetOptsOO; # uses the DEBUG.
31 use Carp qw(croak carp);
33 # these are also in BaseTo, which I don't want to inherit
35 my( $self, @messages ) = @_;
37 carp( join "\n", @messages, '' );
41 my( $self, @messages ) = @_;
43 croak( join "\n", @messages, '' );
46 #..........................................................................
53 *is_vms = $^O eq 'VMS' ? \&TRUE : \&FALSE unless defined &is_vms;
54 *is_mswin32 = $^O eq 'MSWin32' ? \&TRUE : \&FALSE unless defined &is_mswin32;
55 *is_dos = $^O eq 'dos' ? \&TRUE : \&FALSE unless defined &is_dos;
56 *is_os2 = $^O eq 'os2' ? \&TRUE : \&FALSE unless defined &is_os2;
57 *is_cygwin = $^O eq 'cygwin' ? \&TRUE : \&FALSE unless defined &is_cygwin;
58 *is_linux = $^O eq 'linux' ? \&TRUE : \&FALSE unless defined &is_linux;
59 *is_hpux = $^O =~ m/hpux/ ? \&TRUE : \&FALSE unless defined &is_hpux;
62 $Temp_File_Lifetime ||= 60 * 60 * 24 * 5;
63 # If it's older than five days, it's quite unlikely
64 # that anyone's still looking at it!!
65 # (Currently used only by the MSWin cleanup routine)
68 #..........................................................................
69 { my $pager = $Config{'pager'};
70 push @Pagers, $pager if -x (split /\s+/, $pager)[0] or __PACKAGE__->is_vms;
72 $Bindir = $Config{'scriptdirexp'};
73 $Pod2man = "pod2man" . ( $Config{'versiononly'} ? $Config{'version'} : '' );
75 # End of class-init stuff
77 ###########################################################################
81 foreach my $subname (map "opt_$_", split '', q{mhlDriFfXqnTdULv}) {
83 *$subname = do{ use strict 'refs'; sub () { shift->_elem($subname, @_) } };
86 # And these are so that GetOptsOO knows they take options:
87 sub opt_f_with { shift->_elem('opt_f', @_) }
88 sub opt_q_with { shift->_elem('opt_q', @_) }
89 sub opt_d_with { shift->_elem('opt_d', @_) }
90 sub opt_L_with { shift->_elem('opt_L', @_) }
91 sub opt_v_with { shift->_elem('opt_v', @_) }
93 sub opt_w_with { # Specify an option for the formatter subclass
94 my($self, $value) = @_;
95 if($value =~ m/^([-_a-zA-Z][-_a-zA-Z0-9]*)(?:[=\:](.*?))?$/s) {
97 my $option_value = defined($2) ? $2 : "TRUE";
98 $option =~ tr/\-/_/s; # tolerate "foo-bar" for "foo_bar"
99 $self->add_formatter_option( $option, $option_value );
101 $self->warn( qq("$value" isn't a good formatter option name. I'm ignoring it!\n ) );
106 sub opt_M_with { # specify formatter class name(s)
107 my($self, $classes) = @_;
108 return unless defined $classes and length $classes;
109 DEBUG > 4 and print "Considering new formatter classes -M$classes\n";
111 foreach my $classname (split m/[,;]+/s, $classes) {
112 next unless $classname =~ m/\S/;
113 if( $classname =~ m/^(\w+(::\w+)+)$/s ) {
114 # A mildly restrictive concept of what modulenames are valid.
115 push @classes_to_add, $1; # untaint
117 $self->warn( qq("$classname" isn't a valid classname. Ignoring.\n) );
121 unshift @{ $self->{'formatter_classes'} }, @classes_to_add;
124 "Adding @classes_to_add to the list of formatter classes, "
125 . "making them @{ $self->{'formatter_classes'} }.\n"
131 sub opt_V { # report version and exit
133 "Perldoc v$VERSION, under perl v$] for $^O",
135 (defined(&Win32::BuildNumber) and defined &Win32::BuildNumber())
136 ? (" (win32 build ", &Win32::BuildNumber(), ")") : (),
138 (chr(65) eq 'A') ? () : " (non-ASCII)",
145 sub opt_t { # choose plaintext as output format
147 $self->opt_o_with('text') if @_ and $_[0];
148 return $self->_elem('opt_t', @_);
151 sub opt_u { # choose raw pod as output format
153 $self->opt_o_with('pod') if @_ and $_[0];
154 return $self->_elem('opt_u', @_);
158 # choose man as the output format, and specify the proggy to run
160 $self->opt_o_with('man') if @_ and $_[0];
161 $self->_elem('opt_n', @_);
164 sub opt_o_with { # "o" for output format
165 my($self, $rest) = @_;
166 return unless defined $rest and length $rest;
167 if($rest =~ m/^(\w+)$/s) {
170 $self->warn( qq("$rest" isn't a valid output format. Skipping.\n") );
174 $self->aside("Noting \"$rest\" as desired output format...\n");
176 # Figure out what class(es) that could actually mean...
179 foreach my $prefix ("Pod::Perldoc::To", "Pod::Simple::", "Pod::") {
182 $rest, # Yes, try it first with the given capitalization
183 "\L$rest", "\L\u$rest", "\U$rest" # And then try variations
186 $self->aside("Considering $prefix$stem\n");
187 push @classes, $prefix . $stem;
190 # Tidier, but misses too much:
191 #push @classes, $prefix . ucfirst(lc($rest));
193 $self->opt_M_with( join ";", @classes );
197 ###########################################################################
198 # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
200 sub run { # to be called by the "perldoc" executable
203 print "Parameters to $class\->run:\n";
206 $x[1] = '<undef>' unless defined $x[1];
207 $x[1] = "@{$x[1]}" if ref( $x[1] ) eq 'ARRAY';
208 print " [$x[0]] => [$x[1]]\n";
213 return $class -> new(@_) -> process() || 0;
216 # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
217 ###########################################################################
219 sub new { # yeah, nothing fancy
221 my $new = bless {@_}, (ref($class) || $class);
222 DEBUG > 1 and print "New $class object $new\n";
227 #..........................................................................
229 sub aside { # If we're in -D or DEBUG mode, say this.
231 if( DEBUG or $self->opt_D ) {
234 my $callsub = (caller(1))[3];
235 my $package = quotemeta(__PACKAGE__ . '::');
236 $callsub =~ s/^$package/'/os;
237 # the o is justified, as $package really won't change.
242 if(DEBUG) { print $out } else { print STDERR $out }
247 #..........................................................................
251 $self->warn( "@_\n" ) if @_;
253 # Erase evidence of previous errors (if any), so exit status is simple.
257 perldoc [options] PageName|ModuleName|ProgramName|URL...
258 perldoc [options] -f BuiltinFunction
259 perldoc [options] -q FAQRegex
260 perldoc [options] -v PerlVariable
263 -h Display this help message
265 -r Recursive search (slow)
267 -t Display pod using pod2text instead of Pod::Man and groff
268 (-t is the default on win32 unless -n is specified)
269 -u Display unformatted pod text
270 -m Display module's file in its entirety
271 -n Specify replacement for groff
272 -l Display the module's file name
273 -F Arguments are file names, not modules
274 -D Verbosely describe what's going on
275 -T Send output to STDOUT without any pager
276 -d output_filename_to_send_to
277 -o output_format_name
278 -M FormatterModuleNameToUse
279 -w formatter_option:option_value
280 -L translation_code Choose doc translation (if any)
281 -X Use index if present (looks for pod.idx at $Config{archlib})
282 -q Search the text of questions (not answers) in perlfaq[1-9]
283 -f Search Perl built-in functions
284 -v Search predefined Perl variables
286 PageName|ModuleName|ProgramName|URL...
287 is the name of a piece of documentation that you want to look at. You
288 may either give a descriptive name of the page (as in the case of
289 `perlfunc') the name of a module, either like `Term::Info' or like
290 `Term/Info', or the name of a program, like `perldoc', or a URL
291 starting with http(s).
294 is the name of a perl function. Will extract documentation from
295 `perlfunc' or `perlop'.
298 is a regex. Will search perlfaq[1-9] for and extract any
299 questions that match.
301 Any switches in the PERLDOC environment variable will be used before the
302 command line arguments. The optional pod index file contains a list of
303 filenames, one per line.
309 #..........................................................................
314 if( my $link = readlink( $0 ) ) {
315 $self->debug( "The value in $0 is a symbolic link to $link\n" );
318 my $basename = basename( $0 );
320 $self->debug( "\$0 is [$0]\nbasename is [$basename]\n" );
321 # possible name forms
326 # perlvar # an alias mentioned in Camel 3
328 my( $untainted ) = $basename =~ m/(
332 doc | func | faq | help | op | toc | var # Camel 3
334 (?: -? v? \d+ \. \d+ (?:\. \d+)? ) # possible version
335 (?: \. (?: bat | exe | com ) )? # possible extension
340 return $untainted if $untainted;
343 $self->warn(<<"HERE");
344 You called the perldoc command with a name that I didn't recognize.
345 This might mean that someone is tricking you into running a
346 program you don't intend to use, but it also might mean that you
347 created your own link to perldoc. I think your program name is
350 I'll allow this if the filename looks only has [a-zA-Z0-9._-].
354 my( $untainted ) = $basename =~ m/(
355 \A [a-zA-Z0-9._-]+ \z
358 return $untainted if $untainted;
361 $self->die(<<"HERE");
362 I think that your name for perldoc is potentially unsafe, so I'm
363 going to disallow it. I'd rather you be safe than sorry. If you
364 intended to use the name I'm disallowing, please tell the maintainers
367 Pod-Perldoc\@rt.cpan.org
372 #..........................................................................
376 my $program_name = $self->program_name;
378 $self->die( <<"EOUSAGE" );
379 Usage: $program_name [-hVriDtumFXlT] [-n nroffer_program]
380 [-d output_filename] [-o output_format] [-M FormatterModule]
381 [-w formatter_option:option_value] [-L translation_code]
382 PageName|ModuleName|ProgramName
386 $program_name -f PerlFunc
387 $program_name -q FAQKeywords
388 $program_name -v PerlVar
390 The -h option prints more help. Also try "$program_name perldoc" to get
391 acquainted with the system. [Perldoc v$VERSION]
396 #..........................................................................
398 sub pagers { @{ shift->{'pagers'} } }
400 #..........................................................................
402 sub _elem { # handy scalar meta-accessor: shift->_elem("foo", @_)
403 if(@_ > 2) { return $_[0]{ $_[1] } = $_[2] }
404 else { return $_[0]{ $_[1] } }
406 #..........................................................................
407 ###########################################################################
409 # Init formatter switches, and start it off with __bindir and all that
410 # other stuff that ToMan.pm needs.
416 # Make sure creat()s are neither too much nor too little
417 eval { umask(0077) }; # doubtless someone has no mask
419 $self->{'args'} ||= \@ARGV;
420 $self->{'found'} ||= [];
421 $self->{'temp_file_list'} ||= [];
424 $self->{'target'} = undef;
426 $self->init_formatter_class_list;
428 $self->{'pagers' } = [@Pagers] unless exists $self->{'pagers'};
429 $self->{'bindir' } = $Bindir unless exists $self->{'bindir'};
430 $self->{'pod2man'} = $Pod2man unless exists $self->{'pod2man'};
432 push @{ $self->{'formatter_switches'} = [] }, (
433 # Yeah, we could use a hashref, but maybe there's some class where options
434 # have to be ordered; so we'll use an arrayref.
436 [ '__bindir' => $self->{'bindir' } ],
437 [ '__pod2man' => $self->{'pod2man'} ],
440 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
441 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
443 $self->{'translators'} = [];
444 $self->{'extra_search_dirs'} = [];
449 #..........................................................................
451 sub init_formatter_class_list {
453 $self->{'formatter_classes'} ||= [];
455 # Remember, no switches have been read yet, when
456 # we've started this routine.
458 $self->opt_M_with('Pod::Perldoc::ToPod'); # the always-there fallthru
459 $self->opt_o_with('text');
460 $self->opt_o_with('man') unless $self->is_mswin32 || $self->is_dos
462 ($ENV{TERM} || '') !~ /dumb|emacs|none|unknown/i
468 #..........................................................................
471 # if this ever returns, its retval will be used for exit(RETVAL)
474 DEBUG > 1 and print " Beginning process.\n";
475 DEBUG > 1 and print " Args: @{$self->{'args'}}\n\n";
477 print "Object contents:\n";
480 $x[1] = '<undef>' unless defined $x[1];
481 $x[1] = "@{$x[1]}" if ref( $x[1] ) eq 'ARRAY';
482 print " [$x[0]] => [$x[1]]\n";
488 # TODO: make it deal with being invoked as various different things
491 return $self->usage_brief unless @{ $self->{'args'} };
492 $self->pagers_guessing;
493 $self->options_reading;
494 $self->aside(sprintf "$0 => %s v%s\n", ref($self), $self->VERSION);
495 $self->drop_privs_maybe;
496 $self->options_processing;
498 # Hm, we have @pages and @found, but we only really act on one
499 # file per call, with the exception of the opt_q hack, and with
505 $self->{'pages'} = \@pages;
506 if( $self->opt_f) { @pages = qw(perlfunc perlop) }
507 elsif( $self->opt_q) { @pages = ("perlfaq1" .. "perlfaq9") }
508 elsif( $self->opt_v) { @pages = ("perlvar") }
509 else { @pages = @{$self->{'args'}};
511 # if @pages == 1 and $pages[0] eq 'perldoc';
514 return $self->usage_brief unless @pages;
516 $self->find_good_formatter_class();
517 $self->formatter_sanity_check();
519 $self->maybe_diddle_INC();
520 # for when we're apparently in a module or extension directory
522 my @found = $self->grand_search_init(\@pages);
523 exit ($self->is_vms ? 98962 : 1) unless @found;
526 DEBUG and print "We're in -l mode, so byebye after this:\n";
527 print join("\n", @found), "\n";
531 $self->tweak_found_pathnames(\@found);
532 $self->assert_closing_stdout;
533 return $self->page_module_file(@found) if $self->opt_m;
534 DEBUG > 2 and print "Found: [@found]\n";
536 return $self->render_and_page(\@found);
539 #..........................................................................
542 my( %class_seen, %class_loaded );
543 sub find_good_formatter_class {
545 my @class_list = @{ $self->{'formatter_classes'} || [] };
546 $self->die( "WHAT? Nothing in the formatter class list!?" ) unless @class_list;
548 my $good_class_found;
549 foreach my $c (@class_list) {
550 DEBUG > 4 and print "Trying to load $c...\n";
551 if($class_loaded{$c}) {
552 DEBUG > 4 and print "OK, the already-loaded $c it is!\n";
553 $good_class_found = $c;
557 if($class_seen{$c}) {
559 "I've tried $c before, and it's no good. Skipping.\n";
565 if( $c->can('parse_from_file') ) {
567 "Interesting, the formatter class $c is already loaded!\n";
570 ( $self->is_os2 or $self->is_mswin32 or $self->is_dos or $self->is_os2)
571 # the always case-insensitive filesystems
572 and $class_seen{lc("~$c")}++
575 "We already used something quite like \"\L$c\E\", so no point using $c\n";
576 # This avoids redefining the package.
578 DEBUG > 4 and print "Trying to eval 'require $c'...\n";
581 if(DEBUG() or $self->opt_D) {
582 # feh, let 'em see it
585 # The average user just has no reason to be seeing
586 # $^W-suppressible warnings from the the require!
591 DEBUG > 4 and print "Couldn't load $c: $!\n";
596 if( $c->can('parse_from_file') ) {
597 DEBUG > 4 and print "Settling on $c\n";
599 $v = ( defined $v and length $v ) ? " version $v" : '';
600 $self->aside("Formatter class $c$v successfully loaded!\n");
601 $good_class_found = $c;
604 DEBUG > 4 and print "Class $c isn't a formatter?! Skipping.\n";
608 $self->die( "Can't find any loadable formatter class in @class_list?!\nAborting" )
609 unless $good_class_found;
611 $self->{'formatter_class'} = $good_class_found;
612 $self->aside("Will format with the class $good_class_found\n");
618 #..........................................................................
620 sub formatter_sanity_check {
622 my $formatter_class = $self->{'formatter_class'}
623 || $self->die( "NO FORMATTER CLASS YET!?" );
625 if(!$self->opt_T # so -T can FORCE sending to STDOUT
626 and $formatter_class->can('is_pageable')
627 and !$formatter_class->is_pageable
628 and !$formatter_class->can('page_for_perldoc')
631 ($formatter_class->can('output_extension')
632 && $formatter_class->output_extension
634 $ext = ".$ext" if length $ext;
636 my $me = $self->program_name;
638 "When using Perldoc to format with $formatter_class, you have to\n"
639 . "specify -T or -dsomefile$ext\n"
640 . "See `$me perldoc' for more information on those switches.\n" )
645 #..........................................................................
647 sub render_and_page {
648 my($self, $found_list) = @_;
650 $self->maybe_generate_dynamic_pod($found_list);
652 my($out, $formatter) = $self->render_findings($found_list);
655 printf "Perldoc (%s) output saved to %s\n",
656 $self->{'formatter_class'} || ref($self),
658 print "But notice that it's 0 bytes long!\n" unless -s $out;
661 } elsif( # Allow the formatter to "page" itself, if it wants.
662 $formatter->can('page_for_perldoc')
664 $self->aside("Going to call $formatter\->page_for_perldoc(\"$out\")\n");
665 if( $formatter->page_for_perldoc($out, $self) ) {
666 $self->aside("page_for_perldoc returned true, so NOT paging with $self.\n");
669 $self->aside("page_for_perldoc returned false, so paging with $self instead.\n");
674 # Do nothing, since the formatter has "paged" it for itself.
677 # Page it normally (internally)
679 if( -s $out ) { # Usual case:
680 $self->page($out, $self->{'output_to_stdout'}, $self->pagers);
684 $self->aside("Skipping $out (from $$found_list[0] "
685 . "via $$self{'formatter_class'}) as it is 0-length.\n");
687 push @{ $self->{'temp_file_list'} }, $out;
688 $self->unlink_if_temp_file($out);
692 $self->after_rendering(); # any extra cleanup or whatever
697 #..........................................................................
699 sub options_reading {
702 if( defined $ENV{"PERLDOC"} and length $ENV{"PERLDOC"} ) {
703 require Text::ParseWords;
704 $self->aside("Noting env PERLDOC setting of $ENV{'PERLDOC'}\n");
705 # Yes, appends to the beginning
706 unshift @{ $self->{'args'} },
707 Text::ParseWords::shellwords( $ENV{"PERLDOC"} )
709 DEBUG > 1 and print " Args now: @{$self->{'args'}}\n\n";
711 DEBUG > 1 and print " Okay, no PERLDOC setting in ENV.\n";
715 and print " Args right before switch processing: @{$self->{'args'}}\n";
717 Pod::Perldoc::GetOptsOO::getopts( $self, $self->{'args'}, 'YES' )
718 or return $self->usage;
721 and print " Args after switch processing: @{$self->{'args'}}\n";
723 return $self->usage if $self->opt_h;
728 #..........................................................................
730 sub options_processing {
734 my $podidx = "$Config{'archlib'}/pod.idx";
735 $podidx = "" unless -f $podidx && -r _ && -M _ <= 7;
736 $self->{'podidx'} = $podidx;
739 $self->{'output_to_stdout'} = 1 if $self->opt_T or ! -t STDOUT;
741 $self->options_sanity;
743 # This used to set a default, but that's now moved into any
744 # formatter that cares to have a default.
746 $self->add_formatter_option( '__nroffer' => $self->opt_n );
749 # Get language from PERLDOC_POD2 environment variable
750 if ( ! $self->opt_L && $ENV{PERLDOC_POD2} ) {
751 if ( $ENV{PERLDOC_POD2} eq '1' ) {
752 $self->_elem('opt_L',(split(/\_/, $ENV{LC_ALL} || $ENV{LC_LANG} || $ENV{LANG}))[0] );
755 $self->_elem('opt_L', $ENV{PERLDOC_POD2});
759 # Adjust for using translation packages
760 $self->add_translator(split(/\s+/,$self->opt_L)) if $self->opt_L;
765 #..........................................................................
770 # The opts-counting stuff interacts quite badly with
771 # the $ENV{"PERLDOC"} stuff. I.e., if I have $ENV{"PERLDOC"}
772 # set to -t, and I specify -u on the command line, I don't want
773 # to be hectored at that -u and -t don't make sense together.
775 #my $opts = grep $_ && 1, # yes, the count of the set ones
776 # $self->opt_t, $self->opt_u, $self->opt_m, $self->opt_l
779 #$self->usage("only one of -t, -u, -m or -l") if $opts > 1;
782 # Any sanity-checking need doing here?
784 # But does not make sense to set either -f or -q in $ENV{"PERLDOC"}
785 if( $self->opt_f or $self->opt_q ) {
786 $self->usage("Only one of -f -or -q") if $self->opt_f and $self->opt_q;
788 "Perldoc is only really meant for reading one word at a time.\n",
789 "So these parameters are being ignored: ",
790 join(' ', @{$self->{'args'}}),
792 if @{$self->{'args'}}
797 #..........................................................................
799 sub grand_search_init {
800 my($self, $pages, @found) = @_;
803 if (/^http(s)?:\/\//) {
806 my $response = HTTP::Tiny->new->get($_);
807 if ($response->{success}) {
808 my ($fh, $filename) = File::Temp::tempfile(UNLINK => 1);
809 $fh->print($response->{content});
810 push @found, $filename;
811 ($self->{podnames}{$filename} =
812 m{.*/([^/#?]+)} ? uc $1 : "UNKNOWN")
813 =~ s/\.P(?:[ML]|OD)\z//;
817 ($self->opt_m ? "module" : "documentation") . " found for \"$_\".\n";
821 if ($self->{'podidx'} && open(PODIDX, $self->{'podidx'})) {
822 my $searchfor = catfile split '::', $_;
823 $self->aside( "Searching for '$searchfor' in $self->{'podidx'}\n" );
827 push(@found, $_) if m,/$searchfor(?:\.(?:pod|pm))?\z,i;
829 close(PODIDX) or $self->die( "Can't close $$self{'podidx'}: $!" );
833 $self->aside( "Searching for $_\n" );
837 push @found, $_ if $self->opt_l or $self->opt_m or $self->containspod($_);
843 # prepend extra search directories (including language specific)
844 push @searchdirs, @{ $self->{'extra_search_dirs'} };
846 # We must look both in @INC for library modules and in $bindir
847 # for executables, like h2xs or perldoc itself.
848 push @searchdirs, ($self->{'bindir'}, @INC);
849 unless ($self->opt_m) {
852 for ($i = 0; $trn = $ENV{'DCL$PATH;'.$i}; $i++) {
853 push(@searchdirs,$trn);
855 push(@searchdirs,'perl_root:[lib.pods]') # installed pods
858 push(@searchdirs, grep(-d, split($Config{path_sep},
862 my @files = $self->searchfor(0,$_,@searchdirs);
864 $self->aside( "Found as @files\n" );
866 # add "perl" prefix, so "perldoc foo" may find perlfoo.pod
867 elsif (BE_LENIENT and !/\W/ and @files = $self->searchfor(0, "perl$_", @searchdirs)) {
868 $self->aside( "Loosely found as @files\n" );
871 # no match, try recursive search
872 @searchdirs = grep(!/^\.\z/s,@INC);
873 @files= $self->searchfor(1,$_,@searchdirs) if $self->opt_r;
875 $self->aside( "Loosely found as @files\n" );
879 ($self->opt_m ? "module" : "documentation") . " found for \"$_\".\n";
880 if ( @{ $self->{'found'} } ) {
881 print STDERR "However, try\n";
882 my $me = $self->program_name;
883 for my $dir (@{ $self->{'found'} }) {
884 opendir(DIR, $dir) or $self->die( "opendir $dir: $!" );
885 while (my $file = readdir(DIR)) {
886 next if ($file =~ /^\./s);
887 $file =~ s/\.(pm|pod)\z//; # XXX: badfs
888 print STDERR "\t$me $_\::$file\n";
890 closedir(DIR) or $self->die( "closedir $dir: $!" );
900 #..........................................................................
902 sub maybe_generate_dynamic_pod {
903 my($self, $found_things) = @_;
906 $self->search_perlfunc($found_things, \@dynamic_pod) if $self->opt_f;
908 $self->search_perlvar($found_things, \@dynamic_pod) if $self->opt_v;
910 $self->search_perlfaqs($found_things, \@dynamic_pod) if $self->opt_q;
912 if( ! $self->opt_f and ! $self->opt_q and ! $self->opt_v ) {
913 DEBUG > 4 and print "That's a non-dynamic pod search.\n";
914 } elsif ( @dynamic_pod ) {
915 $self->aside("Hm, I found some Pod from that search!\n");
916 my ($buffd, $buffer) = $self->new_tempfile('pod', 'dyn');
918 push @{ $self->{'temp_file_list'} }, $buffer;
919 # I.e., it MIGHT be deleted at the end.
921 my $in_list = !$self->not_dynamic && $self->opt_f || $self->opt_v;
923 print $buffd "=over 8\n\n" if $in_list;
924 print $buffd @dynamic_pod or $self->die( "Can't print $buffer: $!" );
925 print $buffd "=back\n" if $in_list;
927 close $buffd or $self->die( "Can't close $buffer: $!" );
929 @$found_things = $buffer;
930 # Yes, so found_things never has more than one thing in
931 # it, by time we leave here
933 $self->add_formatter_option('__filter_nroff' => 1);
937 $self->aside("I found no Pod from that search!\n");
943 #..........................................................................
946 my ($self,$value) = @_;
947 $self->{__not_dynamic} = $value if @_ == 2;
948 return $self->{__not_dynamic};
951 #..........................................................................
953 sub add_formatter_option { # $self->add_formatter_option('key' => 'value');
955 push @{ $self->{'formatter_switches'} }, [ @_ ] if @_;
957 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
958 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
963 #.........................................................................
965 sub new_translator { # $tr = $self->new_translator($lang);
969 my $pack = 'POD2::' . uc($lang);
970 eval "require $pack";
971 if ( !$@ && $pack->can('new') ) {
975 eval { require POD2::Base };
978 return POD2::Base->new({ lang => $lang });
981 #.........................................................................
983 sub add_translator { # $self->add_translator($lang);
986 my $tr = $self->new_translator($lang);
988 push @{ $self->{'translators'} }, $tr;
989 push @{ $self->{'extra_search_dirs'} }, $tr->pod_dirs;
991 $self->aside( "translator for '$lang' loaded\n" );
993 # non-installed or bad translator package
994 $self->warn( "Perldoc cannot load translator package for '$lang': ignored\n" );
1001 #..........................................................................
1003 sub search_perlvar {
1004 my($self, $found_things, $pod) = @_;
1006 my $opt = $self->opt_v;
1008 if ( $opt !~ /^ (?: [\@\%\$]\S+ | [A-Z]\w* ) $/x ) {
1009 $self->die( "'$opt' does not look like a Perl variable\n" );
1012 DEBUG > 2 and print "Search: @$found_things\n";
1014 my $perlvar = shift @$found_things;
1015 open(PVAR, "<", $perlvar) # "Funk is its own reward"
1016 or $self->die("Can't open $perlvar: $!");
1018 if ( $opt ne '$0' && $opt =~ /^\$\d+$/ ) { # handle $1, $2, ...
1019 $opt = '$<I<digits>>';
1021 my $search_re = quotemeta($opt);
1024 print "Going to perlvar-scan for $search_re in $perlvar\n";
1032 # Look for our variable
1036 while (<PVAR>) { # "The Mothership Connection is here!"
1037 last if /^=head2 Error Indicators/;
1038 # \b at the end of $` and friends borks things!
1039 if ( m/^=item\s+$search_re\s/ ) {
1043 last if $found && !$inheader && !$inlist;
1045 elsif (!/^\s+$/) { # not a blank line
1047 $inheader = 0; # don't accept more =item (unless inlist)
1051 $inheader = 1; # start over
1060 last if $found && !$inheader && !$inlist;
1064 # ++$found if /^\w/; # found descriptive text
1066 @$pod = () unless $found;
1068 $self->die( "No documentation for perl variable '$opt' found\n" );
1070 close PVAR or $self->die( "Can't open $perlvar: $!" );
1075 #..........................................................................
1078 my ($self,$found_things,$pod) = @_;
1080 $self->not_dynamic( 1 );
1082 my $perlop = shift @$found_things;
1083 open( PERLOP, '<', $perlop ) or $self->die( "Can't open $perlop: $!" );
1086 my $has_text_seen = 0;
1087 my $thing = $self->opt_f;
1090 while( my $line = <PERLOP> ){
1091 if( $paragraph and $line =~ m!^=(?:head|item)! and $paragraph =~ m!X<+\s*\Q$thing\E\s*>+! ){
1093 $paragraph =~ s!=back.*?\z!!s;
1096 if( $paragraph =~ m!^=item! ){
1097 $paragraph = "=over 8\n\n" . $paragraph . "=back\n";
1100 push @$pod, $paragraph;
1106 if( $line =~ m!^=over! ){
1109 elsif( $line =~ m!^=back! ){
1113 if( $line =~ m!^=(?:head|item)! and $has_text_seen ){
1116 elsif( $line !~ m!^=(?:head|item)! and $line !~ m!^\s*$! and $line !~ m!^\s*X<! ){
1120 $paragraph .= $line;
1128 #..........................................................................
1130 sub search_perlfunc {
1131 my($self, $found_things, $pod) = @_;
1133 DEBUG > 2 and print "Search: @$found_things\n";
1135 my $perlfunc = shift @$found_things;
1136 open(PFUNC, "<", $perlfunc) # "Funk is its own reward"
1137 or $self->die("Can't open $perlfunc: $!");
1139 # Functions like -r, -e, etc. are listed under `-X'.
1140 my $search_re = ($self->opt_f =~ /^-[rwxoRWXOeszfdlpSbctugkTBMAC]$/)
1141 ? '(?:I<)?-X' : quotemeta($self->opt_f) ;
1144 print "Going to perlfunc-scan for $search_re in $perlfunc\n";
1146 my $re = 'Alphabetical Listing of Perl Functions';
1148 # Check available translator or backup to default (english)
1149 if ( $self->opt_L && defined $self->{'translators'}->[0] ) {
1150 my $tr = $self->{'translators'}->[0];
1151 $re = $tr->search_perlfunc_re if $tr->can('search_perlfunc_re');
1157 last if /^=head2 $re/;
1160 # Look for our function
1164 my @perlops = qw(m q qq qr qx qw s tr y);
1168 while (<PFUNC>) { # "The Mothership Connection is here!"
1169 last if( grep{ $self->opt_f eq $_ }@perlops );
1170 if ( m/^=item\s+$search_re\b/ ) {
1173 elsif (@related > 1 and /^=item/) {
1174 $related_re ||= join "|", @related;
1175 if (m/^=item\s+(?:$related_re)\b/) {
1183 last if $found > 1 and not $inlist;
1185 elsif ($found and /^X<[^>]+>/) {
1186 push @related, m/X<([^>]+)>/g;
1193 last if $found > 1 and not $inlist;
1197 ++$found if /^\w/; # found descriptive text
1201 $self->search_perlop( $found_things, $pod );
1206 "No documentation for perl function `%s' found\n",
1210 close PFUNC or $self->die( "Can't open $perlfunc: $!" );
1215 #..........................................................................
1217 sub search_perlfaqs {
1218 my( $self, $found_things, $pod) = @_;
1222 my $search_key = $self->opt_q;
1224 my $rx = eval { qr/$search_key/ }
1225 or $self->die( <<EOD );
1226 Invalid regular expression '$search_key' given as -q pattern:
1228 Did you mean \\Q$search_key ?
1233 foreach my $file (@$found_things) {
1234 $self->die( "invalid file spec: $!" ) if $file =~ /[<>|]/;
1235 open(INFAQ, "<", $file) # XXX 5.6ism
1236 or $self->die( "Can't read-open $file: $!\nAborting" );
1238 if ( m/^=head2\s+.*(?:$search_key)/i ) {
1240 push @$pod, "=head1 Found in $file\n\n" unless $found_in{$file}++;
1242 elsif (/^=head[12]/) {
1250 $self->die("No documentation for perl FAQ keyword `$search_key' found\n")
1257 #..........................................................................
1259 sub render_findings {
1260 # Return the filename to open
1262 my($self, $found_things) = @_;
1264 my $formatter_class = $self->{'formatter_class'}
1265 || $self->die( "No formatter class set!?" );
1266 my $formatter = $formatter_class->can('new')
1267 ? $formatter_class->new
1271 if(! @$found_things) {
1272 $self->die( "Nothing found?!" );
1273 # should have been caught before here
1274 } elsif(@$found_things > 1) {
1276 "Perldoc is only really meant for reading one document at a time.\n",
1277 "So these parameters are being ignored: ",
1278 join(' ', @$found_things[1 .. $#$found_things] ),
1282 my $file = $found_things->[0];
1284 DEBUG > 3 and printf "Formatter switches now: [%s]\n",
1285 join ' ', map "[@$_]", @{ $self->{'formatter_switches'} };
1287 # Set formatter options:
1288 if( ref $formatter ) {
1289 foreach my $f (@{ $self->{'formatter_switches'} || [] }) {
1290 my($switch, $value, $silent_fail) = @$f;
1291 if( $formatter->can($switch) ) {
1292 eval { $formatter->$switch( defined($value) ? $value : () ) };
1293 $self->warn( "Got an error when setting $formatter_class\->$switch:\n$@\n" )
1296 if( $silent_fail or $switch =~ m/^__/s ) {
1297 DEBUG > 2 and print "Formatter $formatter_class doesn't support $switch\n";
1299 $self->warn( "$formatter_class doesn't recognize the $switch switch.\n" );
1305 $self->{'output_is_binary'} =
1306 $formatter->can('write_with_binmode') && $formatter->write_with_binmode;
1308 if( $self->{podnames} and exists $self->{podnames}{$file} and
1309 $formatter->can('name') ) {
1310 $formatter->name($self->{podnames}{$file});
1313 my ($out_fh, $out) = $self->new_output_file(
1314 ( $formatter->can('output_extension') && $formatter->output_extension )
1316 $self->useful_filename_bit,
1319 # Now, finally, do the formatting!
1322 if(DEBUG() or $self->opt_D) {
1323 # feh, let 'em see it
1326 # The average user just has no reason to be seeing
1327 # $^W-suppressible warnings from the formatting!
1330 eval { $formatter->parse_from_file( $file, $out_fh ) };
1333 $self->warn( "Error while formatting with $formatter_class:\n $@\n" ) if $@;
1334 DEBUG > 2 and print "Back from formatting with $formatter_class\n";
1337 or $self->warn( "Can't close $out: $!\n(Did $formatter already close it?)" );
1338 sleep 0; sleep 0; sleep 0;
1339 # Give the system a few timeslices to meditate on the fact
1340 # that the output file does in fact exist and is closed.
1342 $self->unlink_if_temp_file($file);
1345 if( $formatter->can( 'if_zero_length' ) ) {
1346 # Basically this is just a hook for Pod::Simple::Checker; since
1347 # what other class could /happily/ format an input file with Pod
1348 # as a 0-length output file?
1349 $formatter->if_zero_length( $file, $out, $out_fh );
1351 $self->warn( "Got a 0-length file from $$found_things[0] via $formatter_class!?\n" );
1355 DEBUG and print "Finished writing to $out.\n";
1356 return($out, $formatter) if wantarray;
1360 #..........................................................................
1362 sub unlink_if_temp_file {
1363 # Unlink the specified file IFF it's in the list of temp files.
1364 # Really only used in the case of -f / -q things when we can
1365 # throw away the dynamically generated source pod file once
1366 # we've formatted it.
1368 my($self, $file) = @_;
1369 return unless defined $file and length $file;
1371 my $temp_file_list = $self->{'temp_file_list'} || return;
1372 if(grep $_ eq $file, @$temp_file_list) {
1373 $self->aside("Unlinking $file\n");
1374 unlink($file) or $self->warn( "Odd, couldn't unlink $file: $!" );
1376 DEBUG > 1 and print "$file isn't a temp file, so not unlinking.\n";
1381 #..........................................................................
1384 sub after_rendering {
1386 $self->after_rendering_VMS if $self->is_vms;
1387 $self->after_rendering_MSWin32 if $self->is_mswin32;
1388 $self->after_rendering_Dos if $self->is_dos;
1389 $self->after_rendering_OS2 if $self->is_os2;
1393 sub after_rendering_VMS { return }
1394 sub after_rendering_Dos { return }
1395 sub after_rendering_OS2 { return }
1396 sub after_rendering_MSWin32 { return }
1398 #..........................................................................
1400 #..........................................................................
1402 sub minus_f_nocase { # i.e., do like -f, but without regard to case
1404 my($self, $dir, $file) = @_;
1405 my $path = catfile($dir,$file);
1406 return $path if -f $path and -r _;
1409 or $self->is_vms or $self->is_mswin32
1410 or $self->Is_dos or $self->is_os2
1412 # On a case-forgiving file system, or if case is important,
1413 # that is it, all we can do.
1414 $self->warn( "Ignored $path: unreadable\n" ) if -f _;
1421 foreach $p (splitdir $file){
1422 my $try = catfile @p, $p;
1423 $self->aside("Scrutinizing $try...\n");
1427 if ( $p eq $self->{'target'} ) {
1428 my $tmp_path = catfile @p;
1430 for (@{ $self->{'found'} }) {
1431 $path_f = 1 if $_ eq $tmp_path;
1433 push (@{ $self->{'found'} }, $tmp_path) unless $path_f;
1434 $self->aside( "Found as $tmp_path but directory\n" );
1437 elsif (-f _ && -r _ && lc($try) eq lc($path)) {
1441 $self->warn( "Ignored $try: unreadable or file/dir mismatch\n" );
1443 elsif (-d catdir(@p)) { # at least we see the containing directory!
1446 my $p_dirspec = catdir(@p);
1447 opendir DIR, $p_dirspec or $self->die( "opendir $p_dirspec: $!" );
1448 while(defined( $cip = readdir(DIR) )) {
1449 if (lc $cip eq $lcp){
1451 last; # XXX stop at the first? what if there's others?
1454 closedir DIR or $self->die( "closedir $p_dirspec: $!" );
1455 return "" unless $found;
1458 my $p_filespec = catfile(@p);
1459 return $p_filespec if -f $p_filespec and -r _;
1460 $self->warn( "Ignored $p_filespec: unreadable\n" ) if -f _;
1466 #..........................................................................
1468 sub pagers_guessing {
1472 push @pagers, $self->pagers;
1473 $self->{'pagers'} = \@pagers;
1475 if ($self->is_mswin32) {
1476 push @pagers, qw( more< less notepad );
1477 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1479 elsif ($self->is_vms) {
1480 push @pagers, qw( most more less type/page );
1482 elsif ($self->is_dos) {
1483 push @pagers, qw( less.exe more.com< );
1484 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1487 if ($self->is_os2) {
1488 unshift @pagers, 'less', 'cmd /c more <';
1490 push @pagers, qw( more less pg view cat );
1491 unshift @pagers, "$ENV{PAGER}<" if $ENV{PAGER};
1494 if ($self->is_cygwin) {
1495 if (($pagers[0] eq 'less') || ($pagers[0] eq '/usr/bin/less')) {
1496 unshift @pagers, '/usr/bin/less -isrR';
1497 unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
1501 unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER};
1506 #..........................................................................
1508 sub page_module_file {
1509 my($self, @found) = @_;
1512 # Don't ever just pass this off to anything like MSWin's "start.exe",
1513 # since we might be calling on a .pl file, and we wouldn't want that
1514 # to actually /execute/ the file that we just want to page thru!
1515 # Also a consideration if one were to use a web browser as a pager;
1516 # doing so could trigger the browser's MIME mapping for whatever
1517 # it thinks .pm/.pl/whatever is. Probably just a (useless and
1518 # annoying) "Save as..." dialog, but potentially executing the file
1519 # in question -- particularly in the case of MSIE and it's, ahem,
1520 # occasionally hazy distinction between OS-local extension
1521 # associations, and browser-specific MIME mappings.
1525 "Perldoc is only really meant for reading one document at a time.\n" .
1526 "So these files are being ignored: " .
1527 join(' ', @found[1 .. $#found] ) .
1531 return $self->page($found[0], $self->{'output_to_stdout'}, $self->pagers);
1535 #..........................................................................
1538 my($self, $dir, $file) = @_;
1540 unless( ref $self ) {
1541 # Should never get called:
1544 Carp::croak( join '',
1545 "Crazy ", __PACKAGE__, " error:\n",
1546 "check_file must be an object_method!\n",
1551 if(length $dir and not -d $dir) {
1552 DEBUG > 3 and print " No dir $dir -- skipping.\n";
1556 my $path = $self->minus_f_nocase($dir,$file);
1557 if( length $path and ($self->opt_m ? $self->isprintable($path)
1558 : $self->containspod($path)) ) {
1560 " The file $path indeed looks promising!\n";
1563 DEBUG > 3 and print " No good: $file in $dir\n";
1569 my($self, $file, $readit) = @_;
1571 my $maxunprintfrac= 0.2; # tolerate some unprintables for UTF-8 comments etc.
1573 return 1 if !$readit && $file =~ /\.(?:pl|pm|pod|cmd|com|bat)\z/i;
1577 open(TEST,"<", $file) or $self->die( "Can't open $file: $!" );
1578 read TEST, $data, $size;
1580 $size= length($data);
1581 $data =~ tr/\x09-\x0D\x20-\x7E//d;
1582 return length($data) <= $size*$maxunprintfrac;
1585 #..........................................................................
1588 my($self, $file, $readit) = @_;
1589 return 1 if !$readit && $file =~ /\.pod\z/i;
1592 # Under cygwin the /usr/bin/perl is legal executable, but
1593 # you cannot open a file with that name. It must be spelled
1594 # out as "/usr/bin/perl.exe".
1596 # The following if-case under cygwin prevents error
1599 # Cannot open /usr/bin/perl: no such file or directory
1601 # This would work though
1603 # $ perldoc perl.pod
1605 if ( $self->is_cygwin and -x $file and -f "$file.exe" )
1607 $self->warn( "Cygwin $file.exe search skipped\n" ) if DEBUG or $self->opt_D;
1612 open(TEST,"<", $file) or $self->die( "Can't open $file: $!" ); # XXX 5.6ism
1615 close(TEST) or $self->die( "Can't close $file: $!" );
1619 close(TEST) or $self->die( "Can't close $file: $!" );
1623 #..........................................................................
1625 sub maybe_diddle_INC {
1628 # Does this look like a module or extension directory?
1630 if (-f "Makefile.PL" || -f "Build.PL") {
1632 # Add "." and "lib" to @INC (if they exist)
1633 eval q{ use lib qw(. lib); 1; } or $self->die;
1635 # don't add if superuser
1636 if ($< && $> && -d "blib") { # don't be looking too hard now!
1637 eval q{ use blib; 1 };
1638 $self->warn( $@ ) if $@ && $self->opt_D;
1645 #..........................................................................
1647 sub new_output_file {
1649 my $outspec = $self->opt_d; # Yes, -d overrides all else!
1650 # So don't call this twice per format-job!
1652 return $self->new_tempfile(@_) unless defined $outspec and length $outspec;
1654 # Otherwise open a write-handle on opt_d!f
1657 # If we are running before perl5.6.0, we can't autovivify
1660 $fh = Symbol::gensym();
1662 DEBUG > 3 and print "About to try writing to specified output file $outspec\n";
1663 $self->die( "Can't write-open $outspec: $!" )
1664 unless open($fh, ">", $outspec); # XXX 5.6ism
1666 DEBUG > 3 and print "Successfully opened $outspec\n";
1667 binmode($fh) if $self->{'output_is_binary'};
1668 return($fh, $outspec);
1671 #..........................................................................
1673 sub useful_filename_bit {
1674 # This tries to provide a meaningful bit of text to do with the query,
1675 # such as can be used in naming the file -- since if we're going to be
1676 # opening windows on temp files (as a "pager" may well do!) then it's
1677 # better if the temp file's name (which may well be used as the window
1678 # title) isn't ALL just random garbage!
1679 # In other words "perldoc_LWPSimple_2371981429" is a better temp file
1680 # name than "perldoc_2371981429". So this routine is what tries to
1681 # provide the "LWPSimple" bit.
1684 my $pages = $self->{'pages'} || return undef;
1685 return undef unless @$pages;
1687 my $chunk = $pages->[0];
1688 return undef unless defined $chunk;
1690 $chunk =~ s/\.\w+$//g; # strip any extension
1691 if( $chunk =~ m/([^\#\\:\/\$]+)$/s ) { # get basename, if it's a file
1696 $chunk =~ s/[^a-zA-Z0-9]+//g; # leave ONLY a-zA-Z0-9 things!
1697 $chunk = substr($chunk, -10) if length($chunk) > 10;
1701 #..........................................................................
1703 sub new_tempfile { # $self->new_tempfile( [$suffix, [$infix] ] )
1706 ++$Temp_Files_Created;
1709 return File::Temp::tempfile(UNLINK => 1);
1712 #..........................................................................
1714 sub page { # apply a pager to the output file
1715 my ($self, $output, $output_to_stdout, @pagers) = @_;
1716 if ($output_to_stdout) {
1717 $self->aside("Sending unpaged output to STDOUT.\n");
1718 open(TMP, "<", $output) or $self->die( "Can't open $output: $!" ); # XXX 5.6ism
1721 print or $self->die( "Can't print to stdout: $!" );
1723 close TMP or $self->die( "Can't close while $output: $!" );
1724 $self->unlink_if_temp_file($output);
1726 # On VMS, quoting prevents logical expansion, and temp files with no
1727 # extension get the wrong default extension (such as .LIS for TYPE)
1729 $output = VMS::Filespec::rmsexpand($output, '.') if $self->is_vms;
1731 $output =~ s{/}{\\}g if $self->is_mswin32 || $self->is_dos;
1732 # Altho "/" under MSWin is in theory good as a pathsep,
1733 # many many corners of the OS don't like it. So we
1734 # have to force it to be "\" to make everyone happy.
1736 foreach my $pager (@pagers) {
1737 $self->aside("About to try calling $pager $output\n");
1738 if ($self->is_vms) {
1739 last if system("$pager $output") == 0;
1741 last if system("$pager \"$output\"") == 0;
1748 #..........................................................................
1751 my($self, $recurse,$s,@dirs) = @_;
1753 $s = VMS::Filespec::unixify($s) if $self->is_vms;
1754 return $s if -f $s && $self->containspod($s);
1755 $self->aside( "Looking for $s in @dirs\n" );
1759 $self->{'target'} = (splitdir $s)[-1]; # XXX: why not use File::Basename?
1760 for ($i=0; $i<@dirs; $i++) {
1762 next unless -d $dir;
1763 ($dir = VMS::Filespec::unixpath($dir)) =~ s!/\z!! if $self->is_vms;
1764 if ( (! $self->opt_m && ( $ret = $self->check_file($dir,"$s.pod")))
1765 or ( $ret = $self->check_file($dir,"$s.pm"))
1766 or ( $ret = $self->check_file($dir,$s))
1767 or ( $self->is_vms and
1768 $ret = $self->check_file($dir,"$s.com"))
1769 or ( $self->is_os2 and
1770 $ret = $self->check_file($dir,"$s.cmd"))
1771 or ( ($self->is_mswin32 or $self->is_dos or $self->is_os2) and
1772 $ret = $self->check_file($dir,"$s.bat"))
1773 or ( $ret = $self->check_file("$dir/pod","$s.pod"))
1774 or ( $ret = $self->check_file("$dir/pod",$s))
1775 or ( $ret = $self->check_file("$dir/pods","$s.pod"))
1776 or ( $ret = $self->check_file("$dir/pods",$s))
1778 DEBUG > 1 and print " Found $ret\n";
1783 opendir(D,$dir) or $self->die( "Can't opendir $dir: $!" );
1784 my @newdirs = map catfile($dir, $_), grep {
1786 not /^auto\z/s and # save time! don't search auto dirs
1787 -d catfile($dir, $_)
1789 closedir(D) or $self->die( "Can't closedir $dir: $!" );
1790 next unless @newdirs;
1791 # what a wicked map!
1792 @newdirs = map((s/\.dir\z//,$_)[1],@newdirs) if $self->is_vms;
1793 $self->aside( "Also looking in @newdirs\n" );
1794 push(@dirs,@newdirs);
1800 #..........................................................................
1802 my $already_asserted;
1803 sub assert_closing_stdout {
1806 return if $already_asserted;
1808 eval q~ END { close(STDOUT) || CORE::die "Can't close STDOUT: $!" } ~;
1809 # What for? to let the pager know that nothing more will come?
1811 $self->die( $@ ) if $@;
1812 $already_asserted = 1;
1817 #..........................................................................
1819 sub tweak_found_pathnames {
1820 my($self, $found) = @_;
1821 if ($self->is_mswin32) {
1822 foreach (@$found) { s,/,\\,g }
1824 foreach (@$found) { s,',\\',g } # RT 37347
1828 #..........................................................................
1830 #..........................................................................
1832 sub am_taint_checking {
1834 $self->die( "NO ENVIRONMENT?!?!" ) unless keys %ENV; # reset iterator along the way
1835 my($k,$v) = each %ENV;
1836 return is_tainted($v);
1839 #..........................................................................
1841 sub is_tainted { # just a function
1843 my $nada = substr($arg, 0, 0); # zero-length!
1844 local $@; # preserve the caller's version of $@
1845 eval { eval "# $nada" };
1846 return length($@) != 0;
1849 #..........................................................................
1851 sub drop_privs_maybe {
1854 # Attempt to drop privs if we should be tainting and aren't
1855 if (!( $self->is_vms || $self->is_mswin32 || $self->is_dos
1858 && ($> == 0 || $< == 0)
1859 && !$self->am_taint_checking()
1861 my $id = eval { getpwnam("nobody") };
1862 $id = eval { getpwnam("nouser") } unless defined $id;
1863 $id = -2 unless defined $id;
1865 # According to Stevens' APUE and various
1866 # (BSD, Solaris, HP-UX) man pages, setting
1867 # the real uid first and effective uid second
1868 # is the way to go if one wants to drop privileges,
1869 # because if one changes into an effective uid of
1870 # non-zero, one cannot change the real uid any more.
1872 # Actually, it gets even messier. There is
1873 # a third uid, called the saved uid, and as
1874 # long as that is zero, one can get back to
1875 # uid of zero. Setting the real-effective *twice*
1876 # helps in *most* systems (FreeBSD and Solaris)
1877 # but apparently in HP-UX even this doesn't help:
1878 # the saved uid stays zero (apparently the only way
1879 # in HP-UX to change saved uid is to call setuid()
1880 # when the effective uid is zero).
1883 $< = $id; # real uid
1884 $> = $id; # effective uid
1885 $< = $id; # real uid
1886 $> = $id; # effective uid
1888 if( !$@ && $< && $> ) {
1889 DEBUG and print "OK, I dropped privileges.\n";
1890 } elsif( $self->opt_U ) {
1891 DEBUG and print "Couldn't drop privileges, but in -U mode, so feh."
1893 DEBUG and print "Hm, couldn't drop privileges. Ah well.\n";
1894 # We used to die here; but that seemed pointless.
1900 #..........................................................................
1908 Pod::Perldoc - Look up Perl documentation in Pod format.
1912 use Pod::Perldoc ();
1914 Pod::Perldoc->run();
1918 The guts of L<perldoc> utility.
1924 =head1 COPYRIGHT AND DISCLAIMERS
1926 Copyright (c) 2002-2007 Sean M. Burke.
1928 This library is free software; you can redistribute it and/or modify it
1929 under the same terms as Perl itself.
1931 This program is distributed in the hope that it will be useful, but
1932 without any warranty; without even the implied warranty of
1933 merchantability or fitness for a particular purpose.
1937 Current maintainer: Mark Allen C<< <mallen@cpan.org> >>
1939 Past contributions from:
1940 brian d foy C<< <bdfoy@cpan.org> >>
1941 Adriano R. Ferreira C<< <ferreira@cpan.org> >>,
1942 Sean M. Burke C<< <sburke@cpan.org> >>