2 use vars qw{$Try_autoload
4 $META $Signal $Cwd $End
5 $Suppress_readline %Dontload
11 # $Id: CPAN.pm,v 1.264 1999/05/23 14:26:49 k Exp $
13 # only used during development:
15 # $Revision = "[".substr(q$Revision: 1.264 $, 10)."]";
23 use ExtUtils::MakeMaker (); # $SelfLoader::DEBUG=1;
24 use File::Basename ();
30 use Text::ParseWords ();
34 END { $End++; &cleanup; }
55 $CPAN::Frontend ||= "CPAN::Shell";
56 $CPAN::Defaultsite ||= "ftp://ftp.perl.org/pub/CPAN";
59 use vars qw($VERSION @EXPORT $AUTOLOAD $DEBUG $META $term);
62 @CPAN::ISA = qw(CPAN::Debug Exporter);
65 autobundle bundle expand force get
66 install make readme recompile shell test clean
69 #-> sub CPAN::AUTOLOAD ;
74 @EXPORT{@EXPORT} = '';
75 CPAN::Config->load unless $CPAN::Config_loaded++;
76 if (exists $EXPORT{$l}){
79 my $ok = CPAN::Shell->try_dot_al($AUTOLOAD);
83 # $CPAN::Frontend->mywarn("Could not autoload $AUTOLOAD");
85 $CPAN::Frontend->mywarn(qq{Unknown command "$AUTOLOAD". }.
94 $Suppress_readline ||= ! -t STDIN;
95 CPAN::Config->load unless $CPAN::Config_loaded++;
97 my $prompt = "cpan> ";
99 unless ($Suppress_readline) {
100 require Term::ReadLine;
101 # import Term::ReadLine;
102 $term = Term::ReadLine->new('CPAN Monitor');
103 if ($term->ReadLine eq "Term::ReadLine::Gnu") {
104 my $attribs = $term->Attribs;
105 # $attribs->{completion_entry_function} =
106 # $attribs->{'list_completion_function'};
107 $attribs->{attempted_completion_function} = sub {
108 &CPAN::Complete::gnu_cpl;
110 # $attribs->{completion_word} =
111 # [qw(help me somebody to find out how
112 # to use completion with GNU)];
114 $readline::rl_completion_function =
115 $readline::rl_completion_function = 'CPAN::Complete::cpl';
122 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
123 my $cwd = CPAN->$getcwd();
124 my $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub";
125 my $rl_avail = $Suppress_readline ? "suppressed" :
126 ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" :
127 "available (try ``install Bundle::CPAN'')";
129 $CPAN::Frontend->myprint(
131 cpan shell -- CPAN exploration and modules installation (v$CPAN::VERSION$CPAN::Revision)
132 ReadLine support $rl_avail
134 }) unless $CPAN::Config->{'inhibit_startup_message'} ;
135 my($continuation) = "";
137 if ($Suppress_readline) {
139 last unless defined ($_ = <> );
142 last unless defined ($_ = $term->readline($prompt));
144 $_ = "$continuation$_" if $continuation;
147 $_ = 'h' if /^\s*\?/;
148 if (/^(?:q(?:uit)?|bye|exit)$/i) {
158 use vars qw($import_done);
159 CPAN->import(':DEFAULT') unless $import_done++;
160 CPAN->debug("eval[$eval]") if $CPAN::DEBUG;
167 if ($] < 5.00322) { # parsewords had a bug until recently
170 eval { @line = Text::ParseWords::shellwords($_) };
171 warn($@), next if $@;
173 $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG;
174 my $command = shift @line;
175 eval { CPAN::Shell->$command(@line) };
178 $CPAN::Frontend->myprint("\n");
184 CPAN::Queue->nullify_queue;
185 if ($try_detect_readline) {
186 if ($CPAN::META->has_inst("Term::ReadLine::Gnu")
188 $CPAN::META->has_inst("Term::ReadLine::Perl")
190 delete $INC{"Term/ReadLine.pm"};
192 local($SIG{__WARN__}) = CPAN::Shell::dotdot_onreload(\$redef);
193 require Term::ReadLine;
194 $CPAN::Frontend->myprint("\n$redef subroutines in Term::ReadLine redefined\n");
201 package CPAN::CacheMgr;
202 @CPAN::CacheMgr::ISA = qw(CPAN::InfoObj CPAN);
205 package CPAN::Config;
206 import ExtUtils::MakeMaker 'neatvalue';
207 use vars qw(%can $dot_cpan);
210 'commit' => "Commit changes to disk",
211 'defaults' => "Reload defaults from disk",
212 'init' => "Interactive setting of all options",
216 use vars qw($Ua $Thesite $Themethod);
217 @CPAN::FTP::ISA = qw(CPAN::Debug);
219 package CPAN::Complete;
220 @CPAN::Complete::ISA = qw(CPAN::Debug);
223 use vars qw($last_time $date_of_03);
224 @CPAN::Index::ISA = qw(CPAN::Debug);
228 package CPAN::InfoObj;
229 @CPAN::InfoObj::ISA = qw(CPAN::Debug);
231 package CPAN::Author;
232 @CPAN::Author::ISA = qw(CPAN::InfoObj);
234 package CPAN::Distribution;
235 @CPAN::Distribution::ISA = qw(CPAN::InfoObj);
237 package CPAN::Bundle;
238 @CPAN::Bundle::ISA = qw(CPAN::Module);
240 package CPAN::Module;
241 @CPAN::Module::ISA = qw(CPAN::InfoObj);
244 use vars qw($AUTOLOAD $redef @ISA);
245 @CPAN::Shell::ISA = qw(CPAN::Debug);
247 #-> sub CPAN::Shell::AUTOLOAD ;
249 my($autoload) = $AUTOLOAD;
250 my $class = shift(@_);
251 # warn "autoload[$autoload] class[$class]";
252 $autoload =~ s/.*:://;
253 if ($autoload =~ /^w/) {
254 if ($CPAN::META->has_inst('CPAN::WAIT')) {
255 CPAN::WAIT->$autoload(@_);
257 $CPAN::Frontend->mywarn(qq{
258 Commands starting with "w" require CPAN::WAIT to be installed.
259 Please consider installing CPAN::WAIT to use the fulltext index.
260 For this you just need to type
265 my $ok = CPAN::Shell->try_dot_al($AUTOLOAD);
269 # $CPAN::Frontend->mywarn("Could not autoload $autoload");
271 $CPAN::Frontend->mywarn(qq{Unknown command '$autoload'. }.
277 #-> CPAN::Shell::try_dot_al
279 my($class,$autoload) = @_;
280 return unless $CPAN::Try_autoload;
281 # I don't see how to re-use that from the AutoLoader...
283 # Braces used to preserve $1 et al.
285 my ($pkg,$func) = $autoload =~ /(.*)::([^:]+)$/;
287 if (defined($name=$INC{"$pkg.pm"}))
289 $name =~ s|^(.*)$pkg\.pm$|$1auto/$pkg/$func.al|;
290 $name = undef unless (-r $name);
292 unless (defined $name)
294 $name = "auto/$autoload.al";
299 eval {local $SIG{__DIE__};require $name};
301 if (substr($autoload,-9) eq '::DESTROY') {
305 if ($name =~ s{(\w{12,})\.al$}{substr($1,0,11).".al"}e){
306 eval {local $SIG{__DIE__};require $name};
321 # my $lm = Carp::longmess();
322 # warn "ok[$ok] autoload[$autoload] longmess[$lm]"; # debug
326 #### autoloader is experimental
327 #### to try it we have to set $Try_autoload and uncomment
328 #### the use statement and uncomment the __END__ below
329 #### You also need AutoSplit 1.01 available. MakeMaker will
330 #### then build CPAN with all the AutoLoad stuff.
334 if ($CPAN::Try_autoload) {
337 CPAN::Author CPAN::Bundle CPAN::CacheMgr CPAN::Complete
338 CPAN::Config CPAN::Debug CPAN::Distribution CPAN::FTP
339 CPAN::FTP::netrc CPAN::Index CPAN::InfoObj CPAN::Module
341 *{"$p\::AUTOLOAD"} = \&AutoLoader::AUTOLOAD;
345 package CPAN::Tarzip;
346 use vars qw($AUTOLOAD @ISA);
347 @CPAN::Tarzip::ISA = qw(CPAN::Debug);
351 # One use of the queue is to determine if we should or shouldn't
352 # announce the availability of a new CPAN module
354 # Now we try to use it for dependency tracking. For that to happen
355 # we need to draw a dependency tree and do the leaves first. This can
356 # easily be reached by running CPAN.pm recursively, but we don't want
357 # to waste memory and run into deep recursion. So what we can do is
360 # CPAN::Queue is the package where the queue is maintained. Dependencies
361 # often have high priority and must be brought to the head of the queue,
362 # possibly by jumping the queue if they are already there. My first code
363 # attempt tried to be extremely correct. Whenever a module needed
364 # immediate treatment, I either unshifted it to the front of the queue,
365 # or, if it was already in the queue, I spliced and let it bypass the
366 # others. This became a too correct model that made it impossible to put
367 # an item more than once into the queue. Why would you need that? Well,
368 # you need temporary duplicates as the manager of the queue is a loop
371 # (1) looks at the first item in the queue without shifting it off
373 # (2) cares for the item
375 # (3) removes the item from the queue, *even if its agenda failed and
376 # even if the item isn't the first in the queue anymore* (that way
377 # protecting against never ending queues)
379 # So if an item has prerequisites, the installation fails now, but we
380 # want to retry later. That's easy if we have it twice in the queue.
382 # I also expect insane dependency situations where an item gets more
383 # than two lives in the queue. Simplest example is triggered by 'install
384 # Foo Foo Foo'. People make this kind of mistakes and I don't want to
385 # get in the way. I wanted the queue manager to be a dumb servant, not
386 # one that knows everything.
388 # Who would I tell in this model that the user wants to be asked before
389 # processing? I can't attach that information to the module object,
390 # because not modules are installed but distributions. So I'd have to
391 # tell the distribution object that it should ask the user before
392 # processing. Where would the question be triggered then? Most probably
393 # in CPAN::Distribution::rematein.
394 # Hope that makes sense, my head is a bit off:-) -- AK
399 my($class,$mod) = @_;
400 my $self = bless {mod => $mod}, $class;
402 # my @all = map { $_->{mod} } @All;
403 # warn "Adding Queue object for mod[$mod] all[@all]";
413 my($class,$what) = @_;
415 for my $i (0..$#All) {
416 if ( $All[$i]->{mod} eq $what ) {
427 WHAT: for my $what (reverse @what) {
429 for (my $i=0; $i<$#All;$i++) { #prevent deep recursion
430 if ($All[$i]->{mod} eq $what){
432 if ($jumped > 100) { # one's OK if e.g. just processing now;
433 # more are OK if user typed it several
435 $CPAN::Frontend->mywarn(
436 qq{Object [$what] queued more than 100 times, ignoring}
442 my $obj = bless { mod => $what }, $class;
448 my($self,$what) = @_;
449 my @all = map { $_->{mod} } @All;
450 my $exists = grep { $_->{mod} eq $what } @All;
451 # warn "Checking exists in Queue object for mod[$what] all[@all] exists[$exists]";
457 @All = grep { $_->{mod} ne $mod } @All;
458 # my @all = map { $_->{mod} } @All;
459 # warn "Deleting Queue object for mod[$mod] all[@all]";
470 $META ||= CPAN->new; # In case we re-eval ourselves we need the ||
474 # __END__ # uncomment this and AutoSplit version 1.01 will split it
476 #-> sub CPAN::autobundle ;
478 #-> sub CPAN::bundle ;
480 #-> sub CPAN::expand ;
482 #-> sub CPAN::force ;
484 #-> sub CPAN::install ;
488 #-> sub CPAN::clean ;
495 my($mgr,$class) = @_;
496 CPAN::Config->load unless $CPAN::Config_loaded++;
497 CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG;
499 values %{ $META->{$class} };
501 *all = \&all_objects;
503 # Called by shell, not in batch mode. Not clean XXX
504 #-> sub CPAN::checklock ;
507 my $lockfile = MM->catfile($CPAN::Config->{cpan_home},".lock");
508 if (-f $lockfile && -M _ > 0) {
509 my $fh = FileHandle->new($lockfile);
512 if (defined $other && $other) {
514 return if $$==$other; # should never happen
515 $CPAN::Frontend->mywarn(
517 There seems to be running another CPAN process ($other). Contacting...
519 if (kill 0, $other) {
520 $CPAN::Frontend->mydie(qq{Other job is running.
521 You may want to kill it and delete the lockfile, maybe. On UNIX try:
525 } elsif (-w $lockfile) {
527 ExtUtils::MakeMaker::prompt
528 (qq{Other job not responding. Shall I overwrite }.
529 qq{the lockfile? (Y/N)},"y");
530 $CPAN::Frontend->myexit("Ok, bye\n")
531 unless $ans =~ /^y/i;
534 qq{Lockfile $lockfile not writeable by you. }.
535 qq{Cannot proceed.\n}.
538 qq{ and then rerun us.\n}
543 my $dotcpan = $CPAN::Config->{cpan_home};
544 eval { File::Path::mkpath($dotcpan);};
546 # A special case at least for Jarkko.
551 $symlinkcpan = readlink $dotcpan;
552 die "readlink $dotcpan failed: $!" unless defined $symlinkcpan;
553 eval { File::Path::mkpath($symlinkcpan); };
557 $CPAN::Frontend->mywarn(qq{
558 Working directory $symlinkcpan created.
562 unless (-d $dotcpan) {
564 Your configuration suggests "$dotcpan" as your
565 CPAN.pm working directory. I could not create this directory due
566 to this error: $firsterror\n};
568 As "$dotcpan" is a symlink to "$symlinkcpan",
569 I tried to create that, but I failed with this error: $seconderror
572 Please make sure the directory exists and is writable.
574 $CPAN::Frontend->mydie($diemess);
578 unless ($fh = FileHandle->new(">$lockfile")) {
579 if ($!{EACCES} || $! =~ /Permission/) {
580 my $incc = $INC{'CPAN/Config.pm'};
581 my $myincc = MM->catfile($ENV{HOME},'.cpan','CPAN','MyConfig.pm');
582 $CPAN::Frontend->myprint(qq{
584 Your configuration suggests that CPAN.pm should use a working
586 $CPAN::Config->{cpan_home}
587 Unfortunately we could not create the lock file
589 due to permission problems.
591 Please make sure that the configuration variable
592 \$CPAN::Config->{cpan_home}
593 points to a directory where you can write a .lock file. You can set
594 this variable in either
601 $CPAN::Frontend->mydie("Could not open >$lockfile: $!");
603 $fh->print($$, "\n");
604 $self->{LOCK} = $lockfile;
608 $CPAN::Frontend->mydie("Got SIGTERM, leaving");
613 $CPAN::Frontend->mydie("Got another SIGINT") if $Signal;
614 print "Caught SIGINT\n";
617 $SIG{'__DIE__'} = \&cleanup;
618 $self->debug("Signal handler set.") if $CPAN::DEBUG;
621 #-> sub CPAN::DESTROY ;
623 &cleanup; # need an eval?
627 sub cwd {Cwd::cwd();}
629 #-> sub CPAN::getcwd ;
630 sub getcwd {Cwd::getcwd();}
632 #-> sub CPAN::exists ;
634 my($mgr,$class,$id) = @_;
636 ### Carp::croak "exists called without class argument" unless $class;
638 exists $META->{$class}{$id};
641 #-> sub CPAN::delete ;
643 my($mgr,$class,$id) = @_;
644 delete $META->{$class}{$id};
647 #-> sub CPAN::has_inst
649 my($self,$mod,$message) = @_;
650 Carp::croak("CPAN->has_inst() called without an argument")
652 if (defined $message && $message eq "no") {
655 } elsif (exists $Dontload{$mod}) {
661 $file =~ s|/|\\|g if $^O eq 'MSWin32';
664 # checking %INC is wrong, because $INC{LWP} may be true
665 # although $INC{"URI/URL.pm"} may have failed. But as
666 # I really want to say "bla loaded OK", I have to somehow
668 ### warn "$file in %INC"; #debug
670 } elsif (eval { require $file }) {
671 # eval is good: if we haven't yet read the database it's
672 # perfect and if we have installed the module in the meantime,
673 # it tries again. The second require is only a NOOP returning
674 # 1 if we had success, otherwise it's retrying
676 $CPAN::Frontend->myprint("CPAN: $mod loaded ok\n");
677 if ($mod eq "CPAN::WAIT") {
678 push @CPAN::Shell::ISA, CPAN::WAIT;
681 } elsif ($mod eq "Net::FTP") {
683 Please, install Net::FTP as soon as possible. CPAN.pm installs it for you
685 install Bundle::libnet
689 } elsif ($mod eq "MD5"){
690 $CPAN::Frontend->myprint(qq{
691 CPAN: MD5 security checks disabled because MD5 not installed.
692 Please consider installing the MD5 module.
697 delete $INC{$file}; # if it inc'd LWP but failed during, say, URI
702 #-> sub CPAN::instance ;
704 my($mgr,$class,$id) = @_;
707 $META->{$class}{$id} ||= $class->new(ID => $id );
715 #-> sub CPAN::cleanup ;
717 # warn "cleanup called with arg[@_] End[$End] Signal[$Signal]";
718 local $SIG{__DIE__} = '';
723 0 && # disabled, try reload cpan with it
724 $] > 5.004_60 # thereabouts
729 while ((undef,undef,undef,$subroutine) = caller(++$i)) {
731 $subroutine eq '(eval)';
734 return if $ineval && !$End;
735 return unless defined $META->{'LOCK'};
736 return unless -f $META->{'LOCK'};
737 unlink $META->{'LOCK'};
739 # Carp::cluck("DEBUGGING");
740 $CPAN::Frontend->mywarn("Lockfile removed.\n");
743 package CPAN::CacheMgr;
745 #-> sub CPAN::CacheMgr::as_string ;
747 eval { require Data::Dumper };
749 return shift->SUPER::as_string;
751 return Data::Dumper::Dumper(shift);
755 #-> sub CPAN::CacheMgr::cachesize ;
762 return unless -d $self->{ID};
763 while ($self->{DU} > $self->{'MAX'} ) {
764 my($toremove) = shift @{$self->{FIFO}};
765 $CPAN::Frontend->myprint(sprintf(
766 "Deleting from cache".
767 ": $toremove (%.1f>%.1f MB)\n",
768 $self->{DU}, $self->{'MAX'})
770 return if $CPAN::Signal;
771 $self->force_clean_cache($toremove);
772 return if $CPAN::Signal;
776 #-> sub CPAN::CacheMgr::dir ;
781 #-> sub CPAN::CacheMgr::entries ;
784 return unless defined $dir;
785 $self->debug("reading dir[$dir]") if $CPAN::DEBUG;
786 $dir ||= $self->{ID};
788 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
789 my($cwd) = CPAN->$getcwd();
790 chdir $dir or Carp::croak("Can't chdir to $dir: $!");
791 my $dh = DirHandle->new(File::Spec->curdir)
792 or Carp::croak("Couldn't opendir $dir: $!");
795 next if $_ eq "." || $_ eq "..";
797 push @entries, MM->catfile($dir,$_);
799 push @entries, MM->catdir($dir,$_);
801 $CPAN::Frontend->mywarn("Warning: weird direntry in $dir: $_\n");
804 chdir $cwd or Carp::croak("Can't chdir to $cwd: $!");
805 sort { -M $b <=> -M $a} @entries;
808 #-> sub CPAN::CacheMgr::disk_usage ;
811 return if exists $self->{SIZE}{$dir};
812 return if $CPAN::Signal;
816 $File::Find::prune++ if $CPAN::Signal;
818 if ($^O eq 'MacOS') {
820 my $cat = Mac::Files::FSpGetCatInfo($_);
821 $Du += $cat->ioFlLgLen() + $cat->ioFlRLgLen();
828 return if $CPAN::Signal;
829 $self->{SIZE}{$dir} = $Du/1024/1024;
830 push @{$self->{FIFO}}, $dir;
831 $self->debug("measured $dir is $Du") if $CPAN::DEBUG;
832 $self->{DU} += $Du/1024/1024;
836 #-> sub CPAN::CacheMgr::force_clean_cache ;
837 sub force_clean_cache {
839 return unless -e $dir;
840 $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}")
842 File::Path::rmtree($dir);
843 $self->{DU} -= $self->{SIZE}{$dir};
844 delete $self->{SIZE}{$dir};
847 #-> sub CPAN::CacheMgr::new ;
854 ID => $CPAN::Config->{'build_dir'},
855 MAX => $CPAN::Config->{'build_cache'},
856 SCAN => $CPAN::Config->{'scan_cache'} || 'atstart',
859 File::Path::mkpath($self->{ID});
860 my $dh = DirHandle->new($self->{ID});
864 $debug .= "timing of CacheMgr->new: ".($t2 - $time);
866 CPAN->debug($debug) if $CPAN::DEBUG;
870 #-> sub CPAN::CacheMgr::scan_cache ;
873 return if $self->{SCAN} eq 'never';
874 $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}")
875 unless $self->{SCAN} eq 'atstart';
876 $CPAN::Frontend->myprint(
877 sprintf("Scanning cache %s for sizes\n",
880 for $e ($self->entries($self->{ID})) {
881 next if $e eq ".." || $e eq ".";
882 $self->disk_usage($e);
883 return if $CPAN::Signal;
890 #-> sub CPAN::Debug::debug ;
893 my($caller,$func,$line,@rest) = caller(1); # caller(0) eg
894 # Complete, caller(1)
896 ($caller) = caller(0);
898 $arg = "" unless defined $arg;
899 my $rest = join "|", map { defined $_ ? $_ : "UNDEF" } @rest;
900 if ($CPAN::DEBUG{$caller} & $CPAN::DEBUG){
901 if ($arg and ref $arg) {
902 eval { require Data::Dumper };
904 $CPAN::Frontend->myprint($arg->as_string);
906 $CPAN::Frontend->myprint(Data::Dumper::Dumper($arg));
909 $CPAN::Frontend->myprint("Debug($caller:$func,$line,[$rest]): $arg\n");
914 package CPAN::Config;
916 #-> sub CPAN::Config::edit ;
918 my($class,@args) = @_;
920 CPAN->debug("class[$class]args[".join(" | ",@args)."]");
921 my($o,$str,$func,$args,$key_exists);
927 if (ref($CPAN::Config->{$o}) eq ARRAY) {
930 # Let's avoid eval, it's easier to comprehend without.
931 if ($func eq "push") {
932 push @{$CPAN::Config->{$o}}, @args;
933 } elsif ($func eq "pop") {
934 pop @{$CPAN::Config->{$o}};
935 } elsif ($func eq "shift") {
936 shift @{$CPAN::Config->{$o}};
937 } elsif ($func eq "unshift") {
938 unshift @{$CPAN::Config->{$o}}, @args;
939 } elsif ($func eq "splice") {
940 splice @{$CPAN::Config->{$o}}, @args;
942 $CPAN::Config->{$o} = [@args];
944 $CPAN::Frontend->myprint(
947 ExtUtils::MakeMaker::neatvalue($CPAN::Config->{$o}),
952 $CPAN::Config->{$o} = $args[0] if defined $args[0];
953 $CPAN::Frontend->myprint(" $o " .
954 (defined $CPAN::Config->{$o} ?
955 $CPAN::Config->{$o} : "UNDEFINED"));
960 #-> sub CPAN::Config::commit ;
962 my($self,$configpm) = @_;
963 unless (defined $configpm){
964 $configpm ||= $INC{"CPAN/MyConfig.pm"};
965 $configpm ||= $INC{"CPAN/Config.pm"};
966 $configpm || Carp::confess(q{
967 CPAN::Config::commit called without an argument.
968 Please specify a filename where to save the configuration or try
969 "o conf init" to have an interactive course through configing.
974 $mode = (stat $configpm)[2];
975 if ($mode && ! -w _) {
976 Carp::confess("$configpm is not writable");
980 my $msg = <<EOF unless $configpm =~ /MyConfig/;
982 # This is CPAN.pm's systemwide configuration file. This file provides
983 # defaults for users, and the values can be changed in a per-user
984 # configuration file. The user-config file is being looked for as
985 # ~/.cpan/CPAN/MyConfig.pm.
989 my($fh) = FileHandle->new;
990 rename $configpm, "$configpm~" if -f $configpm;
991 open $fh, ">$configpm" or warn "Couldn't open >$configpm: $!";
992 $fh->print(qq[$msg\$CPAN::Config = \{\n]);
993 foreach (sort keys %$CPAN::Config) {
996 ExtUtils::MakeMaker::neatvalue($CPAN::Config->{$_}),
1001 $fh->print("};\n1;\n__END__\n");
1004 #$mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
1005 #chmod $mode, $configpm;
1006 ###why was that so? $self->defaults;
1007 $CPAN::Frontend->myprint("commit: wrote $configpm\n");
1011 *default = \&defaults;
1012 #-> sub CPAN::Config::defaults ;
1022 undef $CPAN::Config->{'inhibit_startup_message'}; # lazy trick to
1031 #-> sub CPAN::Config::load ;
1036 eval {require CPAN::Config;}; # We eval because of some
1037 # MakeMaker problems
1038 unless ($dot_cpan++){
1039 unshift @INC, MM->catdir($ENV{HOME},".cpan");
1040 eval {require CPAN::MyConfig;}; # where you can override
1041 # system wide settings
1044 return unless @miss = $self->not_loaded;
1045 # XXX better check for arrayrefs too
1046 require CPAN::FirstTime;
1047 my($configpm,$fh,$redo,$theycalled);
1049 $theycalled++ if @miss==1 && $miss[0] eq 'inhibit_startup_message';
1050 if (defined $INC{"CPAN/Config.pm"} && -w $INC{"CPAN/Config.pm"}) {
1051 $configpm = $INC{"CPAN/Config.pm"};
1053 } elsif (defined $INC{"CPAN/MyConfig.pm"} && -w $INC{"CPAN/MyConfig.pm"}) {
1054 $configpm = $INC{"CPAN/MyConfig.pm"};
1057 my($path_to_cpan) = File::Basename::dirname($INC{"CPAN.pm"});
1058 my($configpmdir) = MM->catdir($path_to_cpan,"CPAN");
1059 my($configpmtest) = MM->catfile($configpmdir,"Config.pm");
1060 if (-d $configpmdir or File::Path::mkpath($configpmdir)) {
1061 if (-w $configpmtest) {
1062 $configpm = $configpmtest;
1063 } elsif (-w $configpmdir) {
1064 #_#_# following code dumped core on me with 5.003_11, a.k.
1065 unlink "$configpmtest.bak" if -f "$configpmtest.bak";
1066 rename $configpmtest, "$configpmtest.bak" if -f $configpmtest;
1067 my $fh = FileHandle->new;
1068 if ($fh->open(">$configpmtest")) {
1070 $configpm = $configpmtest;
1072 # Should never happen
1073 Carp::confess("Cannot open >$configpmtest");
1077 unless ($configpm) {
1078 $configpmdir = MM->catdir($ENV{HOME},".cpan","CPAN");
1079 File::Path::mkpath($configpmdir);
1080 $configpmtest = MM->catfile($configpmdir,"MyConfig.pm");
1081 if (-w $configpmtest) {
1082 $configpm = $configpmtest;
1083 } elsif (-w $configpmdir) {
1084 #_#_# following code dumped core on me with 5.003_11, a.k.
1085 my $fh = FileHandle->new;
1086 if ($fh->open(">$configpmtest")) {
1088 $configpm = $configpmtest;
1090 # Should never happen
1091 Carp::confess("Cannot open >$configpmtest");
1094 Carp::confess(qq{WARNING: CPAN.pm is unable to }.
1095 qq{create a configuration file.});
1100 $CPAN::Frontend->myprint(<<END) if $redo && ! $theycalled;
1101 We have to reconfigure CPAN.pm due to following uninitialized parameters:
1105 $CPAN::Frontend->myprint(qq{
1106 $configpm initialized.
1109 CPAN::FirstTime::init($configpm);
1112 #-> sub CPAN::Config::not_loaded ;
1116 cpan_home keep_source_where build_dir build_cache scan_cache
1117 index_expire gzip tar unzip make pager makepl_arg make_arg
1118 make_install_arg urllist inhibit_startup_message
1119 ftp_proxy http_proxy no_proxy prerequisites_policy
1121 push @miss, $_ unless defined $CPAN::Config->{$_};
1126 #-> sub CPAN::Config::unload ;
1128 delete $INC{'CPAN/MyConfig.pm'};
1129 delete $INC{'CPAN/Config.pm'};
1132 #-> sub CPAN::Config::help ;
1134 $CPAN::Frontend->myprint(q[
1136 defaults reload default config values from disk
1137 commit commit session changes to disk
1138 init go through a dialog to set all parameters
1140 You may edit key values in the follow fashion:
1142 o conf build_cache 15
1144 o conf build_dir "/foo/bar"
1146 o conf urllist shift
1148 o conf urllist unshift ftp://ftp.foo.bar/
1151 undef; #don't reprint CPAN::Config
1154 #-> sub CPAN::Config::cpl ;
1156 my($word,$line,$pos) = @_;
1158 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
1159 my(@words) = split " ", substr($line,0,$pos+1);
1164 $words[2] =~ /list$/ && @words == 3
1166 $words[2] =~ /list$/ && @words == 4 && length($word)
1169 return grep /^\Q$word\E/, qw(splice shift unshift pop push);
1170 } elsif (@words >= 4) {
1173 my(@o_conf) = (keys %CPAN::Config::can, keys %$CPAN::Config);
1174 return grep /^\Q$word\E/, @o_conf;
1177 package CPAN::Shell;
1179 #-> sub CPAN::Shell::h ;
1181 my($class,$about) = @_;
1182 if (defined $about) {
1183 $CPAN::Frontend->myprint("Detailed help not yet implemented\n");
1185 $CPAN::Frontend->myprint(q{
1186 command arguments description
1188 b or display bundles
1189 d /regex/ info distributions
1191 i none anything of above
1193 r as reinstall recommendations
1194 u above uninstalled distributions
1195 See manpage for autobundle, recompile, force, look, etc.
1198 test modules, make test (implies make)
1199 install dists, bundles, make install (implies test)
1200 clean "r" or "u" make clean
1201 readme display the README file
1203 reload index|cpan load most recent indices/CPAN.pm
1204 h or ? display this menu
1205 o various set and query options
1206 ! perl-code eval a perl command
1207 q quit the shell subroutine
1214 #-> sub CPAN::Shell::a ;
1215 sub a { $CPAN::Frontend->myprint(shift->format_result('Author',@_));}
1216 #-> sub CPAN::Shell::b ;
1218 my($self,@which) = @_;
1219 CPAN->debug("which[@which]") if $CPAN::DEBUG;
1220 my($incdir,$bdir,$dh);
1221 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) {
1222 $bdir = MM->catdir($incdir,"Bundle");
1223 if ($dh = DirHandle->new($bdir)) { # may fail
1225 for $entry ($dh->read) {
1226 next if -d MM->catdir($bdir,$entry);
1227 next unless $entry =~ s/\.pm$//;
1228 $CPAN::META->instance('CPAN::Bundle',"Bundle::$entry");
1232 $CPAN::Frontend->myprint($self->format_result('Bundle',@which));
1234 #-> sub CPAN::Shell::d ;
1235 sub d { $CPAN::Frontend->myprint(shift->format_result('Distribution',@_));}
1236 #-> sub CPAN::Shell::m ;
1237 sub m { # emacs confused here }; sub mimimimimi { # emacs in sync here
1238 $CPAN::Frontend->myprint(shift->format_result('Module',@_));
1241 #-> sub CPAN::Shell::i ;
1246 @type = qw/Author Bundle Distribution Module/;
1247 @args = '/./' unless @args;
1250 push @result, $self->expand($type,@args);
1252 my $result = @result == 1 ?
1253 $result[0]->as_string :
1254 join "", map {$_->as_glimpse} @result;
1255 $result ||= "No objects found of any type for argument @args\n";
1256 $CPAN::Frontend->myprint($result);
1259 #-> sub CPAN::Shell::o ;
1261 my($self,$o_type,@o_what) = @_;
1263 CPAN->debug("o_type[$o_type] o_what[".join(" | ",@o_what)."]\n");
1264 if ($o_type eq 'conf') {
1265 shift @o_what if @o_what && $o_what[0] eq 'help';
1268 $CPAN::Frontend->myprint("CPAN::Config options");
1269 if (exists $INC{'CPAN/Config.pm'}) {
1270 $CPAN::Frontend->myprint(" from $INC{'CPAN/Config.pm'}");
1272 if (exists $INC{'CPAN/MyConfig.pm'}) {
1273 $CPAN::Frontend->myprint(" and $INC{'CPAN/MyConfig.pm'}");
1275 $CPAN::Frontend->myprint(":\n");
1276 for $k (sort keys %CPAN::Config::can) {
1277 $v = $CPAN::Config::can{$k};
1278 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, $v);
1280 $CPAN::Frontend->myprint("\n");
1281 for $k (sort keys %$CPAN::Config) {
1282 $v = $CPAN::Config->{$k};
1284 $CPAN::Frontend->myprint(
1291 map {"\t$_\n"} @{$v}
1295 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, $v);
1298 $CPAN::Frontend->myprint("\n");
1299 } elsif (!CPAN::Config->edit(@o_what)) {
1300 $CPAN::Frontend->myprint(qq[Type 'o conf' to view configuration edit options\n\n]);
1302 } elsif ($o_type eq 'debug') {
1304 @o_what = () if defined $o_what[0] && $o_what[0] =~ /help/i;
1307 my($what) = shift @o_what;
1308 if ( exists $CPAN::DEBUG{$what} ) {
1309 $CPAN::DEBUG |= $CPAN::DEBUG{$what};
1310 } elsif ($what =~ /^\d/) {
1311 $CPAN::DEBUG = $what;
1312 } elsif (lc $what eq 'all') {
1314 for (values %CPAN::DEBUG) {
1317 $CPAN::DEBUG = $max;
1320 for (keys %CPAN::DEBUG) {
1321 next unless lc($_) eq lc($what);
1322 $CPAN::DEBUG |= $CPAN::DEBUG{$_};
1325 $CPAN::Frontend->myprint("unknown argument [$what]\n")
1330 $CPAN::Frontend->myprint("Valid options for debug are ".
1331 join(", ",sort(keys %CPAN::DEBUG), 'all').
1332 qq{ or a number. Completion works on the options. }.
1333 qq{Case is ignored.\n\n});
1336 $CPAN::Frontend->myprint("Options set for debugging:\n");
1338 for $k (sort {$CPAN::DEBUG{$a} <=> $CPAN::DEBUG{$b}} keys %CPAN::DEBUG) {
1339 $v = $CPAN::DEBUG{$k};
1340 $CPAN::Frontend->myprint(sprintf " %-14s(%s)\n", $k, $v) if $v & $CPAN::DEBUG;
1343 $CPAN::Frontend->myprint("Debugging turned off completely.\n");
1346 $CPAN::Frontend->myprint(qq{
1348 conf set or get configuration variables
1349 debug set or get debugging options
1354 sub dotdot_onreload {
1357 if ( $_[0] =~ /Subroutine (\w+) redefined/ ) {
1361 # $CPAN::Frontend->myprint(".($subr)");
1362 $CPAN::Frontend->myprint(".");
1369 #-> sub CPAN::Shell::reload ;
1371 my($self,$command,@arg) = @_;
1373 $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG;
1374 if ($command =~ /cpan/i) {
1375 CPAN->debug("reloading the whole CPAN.pm") if $CPAN::DEBUG;
1376 my $fh = FileHandle->new($INC{'CPAN.pm'});
1379 local($SIG{__WARN__}) = dotdot_onreload(\$redef);
1382 $CPAN::Frontend->myprint("\n$redef subroutines redefined\n");
1383 } elsif ($command =~ /index/) {
1384 CPAN::Index->force_reload;
1386 $CPAN::Frontend->myprint(qq{cpan re-evals the CPAN.pm file
1387 index re-reads the index files\n});
1391 #-> sub CPAN::Shell::_binary_extensions ;
1392 sub _binary_extensions {
1393 my($self) = shift @_;
1394 my(@result,$module,%seen,%need,$headerdone);
1395 my $isaperl = q{perl5[._-]\\d{3}(_[0-4][0-9])?\\.tar[._-]gz$};
1396 for $module ($self->expand('Module','/./')) {
1397 my $file = $module->cpan_file;
1398 next if $file eq "N/A";
1399 next if $file =~ /^Contact Author/;
1400 next if $file =~ / $isaperl /xo;
1401 next unless $module->xs_file;
1403 $CPAN::Frontend->myprint(".");
1404 push @result, $module;
1406 # print join " | ", @result;
1407 $CPAN::Frontend->myprint("\n");
1411 #-> sub CPAN::Shell::recompile ;
1413 my($self) = shift @_;
1414 my($module,@module,$cpan_file,%dist);
1415 @module = $self->_binary_extensions();
1416 for $module (@module){ # we force now and compile later, so we
1418 $cpan_file = $module->cpan_file;
1419 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
1421 $dist{$cpan_file}++;
1423 for $cpan_file (sort keys %dist) {
1424 $CPAN::Frontend->myprint(" CPAN: Recompiling $cpan_file\n\n");
1425 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
1427 $CPAN::Signal = 0; # it's tempting to reset Signal, so we can
1428 # stop a package from recompiling,
1429 # e.g. IO-1.12 when we have perl5.003_10
1433 #-> sub CPAN::Shell::_u_r_common ;
1435 my($self) = shift @_;
1436 my($what) = shift @_;
1437 CPAN->debug("self[$self] what[$what] args[@_]") if $CPAN::DEBUG;
1438 Carp::croak "Usage: \$obj->_u_r_common($what)" unless defined $what;
1439 Carp::croak "Usage: \$obj->_u_r_common(a|r|u)" unless $what =~ /^[aru]$/;
1441 @args = '/./' unless @args;
1442 my(@result,$module,%seen,%need,$headerdone,
1443 $version_undefs,$version_zeroes);
1444 $version_undefs = $version_zeroes = 0;
1445 my $sprintf = "%-25s %9s %9s %s\n";
1446 for $module ($self->expand('Module',@args)) {
1447 my $file = $module->cpan_file;
1448 next unless defined $file; # ??
1449 my($latest) = $module->cpan_version;
1450 my($inst_file) = $module->inst_file;
1452 return if $CPAN::Signal;
1455 $have = $module->inst_version;
1456 } elsif ($what eq "r") {
1457 $have = $module->inst_version;
1459 if ($have eq "undef"){
1461 } elsif ($have == 0){
1464 next if $have >= $latest;
1465 # to be pedantic we should probably say:
1466 # && !($have eq "undef" && $latest ne "undef" && $latest gt "");
1467 # to catch the case where CPAN has a version 0 and we have a version undef
1468 } elsif ($what eq "u") {
1474 } elsif ($what eq "r") {
1476 } elsif ($what eq "u") {
1480 return if $CPAN::Signal; # this is sometimes lengthy
1483 push @result, sprintf "%s %s\n", $module->id, $have;
1484 } elsif ($what eq "r") {
1485 push @result, $module->id;
1486 next if $seen{$file}++;
1487 } elsif ($what eq "u") {
1488 push @result, $module->id;
1489 next if $seen{$file}++;
1490 next if $file =~ /^Contact/;
1492 unless ($headerdone++){
1493 $CPAN::Frontend->myprint("\n");
1494 $CPAN::Frontend->myprint(sprintf(
1496 "Package namespace",
1502 $latest = substr($latest,0,8) if length($latest) > 8;
1503 $have = substr($have,0,8) if length($have) > 8;
1504 $CPAN::Frontend->myprint(sprintf $sprintf, $module->id, $have, $latest, $file);
1505 $need{$module->id}++;
1509 $CPAN::Frontend->myprint("No modules found for @args\n");
1510 } elsif ($what eq "r") {
1511 $CPAN::Frontend->myprint("All modules are up to date for @args\n");
1515 if ($version_zeroes) {
1516 my $s_has = $version_zeroes > 1 ? "s have" : " has";
1517 $CPAN::Frontend->myprint(qq{$version_zeroes installed module$s_has }.
1518 qq{a version number of 0\n});
1520 if ($version_undefs) {
1521 my $s_has = $version_undefs > 1 ? "s have" : " has";
1522 $CPAN::Frontend->myprint(qq{$version_undefs installed module$s_has no }.
1523 qq{parseable version number\n});
1529 #-> sub CPAN::Shell::r ;
1531 shift->_u_r_common("r",@_);
1534 #-> sub CPAN::Shell::u ;
1536 shift->_u_r_common("u",@_);
1539 #-> sub CPAN::Shell::autobundle ;
1542 CPAN::Config->load unless $CPAN::Config_loaded++;
1543 my(@bundle) = $self->_u_r_common("a",@_);
1544 my($todir) = MM->catdir($CPAN::Config->{'cpan_home'},"Bundle");
1545 File::Path::mkpath($todir);
1546 unless (-d $todir) {
1547 $CPAN::Frontend->myprint("Couldn't mkdir $todir for some reason\n");
1550 my($y,$m,$d) = (localtime)[5,4,3];
1554 my($me) = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, $c;
1555 my($to) = MM->catfile($todir,"$me.pm");
1557 $me = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, ++$c;
1558 $to = MM->catfile($todir,"$me.pm");
1560 my($fh) = FileHandle->new(">$to") or Carp::croak "Can't open >$to: $!";
1562 "package Bundle::$me;\n\n",
1563 "\$VERSION = '0.01';\n\n",
1567 "Bundle::$me - Snapshot of installation on ",
1568 $Config::Config{'myhostname'},
1571 "\n\n=head1 SYNOPSIS\n\n",
1572 "perl -MCPAN -e 'install Bundle::$me'\n\n",
1573 "=head1 CONTENTS\n\n",
1574 join("\n", @bundle),
1575 "\n\n=head1 CONFIGURATION\n\n",
1577 "\n\n=head1 AUTHOR\n\n",
1578 "This Bundle has been generated automatically ",
1579 "by the autobundle routine in CPAN.pm.\n",
1582 $CPAN::Frontend->myprint("\nWrote bundle file
1586 #-> sub CPAN::Shell::expand ;
1589 my($type,@args) = @_;
1593 if ($arg =~ m|^/(.*)/$|) {
1596 my $class = "CPAN::$type";
1598 if (defined $regex) {
1599 for $obj ( sort {$a->id cmp $b->id} $CPAN::META->all_objects($class)) {
1602 $obj->id =~ /$regex/i
1606 $] < 5.00303 ### provide sort of compatibility with 5.003
1611 $obj->name =~ /$regex/i
1616 if ( $type eq 'Bundle' ) {
1617 $xarg =~ s/^(Bundle::)?(.*)/Bundle::$2/;
1619 if ($CPAN::META->exists($class,$xarg)) {
1620 $obj = $CPAN::META->instance($class,$xarg);
1621 } elsif ($CPAN::META->exists($class,$arg)) {
1622 $obj = $CPAN::META->instance($class,$arg);
1629 return wantarray ? @m : $m[0];
1632 #-> sub CPAN::Shell::format_result ;
1635 my($type,@args) = @_;
1636 @args = '/./' unless @args;
1637 my(@result) = $self->expand($type,@args);
1638 my $result = @result == 1 ?
1639 $result[0]->as_string :
1640 join "", map {$_->as_glimpse} @result;
1641 $result ||= "No objects of type $type found for argument @args\n";
1645 # The only reason for this method is currently to have a reliable
1646 # debugging utility that reveals which output is going through which
1647 # channel. No, I don't like the colors ;-)
1648 sub print_ornamented {
1649 my($self,$what,$ornament) = @_;
1651 my $ornamenting = 0; # turn the colors on
1654 unless (defined &color) {
1655 if ($CPAN::META->has_inst("Term::ANSIColor")) {
1656 import Term::ANSIColor "color";
1658 *color = sub { return "" };
1662 for $line (split /\n/, $what) {
1663 $longest = length($line) if length($line) > $longest;
1665 my $sprintf = "%-" . $longest . "s";
1667 $what =~ s/(.*\n?)//m;
1670 my($nl) = chomp $line ? "\n" : "";
1671 # print "line[$line]ornament[$ornament]sprintf[$sprintf]\n";
1672 print color($ornament), sprintf($sprintf,$line), color("reset"), $nl;
1680 my($self,$what) = @_;
1681 $self->print_ornamented($what, 'bold blue on_yellow');
1685 my($self,$what) = @_;
1686 $self->myprint($what);
1691 my($self,$what) = @_;
1692 $self->print_ornamented($what, 'bold red on_yellow');
1696 my($self,$what) = @_;
1697 $self->print_ornamented($what, 'bold red on_white');
1698 Carp::confess "died";
1702 my($self,$what) = @_;
1703 $self->print_ornamented($what, 'bold red on_white');
1707 #-> sub CPAN::Shell::rematein ;
1708 # RE-adme||MA-ke||TE-st||IN-stall
1711 my($meth,@some) = @_;
1713 if ($meth eq 'force') {
1715 $meth = shift @some;
1717 CPAN->debug("pragma[$pragma]meth[$meth] some[@some]") if $CPAN::DEBUG;
1719 foreach $s (@some) {
1720 CPAN::Queue->new($s);
1722 while ($s = CPAN::Queue->first) {
1726 } elsif ($s =~ m|/|) { # looks like a file
1727 $obj = $CPAN::META->instance('CPAN::Distribution',$s);
1728 } elsif ($s =~ m|^Bundle::|) {
1729 $obj = $CPAN::META->instance('CPAN::Bundle',$s);
1731 $obj = $CPAN::META->instance('CPAN::Module',$s)
1732 if $CPAN::META->exists('CPAN::Module',$s);
1736 qq{pragma[$pragma]meth[$meth]obj[$obj]as_string\[}.
1744 ($] < 5.00303 || $obj->can($pragma)); ###
1748 if ($]>=5.00303 && $obj->can('called_for')) {
1749 $obj->called_for($s);
1751 CPAN::Queue->delete($s) if $obj->$meth(); # if it is more
1754 } elsif ($CPAN::META->exists('CPAN::Author',$s)) {
1755 $obj = $CPAN::META->instance('CPAN::Author',$s);
1756 $CPAN::Frontend->myprint(
1758 "Don't be silly, you can't $meth ",
1764 ->myprint(qq{Warning: Cannot $meth $s, }.
1765 qq{don\'t know what it is.
1770 to find objects with similar identifiers.
1773 CPAN::Queue->delete_first($s);
1777 #-> sub CPAN::Shell::force ;
1778 sub force { shift->rematein('force',@_); }
1779 #-> sub CPAN::Shell::get ;
1780 sub get { shift->rematein('get',@_); }
1781 #-> sub CPAN::Shell::readme ;
1782 sub readme { shift->rematein('readme',@_); }
1783 #-> sub CPAN::Shell::make ;
1784 sub make { shift->rematein('make',@_); }
1785 #-> sub CPAN::Shell::test ;
1786 sub test { shift->rematein('test',@_); }
1787 #-> sub CPAN::Shell::install ;
1788 sub install { shift->rematein('install',@_); }
1789 #-> sub CPAN::Shell::clean ;
1790 sub clean { shift->rematein('clean',@_); }
1791 #-> sub CPAN::Shell::look ;
1792 sub look { shift->rematein('look',@_); }
1796 #-> sub CPAN::FTP::ftp_get ;
1798 my($class,$host,$dir,$file,$target) = @_;
1800 qq[Going to fetch file [$file] from dir [$dir]
1801 on host [$host] as local [$target]\n]
1803 my $ftp = Net::FTP->new($host);
1804 return 0 unless defined $ftp;
1805 $ftp->debug(1) if $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG;
1806 $class->debug(qq[Going to ->login("anonymous","$Config::Config{'cf_email'}")\n]);
1807 unless ( $ftp->login("anonymous",$Config::Config{'cf_email'}) ){
1808 warn "Couldn't login on $host";
1811 unless ( $ftp->cwd($dir) ){
1812 warn "Couldn't cwd $dir";
1816 $class->debug(qq[Going to ->get("$file","$target")\n]) if $CPAN::DEBUG;
1817 unless ( $ftp->get($file,$target) ){
1818 warn "Couldn't fetch $file from $host\n";
1821 $ftp->quit; # it's ok if this fails
1825 # If more accuracy is wanted/needed, Chris Leach sent me this patch...
1827 # leach,> *** /install/perl/live/lib/CPAN.pm- Wed Sep 24 13:08:48 1997
1828 # leach,> --- /tmp/cp Wed Sep 24 13:26:40 1997
1829 # leach,> ***************
1830 # leach,> *** 1562,1567 ****
1831 # leach,> --- 1562,1580 ----
1832 # leach,> return 1 if substr($url,0,4) eq "file";
1833 # leach,> return 1 unless $url =~ m|://([^/]+)|;
1834 # leach,> my $host = $1;
1835 # leach,> + my $proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'};
1836 # leach,> + if ($proxy) {
1837 # leach,> + $proxy =~ m|://([^/:]+)|;
1838 # leach,> + $proxy = $1;
1839 # leach,> + my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'};
1840 # leach,> + if ($noproxy) {
1841 # leach,> + if ($host !~ /$noproxy$/) {
1842 # leach,> + $host = $proxy;
1844 # leach,> + } else {
1845 # leach,> + $host = $proxy;
1848 # leach,> require Net::Ping;
1849 # leach,> return 1 unless $Net::Ping::VERSION >= 2;
1853 # this is quite optimistic and returns one on several occasions where
1854 # inappropriate. But this does no harm. It would do harm if we were
1855 # too pessimistic (as I was before the http_proxy
1857 my($self,$url) = @_;
1858 return 1; # we can't simply roll our own, firewalls may break ping
1859 return 0 unless $url;
1860 return 1 if substr($url,0,4) eq "file";
1861 return 1 unless $url =~ m|^(\w+)://([^/]+)|;
1862 my $proxytype = $1 . "_proxy"; # ftp_proxy or http_proxy
1864 return 1 if $CPAN::Config->{$proxytype} || $ENV{$proxytype};
1866 return 1 unless $Net::Ping::VERSION >= 2;
1868 # 1.3101 had it different: only if the first eval raised an
1869 # exception we tried it with TCP. Now we are happy if icmp wins
1870 # the order and return, we don't even check for $@. Thanks to
1871 # thayer@uis.edu for the suggestion.
1872 eval {$p = Net::Ping->new("icmp");};
1873 return 1 if $p && ref($p) && $p->ping($host, 10);
1874 eval {$p = Net::Ping->new("tcp");};
1875 $CPAN::Frontend->mydie($@) if $@;
1876 return $p->ping($host, 10);
1879 #-> sub CPAN::FTP::localize ;
1880 # sorry for the ugly code here, I'll clean it up as soon as Net::FTP
1883 my($self,$file,$aslocal,$force) = @_;
1885 Carp::croak "Usage: ->localize(cpan_file,as_local_file[,$force])"
1886 unless defined $aslocal;
1887 $self->debug("file[$file] aslocal[$aslocal] force[$force]")
1890 if ($^O eq 'MacOS') {
1891 my($name, $path) = File::Basename::fileparse($aslocal, '');
1892 if (length($name) > 31) {
1893 $name =~ s/(\.(readme(\.(gz|Z))?|(tar\.)?(gz|Z)|tgz|zip|pm\.(gz|Z)))$//;
1895 my $size = 31 - length($suf);
1896 while (length($name) > $size) {
1900 $aslocal = File::Spec->catfile($path, $name);
1904 return $aslocal if -f $aslocal && -r _ && !($force & 1);
1907 rename $aslocal, "$aslocal.bak";
1911 my($aslocal_dir) = File::Basename::dirname($aslocal);
1912 File::Path::mkpath($aslocal_dir);
1913 $CPAN::Frontend->mywarn(qq{Warning: You are not allowed to write into }.
1914 qq{directory "$aslocal_dir".
1915 I\'ll continue, but if you encounter problems, they may be due
1916 to insufficient permissions.\n}) unless -w $aslocal_dir;
1918 # Inheritance is not easier to manage than a few if/else branches
1919 if ($CPAN::META->has_inst('LWP::UserAgent')) {
1920 require LWP::UserAgent;
1922 $Ua = LWP::UserAgent->new;
1924 $Ua->proxy('ftp', $var)
1925 if $var = $CPAN::Config->{'ftp_proxy'} || $ENV{'ftp_proxy'};
1926 $Ua->proxy('http', $var)
1927 if $var = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'};
1929 if $var = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'};
1933 # Try the list of urls for each single object. We keep a record
1934 # where we did get a file from
1935 my(@reordered,$last);
1936 $CPAN::Config->{urllist} ||= [];
1937 $last = $#{$CPAN::Config->{urllist}};
1938 if ($force & 2) { # local cpans probably out of date, don't reorder
1939 @reordered = (0..$last);
1943 (substr($CPAN::Config->{urllist}[$b],0,4) eq "file")
1945 (substr($CPAN::Config->{urllist}[$a],0,4) eq "file")
1956 @levels = ($Themethod, grep {$_ ne $Themethod} qw/easy hard hardest/);
1958 @levels = qw/easy hard hardest/;
1960 @levels = qw/easy/ if $^O eq 'MacOS';
1961 for $level (@levels) {
1962 my $method = "host$level";
1963 my @host_seq = $level eq "easy" ?
1964 @reordered : 0..$last; # reordered has CDROM up front
1965 @host_seq = (0) unless @host_seq;
1966 my $ret = $self->$method(\@host_seq,$file,$aslocal);
1968 $Themethod = $level;
1969 $self->debug("level[$level]") if $CPAN::DEBUG;
1977 qq{Please check, if the URLs I found in your configuration file \(}.
1978 join(", ", @{$CPAN::Config->{urllist}}).
1979 qq{\) are valid. The urllist can be edited.},
1980 qq{E.g. with ``o conf urllist push ftp://myurl/''};
1981 $CPAN::Frontend->myprint(Text::Wrap::wrap("","",@mess). "\n\n");
1983 $CPAN::Frontend->myprint("Cannot fetch $file\n\n");
1985 rename "$aslocal.bak", $aslocal;
1986 $CPAN::Frontend->myprint("Trying to get away with old file:\n" .
1987 $self->ls($aslocal));
1994 my($self,$host_seq,$file,$aslocal) = @_;
1996 HOSTEASY: for $i (@$host_seq) {
1997 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite;
1998 unless ($self->is_reachable($url)) {
1999 $CPAN::Frontend->myprint("Skipping $url (seems to be not reachable)\n");
2003 $url .= "/" unless substr($url,-1) eq "/";
2005 $self->debug("localizing perlish[$url]") if $CPAN::DEBUG;
2006 if ($url =~ /^file:/) {
2008 if ($CPAN::META->has_inst('LWP')) {
2010 my $u = URI::URL->new($url);
2012 } else { # works only on Unix, is poorly constructed, but
2013 # hopefully better than nothing.
2014 # RFC 1738 says fileurl BNF is
2015 # fileurl = "file://" [ host | "localhost" ] "/" fpath
2016 # Thanks to "Mark D. Baushke" <mdb@cisco.com> for
2018 ($l = $url) =~ s|^file://[^/]*/|/|; # discard the host part
2019 $l =~ s|^file:||; # assume they
2022 $l =~ s|^/|| unless -f $l; # e.g. /P:
2024 if ( -f $l && -r _) {
2028 # Maybe mirror has compressed it?
2030 $self->debug("found compressed $l.gz") if $CPAN::DEBUG;
2031 CPAN::Tarzip->gunzip("$l.gz", $aslocal);
2038 if ($CPAN::META->has_inst('LWP')) {
2039 $CPAN::Frontend->myprint("Fetching with LWP:
2043 require LWP::UserAgent;
2044 $Ua = LWP::UserAgent->new;
2046 my $res = $Ua->mirror($url, $aslocal);
2047 if ($res->is_success) {
2050 } elsif ($url !~ /\.gz$/) {
2051 my $gzurl = "$url.gz";
2052 $CPAN::Frontend->myprint("Fetching with LWP:
2055 $res = $Ua->mirror($gzurl, "$aslocal.gz");
2056 if ($res->is_success &&
2057 CPAN::Tarzip->gunzip("$aslocal.gz",$aslocal)
2065 # Alan Burlison informed me that in firewall envs Net::FTP
2066 # can still succeed where LWP fails. So we do not skip
2067 # Net::FTP anymore when LWP is available.
2071 $self->debug("LWP not installed") if $CPAN::DEBUG;
2073 if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
2074 # that's the nice and easy way thanks to Graham
2075 my($host,$dir,$getfile) = ($1,$2,$3);
2076 if ($CPAN::META->has_inst('Net::FTP')) {
2078 $CPAN::Frontend->myprint("Fetching with Net::FTP:
2081 $self->debug("getfile[$getfile]dir[$dir]host[$host]" .
2082 "aslocal[$aslocal]") if $CPAN::DEBUG;
2083 if (CPAN::FTP->ftp_get($host,$dir,$getfile,$aslocal)) {
2087 if ($aslocal !~ /\.gz$/) {
2088 my $gz = "$aslocal.gz";
2089 $CPAN::Frontend->myprint("Fetching with Net::FTP
2092 if (CPAN::FTP->ftp_get($host,
2096 CPAN::Tarzip->gunzip($gz,$aslocal)
2109 my($self,$host_seq,$file,$aslocal) = @_;
2111 # Came back if Net::FTP couldn't establish connection (or
2112 # failed otherwise) Maybe they are behind a firewall, but they
2113 # gave us a socksified (or other) ftp program...
2116 my($devnull) = $CPAN::Config->{devnull} || "";
2118 my($aslocal_dir) = File::Basename::dirname($aslocal);
2119 File::Path::mkpath($aslocal_dir);
2120 HOSTHARD: for $i (@$host_seq) {
2121 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite;
2122 unless ($self->is_reachable($url)) {
2123 $CPAN::Frontend->myprint("Skipping $url (not reachable)\n");
2126 $url .= "/" unless substr($url,-1) eq "/";
2128 my($proto,$host,$dir,$getfile);
2130 # Courtesy Mark Conty mark_conty@cargill.com change from
2131 # if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
2133 if ($url =~ m|^([^:]+)://(.*?)/(.*)/(.*)|) {
2134 # proto not yet used
2135 ($proto,$host,$dir,$getfile) = ($1,$2,$3,$4);
2137 next HOSTHARD; # who said, we could ftp anything except ftp?
2139 $self->debug("localizing funkyftpwise[$url]") if $CPAN::DEBUG;
2141 for $f ('lynx','ncftpget','ncftp') {
2142 next unless exists $CPAN::Config->{$f};
2143 $funkyftp = $CPAN::Config->{$f};
2144 next unless defined $funkyftp;
2145 next if $funkyftp =~ /^\s*$/;
2146 my($want_compressed);
2147 my $aslocal_uncompressed;
2148 ($aslocal_uncompressed = $aslocal) =~ s/\.gz//;
2149 my($source_switch) = "";
2150 $source_switch = " -source" if $funkyftp =~ /\blynx$/;
2151 $source_switch = " -c" if $funkyftp =~ /\bncftp$/;
2152 $CPAN::Frontend->myprint(
2154 Trying with "$funkyftp$source_switch" to get
2157 my($system) = "$funkyftp$source_switch '$url' $devnull > ".
2158 "$aslocal_uncompressed";
2159 $self->debug("system[$system]") if $CPAN::DEBUG;
2161 if (($wstatus = system($system)) == 0
2163 -s $aslocal_uncompressed # lynx returns 0 on my
2164 # system even if it fails
2166 if ($aslocal_uncompressed ne $aslocal) {
2167 # test gzip integrity
2169 CPAN::Tarzip->gtest($aslocal_uncompressed)
2171 rename $aslocal_uncompressed, $aslocal;
2173 CPAN::Tarzip->gzip($aslocal_uncompressed,
2174 "$aslocal_uncompressed.gz");
2179 } elsif ($url !~ /\.gz$/) {
2180 unlink $aslocal_uncompressed if
2181 -f $aslocal_uncompressed && -s _ == 0;
2182 my $gz = "$aslocal.gz";
2183 my $gzurl = "$url.gz";
2184 $CPAN::Frontend->myprint(
2186 Trying with "$funkyftp$source_switch" to get
2189 my($system) = "$funkyftp$source_switch '$url.gz' $devnull > ".
2190 "$aslocal_uncompressed.gz";
2191 $self->debug("system[$system]") if $CPAN::DEBUG;
2193 if (($wstatus = system($system)) == 0
2195 -s "$aslocal_uncompressed.gz"
2197 # test gzip integrity
2198 if (CPAN::Tarzip->gtest("$aslocal_uncompressed.gz")) {
2199 CPAN::Tarzip->gunzip("$aslocal_uncompressed.gz",
2202 rename $aslocal_uncompressed, $aslocal;
2207 unlink "$aslocal_uncompressed.gz" if
2208 -f "$aslocal_uncompressed.gz";
2211 my $estatus = $wstatus >> 8;
2212 my $size = -f $aslocal ? ", left\n$aslocal with size ".-s _ : "";
2213 $CPAN::Frontend->myprint(qq{
2214 System call "$system"
2215 returned status $estatus (wstat $wstatus)$size
2223 my($self,$host_seq,$file,$aslocal) = @_;
2226 my($aslocal_dir) = File::Basename::dirname($aslocal);
2227 File::Path::mkpath($aslocal_dir);
2228 HOSTHARDEST: for $i (@$host_seq) {
2229 unless (length $CPAN::Config->{'ftp'}) {
2230 $CPAN::Frontend->myprint("No external ftp command available\n\n");
2233 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite;
2234 unless ($self->is_reachable($url)) {
2235 $CPAN::Frontend->myprint("Skipping $url (not reachable)\n");
2238 $url .= "/" unless substr($url,-1) eq "/";
2240 $self->debug("localizing ftpwise[$url]") if $CPAN::DEBUG;
2241 unless ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
2244 my($host,$dir,$getfile) = ($1,$2,$3);
2247 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
2248 $ctime,$blksize,$blocks) = stat($aslocal);
2249 $timestamp = $mtime ||= 0;
2250 my($netrc) = CPAN::FTP::netrc->new;
2251 my($verbose) = $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG ? " -v" : "";
2252 my $targetfile = File::Basename::basename($aslocal);
2258 map("cd $_", split "/", $dir), # RFC 1738
2260 "get $getfile $targetfile",
2263 if (! $netrc->netrc) {
2264 CPAN->debug("No ~/.netrc file found") if $CPAN::DEBUG;
2265 } elsif ($netrc->hasdefault || $netrc->contains($host)) {
2266 CPAN->debug(sprintf("hasdef[%d]cont($host)[%d]",
2268 $netrc->contains($host))) if $CPAN::DEBUG;
2269 if ($netrc->protected) {
2270 $CPAN::Frontend->myprint(qq{
2271 Trying with external ftp to get
2273 As this requires some features that are not thoroughly tested, we\'re
2274 not sure, that we get it right....
2278 $self->talk_ftp("$CPAN::Config->{'ftp'}$verbose $host",
2280 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
2281 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal);
2283 if ($mtime > $timestamp) {
2284 $CPAN::Frontend->myprint("GOT $aslocal\n");
2288 $CPAN::Frontend->myprint("Hmm... Still failed!\n");
2291 $CPAN::Frontend->mywarn(qq{Your $netrcfile is not }.
2292 qq{correctly protected.\n});
2295 $CPAN::Frontend->mywarn("Your ~/.netrc neither contains $host
2296 nor does it have a default entry\n");
2299 # OK, they don't have a valid ~/.netrc. Use 'ftp -n'
2300 # then and login manually to host, using e-mail as
2302 $CPAN::Frontend->myprint(qq{Issuing "$CPAN::Config->{'ftp'}$verbose -n"\n});
2306 "user anonymous $Config::Config{'cf_email'}"
2308 $self->talk_ftp("$CPAN::Config->{'ftp'}$verbose -n", @dialog);
2309 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
2310 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal);
2312 if ($mtime > $timestamp) {
2313 $CPAN::Frontend->myprint("GOT $aslocal\n");
2317 $CPAN::Frontend->myprint("Bad luck... Still failed!\n");
2319 $CPAN::Frontend->myprint("Can't access URL $url.\n\n");
2325 my($self,$command,@dialog) = @_;
2326 my $fh = FileHandle->new;
2327 $fh->open("|$command") or die "Couldn't open ftp: $!";
2328 foreach (@dialog) { $fh->print("$_\n") }
2329 $fh->close; # Wait for process to complete
2331 my $estatus = $wstatus >> 8;
2332 $CPAN::Frontend->myprint(qq{
2333 Subprocess "|$command"
2334 returned status $estatus (wstat $wstatus)
2338 # find2perl needs modularization, too, all the following is stolen
2342 my($self,$name) = @_;
2343 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm,
2344 $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name);
2346 my($perms,%user,%group);
2350 $blocks = int(($blocks + 1) / 2);
2353 $blocks = int(($sizemm + 1023) / 1024);
2356 if (-f _) { $perms = '-'; }
2357 elsif (-d _) { $perms = 'd'; }
2358 elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; }
2359 elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; }
2360 elsif (-p _) { $perms = 'p'; }
2361 elsif (-S _) { $perms = 's'; }
2362 else { $perms = 'l'; $pname .= ' -> ' . readlink($_); }
2364 my(@rwx) = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx');
2365 my(@moname) = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
2366 my $tmpmode = $mode;
2367 my $tmp = $rwx[$tmpmode & 7];
2369 $tmp = $rwx[$tmpmode & 7] . $tmp;
2371 $tmp = $rwx[$tmpmode & 7] . $tmp;
2372 substr($tmp,2,1) =~ tr/-x/Ss/ if -u _;
2373 substr($tmp,5,1) =~ tr/-x/Ss/ if -g _;
2374 substr($tmp,8,1) =~ tr/-x/Tt/ if -k _;
2377 my $user = $user{$uid} || $uid; # too lazy to implement lookup
2378 my $group = $group{$gid} || $gid;
2380 my($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime);
2382 my($moname) = $moname[$mon];
2383 if (-M _ > 365.25 / 2) {
2384 $timeyear = $year + 1900;
2387 $timeyear = sprintf("%02d:%02d", $hour, $min);
2390 sprintf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n",
2404 package CPAN::FTP::netrc;
2408 my $file = MM->catfile($ENV{HOME},".netrc");
2410 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
2411 $atime,$mtime,$ctime,$blksize,$blocks)
2416 my($fh,@machines,$hasdefault);
2418 $fh = FileHandle->new or die "Could not create a filehandle";
2420 if($fh->open($file)){
2421 $protected = ($mode & 077) == 0;
2423 NETRC: while (<$fh>) {
2424 my(@tokens) = split " ", $_;
2425 TOKEN: while (@tokens) {
2426 my($t) = shift @tokens;
2427 if ($t eq "default"){
2431 last TOKEN if $t eq "macdef";
2432 if ($t eq "machine") {
2433 push @machines, shift @tokens;
2438 $file = $hasdefault = $protected = "";
2442 'mach' => [@machines],
2444 'hasdefault' => $hasdefault,
2445 'protected' => $protected,
2449 sub hasdefault { shift->{'hasdefault'} }
2450 sub netrc { shift->{'netrc'} }
2451 sub protected { shift->{'protected'} }
2453 my($self,$mach) = @_;
2454 for ( @{$self->{'mach'}} ) {
2455 return 1 if $_ eq $mach;
2460 package CPAN::Complete;
2463 my($text, $line, $start, $end) = @_;
2464 my(@perlret) = cpl($text, $line, $start);
2465 # find longest common match. Can anybody show me how to peruse
2466 # T::R::Gnu to have this done automatically? Seems expensive.
2467 return () unless @perlret;
2468 my($newtext) = $text;
2469 for (my $i = length($text)+1;;$i++) {
2470 last unless length($perlret[0]) && length($perlret[0]) >= $i;
2471 my $try = substr($perlret[0],0,$i);
2472 my @tries = grep {substr($_,0,$i) eq $try} @perlret;
2473 # warn "try[$try]tries[@tries]";
2474 if (@tries == @perlret) {
2480 ($newtext,@perlret);
2483 #-> sub CPAN::Complete::cpl ;
2485 my($word,$line,$pos) = @_;
2489 CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
2491 if ($line =~ s/^(force\s*)//) {
2499 ! a b d h i m o q r u autobundle clean
2500 make test install force reload look
2503 } elsif ( $line !~ /^[\!abdhimorutl]/ ) {
2505 } elsif ($line =~ /^a\s/) {
2506 @return = cplx('CPAN::Author',$word);
2507 } elsif ($line =~ /^b\s/) {
2508 @return = cplx('CPAN::Bundle',$word);
2509 } elsif ($line =~ /^d\s/) {
2510 @return = cplx('CPAN::Distribution',$word);
2511 } elsif ($line =~ /^([mru]|make|clean|test|install|readme|look)\s/ ) {
2512 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word));
2513 } elsif ($line =~ /^i\s/) {
2514 @return = cpl_any($word);
2515 } elsif ($line =~ /^reload\s/) {
2516 @return = cpl_reload($word,$line,$pos);
2517 } elsif ($line =~ /^o\s/) {
2518 @return = cpl_option($word,$line,$pos);
2525 #-> sub CPAN::Complete::cplx ;
2527 my($class, $word) = @_;
2528 grep /^\Q$word\E/, map { $_->id } $CPAN::META->all_objects($class);
2531 #-> sub CPAN::Complete::cpl_any ;
2535 cplx('CPAN::Author',$word),
2536 cplx('CPAN::Bundle',$word),
2537 cplx('CPAN::Distribution',$word),
2538 cplx('CPAN::Module',$word),
2542 #-> sub CPAN::Complete::cpl_reload ;
2544 my($word,$line,$pos) = @_;
2546 my(@words) = split " ", $line;
2547 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
2548 my(@ok) = qw(cpan index);
2549 return @ok if @words == 1;
2550 return grep /^\Q$word\E/, @ok if @words == 2 && $word;
2553 #-> sub CPAN::Complete::cpl_option ;
2555 my($word,$line,$pos) = @_;
2557 my(@words) = split " ", $line;
2558 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
2559 my(@ok) = qw(conf debug);
2560 return @ok if @words == 1;
2561 return grep /^\Q$word\E/, @ok if @words == 2 && length($word);
2563 } elsif ($words[1] eq 'index') {
2565 } elsif ($words[1] eq 'conf') {
2566 return CPAN::Config::cpl(@_);
2567 } elsif ($words[1] eq 'debug') {
2568 return sort grep /^\Q$word\E/, sort keys %CPAN::DEBUG, 'all';
2572 package CPAN::Index;
2574 #-> sub CPAN::Index::force_reload ;
2577 $CPAN::Index::last_time = 0;
2581 #-> sub CPAN::Index::reload ;
2583 my($cl,$force) = @_;
2586 # XXX check if a newer one is available. (We currently read it
2587 # from time to time)
2588 for ($CPAN::Config->{index_expire}) {
2589 $_ = 0.001 unless $_ && $_ > 0.001;
2591 return if $last_time + $CPAN::Config->{index_expire}*86400 > $time
2596 my $needshort = $^O eq "dos";
2598 $cl->rd_authindex($cl
2600 "authors/01mailrc.txt.gz",
2602 File::Spec->catfile('authors', '01mailrc.gz') :
2603 File::Spec->catfile('authors', '01mailrc.txt.gz'),
2606 $debug = "timing reading 01[".($t2 - $time)."]";
2608 return if $CPAN::Signal; # this is sometimes lengthy
2609 $cl->rd_modpacks($cl
2611 "modules/02packages.details.txt.gz",
2613 File::Spec->catfile('modules', '02packag.gz') :
2614 File::Spec->catfile('modules', '02packages.details.txt.gz'),
2617 $debug .= "02[".($t2 - $time)."]";
2619 return if $CPAN::Signal; # this is sometimes lengthy
2622 "modules/03modlist.data.gz",
2624 File::Spec->catfile('modules', '03mlist.gz') :
2625 File::Spec->catfile('modules', '03modlist.data.gz'),
2628 $debug .= "03[".($t2 - $time)."]";
2630 CPAN->debug($debug) if $CPAN::DEBUG;
2633 #-> sub CPAN::Index::reload_x ;
2635 my($cl,$wanted,$localname,$force) = @_;
2636 $force |= 2; # means we're dealing with an index here
2637 CPAN::Config->load; # we should guarantee loading wherever we rely
2639 $localname ||= $wanted;
2640 my $abs_wanted = MM->catfile($CPAN::Config->{'keep_source_where'},
2644 -M $abs_wanted < $CPAN::Config->{'index_expire'} &&
2647 my $s = $CPAN::Config->{'index_expire'} == 1 ? "" : "s";
2648 $cl->debug(qq{$abs_wanted younger than $CPAN::Config->{'index_expire'} }.
2649 qq{day$s. I\'ll use that.});
2652 $force |= 1; # means we're quite serious about it.
2654 return CPAN::FTP->localize($wanted,$abs_wanted,$force);
2657 #-> sub CPAN::Index::rd_authindex ;
2659 my($cl, $index_target) = @_;
2661 return unless defined $index_target;
2662 $CPAN::Frontend->myprint("Going to read $index_target\n");
2663 # my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
2664 # while ($_ = $fh->READLINE) {
2667 tie *FH, CPAN::Tarzip, $index_target;
2669 push @lines, split /\012/ while <FH>;
2671 my($userid,$fullname,$email) =
2672 m/alias\s+(\S+)\s+\"([^\"\<]+)\s+\<([^\>]+)\>\"/;
2673 next unless $userid && $fullname && $email;
2675 # instantiate an author object
2676 my $userobj = $CPAN::META->instance('CPAN::Author',$userid);
2677 $userobj->set('FULLNAME' => $fullname, 'EMAIL' => $email);
2678 return if $CPAN::Signal;
2683 my($self,$dist) = @_;
2684 $dist = $self->{'id'} unless defined $dist;
2685 my($ret) = $dist =~ m|(?:\w/\w\w/)?([^/]+)/|;
2689 #-> sub CPAN::Index::rd_modpacks ;
2691 my($cl, $index_target) = @_;
2693 return unless defined $index_target;
2694 $CPAN::Frontend->myprint("Going to read $index_target\n");
2695 my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
2697 while ($_ = $fh->READLINE) {
2699 my @ls = map {"$_\n"} split /\n/, $_;
2700 unshift @ls, "\n" x length($1) if /^(\n+)/;
2704 my $shift = shift(@lines);
2705 last if $shift =~ /^\s*$/;
2709 my($mod,$version,$dist) = split;
2710 ### $version =~ s/^\+//;
2712 # if it is a bundle, instatiate a bundle object
2713 my($bundle,$id,$userid);
2715 if ($mod eq 'CPAN' &&
2717 CPAN::Queue->exists('Bundle::CPAN') ||
2718 CPAN::Queue->exists('CPAN')
2722 if ($version > $CPAN::VERSION){
2723 $CPAN::Frontend->myprint(qq{
2724 There\'s a new CPAN.pm version (v$version) available!
2725 You might want to try
2726 install Bundle::CPAN
2728 without quitting the current session. It should be a seamless upgrade
2729 while we are running...
2732 $CPAN::Frontend->myprint(qq{\n});
2734 last if $CPAN::Signal;
2735 } elsif ($mod =~ /^Bundle::(.*)/) {
2740 $id = $CPAN::META->instance('CPAN::Bundle',$mod);
2741 # warn "made mod[$mod]a bundle";
2742 # Let's make it a module too, because bundles have so much
2743 # in common with modules
2744 $CPAN::META->instance('CPAN::Module',$mod);
2745 # warn "made mod[$mod]a module";
2747 # This "next" makes us faster but if the job is running long, we ignore
2748 # rereads which is bad. So we have to be a bit slower again.
2749 # } elsif ($CPAN::META->exists('CPAN::Module',$mod)) {
2754 # instantiate a module object
2755 $id = $CPAN::META->instance('CPAN::Module',$mod);
2758 if ($id->cpan_file ne $dist){
2759 $userid = $cl->userid($dist);
2761 'CPAN_USERID' => $userid,
2762 'CPAN_VERSION' => $version,
2763 'CPAN_FILE' => $dist
2767 # instantiate a distribution object
2768 unless ($CPAN::META->exists('CPAN::Distribution',$dist)) {
2769 $CPAN::META->instance(
2770 'CPAN::Distribution' => $dist
2772 'CPAN_USERID' => $userid
2776 return if $CPAN::Signal;
2781 #-> sub CPAN::Index::rd_modlist ;
2783 my($cl,$index_target) = @_;
2784 return unless defined $index_target;
2785 $CPAN::Frontend->myprint("Going to read $index_target\n");
2786 my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
2789 while ($_ = $fh->READLINE) {
2791 my @ls = map {"$_\n"} split /\n/, $_;
2792 unshift @ls, "\n" x length($1) if /^(\n+)/;
2796 my $shift = shift(@eval);
2797 if ($shift =~ /^Date:\s+(.*)/){
2798 return if $date_of_03 eq $1;
2801 last if $shift =~ /^\s*$/;
2804 push @eval, q{CPAN::Modulelist->data;};
2806 my($comp) = Safe->new("CPAN::Safe1");
2807 my($eval) = join("", @eval);
2808 my $ret = $comp->reval($eval);
2809 Carp::confess($@) if $@;
2810 return if $CPAN::Signal;
2812 my $obj = $CPAN::META->instance(CPAN::Module,$_);
2813 $obj->set(%{$ret->{$_}});
2814 return if $CPAN::Signal;
2818 package CPAN::InfoObj;
2820 #-> sub CPAN::InfoObj::new ;
2821 sub new { my $this = bless {}, shift; %$this = @_; $this }
2823 #-> sub CPAN::InfoObj::set ;
2825 my($self,%att) = @_;
2826 my(%oldatt) = %$self;
2827 %$self = (%oldatt, %att);
2830 #-> sub CPAN::InfoObj::id ;
2831 sub id { shift->{'ID'} }
2833 #-> sub CPAN::InfoObj::as_glimpse ;
2837 my $class = ref($self);
2838 $class =~ s/^CPAN:://;
2839 push @m, sprintf "%-15s %s\n", $class, $self->{ID};
2843 #-> sub CPAN::InfoObj::as_string ;
2847 my $class = ref($self);
2848 $class =~ s/^CPAN:://;
2849 push @m, $class, " id = $self->{ID}\n";
2850 for (sort keys %$self) {
2853 if ($_ eq "CPAN_USERID") {
2854 $extra .= " (".$self->author;
2855 my $email; # old perls!
2856 if ($email = $CPAN::META->instance(CPAN::Author,
2859 $extra .= " <$email>";
2861 $extra .= " <no email>";
2865 if (ref($self->{$_}) eq "ARRAY") { # language interface? XXX
2866 push @m, sprintf " %-12s %s%s\n", $_, "@{$self->{$_}}", $extra;
2868 push @m, sprintf " %-12s %s%s\n", $_, $self->{$_}, $extra;
2874 #-> sub CPAN::InfoObj::author ;
2877 $CPAN::META->instance(CPAN::Author,$self->{CPAN_USERID})->fullname;
2882 require Data::Dumper;
2883 Data::Dumper::Dumper($self);
2886 package CPAN::Author;
2888 #-> sub CPAN::Author::as_glimpse ;
2892 my $class = ref($self);
2893 $class =~ s/^CPAN:://;
2894 push @m, sprintf "%-15s %s (%s)\n", $class, $self->{ID}, $self->fullname;
2898 # Dead code, I would have liked to have,,, but it was never reached,,,
2901 # return "Don't be silly, you can't make $self->{FULLNAME} ;-)\n";
2904 #-> sub CPAN::Author::fullname ;
2905 sub fullname { shift->{'FULLNAME'} }
2908 #-> sub CPAN::Author::email ;
2909 sub email { shift->{'EMAIL'} }
2911 package CPAN::Distribution;
2913 #-> sub CPAN::Distribution::called_for ;
2916 $self->{'CALLED_FOR'} = $id if defined $id;
2917 return $self->{'CALLED_FOR'};
2920 #-> sub CPAN::Distribution::get ;
2925 exists $self->{'build_dir'} and push @e,
2926 "Unwrapped into directory $self->{'build_dir'}";
2927 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
2932 $CPAN::Config->{keep_source_where},
2935 split("/",$self->{ID})
2938 $self->debug("Doing localize") if $CPAN::DEBUG;
2940 CPAN::FTP->localize("authors/id/$self->{ID}", $local_wanted)
2941 or $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n");
2942 $self->{localfile} = $local_file;
2943 my $builddir = $CPAN::META->{cachemgr}->dir;
2944 $self->debug("doing chdir $builddir") if $CPAN::DEBUG;
2945 chdir $builddir or Carp::croak("Couldn't chdir $builddir: $!");
2948 $self->debug("local_file[$local_file]") if $CPAN::DEBUG;
2949 if ($CPAN::META->has_inst('MD5')) {
2950 $self->debug("MD5 is installed, verifying");
2953 $self->debug("MD5 is NOT installed");
2955 $self->debug("Removing tmp") if $CPAN::DEBUG;
2956 File::Path::rmtree("tmp");
2957 mkdir "tmp", 0755 or Carp::croak "Couldn't mkdir tmp: $!";
2959 $self->debug("Changed directory to tmp") if $CPAN::DEBUG;
2960 if (! $local_file) {
2961 Carp::croak "bad download, can't do anything :-(\n";
2962 } elsif ($local_file =~ /(\.tar\.(gz|Z)|\.tgz)$/i){
2963 $self->untar_me($local_file);
2964 } elsif ( $local_file =~ /\.zip$/i ) {
2965 $self->unzip_me($local_file);
2966 } elsif ( $local_file =~ /\.pm\.(gz|Z)$/) {
2967 $self->pm2dir_me($local_file);
2969 $self->{archived} = "NO";
2971 chdir File::Spec->updir;
2972 if ($self->{archived} ne 'NO') {
2973 chdir File::Spec->catdir(File::Spec->curdir, "tmp");
2974 # Let's check if the package has its own directory.
2975 my $dh = DirHandle->new(File::Spec->curdir)
2976 or Carp::croak("Couldn't opendir .: $!");
2977 my @readdir = grep $_ !~ /^\.\.?$/, $dh->read; ### MAC??
2979 my ($distdir,$packagedir);
2980 if (@readdir == 1 && -d $readdir[0]) {
2981 $distdir = $readdir[0];
2982 $packagedir = MM->catdir($builddir,$distdir);
2983 -d $packagedir and $CPAN::Frontend->myprint("Removing previously used $packagedir\n");
2984 File::Path::rmtree($packagedir);
2985 rename($distdir,$packagedir) or Carp::confess("Couldn't rename $distdir to $packagedir: $!");
2987 my $pragmatic_dir = $self->{'CPAN_USERID'} . '000';
2988 $pragmatic_dir =~ s/\W_//g;
2989 $pragmatic_dir++ while -d "../$pragmatic_dir";
2990 $packagedir = MM->catdir($builddir,$pragmatic_dir);
2991 File::Path::mkpath($packagedir);
2993 for $f (@readdir) { # is already without "." and ".."
2994 my $to = MM->catdir($packagedir,$f);
2995 rename($f,$to) or Carp::confess("Couldn't rename $f to $to: $!");
2998 $self->{'build_dir'} = $packagedir;
2999 chdir File::Spec->updir;
3001 $self->debug("Changed directory to .. (self is $self [".$self->as_string."])")
3003 File::Path::rmtree("tmp");
3004 if ($CPAN::Config->{keep_source_where} =~ /^no/i ){
3005 $CPAN::Frontend->myprint("Going to unlink $local_file\n");
3006 unlink $local_file or Carp::carp "Couldn't unlink $local_file";
3008 my($makefilepl) = MM->catfile($packagedir,"Makefile.PL");
3009 unless (-f $makefilepl) {
3010 my($configure) = MM->catfile($packagedir,"Configure");
3011 if (-f $configure) {
3012 # do we have anything to do?
3013 $self->{'configure'} = $configure;
3014 } elsif (-f MM->catfile($packagedir,"Makefile")) {
3015 $CPAN::Frontend->myprint(qq{
3016 Package comes with a Makefile and without a Makefile.PL.
3017 We\'ll try to build it with that Makefile then.
3019 $self->{writemakefile} = "YES";
3022 my $fh = FileHandle->new(">$makefilepl")
3023 or Carp::croak("Could not open >$makefilepl");
3024 my $cf = $self->called_for || "unknown";
3026 qq{# This Makefile.PL has been autogenerated by the module CPAN.pm
3027 # because there was no Makefile.PL supplied.
3028 # Autogenerated on: }.scalar localtime().qq{
3030 use ExtUtils::MakeMaker;
3031 WriteMakefile(NAME => q[$cf]);
3034 $CPAN::Frontend->myprint(qq{Package comes without Makefile.PL.
3035 Writing one on our own (calling it $cf)\n});
3043 my($self,$local_file) = @_;
3044 $self->{archived} = "tar";
3045 if (CPAN::Tarzip->untar($local_file)) {
3046 $self->{unwrapped} = "YES";
3048 $self->{unwrapped} = "NO";
3053 my($self,$local_file) = @_;
3054 $self->{archived} = "zip";
3055 my $system = "$CPAN::Config->{unzip} $local_file";
3056 if (system($system) == 0) {
3057 $self->{unwrapped} = "YES";
3059 $self->{unwrapped} = "NO";
3064 my($self,$local_file) = @_;
3065 $self->{archived} = "pm";
3066 my $to = File::Basename::basename($local_file);
3067 $to =~ s/\.(gz|Z)$//;
3068 if (CPAN::Tarzip->gunzip($local_file,$to)) {
3069 $self->{unwrapped} = "YES";
3071 $self->{unwrapped} = "NO";
3075 #-> sub CPAN::Distribution::new ;
3077 my($class,%att) = @_;
3079 $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new();
3081 my $this = { %att };
3082 return bless $this, $class;
3085 #-> sub CPAN::Distribution::look ;
3089 if ($^O eq 'MacOS') {
3090 $self->ExtUtils::MM_MacOS::look;
3094 if ( $CPAN::Config->{'shell'} ) {
3095 $CPAN::Frontend->myprint(qq{
3096 Trying to open a subshell in the build directory...
3099 $CPAN::Frontend->myprint(qq{
3100 Your configuration does not define a value for subshells.
3101 Please define it with "o conf shell <your shell>"
3105 my $dist = $self->id;
3106 my $dir = $self->dir or $self->get;
3109 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
3110 my $pwd = CPAN->$getcwd();
3112 $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
3113 system($CPAN::Config->{'shell'}) == 0
3114 or $CPAN::Frontend->mydie("Subprocess shell error");
3118 #-> sub CPAN::Distribution::readme ;
3121 my($dist) = $self->id;
3122 my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/;
3123 $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG;
3127 $CPAN::Config->{keep_source_where},
3130 split("/","$sans.readme"),
3132 $self->debug("Doing localize") if $CPAN::DEBUG;
3133 $local_file = CPAN::FTP->localize("authors/id/$sans.readme",
3135 or $CPAN::Frontend->mydie(qq{No $sans.readme found});;
3137 if ($^O eq 'MacOS') {
3138 ExtUtils::MM_MacOS::launch_file($local_file);
3142 my $fh_pager = FileHandle->new;
3143 local($SIG{PIPE}) = "IGNORE";
3144 $fh_pager->open("|$CPAN::Config->{'pager'}")
3145 or die "Could not open pager $CPAN::Config->{'pager'}: $!";
3146 my $fh_readme = FileHandle->new;
3147 $fh_readme->open($local_file)
3148 or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!});
3149 $CPAN::Frontend->myprint(qq{
3152 with pager "$CPAN::Config->{'pager'}"
3155 $fh_pager->print(<$fh_readme>);
3158 #-> sub CPAN::Distribution::verifyMD5 ;
3163 $self->{MD5_STATUS} ||= "";
3164 $self->{MD5_STATUS} eq "OK" and push @e, "MD5 Checksum was ok";
3165 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
3167 my($lc_want,$lc_file,@local,$basename);
3168 @local = split("/",$self->{ID});
3170 push @local, "CHECKSUMS";
3172 MM->catfile($CPAN::Config->{keep_source_where},
3173 "authors", "id", @local);
3178 $self->MD5_check_file($lc_want)
3180 return $self->{MD5_STATUS} = "OK";
3182 $lc_file = CPAN::FTP->localize("authors/id/@local",
3185 $local[-1] .= ".gz";
3186 $lc_file = CPAN::FTP->localize("authors/id/@local",
3189 $lc_file =~ s/\.gz$//;
3190 CPAN::Tarzip->gunzip("$lc_file.gz",$lc_file);
3195 $self->MD5_check_file($lc_file);
3198 #-> sub CPAN::Distribution::MD5_check_file ;
3199 sub MD5_check_file {
3200 my($self,$chk_file) = @_;
3201 my($cksum,$file,$basename);
3202 $file = $self->{localfile};
3203 $basename = File::Basename::basename($file);
3204 my $fh = FileHandle->new;
3205 if (open $fh, $chk_file){
3208 $eval =~ s/\015?\012/\n/g;
3210 my($comp) = Safe->new();
3211 $cksum = $comp->reval($eval);
3213 rename $chk_file, "$chk_file.bad";
3214 Carp::confess($@) if $@;
3217 Carp::carp "Could not open $chk_file for reading";
3220 if (exists $cksum->{$basename}{md5}) {
3221 $self->debug("Found checksum for $basename:" .
3222 "$cksum->{$basename}{md5}\n") if $CPAN::DEBUG;
3226 my $eq = $self->eq_MD5($fh,$cksum->{$basename}{'md5'});
3228 $fh = CPAN::Tarzip->TIEHANDLE($file);
3231 # had to inline it, when I tied it, the tiedness got lost on
3232 # the call to eq_MD5. (Jan 1998)
3236 while ($fh->READ($ref, 4096) > 0){
3239 my $hexdigest = $md5->hexdigest;
3240 $eq += $hexdigest eq $cksum->{$basename}{'md5-ungz'};
3244 $CPAN::Frontend->myprint("Checksum for $file ok\n");
3245 return $self->{MD5_STATUS} = "OK";
3247 $CPAN::Frontend->myprint(qq{Checksum mismatch for }.
3248 qq{distribution file. }.
3249 qq{Please investigate.\n\n}.
3251 $CPAN::META->instance(
3253 $self->{CPAN_USERID}
3255 my $wrap = qq{I\'d recommend removing $file. It seems to
3256 be a bogus file. Maybe you have configured your \`urllist\' with a
3257 bad URL. Please check this array with \`o conf urllist\', and
3259 $CPAN::Frontend->myprint(Text::Wrap::wrap("","",$wrap));
3260 $CPAN::Frontend->myprint("\n\n");
3264 # close $fh if fileno($fh);
3266 $self->{MD5_STATUS} ||= "";
3267 if ($self->{MD5_STATUS} eq "NIL") {
3268 $CPAN::Frontend->myprint(qq{
3269 No md5 checksum for $basename in local $chk_file.
3272 unlink $chk_file or $CPAN::Frontend->myprint("Could not unlink: $!");
3275 $self->{MD5_STATUS} = "NIL";
3280 #-> sub CPAN::Distribution::eq_MD5 ;
3282 my($self,$fh,$expectMD5) = @_;
3285 while (read($fh, $data, 4096)){
3288 # $md5->addfile($fh);
3289 my $hexdigest = $md5->hexdigest;
3290 # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]";
3291 $hexdigest eq $expectMD5;
3294 #-> sub CPAN::Distribution::force ;
3297 $self->{'force_update'}++;
3299 MD5_STATUS archived build_dir localfile make install unwrapped
3302 delete $self->{$att};
3308 my $file = File::Basename::basename($self->id);
3309 return unless $file =~ m{ ^ perl
3312 (\d{3}(_[0-4][0-9])?)
3319 #-> sub CPAN::Distribution::perl ;
3322 my($perl) = MM->file_name_is_absolute($^X) ? $^X : "";
3323 my $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
3324 my $pwd = CPAN->$getcwd();
3325 my $candidate = MM->catfile($pwd,$^X);
3326 $perl ||= $candidate if MM->maybe_command($candidate);
3328 my ($component,$perl_name);
3329 DIST_PERLNAME: foreach $perl_name ($^X, 'perl', 'perl5', "perl$]") {
3330 PATH_COMPONENT: foreach $component (MM->path(),
3331 $Config::Config{'binexp'}) {
3332 next unless defined($component) && $component;
3333 my($abs) = MM->catfile($component,$perl_name);
3334 if (MM->maybe_command($abs)) {
3344 #-> sub CPAN::Distribution::make ;
3347 $CPAN::Frontend->myprint(sprintf "Running make for %s\n", $self->id);
3348 # Emergency brake if they said install Pippi and get newest perl
3349 if ($self->isa_perl) {
3351 $self->called_for ne $self->id && ! $self->{'force_update'}
3353 $CPAN::Frontend->mydie(sprintf qq{
3354 The most recent version "%s" of the module "%s"
3355 comes with the current version of perl (%s).
3356 I\'ll build that only if you ask for something like
3361 $CPAN::META->instance(
3374 $self->{archived} eq "NO" and push @e,
3375 "Is neither a tar nor a zip archive.";
3377 $self->{unwrapped} eq "NO" and push @e,
3378 "had problems unarchiving. Please build manually";
3380 exists $self->{writemakefile} &&
3381 $self->{writemakefile} =~ m/ ^ NO\s* ( .* ) /sx and push @e,
3382 $1 || "Had some problem writing Makefile";
3384 defined $self->{'make'} and push @e,
3385 "Has already been processed within this session";
3387 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
3389 $CPAN::Frontend->myprint("\n CPAN.pm: Going to build ".$self->id."\n\n");
3390 my $builddir = $self->dir;
3391 chdir $builddir or Carp::croak("Couldn't chdir $builddir: $!");
3392 $self->debug("Changed directory to $builddir") if $CPAN::DEBUG;
3394 if ($^O eq 'MacOS') {
3395 ExtUtils::MM_MacOS::make($self);
3400 if ($self->{'configure'}) {
3401 $system = $self->{'configure'};
3403 my($perl) = $self->perl or die "Couldn\'t find executable perl\n";
3405 # This needs a handler that can be turned on or off:
3406 # $switch = "-MExtUtils::MakeMaker ".
3407 # "-Mops=:default,:filesys_read,:filesys_open,require,chdir"
3409 $system = "$perl $switch Makefile.PL $CPAN::Config->{makepl_arg}";
3411 unless (exists $self->{writemakefile}) {
3412 local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" };
3415 if ($CPAN::Config->{inactivity_timeout}) {
3417 alarm $CPAN::Config->{inactivity_timeout};
3418 local $SIG{CHLD}; # = sub { wait };
3419 if (defined($pid = fork)) {
3424 # note, this exec isn't necessary if
3425 # inactivity_timeout is 0. On the Mac I'd
3426 # suggest, we set it always to 0.
3430 $CPAN::Frontend->myprint("Cannot fork: $!");
3438 $CPAN::Frontend->myprint($@);
3439 $self->{writemakefile} = "NO $@";
3444 $ret = system($system);
3446 $self->{writemakefile} = "NO Makefile.PL returned status $ret";
3450 if (-f "Makefile") {
3451 $self->{writemakefile} = "YES";
3453 $self->{writemakefile} =
3454 qq{NO Makefile.PL refused to write a Makefile.};
3455 # It's probably worth to record the reason, so let's retry
3457 # my $fh = IO::File->new("$system |"); # STDERR? STDIN?
3458 # $self->{writemakefile} .= <$fh>;
3461 return if $CPAN::Signal;
3462 if (my @prereq = $self->needs_prereq){
3464 $CPAN::Frontend->myprint("---- Dependencies detected ".
3465 "during [$id] -----\n");
3467 for my $p (@prereq) {
3468 $CPAN::Frontend->myprint(" $p\n");
3471 if ($CPAN::Config->{prerequisites_policy} eq "follow") {
3473 } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") {
3474 require ExtUtils::MakeMaker;
3475 my $answer = ExtUtils::MakeMaker::prompt(
3476 "Shall I follow them and prepend them to the queue
3477 of modules we are processing right now?", "yes");
3478 $follow = $answer =~ /^\s*y/i;
3481 $CPAN::Frontend->myprint(" Ignoring dependencies on modules @prereq\n");
3484 CPAN::Queue->jumpqueue(@prereq,$id); # requeue yourself
3488 $system = join " ", $CPAN::Config->{'make'}, $CPAN::Config->{make_arg};
3489 if (system($system) == 0) {
3490 $CPAN::Frontend->myprint(" $system -- OK\n");
3491 $self->{'make'} = "YES";
3493 $self->{writemakefile} ||= "YES";
3494 $self->{'make'} = "NO";
3495 $CPAN::Frontend->myprint(" $system -- NOT OK\n");
3499 #-> sub CPAN::Distribution::needs_prereq ;
3502 return unless -f "Makefile"; # we cannot say much
3503 my $fh = FileHandle->new("<Makefile") or
3504 $CPAN::Frontend->mydie("Couldn't open Makefile: $!");
3509 last if /MakeMaker post_initialize section/;
3511 \s+PREREQ_PM\s+=>\s+(.+)
3514 # warn "Found prereq expr[$p]";
3516 while ( $p =~ m/(?:\s)([\w\:]+)=>q\[.*?\],?/g ){
3522 my $mo = $CPAN::META->instance("CPAN::Module",$p);
3523 next if $mo->uptodate;
3524 # it's not needed, so don't push it. We cannot omit this step, because
3525 # if 'force' is in effect, nobody else will check.
3526 if ($self->{have_sponsored}{$p}++){
3527 # We have already sponsored it and for some reason it's still
3528 # not available. So we do nothing. Or what should we do?
3529 # if we push it again, we have a potential infinite loop
3537 #-> sub CPAN::Distribution::test ;
3541 return if $CPAN::Signal;
3542 $CPAN::Frontend->myprint("Running make test\n");
3545 exists $self->{'make'} or push @e,
3546 "Make had some problems, maybe interrupted? Won't test";
3548 exists $self->{'make'} and
3549 $self->{'make'} eq 'NO' and
3550 push @e, "Oops, make had returned bad status";
3552 exists $self->{'build_dir'} or push @e, "Has no own directory";
3553 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
3555 chdir $self->{'build_dir'} or
3556 Carp::croak("Couldn't chdir to $self->{'build_dir'}");
3557 $self->debug("Changed directory to $self->{'build_dir'}")
3560 if ($^O eq 'MacOS') {
3561 ExtUtils::MM_MacOS::make_test($self);
3565 my $system = join " ", $CPAN::Config->{'make'}, "test";
3566 if (system($system) == 0) {
3567 $CPAN::Frontend->myprint(" $system -- OK\n");
3568 $self->{'make_test'} = "YES";
3570 $self->{'make_test'} = "NO";
3571 $CPAN::Frontend->myprint(" $system -- NOT OK\n");
3575 #-> sub CPAN::Distribution::clean ;
3578 $CPAN::Frontend->myprint("Running make clean\n");
3581 exists $self->{'build_dir'} or push @e, "Has no own directory";
3582 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
3584 chdir $self->{'build_dir'} or
3585 Carp::croak("Couldn't chdir to $self->{'build_dir'}");
3586 $self->debug("Changed directory to $self->{'build_dir'}") if $CPAN::DEBUG;
3588 if ($^O eq 'MacOS') {
3589 ExtUtils::MM_MacOS::make_clean($self);
3593 my $system = join " ", $CPAN::Config->{'make'}, "clean";
3594 if (system($system) == 0) {
3595 $CPAN::Frontend->myprint(" $system -- OK\n");
3598 # Hmmm, what to do if make clean failed?
3602 #-> sub CPAN::Distribution::install ;
3606 return if $CPAN::Signal;
3607 $CPAN::Frontend->myprint("Running make install\n");
3610 exists $self->{'build_dir'} or push @e, "Has no own directory";
3612 exists $self->{'make'} or push @e,
3613 "Make had some problems, maybe interrupted? Won't install";
3615 exists $self->{'make'} and
3616 $self->{'make'} eq 'NO' and
3617 push @e, "Oops, make had returned bad status";
3619 push @e, "make test had returned bad status, ".
3620 "won't install without force"
3621 if exists $self->{'make_test'} and
3622 $self->{'make_test'} eq 'NO' and
3623 ! $self->{'force_update'};
3625 exists $self->{'install'} and push @e,
3626 $self->{'install'} eq "YES" ?
3627 "Already done" : "Already tried without success";
3629 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
3631 chdir $self->{'build_dir'} or
3632 Carp::croak("Couldn't chdir to $self->{'build_dir'}");
3633 $self->debug("Changed directory to $self->{'build_dir'}")
3636 if ($^O eq 'MacOS') {
3637 ExtUtils::MM_MacOS::make_install($self);
3641 my $system = join(" ", $CPAN::Config->{'make'},
3642 "install", $CPAN::Config->{make_install_arg});
3643 my($stderr) = $^O =~ /Win/i ? "" : " 2>&1 ";
3644 my($pipe) = FileHandle->new("$system $stderr |");
3647 $CPAN::Frontend->myprint($_);
3652 $CPAN::Frontend->myprint(" $system -- OK\n");
3653 return $self->{'install'} = "YES";
3655 $self->{'install'} = "NO";
3656 $CPAN::Frontend->myprint(" $system -- NOT OK\n");
3657 if ($makeout =~ /permission/s && $> > 0) {
3658 $CPAN::Frontend->myprint(qq{ You may have to su }.
3659 qq{to root to install the package\n});
3664 #-> sub CPAN::Distribution::dir ;
3666 shift->{'build_dir'};
3669 package CPAN::Bundle;
3671 #-> sub CPAN::Bundle::as_string ;
3675 $self->{INST_VERSION} = $self->inst_version;
3676 return $self->SUPER::as_string;
3679 #-> sub CPAN::Bundle::contains ;
3682 my($parsefile) = $self->inst_file;
3683 my($id) = $self->id;
3684 $self->debug("parsefile[$parsefile]id[$id]") if $CPAN::DEBUG;
3685 unless ($parsefile) {
3686 # Try to get at it in the cpan directory
3687 $self->debug("no parsefile") if $CPAN::DEBUG;
3688 Carp::confess "I don't know a $id" unless $self->{CPAN_FILE};
3689 my $dist = $CPAN::META->instance('CPAN::Distribution',
3690 $self->{CPAN_FILE});
3692 $self->debug($dist->as_string) if $CPAN::DEBUG;
3693 my($todir) = $CPAN::Config->{'cpan_home'};
3694 my(@me,$from,$to,$me);
3695 @me = split /::/, $self->id;
3697 $me = MM->catfile(@me);
3698 $from = $self->find_bundle_file($dist->{'build_dir'},$me);
3699 $to = MM->catfile($todir,$me);
3700 File::Path::mkpath(File::Basename::dirname($to));
3701 File::Copy::copy($from, $to)
3702 or Carp::confess("Couldn't copy $from to $to: $!");
3706 my $fh = FileHandle->new;
3708 open($fh,$parsefile) or die "Could not open '$parsefile': $!";
3710 $self->debug("parsefile[$parsefile]") if $CPAN::DEBUG;
3712 $inpod = m/^=(?!head1\s+CONTENTS)/ ? 0 :
3713 m/^=head1\s+CONTENTS/ ? 1 : $inpod;
3718 push @result, (split " ", $_, 2)[0];
3721 delete $self->{STATUS};
3722 $self->{CONTAINS} = join ", ", @result;
3723 $self->debug("CONTAINS[@result]") if $CPAN::DEBUG;
3725 $CPAN::Frontend->mywarn(qq{
3726 The bundle file "$parsefile" may be a broken
3727 bundlefile. It seems not to contain any bundle definition.
3728 Please check the file and if it is bogus, please delete it.
3729 Sorry for the inconvenience.
3735 #-> sub CPAN::Bundle::find_bundle_file
3736 sub find_bundle_file {
3737 my($self,$where,$what) = @_;
3738 $self->debug("where[$where]what[$what]") if $CPAN::DEBUG;
3739 ### The following two lines let CPAN.pm become Bundle/CPAN.pm :-(
3740 ### my $bu = MM->catfile($where,$what);
3741 ### return $bu if -f $bu;
3742 my $manifest = MM->catfile($where,"MANIFEST");
3743 unless (-f $manifest) {
3744 require ExtUtils::Manifest;
3745 my $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
3746 my $cwd = CPAN->$getcwd();
3748 ExtUtils::Manifest::mkmanifest();
3751 my $fh = FileHandle->new($manifest)
3752 or Carp::croak("Couldn't open $manifest: $!");
3755 if ($^O eq 'MacOS') {
3758 $what2 =~ s/:Bundle://;
3761 $what2 =~ s|Bundle/||;
3766 my($file) = /(\S+)/;
3767 if ($file =~ m|\Q$what\E$|) {
3769 # return MM->catfile($where,$bu); # bad
3772 # retry if she managed to
3773 # have no Bundle directory
3774 $bu = $file if $file =~ m|\Q$what2\E$|;
3776 $bu =~ tr|/|:| if $^O eq 'MacOS';
3777 return MM->catfile($where, $bu) if $bu;
3778 Carp::croak("Couldn't find a Bundle file in $where");
3781 #-> sub CPAN::Bundle::inst_file ;
3785 ($me = $self->id) =~ s/.*://;
3786 ## my(@me,$inst_file);
3787 ## @me = split /::/, $self->id;
3788 ## $me[-1] .= ".pm";
3789 $inst_file = MM->catfile($CPAN::Config->{'cpan_home'},
3790 "Bundle", "$me.pm");
3792 return $self->{'INST_FILE'} = $inst_file if -f $inst_file;
3794 $self->SUPER::inst_file;
3795 # return $self->{'INST_FILE'} = $inst_file if -f $inst_file;
3796 # return $self->{'INST_FILE'}; # even if undefined?
3799 #-> sub CPAN::Bundle::rematein ;
3801 my($self,$meth) = @_;
3802 $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG;
3803 my($id) = $self->id;
3804 Carp::croak "Can't $meth $id, don't have an associated bundle file. :-(\n"
3805 unless $self->inst_file || $self->{CPAN_FILE};
3807 for $s ($self->contains) {
3808 my($type) = $s =~ m|/| ? 'CPAN::Distribution' :
3809 $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module';
3810 if ($type eq 'CPAN::Distribution') {
3811 $CPAN::Frontend->mywarn(qq{
3812 The Bundle }.$self->id.qq{ contains
3813 explicitly a file $s.
3817 # possibly noisy action:
3818 my $obj = $CPAN::META->instance($type,$s);
3820 my $success = $obj->can("uptodate") ? $obj->uptodate : 0;
3821 $success ||= $obj->{'install'} && $obj->{'install'} eq "YES";
3822 $fail{$s} = 1 unless $success;
3824 # recap with less noise
3825 if ( $meth eq "install") {
3827 $CPAN::Frontend->myprint(qq{\nBundle summary: }.
3828 qq{The following items seem to }.
3829 qq{have had installation problems:\n});
3830 for $s ($self->contains) {
3831 $CPAN::Frontend->myprint( "$s " ) if $fail{$s};
3833 $CPAN::Frontend->myprint(qq{\n});
3835 $self->{'install'} = 'YES';
3840 #sub CPAN::Bundle::xs_file
3842 # If a bundle contains another that contains an xs_file we have
3843 # here, we just don't bother I suppose
3847 #-> sub CPAN::Bundle::force ;
3848 sub force { shift->rematein('force',@_); }
3849 #-> sub CPAN::Bundle::get ;
3850 sub get { shift->rematein('get',@_); }
3851 #-> sub CPAN::Bundle::make ;
3852 sub make { shift->rematein('make',@_); }
3853 #-> sub CPAN::Bundle::test ;
3854 sub test { shift->rematein('test',@_); }
3855 #-> sub CPAN::Bundle::install ;
3858 $self->rematein('install',@_);
3860 #-> sub CPAN::Bundle::clean ;
3861 sub clean { shift->rematein('clean',@_); }
3863 #-> sub CPAN::Bundle::readme ;
3866 my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{
3867 No File found for bundle } . $self->id . qq{\n}), return;
3868 $self->debug("self[$self] file[$file]") if $CPAN::DEBUG;
3869 $CPAN::META->instance('CPAN::Distribution',$file)->readme;
3872 package CPAN::Module;
3874 #-> sub CPAN::Module::as_glimpse ;
3878 my $class = ref($self);
3879 $class =~ s/^CPAN:://;
3880 push @m, sprintf("%-15s %-15s (%s)\n", $class, $self->{ID},
3885 #-> sub CPAN::Module::as_string ;
3889 CPAN->debug($self) if $CPAN::DEBUG;
3890 my $class = ref($self);
3891 $class =~ s/^CPAN:://;
3893 push @m, $class, " id = $self->{ID}\n";
3894 my $sprintf = " %-12s %s\n";
3895 push @m, sprintf($sprintf, 'DESCRIPTION', $self->{description})
3896 if $self->{description};
3897 my $sprintf2 = " %-12s %s (%s)\n";
3899 if ($userid = $self->{'CPAN_USERID'} || $self->{'userid'}){
3901 if ($author = CPAN::Shell->expand('Author',$userid)) {
3904 if ($m = $author->email) {
3911 $author->fullname . $email
3915 push @m, sprintf($sprintf, 'CPAN_VERSION', $self->{CPAN_VERSION})
3916 if $self->{CPAN_VERSION};
3917 push @m, sprintf($sprintf, 'CPAN_FILE', $self->{CPAN_FILE})
3918 if $self->{CPAN_FILE};
3919 my $sprintf3 = " %-12s %1s%1s%1s%1s (%s,%s,%s,%s)\n";
3920 my(%statd,%stats,%statl,%stati);
3921 @statd{qw,? i c a b R M S,} = qw,unknown idea
3922 pre-alpha alpha beta released mature standard,;
3923 @stats{qw,? m d u n,} = qw,unknown mailing-list
3924 developer comp.lang.perl.* none,;
3925 @statl{qw,? p c + o h,} = qw,unknown perl C C++ other hybrid,;
3926 @stati{qw,? f r O h,} = qw,unknown functions
3927 references+ties object-oriented hybrid,;
3928 $statd{' '} = 'unknown';
3929 $stats{' '} = 'unknown';
3930 $statl{' '} = 'unknown';
3931 $stati{' '} = 'unknown';
3939 $statd{$self->{statd}},
3940 $stats{$self->{stats}},
3941 $statl{$self->{statl}},
3942 $stati{$self->{stati}}
3943 ) if $self->{statd};
3944 my $local_file = $self->inst_file;
3946 $self->{MANPAGE} ||= $self->manpage_headline($local_file);
3949 for $item (qw/MANPAGE CONTAINS/) {
3950 push @m, sprintf($sprintf, $item, $self->{$item})
3951 if exists $self->{$item};
3953 push @m, sprintf($sprintf, 'INST_FILE',
3954 $local_file || "(not installed)");
3955 push @m, sprintf($sprintf, 'INST_VERSION',
3956 $self->inst_version) if $local_file;
3960 sub manpage_headline {
3961 my($self,$local_file) = @_;
3962 my(@local_file) = $local_file;
3963 $local_file =~ s/\.pm$/.pod/;
3964 push @local_file, $local_file;
3966 for $locf (@local_file) {
3967 next unless -f $locf;
3968 my $fh = FileHandle->new($locf)
3969 or $Carp::Frontend->mydie("Couldn't open $locf: $!");
3973 $inpod = m/^=(?!head1\s+NAME)/ ? 0 :
3974 m/^=head1\s+NAME/ ? 1 : $inpod;
3987 #-> sub CPAN::Module::cpan_file ;
3990 CPAN->debug($self->id) if $CPAN::DEBUG;
3991 unless (defined $self->{'CPAN_FILE'}) {
3992 CPAN::Index->reload;
3994 if (exists $self->{'CPAN_FILE'} && defined $self->{'CPAN_FILE'}){
3995 return $self->{'CPAN_FILE'};
3996 } elsif (exists $self->{'userid'} && defined $self->{'userid'}) {
3997 my $fullname = $CPAN::META->instance(CPAN::Author,
3998 $self->{'userid'})->fullname;
3999 my $email = $CPAN::META->instance(CPAN::Author,
4000 $self->{'userid'})->email;
4001 unless (defined $fullname && defined $email) {
4002 return "Contact Author $self->{userid} (Try ``a $self->{userid}'')";
4004 return "Contact Author $fullname <$email>";
4010 *name = \&cpan_file;
4012 #-> sub CPAN::Module::cpan_version ;
4015 $self->{'CPAN_VERSION'} = 'undef'
4016 unless defined $self->{'CPAN_VERSION'}; # I believe this is
4017 # always a bug in the
4018 # index and should be
4020 # but usually I find
4022 # and do not want to
4025 $self->{'CPAN_VERSION'};
4028 #-> sub CPAN::Module::force ;
4031 $self->{'force_update'}++;
4034 #-> sub CPAN::Module::rematein ;
4036 my($self,$meth) = @_;
4037 $self->debug($self->id) if $CPAN::DEBUG;
4038 my $cpan_file = $self->cpan_file;
4039 if ($cpan_file eq "N/A" || $cpan_file =~ /^Contact Author/){
4040 $CPAN::Frontend->mywarn(sprintf qq{
4041 The module %s isn\'t available on CPAN.
4043 Either the module has not yet been uploaded to CPAN, or it is
4044 temporary unavailable. Please contact the author to find out
4045 more about the status. Try ``i %s''.
4052 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
4053 $pack->called_for($self->id);
4054 $pack->force if exists $self->{'force_update'};
4056 delete $self->{'force_update'};
4059 #-> sub CPAN::Module::readme ;
4060 sub readme { shift->rematein('readme') }
4061 #-> sub CPAN::Module::look ;
4062 sub look { shift->rematein('look') }
4063 #-> sub CPAN::Module::get ;
4064 sub get { shift->rematein('get',@_); }
4065 #-> sub CPAN::Module::make ;
4066 sub make { shift->rematein('make') }
4067 #-> sub CPAN::Module::test ;
4068 sub test { shift->rematein('test') }
4069 #-> sub CPAN::Module::uptodate ;
4072 my($latest) = $self->cpan_version;
4074 my($inst_file) = $self->inst_file;
4076 if (defined $inst_file) {
4077 $have = $self->inst_version;
4088 #-> sub CPAN::Module::install ;
4094 not exists $self->{'force_update'}
4096 $CPAN::Frontend->myprint( $self->id. " is up to date.\n");
4100 $self->rematein('install') if $doit;
4102 #-> sub CPAN::Module::clean ;
4103 sub clean { shift->rematein('clean') }
4105 #-> sub CPAN::Module::inst_file ;
4109 @packpath = split /::/, $self->{ID};
4110 $packpath[-1] .= ".pm";
4111 foreach $dir (@INC) {
4112 my $pmfile = MM->catfile($dir,@packpath);
4120 #-> sub CPAN::Module::xs_file ;
4124 @packpath = split /::/, $self->{ID};
4125 push @packpath, $packpath[-1];
4126 $packpath[-1] .= "." . $Config::Config{'dlext'};
4127 foreach $dir (@INC) {
4128 my $xsfile = MM->catfile($dir,'auto',@packpath);
4136 #-> sub CPAN::Module::inst_version ;
4139 my $parsefile = $self->inst_file or return;
4140 local($^W) = 0 if $] < 5.00303 && $ExtUtils::MakeMaker::VERSION < 5.38;
4142 my $have = MM->parse_version($parsefile) || "undef";
4147 package CPAN::Tarzip;
4150 my($class,$read,$write) = @_;
4151 if ($CPAN::META->has_inst("Compress::Zlib")) {
4153 $fhw = FileHandle->new($read)
4154 or $CPAN::Frontend->mydie("Could not open $read: $!");
4155 my $gz = Compress::Zlib::gzopen($write, "wb")
4156 or $CPAN::Frontend->mydie("Cannot gzopen $write: $!\n");
4157 $gz->gzwrite($buffer)
4158 while read($fhw,$buffer,4096) > 0 ;
4163 system("$CPAN::Config->{'gzip'} -c $read > $write")==0;
4168 my($class,$read,$write) = @_;
4169 if ($CPAN::META->has_inst("Compress::Zlib")) {
4171 $fhw = FileHandle->new(">$write")
4172 or $CPAN::Frontend->mydie("Could not open >$write: $!");
4173 my $gz = Compress::Zlib::gzopen($read, "rb")
4174 or $CPAN::Frontend->mydie("Cannot gzopen $read: $!\n");
4175 $fhw->print($buffer)
4176 while $gz->gzread($buffer) > 0 ;
4177 $CPAN::Frontend->mydie("Error reading from $read: $!\n")
4178 if $gz->gzerror != Compress::Zlib::Z_STREAM_END();
4183 system("$CPAN::Config->{'gzip'} -dc $read > $write")==0;
4188 my($class,$read) = @_;
4189 if ($CPAN::META->has_inst("Compress::Zlib")) {
4191 my $gz = Compress::Zlib::gzopen($read, "rb")
4192 or $CPAN::Frontend->mydie("Cannot open $read: $!\n");
4193 1 while $gz->gzread($buffer) > 0 ;
4194 $CPAN::Frontend->mydie("Error reading from $read: $!\n")
4195 if $gz->gzerror != Compress::Zlib::Z_STREAM_END();
4199 return system("$CPAN::Config->{'gzip'} -dt $read")==0;
4204 my($class,$file) = @_;
4206 $class->debug("file[$file]");
4207 if ($CPAN::META->has_inst("Compress::Zlib")) {
4208 my $gz = Compress::Zlib::gzopen($file,"rb") or
4209 die "Could not gzopen $file";
4210 $ret = bless {GZ => $gz}, $class;
4212 my $pipe = "$CPAN::Config->{'gzip'} --decompress --stdout $file |";
4213 my $fh = FileHandle->new($pipe) or die "Could pipe[$pipe]: $!";
4215 $ret = bless {FH => $fh}, $class;
4222 if (exists $self->{GZ}) {
4223 my $gz = $self->{GZ};
4224 my($line,$bytesread);
4225 $bytesread = $gz->gzreadline($line);
4226 return undef if $bytesread <= 0;
4229 my $fh = $self->{FH};
4230 return scalar <$fh>;
4235 my($self,$ref,$length,$offset) = @_;
4236 die "read with offset not implemented" if defined $offset;
4237 if (exists $self->{GZ}) {
4238 my $gz = $self->{GZ};
4239 my $byteread = $gz->gzread($$ref,$length);# 30eaf79e8b446ef52464b5422da328a8
4242 my $fh = $self->{FH};
4243 return read($fh,$$ref,$length);
4249 if (exists $self->{GZ}) {
4250 my $gz = $self->{GZ};
4253 my $fh = $self->{FH};
4260 my($class,$file) = @_;
4261 # had to disable, because version 0.07 seems to be buggy
4262 if (MM->maybe_command($CPAN::Config->{'gzip'})
4264 MM->maybe_command($CPAN::Config->{'tar'})) {
4265 if ($^O =~ /win/i) { # irgggh
4266 # people find the most curious tar binaries that cannot handle
4268 my $system = "$CPAN::Config->{'gzip'} --decompress $file";
4269 if (system($system)==0) {
4270 $CPAN::Frontend->myprint(qq{Uncompressed $file successfully\n});
4272 $CPAN::Frontend->mydie(
4273 qq{Couldn\'t uncompress $file\n}
4277 $system = "$CPAN::Config->{tar} xvf $file";
4278 if (system($system)==0) {
4279 $CPAN::Frontend->myprint(qq{Untarred $file successfully\n});
4281 $CPAN::Frontend->mydie(qq{Couldn\'t untar $file\n});
4285 my $system = "$CPAN::Config->{'gzip'} --decompress --stdout " .
4286 "< $file | $CPAN::Config->{tar} xvf -";
4287 return system($system) == 0;
4289 } elsif ($CPAN::META->has_inst("Archive::Tar")
4291 $CPAN::META->has_inst("Compress::Zlib") ) {
4292 my $tar = Archive::Tar->new($file,1);
4293 $tar->extract($tar->list_files); # I'm pretty sure we have nothing
4294 # that isn't compressed
4296 ExtUtils::MM_MacOS::convert_files([$tar->list_files], 1)
4297 if ($^O eq 'MacOS');
4301 $CPAN::Frontend->mydie(qq{
4302 CPAN.pm needs either both external programs tar and gzip installed or
4303 both the modules Archive::Tar and Compress::Zlib. Neither prerequisite
4304 is available. Can\'t continue.
4317 CPAN - query, download and build perl modules from CPAN sites
4323 perl -MCPAN -e shell;
4329 autobundle, clean, install, make, recompile, test
4333 The CPAN module is designed to automate the make and install of perl
4334 modules and extensions. It includes some searching capabilities and
4335 knows how to use Net::FTP or LWP (or lynx or an external ftp client)
4336 to fetch the raw data from the net.
4338 Modules are fetched from one or more of the mirrored CPAN
4339 (Comprehensive Perl Archive Network) sites and unpacked in a dedicated
4342 The CPAN module also supports the concept of named and versioned
4343 'bundles' of modules. Bundles simplify the handling of sets of
4344 related modules. See BUNDLES below.
4346 The package contains a session manager and a cache manager. There is
4347 no status retained between sessions. The session manager keeps track
4348 of what has been fetched, built and installed in the current
4349 session. The cache manager keeps track of the disk space occupied by
4350 the make processes and deletes excess space according to a simple FIFO
4353 For extended searching capabilities there's a plugin for CPAN available,
4354 L<CPAN::WAIT>. C<CPAN::WAIT> is a full-text search engine that indexes
4355 all documents available in CPAN authors directories. If C<CPAN::WAIT>
4356 is installed on your system, the interactive shell of <CPAN.pm> will
4357 enable the C<wq>, C<wr>, C<wd>, C<wl>, and C<wh> commands which send
4358 queries to the WAIT server that has been configured for your
4361 All other methods provided are accessible in a programmer style and in an
4362 interactive shell style.
4364 =head2 Interactive Mode
4366 The interactive mode is entered by running
4368 perl -MCPAN -e shell
4370 which puts you into a readline interface. You will have the most fun if
4371 you install Term::ReadKey and Term::ReadLine to enjoy both history and
4374 Once you are on the command line, type 'h' and the rest should be
4377 The most common uses of the interactive modes are
4381 =item Searching for authors, bundles, distribution files and modules
4383 There are corresponding one-letter commands C<a>, C<b>, C<d>, and C<m>
4384 for each of the four categories and another, C<i> for any of the
4385 mentioned four. Each of the four entities is implemented as a class
4386 with slightly differing methods for displaying an object.
4388 Arguments you pass to these commands are either strings exactly matching
4389 the identification string of an object or regular expressions that are
4390 then matched case-insensitively against various attributes of the
4391 objects. The parser recognizes a regular expression only if you
4392 enclose it between two slashes.
4394 The principle is that the number of found objects influences how an
4395 item is displayed. If the search finds one item, the result is displayed
4396 as object-E<gt>as_string, but if we find more than one, we display
4397 each as object-E<gt>as_glimpse. E.g.
4401 EMAIL a.koenig@franz.ww.TU-Berlin.DE
4402 FULLNAME Andreas König
4407 EMAIL a.koenig@franz.ww.TU-Berlin.DE
4408 FULLNAME Andreas König
4412 Author ANDYD (Andy Dougherty)
4413 Author MERLYN (Randal L. Schwartz)
4415 =item make, test, install, clean modules or distributions
4417 These commands take any number of arguments and investigates what is
4418 necessary to perform the action. If the argument is a distribution
4419 file name (recognized by embedded slashes), it is processed. If it is
4420 a module, CPAN determines the distribution file in which this module
4421 is included and processes that, following any dependencies named in
4422 the module's Makefile.PL (this behavior is controlled by
4423 I<prerequisites_policy>.)
4425 Any C<make> or C<test> are run unconditionally. An
4427 install <distribution_file>
4429 also is run unconditionally. But for
4433 CPAN checks if an install is actually needed for it and prints
4434 I<module up to date> in the case that the distribution file containing
4435 the module doesnE<39>t need to be updated.
4437 CPAN also keeps track of what it has done within the current session
4438 and doesnE<39>t try to build a package a second time regardless if it
4439 succeeded or not. The C<force> command takes as a first argument the
4440 method to invoke (currently: C<make>, C<test>, or C<install>) and executes the
4441 command from scratch.
4445 cpan> install OpenGL
4446 OpenGL is up to date.
4447 cpan> force install OpenGL
4450 OpenGL-0.4/COPYRIGHT
4453 A C<clean> command results in a
4457 being executed within the distribution file's working directory.
4459 =item readme, look module or distribution
4461 These two commands take only one argument, be it a module or a
4462 distribution file. C<readme> unconditionally runs, displaying the
4463 README of the associated distribution file. C<Look> gets and
4464 untars (if not yet done) the distribution file, changes to the
4465 appropriate directory and opens a subshell process in that directory.
4469 CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are
4470 in the cpan-shell it is intended that you can press C<^C> anytime and
4471 return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell
4472 to clean up and leave the shell loop. You can emulate the effect of a
4473 SIGTERM by sending two consecutive SIGINTs, which usually means by
4474 pressing C<^C> twice.
4476 CPAN.pm ignores a SIGPIPE. If the user sets inactivity_timeout, a
4477 SIGALRM is used during the run of the C<perl Makefile.PL> subprocess.
4483 The commands that are available in the shell interface are methods in
4484 the package CPAN::Shell. If you enter the shell command, all your
4485 input is split by the Text::ParseWords::shellwords() routine which
4486 acts like most shells do. The first word is being interpreted as the
4487 method to be called and the rest of the words are treated as arguments
4488 to this method. Continuation lines are supported if a line ends with a
4493 C<autobundle> writes a bundle file into the
4494 C<$CPAN::Config-E<gt>{cpan_home}/Bundle> directory. The file contains
4495 a list of all modules that are both available from CPAN and currently
4496 installed within @INC. The name of the bundle file is based on the
4497 current date and a counter.
4501 recompile() is a very special command in that it takes no argument and
4502 runs the make/test/install cycle with brute force over all installed
4503 dynamically loadable extensions (aka XS modules) with 'force' in
4504 effect. The primary purpose of this command is to finish a network
4505 installation. Imagine, you have a common source tree for two different
4506 architectures. You decide to do a completely independent fresh
4507 installation. You start on one architecture with the help of a Bundle
4508 file produced earlier. CPAN installs the whole Bundle for you, but
4509 when you try to repeat the job on the second architecture, CPAN
4510 responds with a C<"Foo up to date"> message for all modules. So you
4511 invoke CPAN's recompile on the second architecture and youE<39>re done.
4513 Another popular use for C<recompile> is to act as a rescue in case your
4514 perl breaks binary compatibility. If one of the modules that CPAN uses
4515 is in turn depending on binary compatibility (so you cannot run CPAN
4516 commands), then you should try the CPAN::Nox module for recovery.
4518 =head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution
4520 Although it may be considered internal, the class hierarchy does matter
4521 for both users and programmer. CPAN.pm deals with above mentioned four
4522 classes, and all those classes share a set of methods. A classical
4523 single polymorphism is in effect. A metaclass object registers all
4524 objects of all kinds and indexes them with a string. The strings
4525 referencing objects have a separated namespace (well, not completely
4530 words containing a "/" (slash) Distribution
4531 words starting with Bundle:: Bundle
4532 everything else Module or Author
4534 Modules know their associated Distribution objects. They always refer
4535 to the most recent official release. Developers may mark their releases
4536 as unstable development versions (by inserting an underbar into the
4537 visible version number), so the really hottest and newest distribution
4538 file is not always the default. If a module Foo circulates on CPAN in
4539 both version 1.23 and 1.23_90, CPAN.pm offers a convenient way to
4540 install version 1.23 by saying
4544 This would install the complete distribution file (say
4545 BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would
4546 like to install version 1.23_90, you need to know where the
4547 distribution file resides on CPAN relative to the authors/id/
4548 directory. If the author is BAR, this might be BAR/Foo-1.23_90.tar.gz;
4549 so you would have to say
4551 install BAR/Foo-1.23_90.tar.gz
4553 The first example will be driven by an object of the class
4554 CPAN::Module, the second by an object of class CPAN::Distribution.
4556 =head2 ProgrammerE<39>s interface
4558 If you do not enter the shell, the available shell commands are both
4559 available as methods (C<CPAN::Shell-E<gt>install(...)>) and as
4560 functions in the calling package (C<install(...)>).
4562 There's currently only one class that has a stable interface -
4563 CPAN::Shell. All commands that are available in the CPAN shell are
4564 methods of the class CPAN::Shell. Each of the commands that produce
4565 listings of modules (C<r>, C<autobundle>, C<u>) also return a list of
4566 the IDs of all modules within the list.
4570 =item expand($type,@things)
4572 The IDs of all objects available within a program are strings that can
4573 be expanded to the corresponding real objects with the
4574 C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a
4575 list of CPAN::Module objects according to the C<@things> arguments
4576 given. In scalar context it only returns the first element of the
4579 =item Programming Examples
4581 This enables the programmer to do operations that combine
4582 functionalities that are available in the shell.
4584 # install everything that is outdated on my disk:
4585 perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'
4587 # install my favorite programs if necessary:
4588 for $mod (qw(Net::FTP MD5 Data::Dumper)){
4589 my $obj = CPAN::Shell->expand('Module',$mod);
4593 # list all modules on my disk that have no VERSION number
4594 for $mod (CPAN::Shell->expand("Module","/./")){
4595 next unless $mod->inst_file;
4596 # MakeMaker convention for undefined $VERSION:
4597 next unless $mod->inst_version eq "undef";
4598 print "No VERSION in ", $mod->id, "\n";
4601 Or if you want to write a cronjob to watch The CPAN, you could list
4602 all modules that need updating:
4604 perl -e 'use CPAN; CPAN::Shell->r;'
4606 If you don't want to get any output if all modules are up to date, you
4607 can parse the output of above command for the regular expression
4608 //modules are up to date// and decide to mail the output only if it
4611 If you prefer to do it more in a programmer style in one single
4612 process, maybe something like this suites you better:
4614 # list all modules on my disk that have newer versions on CPAN
4615 for $mod (CPAN::Shell->expand("Module","/./")){
4616 next unless $mod->inst_file;
4617 next if $mod->uptodate;
4618 printf "Module %s is installed as %s, could be updated to %s from CPAN\n",
4619 $mod->id, $mod->inst_version, $mod->cpan_version;
4622 If that gives you too much output every day, you maybe only want to
4623 watch for three modules. You can write
4625 for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")){
4627 as the first line instead. Or you can combine some of the above
4630 # watch only for a new mod_perl module
4631 $mod = CPAN::Shell->expand("Module","mod_perl");
4632 exit if $mod->uptodate;
4633 # new mod_perl arrived, let me know all update recommendations
4638 =head2 Methods in the four Classes
4640 =head2 Cache Manager
4642 Currently the cache manager only keeps track of the build directory
4643 ($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that
4644 deletes complete directories below C<build_dir> as soon as the size of
4645 all directories there gets bigger than $CPAN::Config->{build_cache}
4646 (in MB). The contents of this cache may be used for later
4647 re-installations that you intend to do manually, but will never be
4648 trusted by CPAN itself. This is due to the fact that the user might
4649 use these directories for building modules on different architectures.
4651 There is another directory ($CPAN::Config->{keep_source_where}) where
4652 the original distribution files are kept. This directory is not
4653 covered by the cache manager and must be controlled by the user. If
4654 you choose to have the same directory as build_dir and as
4655 keep_source_where directory, then your sources will be deleted with
4656 the same fifo mechanism.
4660 A bundle is just a perl module in the namespace Bundle:: that does not
4661 define any functions or methods. It usually only contains documentation.
4663 It starts like a perl module with a package declaration and a $VERSION
4664 variable. After that the pod section looks like any other pod with the
4665 only difference being that I<one special pod section> exists starting with
4670 In this pod section each line obeys the format
4672 Module_Name [Version_String] [- optional text]
4674 The only required part is the first field, the name of a module
4675 (e.g. Foo::Bar, ie. I<not> the name of the distribution file). The rest
4676 of the line is optional. The comment part is delimited by a dash just
4677 as in the man page header.
4679 The distribution of a bundle should follow the same convention as
4680 other distributions.
4682 Bundles are treated specially in the CPAN package. If you say 'install
4683 Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all
4684 the modules in the CONTENTS section of the pod. You can install your
4685 own Bundles locally by placing a conformant Bundle file somewhere into
4686 your @INC path. The autobundle() command which is available in the
4687 shell interface does that for you by including all currently installed
4688 modules in a snapshot bundle file.
4690 =head2 Prerequisites
4692 If you have a local mirror of CPAN and can access all files with
4693 "file:" URLs, then you only need a perl better than perl5.003 to run
4694 this module. Otherwise Net::FTP is strongly recommended. LWP may be
4695 required for non-UNIX systems or if your nearest CPAN site is
4696 associated with an URL that is not C<ftp:>.
4698 If you have neither Net::FTP nor LWP, there is a fallback mechanism
4699 implemented for an external ftp command or for an external lynx
4702 =head2 Finding packages and VERSION
4704 This module presumes that all packages on CPAN
4710 declare their $VERSION variable in an easy to parse manner. This
4711 prerequisite can hardly be relaxed because it consumes far too much
4712 memory to load all packages into the running program just to determine
4713 the $VERSION variable. Currently all programs that are dealing with
4714 version use something like this
4716 perl -MExtUtils::MakeMaker -le \
4717 'print MM->parse_version(shift)' filename
4719 If you are author of a package and wonder if your $VERSION can be
4720 parsed, please try the above method.
4724 come as compressed or gzipped tarfiles or as zip files and contain a
4725 Makefile.PL (well, we try to handle a bit more, but without much
4732 The debugging of this module is pretty difficult, because we have
4733 interferences of the software producing the indices on CPAN, of the
4734 mirroring process on CPAN, of packaging, of configuration, of
4735 synchronicity, and of bugs within CPAN.pm.
4737 In interactive mode you can try "o debug" which will list options for
4738 debugging the various parts of the package. The output may not be very
4739 useful for you as it's just a by-product of my own testing, but if you
4740 have an idea which part of the package may have a bug, it's sometimes
4741 worth to give it a try and send me more specific output. You should
4742 know that "o debug" has built-in completion support.
4744 =head2 Floppy, Zip, Offline Mode
4746 CPAN.pm works nicely without network too. If you maintain machines
4747 that are not networked at all, you should consider working with file:
4748 URLs. Of course, you have to collect your modules somewhere first. So
4749 you might use CPAN.pm to put together all you need on a networked
4750 machine. Then copy the $CPAN::Config->{keep_source_where} (but not
4751 $CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind
4752 of a personal CPAN. CPAN.pm on the non-networked machines works nicely
4753 with this floppy. See also below the paragraph about CD-ROM support.
4755 =head1 CONFIGURATION
4757 When the CPAN module is installed, a site wide configuration file is
4758 created as CPAN/Config.pm. The default values defined there can be
4759 overridden in another configuration file: CPAN/MyConfig.pm. You can
4760 store this file in $HOME/.cpan/CPAN/MyConfig.pm if you want, because
4761 $HOME/.cpan is added to the search path of the CPAN module before the
4762 use() or require() statements.
4764 Currently the following keys in the hash reference $CPAN::Config are
4767 build_cache size of cache for directories to build modules
4768 build_dir locally accessible directory to build modules
4769 index_expire after this many days refetch index files
4770 cpan_home local directory reserved for this package
4771 gzip location of external program gzip
4772 inactivity_timeout breaks interactive Makefile.PLs after this
4773 many seconds inactivity. Set to 0 to never break.
4774 inhibit_startup_message
4775 if true, does not print the startup message
4776 keep_source_where directory in which to keep the source (if we do)
4777 make location of external make program
4778 make_arg arguments that should always be passed to 'make'
4779 make_install_arg same as make_arg for 'make install'
4780 makepl_arg arguments passed to 'perl Makefile.PL'
4781 pager location of external program more (or any pager)
4782 prerequisites_policy
4783 what to do if you are missing module prerequisites
4784 ('follow' automatically, 'ask' me, or 'ignore')
4785 scan_cache controls scanning of cache ('atstart' or 'never')
4786 tar location of external program tar
4787 unzip location of external program unzip
4788 urllist arrayref to nearby CPAN sites (or equivalent locations)
4789 wait_list arrayref to a wait server to try (See CPAN::WAIT)
4790 ftp_proxy, } the three usual variables for configuring
4791 http_proxy, } proxy requests. Both as CPAN::Config variables
4792 no_proxy } and as environment variables configurable.
4794 You can set and query each of these options interactively in the cpan
4795 shell with the command set defined within the C<o conf> command:
4799 =item o conf E<lt>scalar optionE<gt>
4801 prints the current value of the I<scalar option>
4803 =item o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>
4805 Sets the value of the I<scalar option> to I<value>
4807 =item o conf E<lt>list optionE<gt>
4809 prints the current value of the I<list option> in MakeMaker's
4812 =item o conf E<lt>list optionE<gt> [shift|pop]
4814 shifts or pops the array in the I<list option> variable
4816 =item o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>
4818 works like the corresponding perl commands.
4822 =head2 Note on urllist parameter's format
4824 urllist parameters are URLs according to RFC 1738. We do a little
4825 guessing if your URL is not compliant, but if you have problems with file URLs, please try the correct format. Either:
4827 file://localhost/whatever/ftp/pub/CPAN/
4831 file:///home/ftp/pub/CPAN/
4833 =head2 urllist parameter has CD-ROM support
4835 The C<urllist> parameter of the configuration table contains a list of
4836 URLs that are to be used for downloading. If the list contains any
4837 C<file> URLs, CPAN always tries to get files from there first. This
4838 feature is disabled for index files. So the recommendation for the
4839 owner of a CD-ROM with CPAN contents is: include your local, possibly
4840 outdated CD-ROM as a C<file> URL at the end of urllist, e.g.
4842 o conf urllist push file://localhost/CDROM/CPAN
4844 CPAN.pm will then fetch the index files from one of the CPAN sites
4845 that come at the beginning of urllist. It will later check for each
4846 module if there is a local copy of the most recent version.
4848 Another peculiarity of urllist is that the site that we could
4849 successfully fetch the last file from automatically gets a preference
4850 token and is tried as the first site for the next request. So if you
4851 add a new site at runtime it may happen that the previously preferred
4852 site will be tried another time. This means that if you want to disallow
4853 a site for the next transfer, it must be explicitly removed from
4858 There's no strong security layer in CPAN.pm. CPAN.pm helps you to
4859 install foreign, unmasked, unsigned code on your machine. We compare
4860 to a checksum that comes from the net just as the distribution file
4861 itself. If somebody has managed to tamper with the distribution file,
4862 they may have as well tampered with the CHECKSUMS file. Future
4863 development will go towards strong authentication.
4867 Most functions in package CPAN are exported per default. The reason
4868 for this is that the primary use is intended for the cpan shell or for
4871 =head1 POPULATE AN INSTALLATION WITH LOTS OF MODULES
4873 To populate a freshly installed perl with my favorite modules is pretty
4874 easiest by maintaining a private bundle definition file. To get a useful
4875 blueprint of a bundle definition file, the command autobundle can be used
4876 on the CPAN shell command line. This command writes a bundle definition
4877 file for all modules that are installed for the currently running perl
4878 interpreter. It's recommended to run this command only once and from then
4879 on maintain the file manually under a private name, say
4880 Bundle/my_bundle.pm. With a clever bundle file you can then simply say
4882 cpan> install Bundle::my_bundle
4884 then answer a few questions and then go out for a coffee.
4886 Maintaining a bundle definition file means to keep track of two
4887 things: dependencies and interactivity. CPAN.pm sometimes fails on
4888 calculating dependencies because not all modules define all MakeMaker
4889 attributes correctly, so a bundle definition file should specify
4890 prerequisites as early as possible. On the other hand, it's a bit
4891 annoying that many distributions need some interactive configuring. So
4892 what I try to accomplish in my private bundle file is to have the
4893 packages that need to be configured early in the file and the gentle
4894 ones later, so I can go out after a few minutes and leave CPAN.pm
4897 =head1 WORKING WITH CPAN.pm BEHIND FIREWALLS
4899 Thanks to Graham Barr for contributing the following paragraphs about
4900 the interaction between perl, and various firewall configurations.
4902 Firewalls can be categorized into three basic types.
4908 This is where the firewall machine runs a web server and to access the
4909 outside world you must do it via the web server. If you set environment
4910 variables like http_proxy or ftp_proxy to a values beginning with http://
4911 or in your web browser you have to set proxy information then you know
4912 you are running a http firewall.
4914 To access servers outside these types of firewalls with perl (even for
4915 ftp) you will need to use LWP.
4919 This where the firewall machine runs a ftp server. This kind of firewall will
4920 only let you access ftp serves outside the firewall. This is usually done by
4921 connecting to the firewall with ftp, then entering a username like
4922 "user@outside.host.com"
4924 To access servers outside these type of firewalls with perl you
4925 will need to use Net::FTP.
4927 =item One way visibility
4929 I say one way visibility as these firewalls try to make themselve look
4930 invisible to the users inside the firewall. An FTP data connection is
4931 normally created by sending the remote server your IP address and then
4932 listening for the connection. But the remote server will not be able to
4933 connect to you because of the firewall. So for these types of firewall
4934 FTP connections need to be done in a passive mode.
4936 There are two that I can think off.
4942 If you are using a SOCKS firewall you will need to compile perl and link
4943 it with the SOCKS library, this is what is normally called a ``socksified''
4944 perl. With this executable you will be able to connect to servers outside
4945 the firewall as if it is not there.
4949 This is the firewall implemented in the Linux kernel, it allows you to
4950 hide a complete network behind one IP address. With this firewall no
4951 special compiling is need as you can access hosts directly.
4959 We should give coverage for B<all> of the CPAN and not just the PAUSE
4960 part, right? In this discussion CPAN and PAUSE have become equal --
4961 but they are not. PAUSE is authors/ and modules/. CPAN is PAUSE plus
4962 the clpa/, doc/, misc/, ports/, src/, scripts/.
4964 Future development should be directed towards a better integration of
4967 If a Makefile.PL requires special customization of libraries, prompts
4968 the user for special input, etc. then you may find CPAN is not able to
4969 build the distribution. In that case, you should attempt the
4970 traditional method of building a Perl module package from a shell.
4974 Andreas König E<lt>a.koenig@kulturbox.deE<gt>
4978 perl(1), CPAN::Nox(3)