4 use File::Basename qw(&basename &dirname);
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
12 # to ensure Configure will look for $Config{startperl}.
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.
18 $file = basename($0, '.PL');
19 $file .= '.com' if $^O eq 'VMS';
21 open OUT,">$file" or die "Can't create $file: $!";
23 print "Extracting $file (with variable substitutions)\n";
25 # In this section, perl variables will be expanded during extraction.
26 # You can use $Config{...} to use Configure variables.
28 print OUT <<"!GROK!THIS!";
30 eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
31 if \$running_under_some_shell;
32 (my \$perlpath = <<'/../') =~ s/\\s*\\z//;
37 # In the following, perl variables are not expanded during extraction.
39 print OUT <<'!NO!SUBS!';
41 use vars qw/$statdone/;
42 use File::Spec::Functions 'curdir';
43 my $startperl = "#! $perlpath -w";
46 # Modified September 26, 1993 to provide proper handling of years after 1999
47 # Tom Link <tml+@pitt.edu>
48 # University of Pittsburgh
50 # Modified April 7, 1998 with nasty hacks to implement the troublesome -follow
51 # Billy Constantine <wdconsta@cs.adelaide.edu.au> <billy@smug.adelaide.edu.au>
52 # University of Adelaide, Adelaide, South Australia
54 # Modified 1999-06-10, 1999-07-07 to migrate to cleaner perl5 usage
55 # Ken Pizzini <ken@halcyon.com>
57 # Modified 2000-01-28 to use the 'follow' option of File::Find
61 sub fileglob_to_re ($);
65 while ($ARGV[0] =~ /^[^-!(]/) {
68 @roots = (curdir()) unless @roots;
69 for (@roots) { $_ = quote($_) }
70 my $roots = join(', ', @roots);
80 my $declaresubs = "sub wanted;\n";
82 my ($follow_in_effect,$Skip_And) = (0,0);
86 s/^-// || /^[()!]/ || die "Unrecognized switch: $_\n";
94 } elsif ($_ eq 'follow') {
101 } elsif ($_ eq 'name') {
102 $out .= tab . '/' . fileglob_to_re(shift) . "/s";
103 } elsif ($_ eq 'perm') {
105 $onum =~ /^-?[0-7]+$/
106 || die "Malformed -perm argument: $onum\n";
108 if ($onum =~ s/^-//) {
109 $onum = sprintf("0%o", oct($onum) & 07777);
110 $out .= "((\$mode & $onum) == $onum)";
113 $out .= "((\$mode & 0777) == $onum)";
115 } elsif ($_ eq 'type') {
116 (my $filetest = shift) =~ tr/s/S/;
117 $out .= tab . "-$filetest _";
118 } elsif ($_ eq 'print') {
119 $out .= tab . 'print("$name\n")';
120 } elsif ($_ eq 'print0') {
121 $out .= tab . 'print("$name\0")';
122 } elsif ($_ eq 'fstype') {
125 if ($type eq 'nfs') {
126 $out .= '($dev < 0)';
128 $out .= '($dev >= 0)'; #XXX
130 } elsif ($_ eq 'user') {
132 $out .= tab . "(\$uid == \$uid{'$uname'})";
134 } elsif ($_ eq 'group') {
136 $out .= tab . "(\$gid == \$gid{'$gname'})";
138 } elsif ($_ eq 'nouser') {
139 $out .= tab . '!exists $uid{$uid}';
141 } elsif ($_ eq 'nogroup') {
142 $out .= tab . '!exists $gid{$gid}';
144 } elsif ($_ eq 'links') {
145 $out .= tab . n('$nlink', shift);
146 } elsif ($_ eq 'inum') {
147 $out .= tab . n('$ino', shift);
148 } elsif ($_ eq 'size') {
150 my $n = 'int(((-s _) + 511) / 512)';
154 $n = 'int(((-s _) + 1023) / 1024)';
156 $out .= tab . n($n, $_);
157 } elsif ($_ eq 'atime') {
158 $out .= tab . n('int(-A _)', shift);
159 } elsif ($_ eq 'mtime') {
160 $out .= tab . n('int(-M _)', shift);
161 } elsif ($_ eq 'ctime') {
162 $out .= tab . n('int(-C _)', shift);
163 } elsif ($_ eq 'exec') {
165 while (@ARGV && $ARGV[0] ne ';')
166 { push(@cmd, shift) }
169 if ($cmd[0] =~m#^(?:(?:/usr)?/bin/)?rm$#
170 && $cmd[$#cmd] eq '{}'
171 && (@cmd == 2 || (@cmd == 3 && $cmd[1] eq '-f'))) {
173 $out .= '(unlink($_) || warn "$name: $!\n")';
175 $out .= 'unlink($_)';
177 $out .= '(unlink($_) || 1)';
182 { local $" = "','"; $out .= "doexec(0, '@cmd')"; }
183 $declaresubs .= "sub doexec (\$\@);\n";
186 } elsif ($_ eq 'ok') {
188 while (@ARGV && $ARGV[0] ne ';')
189 { push(@cmd, shift) }
194 { local $" = "','"; $out .= "doexec(1, '@cmd')"; }
195 $declaresubs .= "sub doexec (\$\@);\n";
197 } elsif ($_ eq 'prune') {
198 $out .= tab . '($File::Find::prune = 1)';
199 } elsif ($_ eq 'xdev') {
200 $out .= tab . '!($File::Find::prune |= ($dev != $File::Find::topdev))'
202 } elsif ($_ eq 'newer') {
204 my $newername = 'AGE_OF' . $file;
205 $newername =~ s/\W/_/g;
206 $newername = '$' . $newername;
207 $out .= tab . "(-M _ < $newername)";
208 $initnewer .= "my $newername = -M " . quote($file) . ";\n";
209 } elsif ($_ eq 'eval') {
212 $out .= tab . "eval {$prog}";
213 } elsif ($_ eq 'depth') {
216 } elsif ($_ eq 'ls') {
218 $declaresubs .= "sub ls ();\n";
220 } elsif ($_ eq 'tar') {
221 die "-tar must have a filename argument\n" unless @ARGV;
223 my $fh = 'FH' . $file;
225 $out .= tab . "tar(*$fh, \$name)";
226 $flushall .= "tflushall;\n";
227 $declaresubs .= "sub tar;\nsub tflushall ();\n";
228 $initfile .= "open($fh, " . quote('> ' . $file) .
229 qq{) || die "Can't open $fh: \$!\\n";\n};
231 } elsif (/^(n?)cpio\z/) {
232 die "-$_ must have a filename argument\n" unless @ARGV;
234 my $fh = 'FH' . $file;
236 $out .= tab . "cpio(*$fh, \$name, '$1')";
238 $flushall .= "cflushall;\n";
239 $declaresubs .= "sub cpio;\nsub cflushall ();\n";
240 $initfile .= "open($fh, " . quote('> ' . $file) .
241 qq{) || die "Can't open $fh: \$!\\n";\n};
244 die "Unrecognized switch: -$_\n";
248 if ($ARGV[0] eq '-o') {
249 { local($statdone) = 1; $out .= "\n" . tab . "||\n"; }
250 $statdone = 0 if $indent_depth == 1 && exists $init{delayedstat};
254 $out .= " &&" unless $Skip_And || $ARGV[0] eq ')';
256 shift if $ARGV[0] eq '-a';
264 eval 'exec $perlpath -S \$0 \${1+"\$@"}'
265 if 0; #\$running_under_some_shell
270 # Set the variable \$File::Find::dont_use_nlink if you're using AFS,
273 # for the convenience of &wanted calls, including -eval statements:
274 use vars qw/*name *dir *prune/;
275 *name = *File::Find::name;
276 *dir = *File::Find::dir;
277 *prune = *File::Find::prune;
283 if (exists $init{ls}) {
285 my @rwx = qw(--- --x -w- -wx r-- r-x rw- rwx);
286 my @moname = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
291 if (exists $init{user} || exists $init{ls} || exists $init{tar}) {
292 print "my (%uid, %user);\n";
293 print "while (my (\$name, \$pw, \$uid) = getpwent) {\n";
294 print ' $uid{$name} = $uid{$uid} = $uid;', "\n"
295 if exists $init{user};
296 print ' $user{$uid} = $name unless exists $user{$uid};', "\n"
297 if exists $init{ls} || exists $init{tar};
301 if (exists $init{group} || exists $init{ls} || exists $init{tar}) {
302 print "my (%gid, %group);\n";
303 print "while (my (\$name, \$pw, \$gid) = getgrent) {\n";
304 print ' $gid{$name} = $gid{$gid} = $gid;', "\n"
305 if exists $init{group};
306 print ' $group{$gid} = $name unless exists $group{$gid};', "\n"
307 if exists $init{ls} || exists $init{tar};
311 print $initnewer, "\n" if $initnewer ne '';
312 print $initfile, "\n" if $initfile ne '';
313 $flushall .= "exit;\n";
314 if (exists $init{declarestat}) {
315 $out = <<'END' . $out;
316 my ($dev,$ino,$mode,$nlink,$uid,$gid);
321 if ( $follow_in_effect ) {
322 $out =~ s/lstat\(\$_\)/lstat(_)/;
325 # Traverse desired filesystems
326 File::Find::$find( {wanted => \\&wanted, follow => 1}, $roots);
337 # Traverse desired filesystems
338 File::Find::$find({wanted => \\&wanted}, $roots);
348 if (exists $init{doexec}) {
352 my $cwd = Cwd::cwd();
356 my @command = @_; # copy so we don't try to s/// aliases to constants
357 for my $word (@command)
358 { $word =~ s#{}#$name#g }
360 my $old = select(STDOUT);
364 return 0 unless <STDIN> =~ /^y/;
368 chdir $File::Find::dir;
375 if (exists $init{ls}) {
376 print <<'INTRO', <<"SUB", <<'END';
380 sprintf("%3d, %3d", ($rdev >> 8) & 0xff, $rdev & 0xff);
384 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
386 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
391 or $blocks = int(($size + 1023) / 1024);
393 my $perms = $rwx[$mode & 7];
395 $perms = $rwx[$mode & 7] . $perms;
397 $perms = $rwx[$mode & 7] . $perms;
398 substr($perms, 2, 1) =~ tr/-x/Ss/ if -u _;
399 substr($perms, 5, 1) =~ tr/-x/Ss/ if -g _;
400 substr($perms, 8, 1) =~ tr/-x/Tt/ if -k _;
401 if (-f _) { $perms = '-' . $perms; }
402 elsif (-d _) { $perms = 'd' . $perms; }
403 elsif (-l _) { $perms = 'l' . $perms; $pname .= ' -> ' . readlink($_); }
404 elsif (-c _) { $perms = 'c' . $perms; $size = sizemm($rdev); }
405 elsif (-b _) { $perms = 'b' . $perms; $size = sizemm($rdev); }
406 elsif (-p _) { $perms = 'p' . $perms; }
407 elsif (-S _) { $perms = 's' . $perms; }
408 else { $perms = '?' . $perms; }
410 my $user = $user{$uid} || $uid;
411 my $group = $group{$gid} || $gid;
413 my ($sec,$min,$hour,$mday,$mon,$timeyear) = localtime($mtime);
414 if (-M _ > 365.25 / 2) {
417 $timeyear = sprintf("%02d:%02d", $hour, $min);
420 printf "%5lu %4ld %-10s %3d %-8s %-8s %8s %s %2d %5s %s\n",
439 if (exists $init{cpio} || exists $init{tar}) {
445 my ($fh, $varref, $blksz) = @_;
447 while (length($$varref) >= $blksz) {
449 syswrite($fh, $$varref, $blksz);
450 substr($$varref, 0, $blksz) = '';
459 if (exists $init{cpio}) {
460 print <<'INTRO', <<"SUB", <<'END';
466 my ($fh, $fname, $nc) = @_;
468 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
469 $atime,$mtime,$ctime,$blksize,$blocks);
472 if ( ! defined $fname ) {
473 $fname = 'TRAILER!!!';
474 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
475 $atime,$mtime,$ctime,$blksize,$blocks) = (0) x 13;
477 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
479 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
482 open(IN, "./$_\0") || do {
483 warn "Couldn't open $fname: $!\n";
487 $text = readlink($_);
488 $size = 0 unless defined $text;
496 sprintf("%06o%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo%s\0",
510 $cpout{$fh} .= "\0" if length($cpout{$fh}) & 1;
511 $cpout{$fh} .= pack("SSSSSSSSLSLa*",
512 070707, $dev, $ino, $mode, $uid, $gid, $nlink, $rdev, $mtime,
513 length($fname)+1, $size,
514 $fname . (length($fname) & 1 ? "\0" : "\0\0"));
518 $cpout{$fh} .= $text;
521 flush($fh, \$cpout{$fh}, 5120)
522 while ($l = length($cpout{$fh})) >= 5120;
523 while (sysread(IN, $cpout{$fh}, 5120 - $l, $l)) {
524 flush($fh, \$cpout{$fh}, 5120);
525 $l = length($cpout{$fh});
532 for my $fh (keys %cpout) {
533 cpio($fh, undef, $nc{$fh});
534 $cpout{$fh} .= "0" x (5120 - length($cpout{$fh}));
535 flush($fh, \$cpout{$fh}, 5120);
536 print $blocks{$fh} * 10, " blocks\n";
543 if (exists $init{tar}) {
544 print <<'INTRO', <<"SUB", <<'END';
550 my ($fh, $fname) = @_;
554 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
556 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
561 if ($linkname = $linkseen{$fh, $dev, $ino}) {
562 if (length($linkname) > 100) {
563 warn "$0: omitting file with linkname ",
564 "too long for tar output: $linkname\n";
570 $linkseen{$fh, $dev, $ino} = $fname;
573 if ($typeflag eq '0') {
575 open(IN, "./$_\0") || do {
576 warn "Couldn't open $fname: $!\n";
580 $linkname = readlink($_);
581 if (defined $linkname) { $typeflag = '2' }
582 elsif (-c _) { $typeflag = '3' }
583 elsif (-b _) { $typeflag = '4' }
584 elsif (-d _) { $typeflag = '5' }
585 elsif (-p _) { $typeflag = '6' }
589 if (length($fname) > 100) {
590 ($prefix, $fname) = ($fname =~ m#\A(.*?)/(.{,100})\Z(?!\n)#);
591 if (!defined($fname) || length($prefix) > 155) {
592 warn "$0: omitting file with name too long for tar output: ",
598 $size = 0 if $typeflag ne '0';
599 my $header = pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155",
601 sprintf("%7o ", $mode & 0777),
602 sprintf("%7o ", $uid & 0777777),
603 sprintf("%7o ", $gid & 0777777),
604 sprintf("%11o ", $size),
605 sprintf("%11o ", $mtime),
608 defined $linkname ? $linkname : '',
617 substr($header, 148, 8) = sprintf("%7o ", unpack("%16C*", $header));
618 my $l = length($header) % 512;
619 $tarout{$fh} .= $header;
620 $tarout{$fh} .= "\0" x (512 - $l) if $l;
623 flush($fh, \$tarout{$fh}, 10240)
624 while ($l = length($tarout{$fh})) >= 10240;
625 while (sysread(IN, $tarout{$fh}, 10240 - $l, $l)) {
626 my $slop = length($tarout{$fh}) % 512;
627 $tarout{$fh} .= "\0" x (512 - $slop) if $slop;
628 flush($fh, \$tarout{$fh}, 10240);
629 $l = length($tarout{$fh});
637 for my $fh (keys %tarout) {
638 $len = 10240 - length($tarout{$fh});
639 $len += 10240 if $len < 1024;
640 $tarout{$fh} .= "\0" x $len;
641 flush($fh, \$tarout{$fh}, 10240);
650 ############################################################################
655 $tabstring = "\t" x ($indent_depth/2) . ' ' x ($indent_depth%2 * 4);
657 if ($_ =~ /^(?:name|print|prune|exec|ok|\(|\))/) {
658 $init{delayedstat} = 1;
660 my $statcall = '(($dev,$ino,$mode,$nlink,$uid,$gid) = '
662 if (exists $init{saw_or}) {
663 $tabstring .= "(\$nlink || $statcall) &&\n" . $tabstring;
665 $tabstring .= "$statcall &&\n" . $tabstring;
668 $init{declarestat} = 1;
671 $tabstring =~ s/^\s+/ / if $out =~ /!$/;
675 sub fileglob_to_re ($) {
677 $x =~ s#([./^\$()+])#\\$1#g;
678 $x =~ s#([?*])#.$1#g;
684 $n =~ s/^-/< / || $n =~ s/^\+/> / || $n =~ s/^/== /;
685 $n =~ s/ 0*(\d)/ $1/;
691 $string =~ s/\\/\\\\/g;
692 $string =~ s/'/\\'/g;
700 find2perl - translate find command lines to Perl code
704 find2perl [paths] [predicates] | perl
708 find2perl is a little translator to convert find command lines to
709 equivalent Perl code. The resulting code is typically faster than
712 "paths" are a set of paths where find2perl will start its searches and
713 "predicates" are taken from the following list.
719 Negate the sense of the following predicate. The C<!> must be passed as
720 a distinct argument, so it may need to be surrounded by whitespace and/or
721 quoted from interpretation by the shell using a backslash (just as with
724 =item C<( PREDICATES )>
726 Group the given PREDICATES. The parentheses must be passed as distinct
727 arguments, so they may need to be surrounded by whitespace and/or
728 quoted from interpretation by the shell using a backslash (just as with
731 =item C<PREDICATE1 PREDICATE2>
733 True if _both_ PREDICATE1 and PREDICATE2 are true; PREDICATE2 is not
734 evaluated if PREDICATE1 is false.
736 =item C<PREDICATE1 -o PREDICATE2>
738 True if either one of PREDICATE1 or PREDICATE2 is true; PREDICATE2 is
739 not evaluated if PREDICATE1 is true.
743 Follow (dereference) symlinks. The checking of file attributes depends
744 on the position of the C<-follow> option. If it precedes the file
745 check option, an C<stat> is done which means the file check applies to the
746 file the symbolic link is pointing to. If C<-follow> option follows the
747 file check option, this now applies to the symbolic link itself, i.e.
752 Change directory traversal algorithm from breadth-first to depth-first.
756 Do not descend into the directory currently matched.
760 Do not traverse mount points (prunes search at mount-point directories).
764 File name matches specified GLOB wildcard pattern. GLOB may need to be
765 quoted to avoid interpretation by the shell (just as with using
770 Low-order 9 bits of permission match octal value PERM.
774 The bits specified in PERM are all set in file's permissions.
778 The file's type matches perl's C<-X> operator.
780 =item C<-fstype TYPE>
782 Filesystem of current path is of type TYPE (only NFS/non-NFS distinction
787 True if USER is owner of file.
789 =item C<-group GROUP>
791 True if file's group is GROUP.
795 True if file's owner is not in password database.
799 True if file's group is not in group database.
803 True file's inode number is INUM.
807 True if (hard) link count of file matches N (see below).
811 True if file's size matches N (see below) N is normally counted in
812 512-byte blocks, but a suffix of "c" specifies that size should be
813 counted in characters (bytes) and a suffix of "k" specifes that
814 size should be counted in 1024-byte blocks.
818 True if last-access time of file matches N (measured in days) (see
823 True if last-changed time of file's inode matches N (measured in days,
828 True if last-modified time of file matches N (measured in days, see below).
832 True if last-modified time of file matches N.
836 Print out path of file (always true).
840 Like -print, but terminates with \0 instead of \n.
842 =item C<-exec OPTIONS ;>
844 exec() the arguments in OPTIONS in a subprocess; any occurrence of {} in
845 OPTIONS will first be substituted with the path of the current
846 file. Note that the command "rm" has been special-cased to use perl's
847 unlink() function instead (as an optimization). The C<;> must be passed as
848 a distinct argument, so it may need to be surrounded by whitespace and/or
849 quoted from interpretation by the shell using a backslash (just as with
852 =item C<-ok OPTIONS ;>
854 Like -exec, but first prompts user; if user's response does not begin
855 with a y, skip the exec. The C<;> must be passed as
856 a distinct argument, so it may need to be surrounded by whitespace and/or
857 quoted from interpretation by the shell using a backslash (just as with
862 Has the perl script eval() the EXPR.
866 Simulates C<-exec ls -dils {} ;>
870 Adds current output to tar-format FILE.
874 Adds current output to old-style cpio-format FILE.
878 Adds current output to "new"-style cpio-format FILE.
882 Predicates which take a numeric argument N can come in three forms:
884 * N is prefixed with a +: match values greater than N
885 * N is prefixed with a -: match values less than N
886 * N is not prefixed with either + or -: match only values equal to N
895 close OUT or die "Can't close $file: $!";
896 chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
897 exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';