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