Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | #!/import/bw/tools/local/perl-5.8.0/bin/perl |
2 | eval 'exec /import/bw/tools/local/perl-5.8.0/bin/perl -S $0 ${1+"$@"}' | |
3 | if 0; | |
4 | ||
5 | use warnings; | |
6 | use strict; | |
7 | ||
8 | # make sure creat()s are neither too much nor too little | |
9 | INIT { eval { umask(0077) } } # doubtless someone has no mask | |
10 | ||
11 | (my $pager = <<'/../') =~ s/\s*\z//; | |
12 | /usr/bin/less | |
13 | /../ | |
14 | my @pagers = (); | |
15 | push @pagers, $pager if -x $pager; | |
16 | ||
17 | (my $bindir = <<'/../') =~ s/\s*\z//; | |
18 | /import/bw/tools/local/perl-5.8.0/bin | |
19 | /../ | |
20 | ||
21 | (my $pod2man = <<'/../') =~ s/\s*\z//; | |
22 | pod2man | |
23 | /../ | |
24 | ||
25 | ||
26 | use Fcntl; # for sysopen | |
27 | use Getopt::Std; | |
28 | use Config '%Config'; | |
29 | use File::Spec::Functions qw(catfile splitdir); | |
30 | ||
31 | # | |
32 | # Perldoc revision #1 -- look up a piece of documentation in .pod format that | |
33 | # is embedded in the perl installation tree. | |
34 | # | |
35 | # This is not to be confused with Tom Christiansen's perlman, which is a | |
36 | # man replacement, written in perl. This perldoc is strictly for reading | |
37 | # the perl manuals, though it too is written in perl. | |
38 | # | |
39 | # Massive security and correctness patches applied to this | |
40 | # noisome program by Tom Christiansen Sat Mar 11 15:22:33 MST 2000 | |
41 | ||
42 | if (@ARGV<1) { | |
43 | my $me = $0; # Editing $0 is unportable | |
44 | $me =~ s,.*/,,; | |
45 | die <<EOF; | |
46 | Usage: $me [-h] [-r] [-i] [-v] [-t] [-u] [-m] [-n program] [-l] [-F] [-X] PageName|ModuleName|ProgramName | |
47 | $me -f PerlFunc | |
48 | $me -q FAQKeywords | |
49 | ||
50 | The -h option prints more help. Also try "perldoc perldoc" to get | |
51 | acquainted with the system. | |
52 | EOF | |
53 | } | |
54 | ||
55 | my @global_found = (); | |
56 | my $global_target = ""; | |
57 | ||
58 | my $Is_VMS = $^O eq 'VMS'; | |
59 | my $Is_MSWin32 = $^O eq 'MSWin32'; | |
60 | my $Is_Dos = $^O eq 'dos'; | |
61 | my $Is_OS2 = $^O eq 'os2'; | |
62 | ||
63 | sub usage{ | |
64 | warn "@_\n" if @_; | |
65 | # Erase evidence of previous errors (if any), so exit status is simple. | |
66 | $! = 0; | |
67 | die <<EOF; | |
68 | perldoc [options] PageName|ModuleName|ProgramName... | |
69 | perldoc [options] -f BuiltinFunction | |
70 | perldoc [options] -q FAQRegex | |
71 | ||
72 | Options: | |
73 | -h Display this help message | |
74 | -r Recursive search (slow) | |
75 | -i Ignore case | |
76 | -t Display pod using pod2text instead of pod2man and nroff | |
77 | (-t is the default on win32) | |
78 | -u Display unformatted pod text | |
79 | -m Display module's file in its entirety | |
80 | -n Specify replacement for nroff | |
81 | -l Display the module's file name | |
82 | -F Arguments are file names, not modules | |
83 | -v Verbosely describe what's going on | |
84 | -X use index if present (looks for pod.idx at $Config{archlib}) | |
85 | -q Search the text of questions (not answers) in perlfaq[1-9] | |
86 | -U Run in insecure mode (superuser only) | |
87 | ||
88 | PageName|ModuleName... | |
89 | is the name of a piece of documentation that you want to look at. You | |
90 | may either give a descriptive name of the page (as in the case of | |
91 | `perlfunc') the name of a module, either like `Term::Info' or like | |
92 | `Term/Info', or the name of a program, like `perldoc'. | |
93 | ||
94 | BuiltinFunction | |
95 | is the name of a perl function. Will extract documentation from | |
96 | `perlfunc'. | |
97 | ||
98 | FAQRegex | |
99 | is a regex. Will search perlfaq[1-9] for and extract any | |
100 | questions that match. | |
101 | ||
102 | Any switches in the PERLDOC environment variable will be used before the | |
103 | command line arguments. The optional pod index file contains a list of | |
104 | filenames, one per line. | |
105 | ||
106 | EOF | |
107 | } | |
108 | ||
109 | if (defined $ENV{"PERLDOC"}) { | |
110 | require Text::ParseWords; | |
111 | unshift(@ARGV, Text::ParseWords::shellwords($ENV{"PERLDOC"})); | |
112 | } | |
113 | ||
114 | use vars qw( $opt_m $opt_h $opt_t $opt_l $opt_u $opt_v $opt_r $opt_i $opt_F $opt_f $opt_X $opt_q $opt_n $opt_U ); | |
115 | ||
116 | getopts("mhtluvriFf:Xq:n:U") || usage; | |
117 | ||
118 | usage if $opt_h; | |
119 | ||
120 | # refuse to run if we should be tainting and aren't | |
121 | # (but regular users deserve protection too, though!) | |
122 | if (!($Is_VMS || $Is_MSWin32 || $Is_Dos || $Is_OS2) && ($> == 0 || $< == 0) | |
123 | && !am_taint_checking()) | |
124 | {{ | |
125 | if ($opt_U) { | |
126 | my $id = eval { getpwnam("nobody") }; | |
127 | $id = eval { getpwnam("nouser") } unless defined $id; | |
128 | $id = -2 unless defined $id; | |
129 | # | |
130 | # According to Stevens' APUE and various | |
131 | # (BSD, Solaris, HP-UX) man pages setting | |
132 | # the real uid first and effective uid second | |
133 | # is the way to go if one wants to drop privileges, | |
134 | # because if one changes into an effective uid of | |
135 | # non-zero, one cannot change the real uid any more. | |
136 | # | |
137 | # Actually, it gets even messier. There is | |
138 | # a third uid, called the saved uid, and as | |
139 | # long as that is zero, one can get back to | |
140 | # uid of zero. Setting the real-effective *twice* | |
141 | # helps in *most* systems (FreeBSD and Solaris) | |
142 | # but apparently in HP-UX even this doesn't help: | |
143 | # the saved uid stays zero (apparently the only way | |
144 | # in HP-UX to change saved uid is to call setuid() | |
145 | # when the effective uid is zero). | |
146 | # | |
147 | eval { | |
148 | $< = $id; # real uid | |
149 | $> = $id; # effective uid | |
150 | $< = $id; # real uid | |
151 | $> = $id; # effective uid | |
152 | }; | |
153 | last if !$@ && $< && $>; | |
154 | } | |
155 | die "Superuser must not run $0 without security audit and taint checks.\n"; | |
156 | }} | |
157 | ||
158 | $opt_n = "nroff" if !$opt_n; | |
159 | ||
160 | my $podidx; | |
161 | if ($opt_X) { | |
162 | $podidx = "$Config{'archlib'}/pod.idx"; | |
163 | $podidx = "" unless -f $podidx && -r _ && -M _ <= 7; | |
164 | } | |
165 | ||
166 | if ((my $opts = do{ no warnings; $opt_t + $opt_u + $opt_m + $opt_l }) > 1) { | |
167 | usage("only one of -t, -u, -m or -l") | |
168 | } | |
169 | elsif ($Is_MSWin32 | |
170 | || $Is_Dos | |
171 | || !($ENV{TERM} && $ENV{TERM} !~ /dumb|emacs|none|unknown/i)) | |
172 | { | |
173 | $opt_t = 1 unless $opts; | |
174 | } | |
175 | ||
176 | if ($opt_t) { require Pod::Text; import Pod::Text; } | |
177 | ||
178 | my @pages; | |
179 | if ($opt_f) { | |
180 | @pages = ("perlfunc"); | |
181 | } | |
182 | elsif ($opt_q) { | |
183 | @pages = ("perlfaq1" .. "perlfaq9"); | |
184 | } | |
185 | else { | |
186 | @pages = @ARGV; | |
187 | } | |
188 | ||
189 | # Does this look like a module or extension directory? | |
190 | if (-f "Makefile.PL") { | |
191 | ||
192 | # Add ., lib to @INC (if they exist) | |
193 | eval q{ use lib qw(. lib); 1; } or die; | |
194 | ||
195 | # don't add if superuser | |
196 | if ($< && $> && -f "blib") { # don't be looking too hard now! | |
197 | eval q{ use blib; 1 }; | |
198 | warn $@ if $@ && $opt_v; | |
199 | } | |
200 | } | |
201 | ||
202 | sub containspod { | |
203 | my($file, $readit) = @_; | |
204 | return 1 if !$readit && $file =~ /\.pod\z/i; | |
205 | local($_); | |
206 | open(TEST,"<", $file) or die "Can't open $file: $!"; | |
207 | while (<TEST>) { | |
208 | if (/^=head/) { | |
209 | close(TEST) or die "Can't close $file: $!"; | |
210 | return 1; | |
211 | } | |
212 | } | |
213 | close(TEST) or die "Can't close $file: $!"; | |
214 | return 0; | |
215 | } | |
216 | ||
217 | sub minus_f_nocase { | |
218 | my($dir,$file) = @_; | |
219 | my $path = catfile($dir,$file); | |
220 | return $path if -f $path and -r _; | |
221 | if (!$opt_i or $Is_VMS or $Is_MSWin32 or $Is_Dos or $^O eq 'os2') { | |
222 | # on a case-forgiving file system or if case is important | |
223 | # that is it all we can do | |
224 | warn "Ignored $path: unreadable\n" if -f _; | |
225 | return ''; | |
226 | } | |
227 | local *DIR; | |
228 | # this is completely wicked. don't mess with $", and if | |
229 | # you do, don't assume / is the dirsep! | |
230 | local($")="/"; | |
231 | my @p = ($dir); | |
232 | my($p,$cip); | |
233 | foreach $p (splitdir $file){ | |
234 | my $try = catfile @p, $p; | |
235 | stat $try; | |
236 | if (-d _) { | |
237 | push @p, $p; | |
238 | if ( $p eq $global_target) { | |
239 | my $tmp_path = catfile @p; | |
240 | my $path_f = 0; | |
241 | for (@global_found) { | |
242 | $path_f = 1 if $_ eq $tmp_path; | |
243 | } | |
244 | push (@global_found, $tmp_path) unless $path_f; | |
245 | print STDERR "Found as @p but directory\n" if $opt_v; | |
246 | } | |
247 | } | |
248 | elsif (-f _ && -r _) { | |
249 | return $try; | |
250 | } | |
251 | elsif (-f _) { | |
252 | warn "Ignored $try: unreadable\n"; | |
253 | } | |
254 | elsif (-d "@p") { | |
255 | my $found=0; | |
256 | my $lcp = lc $p; | |
257 | opendir DIR, "@p" or die "opendir @p: $!"; | |
258 | while ($cip=readdir(DIR)) { | |
259 | if (lc $cip eq $lcp){ | |
260 | $found++; | |
261 | last; | |
262 | } | |
263 | } | |
264 | closedir DIR or die "closedir @p: $!"; | |
265 | return "" unless $found; | |
266 | push @p, $cip; | |
267 | return "@p" if -f "@p" and -r _; | |
268 | warn "Ignored @p: unreadable\n" if -f _; | |
269 | } | |
270 | } | |
271 | return ""; | |
272 | } | |
273 | ||
274 | ||
275 | sub check_file { | |
276 | my($dir,$file) = @_; | |
277 | return "" if length $dir and not -d $dir; | |
278 | if ($opt_m) { | |
279 | return minus_f_nocase($dir,$file); | |
280 | } | |
281 | else { | |
282 | my $path = minus_f_nocase($dir,$file); | |
283 | return $path if length $path and containspod($path); | |
284 | } | |
285 | return ""; | |
286 | } | |
287 | ||
288 | ||
289 | sub searchfor { | |
290 | my($recurse,$s,@dirs) = @_; | |
291 | $s =~ s!::!/!g; | |
292 | $s = VMS::Filespec::unixify($s) if $Is_VMS; | |
293 | return $s if -f $s && containspod($s); | |
294 | printf STDERR "Looking for $s in @dirs\n" if $opt_v; | |
295 | my $ret; | |
296 | my $i; | |
297 | my $dir; | |
298 | $global_target = (splitdir $s)[-1]; # XXX: why not use File::Basename? | |
299 | for ($i=0; $i<@dirs; $i++) { | |
300 | $dir = $dirs[$i]; | |
301 | ($dir = VMS::Filespec::unixpath($dir)) =~ s!/\z!! if $Is_VMS; | |
302 | if ( (! $opt_m && ( $ret = check_file $dir,"$s.pod")) | |
303 | or ( $ret = check_file $dir,"$s.pm") | |
304 | or ( $ret = check_file $dir,$s) | |
305 | or ( $Is_VMS and | |
306 | $ret = check_file $dir,"$s.com") | |
307 | or ( $^O eq 'os2' and | |
308 | $ret = check_file $dir,"$s.cmd") | |
309 | or ( ($Is_MSWin32 or $Is_Dos or $^O eq 'os2') and | |
310 | $ret = check_file $dir,"$s.bat") | |
311 | or ( $ret = check_file "$dir/pod","$s.pod") | |
312 | or ( $ret = check_file "$dir/pod",$s) | |
313 | or ( $ret = check_file "$dir/pods","$s.pod") | |
314 | or ( $ret = check_file "$dir/pods",$s) | |
315 | ) { | |
316 | return $ret; | |
317 | } | |
318 | ||
319 | if ($recurse) { | |
320 | opendir(D,$dir) or die "Can't opendir $dir: $!"; | |
321 | my @newdirs = map catfile($dir, $_), grep { | |
322 | not /^\.\.?\z/s and | |
323 | not /^auto\z/s and # save time! don't search auto dirs | |
324 | -d catfile($dir, $_) | |
325 | } readdir D; | |
326 | closedir(D) or die "Can't closedir $dir: $!"; | |
327 | next unless @newdirs; | |
328 | # what a wicked map! | |
329 | @newdirs = map((s/\.dir\z//,$_)[1],@newdirs) if $Is_VMS; | |
330 | print STDERR "Also looking in @newdirs\n" if $opt_v; | |
331 | push(@dirs,@newdirs); | |
332 | } | |
333 | } | |
334 | return (); | |
335 | } | |
336 | ||
337 | sub filter_nroff { | |
338 | my @data = split /\n{2,}/, shift; | |
339 | shift @data while @data and $data[0] !~ /\S/; # Go to header | |
340 | shift @data if @data and $data[0] =~ /Contributed\s+Perl/; # Skip header | |
341 | pop @data if @data and $data[-1] =~ /^\w/; # Skip footer, like | |
342 | # 28/Jan/99 perl 5.005, patch 53 1 | |
343 | join "\n\n", @data; | |
344 | } | |
345 | ||
346 | sub page { | |
347 | my ($tmp, $no_tty, @pagers) = @_; | |
348 | if ($no_tty) { | |
349 | open(TMP,"<", $tmp) or die "Can't open $tmp: $!"; | |
350 | local $_; | |
351 | while (<TMP>) { | |
352 | print or die "Can't print to stdout: $!"; | |
353 | } | |
354 | close TMP or die "Can't close while $tmp: $!"; | |
355 | } | |
356 | else { | |
357 | # On VMS, quoting prevents logical expansion, and temp files with no | |
358 | # extension get the wrong default extension (such as .LIS for TYPE) | |
359 | ||
360 | $tmp = VMS::Filespec::rmsexpand($tmp, '.') if ($Is_VMS); | |
361 | foreach my $pager (@pagers) { | |
362 | if ($Is_VMS) { | |
363 | last if system("$pager $tmp") == 0; | |
364 | } else { | |
365 | last if system("$pager \"$tmp\"") == 0; | |
366 | } | |
367 | } | |
368 | } | |
369 | } | |
370 | ||
371 | my @found; | |
372 | foreach (@pages) { | |
373 | if ($podidx && open(PODIDX, $podidx)) { | |
374 | my $searchfor = catfile split '::'; | |
375 | print STDERR "Searching for '$searchfor' in $podidx\n" if $opt_v; | |
376 | local $_; | |
377 | while (<PODIDX>) { | |
378 | chomp; | |
379 | push(@found, $_) if m,/$searchfor(?:\.(?:pod|pm))?\z,i; | |
380 | } | |
381 | close(PODIDX) or die "Can't close $podidx: $!"; | |
382 | next; | |
383 | } | |
384 | print STDERR "Searching for $_\n" if $opt_v; | |
385 | if ($opt_F) { | |
386 | next unless -r; | |
387 | push @found, $_ if $opt_m or containspod($_); | |
388 | next; | |
389 | } | |
390 | # We must look both in @INC for library modules and in $bindir | |
391 | # for executables, like h2xs or perldoc itself. | |
392 | my @searchdirs = ($bindir, @INC); | |
393 | unless ($opt_m) { | |
394 | if ($Is_VMS) { | |
395 | my($i,$trn); | |
396 | for ($i = 0; $trn = $ENV{'DCL$PATH;'.$i}; $i++) { | |
397 | push(@searchdirs,$trn); | |
398 | } | |
399 | push(@searchdirs,'perl_root:[lib.pod]') # installed pods | |
400 | } | |
401 | else { | |
402 | push(@searchdirs, grep(-d, split($Config{path_sep}, | |
403 | $ENV{'PATH'}))); | |
404 | } | |
405 | } | |
406 | my @files = searchfor(0,$_,@searchdirs); | |
407 | if (@files) { | |
408 | print STDERR "Found as @files\n" if $opt_v; | |
409 | } | |
410 | else { | |
411 | # no match, try recursive search | |
412 | @searchdirs = grep(!/^\.\z/s,@INC); | |
413 | @files= searchfor(1,$_,@searchdirs) if $opt_r; | |
414 | if (@files) { | |
415 | print STDERR "Loosely found as @files\n" if $opt_v; | |
416 | } | |
417 | else { | |
418 | print STDERR "No " . | |
419 | ($opt_m ? "module" : "documentation") . " found for \"$_\".\n"; | |
420 | if (@global_found) { | |
421 | print STDERR "However, try\n"; | |
422 | for my $dir (@global_found) { | |
423 | opendir(DIR, $dir) or die "opendir $dir: $!"; | |
424 | while (my $file = readdir(DIR)) { | |
425 | next if ($file =~ /^\./s); | |
426 | $file =~ s/\.(pm|pod)\z//; # XXX: badfs | |
427 | print STDERR "\tperldoc $_\::$file\n"; | |
428 | } | |
429 | closedir DIR or die "closedir $dir: $!"; | |
430 | } | |
431 | } | |
432 | } | |
433 | } | |
434 | push(@found,@files); | |
435 | } | |
436 | ||
437 | if (!@found) { | |
438 | exit ($Is_VMS ? 98962 : 1); | |
439 | } | |
440 | ||
441 | if ($opt_l) { | |
442 | print join("\n", @found), "\n"; | |
443 | exit; | |
444 | } | |
445 | ||
446 | my $lines = $ENV{LINES} || 24; | |
447 | ||
448 | my $no_tty; | |
449 | if (! -t STDOUT) { $no_tty = 1 } | |
450 | END { close(STDOUT) || die "Can't close STDOUT: $!" } | |
451 | ||
452 | if ($Is_MSWin32) { | |
453 | push @pagers, qw( more< less notepad ); | |
454 | unshift @pagers, $ENV{PAGER} if $ENV{PAGER}; | |
455 | for (@found) { s,/,\\,g } | |
456 | } | |
457 | elsif ($Is_VMS) { | |
458 | push @pagers, qw( most more less type/page ); | |
459 | } | |
460 | elsif ($Is_Dos) { | |
461 | push @pagers, qw( less.exe more.com< ); | |
462 | unshift @pagers, $ENV{PAGER} if $ENV{PAGER}; | |
463 | } | |
464 | else { | |
465 | if ($^O eq 'os2') { | |
466 | unshift @pagers, 'less', 'cmd /c more <'; | |
467 | } | |
468 | push @pagers, qw( more less pg view cat ); | |
469 | unshift @pagers, $ENV{PAGER} if $ENV{PAGER}; | |
470 | } | |
471 | unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER}; | |
472 | ||
473 | if ($opt_m) { | |
474 | foreach my $pager (@pagers) { | |
475 | if (system($pager, @found) == 0) { | |
476 | exit; | |
477 | } | |
478 | } | |
479 | if ($Is_VMS) { | |
480 | eval q{ | |
481 | use vmsish qw(status exit); | |
482 | exit $?; | |
483 | 1; | |
484 | } or die; | |
485 | } | |
486 | exit(1); | |
487 | } | |
488 | ||
489 | my @pod; | |
490 | if ($opt_f) { | |
491 | my $perlfunc = shift @found; | |
492 | open(PFUNC, "<", $perlfunc) | |
493 | or die("Can't open $perlfunc: $!"); | |
494 | ||
495 | # Functions like -r, -e, etc. are listed under `-X'. | |
496 | my $search_string = ($opt_f =~ /^-[rwxoRWXOeszfdlpSbctugkTBMAC]$/) | |
497 | ? 'I<-X' : $opt_f ; | |
498 | ||
499 | # Skip introduction | |
500 | local $_; | |
501 | while (<PFUNC>) { | |
502 | last if /^=head2 Alphabetical Listing of Perl Functions/; | |
503 | } | |
504 | ||
505 | # Look for our function | |
506 | my $found = 0; | |
507 | my $inlist = 0; | |
508 | while (<PFUNC>) { | |
509 | if (/^=item\s+\Q$search_string\E\b/o) { | |
510 | $found = 1; | |
511 | } | |
512 | elsif (/^=item/) { | |
513 | last if $found > 1 and not $inlist; | |
514 | } | |
515 | next unless $found; | |
516 | if (/^=over/) { | |
517 | ++$inlist; | |
518 | } | |
519 | elsif (/^=back/) { | |
520 | --$inlist; | |
521 | } | |
522 | push @pod, $_; | |
523 | ++$found if /^\w/; # found descriptive text | |
524 | } | |
525 | if (!@pod) { | |
526 | die "No documentation for perl function `$opt_f' found\n"; | |
527 | } | |
528 | close PFUNC or die "Can't open $perlfunc: $!"; | |
529 | } | |
530 | ||
531 | if ($opt_q) { | |
532 | local @ARGV = @found; # I'm lazy, sue me. | |
533 | my $found = 0; | |
534 | my %found_in; | |
535 | my $rx = eval { qr/$opt_q/ } or die <<EOD; | |
536 | Invalid regular expression '$opt_q' given as -q pattern: | |
537 | $@ | |
538 | Did you mean \\Q$opt_q ? | |
539 | ||
540 | EOD | |
541 | ||
542 | for (@found) { die "invalid file spec: $!" if /[<>|]/ } | |
543 | local $_; | |
544 | while (<>) { | |
545 | if (/^=head2\s+.*(?:$opt_q)/oi) { | |
546 | $found = 1; | |
547 | push @pod, "=head1 Found in $ARGV\n\n" unless $found_in{$ARGV}++; | |
548 | } | |
549 | elsif (/^=head[12]/) { | |
550 | $found = 0; | |
551 | } | |
552 | next unless $found; | |
553 | push @pod, $_; | |
554 | } | |
555 | if (!@pod) { | |
556 | die("No documentation for perl FAQ keyword `$opt_q' found\n"); | |
557 | } | |
558 | } | |
559 | ||
560 | require File::Temp; | |
561 | ||
562 | my ($tmpfd, $tmp) = File::Temp::tempfile(UNLINK => 1); | |
563 | ||
564 | my $filter; | |
565 | ||
566 | if (@pod) { | |
567 | my ($buffd, $buffer) = File::Temp::tempfile(UNLINK => 1); | |
568 | print $buffd "=over 8\n\n"; | |
569 | print $buffd @pod or die "Can't print $buffer: $!"; | |
570 | print $buffd "=back\n"; | |
571 | close $buffd or die "Can't close $buffer: $!"; | |
572 | @found = $buffer; | |
573 | $filter = 1; | |
574 | } | |
575 | ||
576 | foreach (@found) { | |
577 | my $file = $_; | |
578 | my $err; | |
579 | ||
580 | if ($opt_t) { | |
581 | Pod::Text->new()->parse_from_file($file, $tmpfd); | |
582 | } | |
583 | elsif (not $opt_u) { | |
584 | my $cmd = catfile($bindir, $pod2man) . " --lax $file | $opt_n -man"; | |
585 | $cmd .= " | col -x" if $^O =~ /hpux/; | |
586 | my $rslt = `$cmd`; | |
587 | $rslt = filter_nroff($rslt) if $filter; | |
588 | unless (($err = $?)) { | |
589 | print $tmpfd $rslt | |
590 | or die "Can't print $tmp: $!"; | |
591 | } | |
592 | } | |
593 | if ($opt_u or $err) { | |
594 | open(IN,"<", $file) or die("Can't open $file: $!"); | |
595 | my $cut = 1; | |
596 | local $_; | |
597 | while (<IN>) { | |
598 | $cut = $1 eq 'cut' if /^=(\w+)/; | |
599 | next if $cut; | |
600 | print $tmpfd $_ | |
601 | or die "Can't print $tmp: $!"; | |
602 | } | |
603 | close IN or die "Can't close $file: $!"; | |
604 | } | |
605 | } | |
606 | close $tmpfd | |
607 | or die "Can't close $tmp: $!"; | |
608 | page($tmp, $no_tty, @pagers); | |
609 | ||
610 | exit; | |
611 | ||
612 | sub is_tainted { | |
613 | my $arg = shift; | |
614 | my $nada = substr($arg, 0, 0); # zero-length | |
615 | local $@; # preserve caller's version | |
616 | eval { eval "# $nada" }; | |
617 | return length($@) != 0; | |
618 | } | |
619 | ||
620 | sub am_taint_checking { | |
621 | my($k,$v) = each %ENV; | |
622 | return is_tainted($v); | |
623 | } | |
624 | ||
625 | ||
626 | __END__ | |
627 | ||
628 | =head1 NAME | |
629 | ||
630 | perldoc - Look up Perl documentation in pod format. | |
631 | ||
632 | =head1 SYNOPSIS | |
633 | ||
634 | B<perldoc> [B<-h>] [B<-v>] [B<-t>] [B<-u>] [B<-m>] [B<-l>] [B<-F>] [B<-X>] PageName|ModuleName|ProgramName | |
635 | ||
636 | B<perldoc> B<-f> BuiltinFunction | |
637 | ||
638 | B<perldoc> B<-q> FAQ Keyword | |
639 | ||
640 | =head1 DESCRIPTION | |
641 | ||
642 | I<perldoc> looks up a piece of documentation in .pod format that is embedded | |
643 | in the perl installation tree or in a perl script, and displays it via | |
644 | C<pod2man | nroff -man | $PAGER>. (In addition, if running under HP-UX, | |
645 | C<col -x> will be used.) This is primarily used for the documentation for | |
646 | the perl library modules. | |
647 | ||
648 | Your system may also have man pages installed for those modules, in | |
649 | which case you can probably just use the man(1) command. | |
650 | ||
651 | If you are looking for a table of contents to the Perl library modules | |
652 | documentation, see the L<perltoc> page. | |
653 | ||
654 | =head1 OPTIONS | |
655 | ||
656 | =over 5 | |
657 | ||
658 | =item B<-h> help | |
659 | ||
660 | Prints out a brief help message. | |
661 | ||
662 | =item B<-v> verbose | |
663 | ||
664 | Describes search for the item in detail. | |
665 | ||
666 | =item B<-t> text output | |
667 | ||
668 | Display docs using plain text converter, instead of nroff. This may be faster, | |
669 | but it won't look as nice. | |
670 | ||
671 | =item B<-u> unformatted | |
672 | ||
673 | Find docs only; skip reformatting by pod2* | |
674 | ||
675 | =item B<-m> module | |
676 | ||
677 | Display the entire module: both code and unformatted pod documentation. | |
678 | This may be useful if the docs don't explain a function in the detail | |
679 | you need, and you'd like to inspect the code directly; perldoc will find | |
680 | the file for you and simply hand it off for display. | |
681 | ||
682 | =item B<-l> file name only | |
683 | ||
684 | Display the file name of the module found. | |
685 | ||
686 | =item B<-F> file names | |
687 | ||
688 | Consider arguments as file names, no search in directories will be performed. | |
689 | ||
690 | =item B<-f> perlfunc | |
691 | ||
692 | The B<-f> option followed by the name of a perl built in function will | |
693 | extract the documentation of this function from L<perlfunc>. | |
694 | ||
695 | =item B<-q> perlfaq | |
696 | ||
697 | The B<-q> option takes a regular expression as an argument. It will search | |
698 | the question headings in perlfaq[1-9] and print the entries matching | |
699 | the regular expression. | |
700 | ||
701 | =item B<-X> use an index if present | |
702 | ||
703 | The B<-X> option looks for an entry whose basename matches the name given on the | |
704 | command line in the file C<$Config{archlib}/pod.idx>. The pod.idx file should | |
705 | contain fully qualified filenames, one per line. | |
706 | ||
707 | =item B<-U> run insecurely | |
708 | ||
709 | Because B<perldoc> does not run properly tainted, and is known to | |
710 | have security issues, it will not normally execute as the superuser. | |
711 | If you use the B<-U> flag, it will do so, but only after setting | |
712 | the effective and real IDs to nobody's or nouser's account, or -2 | |
713 | if unavailable. If it cannot relinquish its privileges, it will not | |
714 | run. | |
715 | ||
716 | =item B<PageName|ModuleName|ProgramName> | |
717 | ||
718 | The item you want to look up. Nested modules (such as C<File::Basename>) | |
719 | are specified either as C<File::Basename> or C<File/Basename>. You may also | |
720 | give a descriptive name of a page, such as C<perlfunc>. | |
721 | ||
722 | =back | |
723 | ||
724 | =head1 ENVIRONMENT | |
725 | ||
726 | Any switches in the C<PERLDOC> environment variable will be used before the | |
727 | command line arguments. C<perldoc> also searches directories | |
728 | specified by the C<PERL5LIB> (or C<PERLLIB> if C<PERL5LIB> is not | |
729 | defined) and C<PATH> environment variables. | |
730 | (The latter is so that embedded pods for executables, such as | |
731 | C<perldoc> itself, are available.) C<perldoc> will use, in order of | |
732 | preference, the pager defined in C<PERLDOC_PAGER>, C<MANPAGER>, or | |
733 | C<PAGER> before trying to find a pager on its own. (C<MANPAGER> is not | |
734 | used if C<perldoc> was told to display plain text or unformatted pod.) | |
735 | ||
736 | One useful value for C<PERLDOC_PAGER> is C<less -+C -E>. | |
737 | ||
738 | =head1 VERSION | |
739 | ||
740 | This is perldoc v2.03. | |
741 | ||
742 | =head1 AUTHOR | |
743 | ||
744 | Kenneth Albanowski <kjahds@kjahds.com> | |
745 | ||
746 | Minor updates by Andy Dougherty <doughera@lafcol.lafayette.edu>, | |
747 | and others. | |
748 | ||
749 | =cut | |
750 | ||
751 | # | |
752 | # Version 2.03: Sun Apr 23 16:56:34 BST 2000 | |
753 | # Hugo van der Sanden <hv@crypt0.demon.co.uk> | |
754 | # don't die when 'use blib' fails | |
755 | # Version 2.02: Mon Mar 13 18:03:04 MST 2000 | |
756 | # Tom Christiansen <tchrist@perl.com> | |
757 | # Added -U insecurity option | |
758 | # Version 2.01: Sat Mar 11 15:22:33 MST 2000 | |
759 | # Tom Christiansen <tchrist@perl.com>, querulously. | |
760 | # Security and correctness patches. | |
761 | # What a twisted bit of distasteful spaghetti code. | |
762 | # Version 2.0: ???? | |
763 | # Version 1.15: Tue Aug 24 01:50:20 EST 1999 | |
764 | # Charles Wilson <cwilson@ece.gatech.edu> | |
765 | # changed /pod/ directory to /pods/ for cygwin | |
766 | # to support cygwin/win32 | |
767 | # Version 1.14: Wed Jul 15 01:50:20 EST 1998 | |
768 | # Robin Barker <rmb1@cise.npl.co.uk> | |
769 | # -strict, -w cleanups | |
770 | # Version 1.13: Fri Feb 27 16:20:50 EST 1997 | |
771 | # Gurusamy Sarathy <gsar@activestate.com> | |
772 | # -doc tweaks for -F and -X options | |
773 | # Version 1.12: Sat Apr 12 22:41:09 EST 1997 | |
774 | # Gurusamy Sarathy <gsar@activestate.com> | |
775 | # -various fixes for win32 | |
776 | # Version 1.11: Tue Dec 26 09:54:33 EST 1995 | |
777 | # Kenneth Albanowski <kjahds@kjahds.com> | |
778 | # -added Charles Bailey's further VMS patches, and -u switch | |
779 | # -added -t switch, with pod2text support | |
780 | # | |
781 | # Version 1.10: Thu Nov 9 07:23:47 EST 1995 | |
782 | # Kenneth Albanowski <kjahds@kjahds.com> | |
783 | # -added VMS support | |
784 | # -added better error recognition (on no found pages, just exit. On | |
785 | # missing nroff/pod2man, just display raw pod.) | |
786 | # -added recursive/case-insensitive matching (thanks, Andreas). This | |
787 | # slows things down a bit, unfortunately. Give a precise name, and | |
788 | # it'll run faster. | |
789 | # | |
790 | # Version 1.01: Tue May 30 14:47:34 EDT 1995 | |
791 | # Andy Dougherty <doughera@lafcol.lafayette.edu> | |
792 | # -added pod documentation. | |
793 | # -added PATH searching. | |
794 | # -added searching pod/ subdirectory (mainly to pick up perlfunc.pod | |
795 | # and friends. | |
796 | # | |
797 | # | |
798 | # TODO: | |
799 | # | |
800 | # Cache directories read during sloppy match |