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);
87 s/^-// || /^[()!]/ || die "Unrecognized switch: $_\n";
95 } elsif ($_ eq 'follow') {
102 } elsif (/^(i)?name$/) {
103 $out .= tab . '/' . fileglob_to_re(shift) . "/s$1";
104 } elsif (/^(i)?path$/) {
105 $out .= tab . '$File::Find::name =~ /' . fileglob_to_re(shift) . "/s$1";
106 } elsif ($_ eq 'perm') {
108 $onum =~ /^-?[0-7]+$/
109 || die "Malformed -perm argument: $onum\n";
111 if ($onum =~ s/^-//) {
112 $onum = sprintf("0%o", oct($onum) & 07777);
113 $out .= "((\$mode & $onum) == $onum)";
116 $out .= "((\$mode & 0777) == $onum)";
118 } elsif ($_ eq 'type') {
119 (my $filetest = shift) =~ tr/s/S/;
120 $out .= tab . "-$filetest _";
121 } elsif ($_ eq 'print') {
122 $out .= tab . 'print("$name\n")';
124 } elsif ($_ eq 'print0') {
125 $out .= tab . 'print("$name\0")';
127 } elsif ($_ eq 'fstype') {
130 if ($type eq 'nfs') {
131 $out .= '($dev < 0)';
133 $out .= '($dev >= 0)'; #XXX
135 } elsif ($_ eq 'user') {
137 $out .= tab . "(\$uid == \$uid{'$uname'})";
139 } elsif ($_ eq 'group') {
141 $out .= tab . "(\$gid == \$gid{'$gname'})";
143 } elsif ($_ eq 'nouser') {
144 $out .= tab . '!exists $uid{$uid}';
146 } elsif ($_ eq 'nogroup') {
147 $out .= tab . '!exists $gid{$gid}';
149 } elsif ($_ eq 'links') {
150 $out .= tab . n('$nlink', shift);
151 } elsif ($_ eq 'inum') {
152 $out .= tab . n('$ino', shift);
153 } elsif ($_ eq 'size') {
155 my $n = 'int(((-s _) + 511) / 512)';
159 $n = 'int(((-s _) + 1023) / 1024)';
161 $out .= tab . n($n, $_);
162 } elsif ($_ eq 'atime') {
163 $out .= tab . n('int(-A _)', shift);
164 } elsif ($_ eq 'mtime') {
165 $out .= tab . n('int(-M _)', shift);
166 } elsif ($_ eq 'ctime') {
167 $out .= tab . n('int(-C _)', shift);
168 } elsif ($_ eq 'exec') {
170 while (@ARGV && $ARGV[0] ne ';')
171 { push(@cmd, shift) }
174 if ($cmd[0] =~m#^(?:(?:/usr)?/bin/)?rm$#
175 && $cmd[$#cmd] eq '{}'
176 && (@cmd == 2 || (@cmd == 3 && $cmd[1] eq '-f'))) {
178 $out .= '(unlink($_) || warn "$name: $!\n")';
180 $out .= 'unlink($_)';
182 $out .= '(unlink($_) || 1)';
187 { local $" = "','"; $out .= "doexec(0, '@cmd')"; }
188 $declaresubs .= "sub doexec (\$\@);\n";
192 } elsif ($_ eq 'ok') {
194 while (@ARGV && $ARGV[0] ne ';')
195 { push(@cmd, shift) }
200 { local $" = "','"; $out .= "doexec(1, '@cmd')"; }
201 $declaresubs .= "sub doexec (\$\@);\n";
204 } elsif ($_ eq 'prune') {
205 $out .= tab . '($File::Find::prune = 1)';
206 } elsif ($_ eq 'xdev') {
207 $out .= tab . '!($File::Find::prune |= ($dev != $File::Find::topdev))'
209 } elsif ($_ eq 'newer') {
211 my $newername = 'AGE_OF' . $file;
212 $newername =~ s/\W/_/g;
213 $newername = '$' . $newername;
214 $out .= tab . "(-M _ < $newername)";
215 $initnewer .= "my $newername = -M " . quote($file) . ";\n";
216 } elsif ($_ eq 'eval') {
219 $out .= tab . "eval {$prog}";
221 } elsif ($_ eq 'depth') {
224 } elsif ($_ eq 'ls') {
226 $declaresubs .= "sub ls ();\n";
229 } elsif ($_ eq 'tar') {
230 die "-tar must have a filename argument\n" unless @ARGV;
232 my $fh = 'FH' . $file;
234 $out .= tab . "tar(*$fh, \$name)";
235 $flushall .= "tflushall;\n";
236 $declaresubs .= "sub tar;\nsub tflushall ();\n";
237 $initfile .= "open($fh, " . quote('> ' . $file) .
238 qq{) || die "Can't open $fh: \$!\\n";\n};
240 } elsif (/^(n?)cpio\z/) {
241 die "-$_ must have a filename argument\n" unless @ARGV;
243 my $fh = 'FH' . $file;
245 $out .= tab . "cpio(*$fh, \$name, '$1')";
247 $flushall .= "cflushall;\n";
248 $declaresubs .= "sub cpio;\nsub cflushall ();\n";
249 $initfile .= "open($fh, " . quote('> ' . $file) .
250 qq{) || die "Can't open $fh: \$!\\n";\n};
253 die "Unrecognized switch: -$_\n";
257 if ($ARGV[0] eq '-o') {
258 { local($statdone) = 1; $out .= "\n" . tab . "||\n"; }
259 $statdone = 0 if $indent_depth == 1 && exists $init{delayedstat};
263 $out .= " &&" unless $Skip_And || $ARGV[0] eq ')';
265 shift if $ARGV[0] eq '-a';
272 if ($t !~ /&&\s*$/) { $t .= '&& ' }
273 $out .= "\n" . $t . 'print("$name\n")';
279 eval 'exec $perlpath -S \$0 \${1+"\$@"}'
280 if 0; #\$running_under_some_shell
285 # Set the variable \$File::Find::dont_use_nlink if you're using AFS,
288 # for the convenience of &wanted calls, including -eval statements:
289 use vars qw/*name *dir *prune/;
290 *name = *File::Find::name;
291 *dir = *File::Find::dir;
292 *prune = *File::Find::prune;
298 if (exists $init{doexec}) {
301 my $cwd = Cwd::cwd();
306 if (exists $init{ls}) {
308 my @rwx = qw(--- --x -w- -wx r-- r-x rw- rwx);
309 my @moname = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
314 if (exists $init{user} || exists $init{ls} || exists $init{tar}) {
315 print "my (%uid, %user);\n";
316 print "while (my (\$name, \$pw, \$uid) = getpwent) {\n";
317 print ' $uid{$name} = $uid{$uid} = $uid;', "\n"
318 if exists $init{user};
319 print ' $user{$uid} = $name unless exists $user{$uid};', "\n"
320 if exists $init{ls} || exists $init{tar};
324 if (exists $init{group} || exists $init{ls} || exists $init{tar}) {
325 print "my (%gid, %group);\n";
326 print "while (my (\$name, \$pw, \$gid) = getgrent) {\n";
327 print ' $gid{$name} = $gid{$gid} = $gid;', "\n"
328 if exists $init{group};
329 print ' $group{$gid} = $name unless exists $group{$gid};', "\n"
330 if exists $init{ls} || exists $init{tar};
334 print $initnewer, "\n" if $initnewer ne '';
335 print $initfile, "\n" if $initfile ne '';
336 $flushall .= "exit;\n";
337 if (exists $init{declarestat}) {
338 $out = <<'END' . $out;
339 my ($dev,$ino,$mode,$nlink,$uid,$gid);
344 if ( $follow_in_effect ) {
345 $out =~ s/lstat\(\$_\)/lstat(_)/;
348 # Traverse desired filesystems
349 File::Find::$find( {wanted => \\&wanted, follow => 1}, $roots);
360 # Traverse desired filesystems
361 File::Find::$find({wanted => \\&wanted}, $roots);
371 if (exists $init{doexec}) {
376 my @command = @_; # copy so we don't try to s/// aliases to constants
377 for my $word (@command)
378 { $word =~ s#{}#$name#g }
380 my $old = select(STDOUT);
384 return 0 unless <STDIN> =~ /^y/;
388 chdir $File::Find::dir;
395 if (exists $init{ls}) {
396 print <<'INTRO', <<"SUB", <<'END';
400 sprintf("%3d, %3d", ($rdev >> 8) & 0xff, $rdev & 0xff);
404 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
406 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
411 or $blocks = int(($size + 1023) / 1024);
413 my $perms = $rwx[$mode & 7];
415 $perms = $rwx[$mode & 7] . $perms;
417 $perms = $rwx[$mode & 7] . $perms;
418 substr($perms, 2, 1) =~ tr/-x/Ss/ if -u _;
419 substr($perms, 5, 1) =~ tr/-x/Ss/ if -g _;
420 substr($perms, 8, 1) =~ tr/-x/Tt/ if -k _;
421 if (-f _) { $perms = '-' . $perms; }
422 elsif (-d _) { $perms = 'd' . $perms; }
423 elsif (-l _) { $perms = 'l' . $perms; $pname .= ' -> ' . readlink($_); }
424 elsif (-c _) { $perms = 'c' . $perms; $size = sizemm($rdev); }
425 elsif (-b _) { $perms = 'b' . $perms; $size = sizemm($rdev); }
426 elsif (-p _) { $perms = 'p' . $perms; }
427 elsif (-S _) { $perms = 's' . $perms; }
428 else { $perms = '?' . $perms; }
430 my $user = $user{$uid} || $uid;
431 my $group = $group{$gid} || $gid;
433 my ($sec,$min,$hour,$mday,$mon,$timeyear) = localtime($mtime);
434 if (-M _ > 365.25 / 2) {
437 $timeyear = sprintf("%02d:%02d", $hour, $min);
440 printf "%5lu %4ld %-10s %3d %-8s %-8s %8s %s %2d %5s %s\n",
459 if (exists $init{cpio} || exists $init{tar}) {
465 my ($fh, $varref, $blksz) = @_;
467 while (length($$varref) >= $blksz) {
469 syswrite($fh, $$varref, $blksz);
470 substr($$varref, 0, $blksz) = '';
479 if (exists $init{cpio}) {
480 print <<'INTRO', <<"SUB", <<'END';
486 my ($fh, $fname, $nc) = @_;
488 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
489 $atime,$mtime,$ctime,$blksize,$blocks);
492 if ( ! defined $fname ) {
493 $fname = 'TRAILER!!!';
494 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
495 $atime,$mtime,$ctime,$blksize,$blocks) = (0) x 13;
497 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
499 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
502 open(IN, "./$_\0") || do {
503 warn "Couldn't open $fname: $!\n";
507 $text = readlink($_);
508 $size = 0 unless defined $text;
516 sprintf("%06o%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo%s\0",
530 $cpout{$fh} .= "\0" if length($cpout{$fh}) & 1;
531 $cpout{$fh} .= pack("SSSSSSSSLSLa*",
532 070707, $dev, $ino, $mode, $uid, $gid, $nlink, $rdev, $mtime,
533 length($fname)+1, $size,
534 $fname . (length($fname) & 1 ? "\0" : "\0\0"));
538 $cpout{$fh} .= $text;
541 flush($fh, \$cpout{$fh}, 5120)
542 while ($l = length($cpout{$fh})) >= 5120;
543 while (sysread(IN, $cpout{$fh}, 5120 - $l, $l)) {
544 flush($fh, \$cpout{$fh}, 5120);
545 $l = length($cpout{$fh});
552 for my $fh (keys %cpout) {
553 cpio($fh, undef, $nc{$fh});
554 $cpout{$fh} .= "0" x (5120 - length($cpout{$fh}));
555 flush($fh, \$cpout{$fh}, 5120);
556 print $blocks{$fh} * 10, " blocks\n";
563 if (exists $init{tar}) {
564 print <<'INTRO', <<"SUB", <<'END';
570 my ($fh, $fname) = @_;
574 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
576 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
581 if ($linkname = $linkseen{$fh, $dev, $ino}) {
582 if (length($linkname) > 100) {
583 warn "$0: omitting file with linkname ",
584 "too long for tar output: $linkname\n";
590 $linkseen{$fh, $dev, $ino} = $fname;
593 if ($typeflag eq '0') {
595 open(IN, "./$_\0") || do {
596 warn "Couldn't open $fname: $!\n";
600 $linkname = readlink($_);
601 if (defined $linkname) { $typeflag = '2' }
602 elsif (-c _) { $typeflag = '3' }
603 elsif (-b _) { $typeflag = '4' }
604 elsif (-d _) { $typeflag = '5' }
605 elsif (-p _) { $typeflag = '6' }
609 if (length($fname) > 100) {
610 ($prefix, $fname) = ($fname =~ m#\A(.*?)/(.{,100})\Z(?!\n)#);
611 if (!defined($fname) || length($prefix) > 155) {
612 warn "$0: omitting file with name too long for tar output: ",
618 $size = 0 if $typeflag ne '0';
619 my $header = pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155",
621 sprintf("%7o ", $mode & 0777),
622 sprintf("%7o ", $uid & 0777777),
623 sprintf("%7o ", $gid & 0777777),
624 sprintf("%11o ", $size),
625 sprintf("%11o ", $mtime),
628 defined $linkname ? $linkname : '',
637 substr($header, 148, 8) = sprintf("%7o ", unpack("%16C*", $header));
638 my $l = length($header) % 512;
639 $tarout{$fh} .= $header;
640 $tarout{$fh} .= "\0" x (512 - $l) if $l;
643 flush($fh, \$tarout{$fh}, 10240)
644 while ($l = length($tarout{$fh})) >= 10240;
645 while (sysread(IN, $tarout{$fh}, 10240 - $l, $l)) {
646 my $slop = length($tarout{$fh}) % 512;
647 $tarout{$fh} .= "\0" x (512 - $slop) if $slop;
648 flush($fh, \$tarout{$fh}, 10240);
649 $l = length($tarout{$fh});
657 for my $fh (keys %tarout) {
658 $len = 10240 - length($tarout{$fh});
659 $len += 10240 if $len < 1024;
660 $tarout{$fh} .= "\0" x $len;
661 flush($fh, \$tarout{$fh}, 10240);
670 ############################################################################
675 $tabstring = "\t" x ($indent_depth/2) . ' ' x ($indent_depth%2 * 4);
677 if ($_ =~ /^(?:name|print|prune|exec|ok|\(|\))/) {
678 $init{delayedstat} = 1;
680 my $statcall = '(($dev,$ino,$mode,$nlink,$uid,$gid) = '
682 if (exists $init{saw_or}) {
683 $tabstring .= "(\$nlink || $statcall) &&\n" . $tabstring;
685 $tabstring .= "$statcall &&\n" . $tabstring;
688 $init{declarestat} = 1;
691 $tabstring =~ s/^\s+/ / if $out =~ /!$/;
695 sub fileglob_to_re ($) {
697 $x =~ s#([./^\$()+])#\\$1#g;
698 $x =~ s#([?*])#.$1#g;
704 $n =~ s/^-/< / || $n =~ s/^\+/> / || $n =~ s/^/== /;
705 $n =~ s/ 0*(\d)/ $1/;
711 $string =~ s/\\/\\\\/g;
712 $string =~ s/'/\\'/g;
720 find2perl - translate find command lines to Perl code
724 find2perl [paths] [predicates] | perl
728 find2perl is a little translator to convert find command lines to
729 equivalent Perl code. The resulting code is typically faster than
732 "paths" are a set of paths where find2perl will start its searches and
733 "predicates" are taken from the following list.
739 Negate the sense of the following predicate. The C<!> must be passed as
740 a distinct argument, so it may need to be surrounded by whitespace and/or
741 quoted from interpretation by the shell using a backslash (just as with
744 =item C<( PREDICATES )>
746 Group the given PREDICATES. The parentheses must be passed as distinct
747 arguments, so they may need to be surrounded by whitespace and/or
748 quoted from interpretation by the shell using a backslash (just as with
751 =item C<PREDICATE1 PREDICATE2>
753 True if _both_ PREDICATE1 and PREDICATE2 are true; PREDICATE2 is not
754 evaluated if PREDICATE1 is false.
756 =item C<PREDICATE1 -o PREDICATE2>
758 True if either one of PREDICATE1 or PREDICATE2 is true; PREDICATE2 is
759 not evaluated if PREDICATE1 is true.
763 Follow (dereference) symlinks. The checking of file attributes depends
764 on the position of the C<-follow> option. If it precedes the file
765 check option, an C<stat> is done which means the file check applies to the
766 file the symbolic link is pointing to. If C<-follow> option follows the
767 file check option, this now applies to the symbolic link itself, i.e.
772 Change directory traversal algorithm from breadth-first to depth-first.
776 Do not descend into the directory currently matched.
780 Do not traverse mount points (prunes search at mount-point directories).
784 File name matches specified GLOB wildcard pattern. GLOB may need to be
785 quoted to avoid interpretation by the shell (just as with using
790 Like C<-name>, but the match is case insensitive.
794 Path name matches specified GLOB wildcard pattern.
798 Like C<-path>, but the match is case insensitive.
802 Low-order 9 bits of permission match octal value PERM.
806 The bits specified in PERM are all set in file's permissions.
810 The file's type matches perl's C<-X> operator.
812 =item C<-fstype TYPE>
814 Filesystem of current path is of type TYPE (only NFS/non-NFS distinction
819 True if USER is owner of file.
821 =item C<-group GROUP>
823 True if file's group is GROUP.
827 True if file's owner is not in password database.
831 True if file's group is not in group database.
835 True file's inode number is INUM.
839 True if (hard) link count of file matches N (see below).
843 True if file's size matches N (see below) N is normally counted in
844 512-byte blocks, but a suffix of "c" specifies that size should be
845 counted in characters (bytes) and a suffix of "k" specifes that
846 size should be counted in 1024-byte blocks.
850 True if last-access time of file matches N (measured in days) (see
855 True if last-changed time of file's inode matches N (measured in days,
860 True if last-modified time of file matches N (measured in days, see below).
864 True if last-modified time of file matches N.
868 Print out path of file (always true). If none of C<-exec>, C<-ls>,
869 C<-print0>, or C<-ok> is specified, then C<-print> will be added
874 Like -print, but terminates with \0 instead of \n.
876 =item C<-exec OPTIONS ;>
878 exec() the arguments in OPTIONS in a subprocess; any occurrence of {} in
879 OPTIONS will first be substituted with the path of the current
880 file. Note that the command "rm" has been special-cased to use perl's
881 unlink() function instead (as an optimization). The C<;> must be passed as
882 a distinct argument, so it may need to be surrounded by whitespace and/or
883 quoted from interpretation by the shell using a backslash (just as with
886 =item C<-ok OPTIONS ;>
888 Like -exec, but first prompts user; if user's response does not begin
889 with a y, skip the exec. The C<;> must be passed as
890 a distinct argument, so it may need to be surrounded by whitespace and/or
891 quoted from interpretation by the shell using a backslash (just as with
896 Has the perl script eval() the EXPR.
900 Simulates C<-exec ls -dils {} ;>
904 Adds current output to tar-format FILE.
908 Adds current output to old-style cpio-format FILE.
912 Adds current output to "new"-style cpio-format FILE.
916 Predicates which take a numeric argument N can come in three forms:
918 * N is prefixed with a +: match values greater than N
919 * N is prefixed with a -: match values less than N
920 * N is not prefixed with either + or -: match only values equal to N
929 close OUT or die "Can't close $file: $!";
930 chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
931 exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';