diff -pru perl-5.8.7-orig/configpm perl-5.8.7/configpm
--- perl-5.8.7-orig/configpm	Sun Nov 28 07:48:14 2004
+++ perl-5.8.7/configpm	Sat Sep 10 16:32:56 2005
@@ -475,51 +475,59 @@ sub launcher {
 1;
 ENDOFEND
 
-if ($^O eq 'os2') {
-    print CONFIG <<'ENDOFSET';
-my %preconfig;
-if ($OS2::is_aout) {
-    my ($value, $v) = $Config_SH_expanded =~ m/^used_aout='(.*)'\s*$/m;
-    for (split ' ', $value) {
-        ($v) = $Config_SH_expanded =~ m/^aout_$_='(.*)'\s*$/m;
-        $preconfig{$_} = $v eq 'undef' ? undef : $v;
+sub quote_pair ($$) {
+    my ($key, $value) = (shift, shift);
+    # Is it safe on the LHS of => ?
+    my $qkey = $key =~ /^[A-Za-z_][A-Za-z0-9_]*$/ ? $key : "'$key'";
+    if (defined $value) {
+	# Quote things for a '' string
+	$value =~ s!\\!\\\\!g;
+	$value =~ s!'!\\'!g;
+	$value = "'$value'";
+    } else {
+	$value = "undef";
     }
+    "$qkey => $value";
 }
-$preconfig{d_fork} = undef unless $OS2::can_fork; # Some funny cases can't
-sub TIEHASH { bless {%preconfig} }
-ENDOFSET
+
+my ($Extra, %Extra) = '';
+if ($^O eq 'os2') {
+    my $used_aout = fetch_string ({}, 'used_aout');
+    for my $k (split ' ', $used_aout) {
+        my ($v) = fetch_string ({}, "aout_$k");
+	$Extra{$k} = quote_pair($k, $v);
+    }
     # Extract the name of the DLL from the makefile to avoid duplication
     my ($f) = grep -r, qw(GNUMakefile Makefile);
-    my $dll;
+    my $dll = '';
     if (open my $fh, '<', $f) {
 	while (<$fh>) {
 	    $dll = $1, last if /^PERL_DLL_BASE\s*=\s*(\S*)\s*$/;
 	}
+	$dll = "    " . quote_pair(dll_name => $dll) . ",\n" if $dll;
     }
-    print CONFIG <<ENDOFSET if $dll;
-\$preconfig{dll_name} = '$dll';
-ENDOFSET
-} else {
-    print CONFIG <<'ENDOFSET';
+    my $fill_Extra = join '', map { "\t$_,\n" } sort values %Extra;
+    printf CONFIG <<'ENDOFPAT', $dll, $fill_Extra;
+my @Extra = (
+    d_fork => $OS2::can_fork || undef, # Some funny cases can't
+%s);
+if ($OS2::is_aout) {
+    @Extra = ( @Extra,
+%s    );
+}
+ENDOFPAT
+    $Extra = "    \@Extra,\n";
+}
+
+print CONFIG <<'ENDOFSET';
 sub TIEHASH {
     bless $_[1], $_[0];
 }
 ENDOFSET
-}
 
 foreach my $key (keys %Common) {
     my $value = fetch_string ({}, $key);
-    # Is it safe on the LHS of => ?
-    my $qkey = $key =~ /^[A-Za-z_][A-Za-z0-9_]*$/ ? $key : "'$key'";
-    if (defined $value) {
-	# Quote things for a '' string
-	$value =~ s!\\!\\\\!g;
-	$value =~ s!'!\\'!g;
-	$value = "'$value'";
-    } else {
-	$value = "undef";
-    }
-    $Common{$key} = "$qkey => $value";
+    $Common{$key} = quote_pair($key, $value);
 }
 
 if ($Common{byteorder}) {
@@ -527,7 +535,7 @@ if ($Common{byteorder}) {
 }
 my $fast_config = join '', map { "    $_,\n" } sort values %Common;
 
-print CONFIG sprintf <<'ENDOFTIE', $fast_config;
+print CONFIG sprintf <<'ENDOFTIE', $fast_config, $Extra;
 
 sub DESTROY { }
 
@@ -538,7 +546,7 @@ sub AUTOLOAD {
 }
 
 tie %%Config, 'Config', {
-%s};
+%s%s};
 
 1;
 ENDOFTIE
diff -pru perl-5.8.7-orig/emacs/ptags perl-5.8.7/emacs/ptags
--- perl-5.8.7-orig/emacs/ptags	Wed Sep 10 21:12:22 2003
+++ perl-5.8.7/emacs/ptags	Sun Sep  4 14:48:20 2005
@@ -36,7 +36,7 @@ case "$1" in
     echo "Building TAGS with relative paths"
 esac
 
-emacs=`(which emacs || which xemacs) 2>/dev/null`
+emacs=`(which emacs || which xemacs || echo emacs) 2>/dev/null`
 [ -x "$emacs" ] || { echo "can't find emacs or xemacs in PATH"; exit 1; }
 
 # Insure proper order (.h after .c, .xs before .c in subdirs):
diff -pru perl-5.8.7-orig/ext/Cwd/t/cwd.t perl-5.8.7/ext/Cwd/t/cwd.t
--- perl-5.8.7-orig/ext/Cwd/t/cwd.t	Sun Apr  3 08:28:10 2005
+++ perl-5.8.7/ext/Cwd/t/cwd.t	Sun Sep  4 01:37:44 2005
@@ -193,6 +193,9 @@ SKIP: {
   my $file;
   {
     my $root = File::Spec->rootdir;
+    my $abs_root = Cwd::abs_path($root);
+    $abs_root =~ /^([a-zA-Z]:)?\Q$root\E\z/ or skip("abs_dir($root) unexpected: '$abs_root'", 2+$EXTRA_ABSPATH_TESTS);
+    $root = $abs_root;
     local *FH;
     opendir FH, $root or skip("Can't opendir($root): $!", 2+$EXTRA_ABSPATH_TESTS);
     ($file) = grep {-f $_ and not -l $_} map File::Spec->catfile($root, $_), readdir FH;
diff -pru perl-5.8.7-orig/ext/DynaLoader/XSLoader_pm.PL perl-5.8.7/ext/DynaLoader/XSLoader_pm.PL
--- perl-5.8.7-orig/ext/DynaLoader/XSLoader_pm.PL	Sun May 30 02:41:18 2004
+++ perl-5.8.7/ext/DynaLoader/XSLoader_pm.PL	Fri Sep  9 14:24:22 2005
@@ -57,6 +57,9 @@ print OUT <<'EOT' if defined &DynaLoader
     # It may also edit @modparts if required.
     $modfname = &mod2fname(\@modparts) if defined &mod2fname;
 
+    # Some systems can dynaload, but cannot dynaload Perl modules...
+    die 'Dynaloaded Perl modules are not available in this build of Perl' if $OS2::is_static;
+
 EOT
 
 print OUT <<'EOT';
diff -pru perl-5.8.7-orig/ext/IO/t/io_unix.t perl-5.8.7/ext/IO/t/io_unix.t
--- perl-5.8.7-orig/ext/IO/t/io_unix.t	Sun Feb  1 05:30:14 2004
+++ perl-5.8.7/ext/IO/t/io_unix.t	Sun Sep  4 01:46:58 2005
@@ -39,6 +39,13 @@ BEGIN {
 
 $PATH = "sock-$$";
 
+if ($^O eq 'os2') {	# Can't create sockets with relative path...
+  require Cwd;
+  my $d = Cwd::cwd();
+  $d =~ s/^[a-z]://i;
+  $PATH = "$d/$PATH";
+}
+
 # Test if we can create the file within the tmp directory
 if (-e $PATH or not open(TEST, ">$PATH") and $^O ne 'os2') {
     print "1..0 # Skip: cannot open '$PATH' for write\n";
diff -pru perl-5.8.7-orig/lib/CPAN/FirstTime.pm perl-5.8.7/lib/CPAN/FirstTime.pm
--- perl-5.8.7-orig/lib/CPAN/FirstTime.pm	Tue Jul 29 09:05:26 2003
+++ perl-5.8.7/lib/CPAN/FirstTime.pm	Fri Sep  9 14:29:44 2005
@@ -168,7 +168,9 @@ with all the intermediate files\?
     $CPAN::Config->{build_cache} = $ans;
 
     # XXX This the time when we refetch the index files (in days)
-    $CPAN::Config->{'index_expire'} = 1;
+    $default = $CPAN::Config->{index_expire} || 1;
+    $ans = prompt("How often should be refetch the listings of CPAN contents (in days)?", $default);
+    $CPAN::Config->{index_expire} = $ans;
 
     print qq{
 
@@ -380,6 +382,45 @@ Your choice: ",$default);
 Typical frequently used setting:
 
     UNINST=1         to always uninstall potentially conflicting files
+
+Your choice: ",$default);
+
+    #
+    # Should we trust old builds?
+    #
+
+    $default = exists $CPAN::Config->{expire_old_builds} ?
+		exists $CPAN::Config->{expire_old_builds} : -1 ;
+    $CPAN::Config->{expire_old_builds} =
+	prompt("When should we expire old successfully tested builds?
+The value is in days; the value of -1 means 'never rebuild'; the value of 0
+means 'rebuild each time the distribution is tested'.
+
+Your choice: ",$default);
+
+    #
+    # Should we test uptodate modules etc?
+    #
+
+    $default = exists $CPAN::Config->{test_uptodate} ?
+		exists $CPAN::Config->{test_uptodate} : "modules bundles distributions" ;
+    $CPAN::Config->{test_uptodate} =
+	prompt("What kinds of test requests for uptodate modules, bundles, distributions
+should be granted?  The value is a combination of words 'modules', 'bundles',
+'distributions'.
+
+Your choice: ",$default);
+
+    #
+    # Should we install uptodate modules etc?
+    #
+
+    $default = exists $CPAN::Config->{install_uptodate} ?
+		exists $CPAN::Config->{install_uptodate} : "bundles distributions" ;
+    $CPAN::Config->{install_uptodate} =
+	prompt("What kinds of install requests for uptodate modules, bundles, distributions
+should be granted?  The value is a combination of words 'modules', 'bundles',
+'distributions'.
 
 Your choice: ",$default);
 
diff -pru perl-5.8.7-orig/lib/CPAN.pm perl-5.8.7/lib/CPAN.pm
--- perl-5.8.7-orig/lib/CPAN.pm	Sun Sep 21 22:42:58 2003
+++ perl-5.8.7/lib/CPAN.pm	Fri Sep  9 14:30:12 2005
@@ -65,7 +65,7 @@ use vars qw($VERSION @EXPORT $AUTOLOAD $
 @CPAN::ISA = qw(CPAN::Debug Exporter);
 
 @EXPORT = qw(
-	     autobundle bundle expand force get cvs_import
+	     autobundle bundle expand force get cvs_import install_tested
 	     install make readme recompile shell test clean
 	    );
 
@@ -256,11 +256,11 @@ package CPAN::Complete;
 @CPAN::Complete::COMMANDS = sort qw(
 		       ! a b d h i m o q r u autobundle clean dump
 		       make test install force readme reload look
-                       cvs_import ls
+                       cvs_import ls install_tested
 ) unless @CPAN::Complete::COMMANDS;
 
 package CPAN::Index;
-use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03);
+use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03 $BUILD_DIRS);
 @CPAN::Index::ISA = qw(CPAN::Debug);
 $LAST_TIME ||= 0;
 $DATE_OF_03 ||= 0;
@@ -808,6 +808,10 @@ sub cleanup {
 	  $subroutine eq '(eval)';
   }
   return if $ineval && !$End;
+  if ($CPAN::Index::BUILD_DIRS and $CPAN::Index::BUILD_DIRS->{'*new*'}) {
+    CPAN::Index->write_metadata_cache();
+    $CPAN::Frontend->mywarn("List of tested dirs updated.\n");
+  }
   return unless defined $META->{LOCK};
   return unless -f $META->{LOCK};
   $META->savehist;
@@ -843,6 +847,7 @@ sub savehist {
     close $fh;
 }
 
+# Actually, this means: tested, but not installed...
 sub is_tested {
     my($self,$what) = @_;
     $self->{is_tested}{$what} = 1;
@@ -861,8 +866,14 @@ sub set_perl5lib {
     $env = $ENV{PERLLIB} unless defined $env;
     my @env;
     push @env, $env if defined $env and length $env;
-    my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}};
-    $CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n");
+    my @dirs = map {("$_/blib/arch", "$_/blib/lib")} sort keys %{$self->{is_tested}};
+    if (@dirs < 15) {
+       $CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n");
+    } else {
+       my @d = map {s/^\Q$CPAN::Config->{'build_dir'}/%BUILDDIR%/; $_ }
+	 sort keys %{$self->{is_tested}};
+       $CPAN::Frontend->myprint("Prepending blib/arch and blib/lib subdirs of @d to PERL5LIB; %BUILDDIR%=$CPAN::Config->{'build_dir'}.\n");
+    }
     $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env;
 }
 
@@ -1286,8 +1297,8 @@ sub missing_config_data {
          "pager",
          "makepl_arg", "make_arg", "make_install_arg", "urllist",
          "inhibit_startup_message", "ftp_proxy", "http_proxy", "no_proxy",
-         "prerequisites_policy",
-         "cache_metadata",
+         "prerequisites_policy", "expire_old_builds",
+         "cache_metadata", "test_uptodate", "install_uptodate"
         ) {
 	push @miss, $_ unless defined $CPAN::Config->{$_};
     }
@@ -1375,7 +1386,8 @@ Other
  h,?           display this menu       ! perl-code   eval a perl command
  o conf [opt]  set and query options   q             quit the cpan shell
  reload cpan   load CPAN.pm again      reload index  load newer indices
- autobundle    Snapshot                force cmd     unconditionally do cmd});
+ autobundle    Snapshot                force cmd     unconditionally do cmd
+ install_tested Only modules tested with this build of perl});
     }
 }
 
@@ -1494,13 +1506,14 @@ sub o {
 	    $CPAN::Frontend->myprint(":\n");
 	    for $k (sort keys %CPAN::Config::can) {
 		$v = $CPAN::Config::can{$k};
-		$CPAN::Frontend->myprint(sprintf "    %-18s %s\n", $k, $v);
+		# use distinctive whitespace to make the commands stand out
+		$CPAN::Frontend->myprint(sprintf "      %-10s %s\n", $k, $v);
 	    }
 	    $CPAN::Frontend->myprint("\n");
 	    for $k (sort keys %$CPAN::Config) {
                 CPAN::Config->prettyprint($k);
 	    }
-	    $CPAN::Frontend->myprint("\n");
+	    # $CPAN::Frontend->myprint("\n");	# Why second empty line?
 	} elsif (!CPAN::Config->edit(@o_what)) {
 	    $CPAN::Frontend->myprint(qq{Type 'o conf' to view configuration }.
                                      qq{edit options\n\n});
@@ -2047,6 +2060,39 @@ sub rematein {
     setup_output();
     CPAN->debug("pragma[$pragma]meth[$meth] some[@some]") if $CPAN::DEBUG;
 
+    if ($meth eq 'install_tested') {
+	$CPAN::Frontend->mywarn("install_tested() requires no arguments.\n"),
+	    return if @some;
+	CPAN::Index->reload;
+	@some = sort keys %$CPAN::Index::BUILD_DIRS if $CPAN::Index::BUILD_DIRS;
+	$CPAN::Frontend->mywarn("No tested distributions found.\n"),
+	    return unless @some;
+
+	$CPAN::Frontend->myprint("Checking which distributions were tested " .
+				 "with this version of perl...\n");
+	@some = grep CPAN::Shell->expandany($_)->persistent_tested_ok, @some;
+	$CPAN::Frontend->mywarn("No distributions tested with this build of perl found.\n"),
+	    return unless @some;
+
+	$CPAN::Frontend->myprint("Looking for obsolete distributions...\n");
+	my ($dist, @process, %seen);
+	# as in CPAN::Distribution::cpntainsmods; but do one run only
+	for my $mod ($CPAN::META->all_objects("CPAN::Module")) {
+	    my $mod_file = $mod->cpan_file or next;
+	    $seen{$mod_file}++;
+	}
+	for $dist (@some) {
+	    # my @mods = CPAN::Shell->expandany($dist)->containsmods;
+	    # The commented out check is meaningless; see containsmods().
+	    # @mods = grep CPAN::Shell->expandany($_)->cpan_file ne $dist, @mods;
+	    push(@process, $dist), next if $seen{$dist};
+	    $CPAN::Frontend->mywarn("$dist: all the modules are obsolete...\n");
+	}
+	@some = @process;
+	$CPAN::Frontend->mywarn("All the tested distributions are obsolete.\n"),
+		return unless @some;
+	$meth = 'install';
+    }
     # Here is the place to set "test_count" on all involved parties to
     # 0. We then can pass this counter on to the involved
     # distributions and those can refuse to test if test_count > X. In
@@ -2169,6 +2215,8 @@ sub clean   { shift->rematein('clean',@_
 sub look   { shift->rematein('look',@_); }
 #-> sub CPAN::Shell::cvs_import ;
 sub cvs_import   { shift->rematein('cvs_import',@_); }
+#-> sub CPAN::Shell::install_tested ;
+sub install_tested   { shift->rematein('install_tested',@_); }
 
 package CPAN::LWP::UserAgent;
 
@@ -3427,6 +3475,11 @@ sub write_metadata_cache {
     $cache->{last_time} = $LAST_TIME;
     $cache->{DATE_OF_02} = $DATE_OF_02;
     $cache->{PROTOCOL} = PROTOCOL;
+    if ($BUILD_DIRS) {
+	$cache->{'CPAN-sitearchexp'} = $Config::Config{sitearchexp};
+	delete $CPAN::Index::BUILD_DIRS->{'*new*'};
+        $cache->{'CPAN-tested-dirs'} = $BUILD_DIRS;
+    }
     $CPAN::Frontend->myprint("Going to write $metadata_file\n");
     eval { Storable::nstore($cache, $metadata_file) };
     $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
@@ -3487,6 +3540,12 @@ sub read_metadata_cache {
                             # does initialize to some protocol
     $LAST_TIME = $cache->{last_time};
     $DATE_OF_02 = $cache->{DATE_OF_02};
+    # Do not trust build directories of different version of Perl:
+    delete $cache->{'CPAN-tested-dirs'}
+	if exists $cache->{'CPAN-sitearchexp'}
+	    and $cache->{'CPAN-sitearchexp'} ne $Config::Config{sitearchexp};
+    $BUILD_DIRS = $cache->{'CPAN-tested-dirs'}
+	if exists $cache->{'CPAN-tested-dirs'};
     $CPAN::Frontend->myprint("  Database was generated on $DATE_OF_02\n")
 	if defined $DATE_OF_02; # An old cache may not contain DATE_OF_02
     return;
@@ -3832,6 +3891,12 @@ sub called_for {
     return $self->{CALLED_FOR};
 }
 
+#-> sub CPAN::Distribution::containsdists
+sub containsdists {
+    my($self) = @_;
+    $self->{ID};
+}
+
 #-> sub CPAN::Distribution::safe_chdir ;
 sub safe_chdir {
     my($self,$todir) = @_;
@@ -3848,6 +3913,53 @@ sub safe_chdir {
     }
 }
 
+#-> sub CPAN::Distribution::patch ;
+sub patch {
+    my ($self, $name) = (@_);
+    return unless chdir $self->{build_dir};
+    my $dir = File::Spec->catdir($CPAN::Config->{'cpan_home'}, 'patches');
+    return unless -d $dir;
+    my $file = File::Spec->catfile($dir, "diff_$name");
+    my $gzip;
+    unless (-r $file) {
+	$gzip = $CPAN::Config->{gzip};
+	$file = File::Spec->catfile($dir, "diff_$name.gz");
+	unless (-r $file and $gzip) {
+	    $gzip = $CPAN::Config->{bzip2} || 'bzip2';
+	    $file = File::Spec->catfile($dir, "diff_$name.bz2");
+	    return unless -r $file;
+	}
+    }
+    $CPAN::Frontend->myprint("Found patch in `$file'");
+    my $patch = $Config::Config{gnupatch} || 'patch';
+    my $cmd = "$patch -p1";
+    if ($gzip) {
+	$cmd = "$gzip -dc $file | $cmd";
+    } else {
+	$cmd .= " <$file";
+    }
+    local *PATCH;
+    open PATCH, "$cmd |"
+      or $CPAN::Frontend->myprint("can't open pipe from `$cmd': $!") and return;
+    local *PATCHOUT;
+    my $out = 'cpan.patching';
+    open PATCHOUT, ">$out"
+      or $CPAN::Frontend->myprint("can't open $out: $!") and return;
+    my $old = select PATCHOUT;
+    $| = 1;
+    select $old;
+    while (<PATCH>) {
+	print PATCHOUT $_;
+	chomp;
+	$CPAN::Frontend->myprint($_);		# What to do if interactive?
+    }
+    close PATCHOUT
+      or $CPAN::Frontend->myprint("can't close $out: $!");
+    close PATCH
+      or $CPAN::Frontend->myprint("errors running `$cmd': rc=$?") and return;
+    $CPAN::Frontend->myprint("Patching from `$file' successful");
+}
+
 #-> sub CPAN::Distribution::get ;
 sub get {
     my($self) = @_;
@@ -3962,6 +4074,7 @@ sub get {
         my $pragmatic_dir = $userid . '000';
         $pragmatic_dir =~ s/\W_//g;
         $pragmatic_dir++ while -d "../$pragmatic_dir";
+	$distdir = $pragmatic_dir;
         $packagedir = File::Spec->catdir($builddir,$pragmatic_dir);
         $self->debug("packagedir[$packagedir]") if $CPAN::DEBUG;
         File::Path::mkpath($packagedir);
@@ -4039,6 +4152,8 @@ WriteMakefile(NAME => q[$cf]);
             $fh->close;
         }
     }
+    $self->patch($distdir);
+    $self->safe_chdir($builddir);	# Back after patching
 
     return $self;
 }
@@ -4375,12 +4490,16 @@ sub force {
   if ($method && $method eq "install") {
     $self->{"force_update"}++; # name should probably have been force_install
   }
+  if ($method && $method eq "test") {
+    $self->{"force_test"}++; # name should probably have been force_install
+  }
 }
 
 #-> sub CPAN::Distribution::unforce ;
 sub unforce {
   my($self) = @_;
   delete $self->{'force_update'};
+  delete $self->{'force_test'};
 }
 
 #-> sub CPAN::Distribution::isa_perl ;
@@ -4508,6 +4627,8 @@ or
 	local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" };
 	my($ret,$pid);
 	$@ = "";
+	local $ENV{PERL5LIB} = $ENV{PERL5LIB} || $ENV{PERLLIB} || "";
+	$CPAN::META->set_perl5lib;
 	if ($CPAN::Config->{inactivity_timeout}) {
 	    eval {
 		alarm $CPAN::Config->{inactivity_timeout};
@@ -4557,12 +4678,15 @@ or
     }
     if ($CPAN::Signal){
       delete $self->{force_update};
+      delete $self->{force_test};
       return;
     }
-    if (my @prereq = $self->unsat_prereq){
+    if (my @prereq = $self->unsat_prereq('make')){
       return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner
     }
     $system = join " ", $CPAN::Config->{'make'}, $CPAN::Config->{make_arg};
+    local $ENV{PERL5LIB} = $ENV{PERL5LIB} || $ENV{PERLLIB} || "";
+    $CPAN::META->set_perl5lib;
     if (system($system) == 0) {
 	 $CPAN::Frontend->myprint("  $system -- OK\n");
 	 $self->{'make'} = "YES";
@@ -4611,13 +4735,14 @@ of modules we are processing right now?"
 
 #-> sub CPAN::Distribution::unsat_prereq ;
 sub unsat_prereq {
-    my($self) = @_;
+    my($self, $for) = @_;
     my $prereq_pm = $self->prereq_pm or return;
     my(@need);
   NEED: while (my($need_module, $need_version) = each %$prereq_pm) {
         my $nmo = $CPAN::META->instance("CPAN::Module",$need_module);
         # we were too demanding:
         next if $nmo->uptodate;
+        next if $nmo->tested_ok and $for ne 'install';
 
         # if they have not specified a version, we accept any installed one
         if (not defined $need_version or
@@ -4698,16 +4823,115 @@ sub prereq_pm {
   return $self->{prereq_pm} = \%p;
 }
 
+#-> sub CPAN::Distribution::persistent_key ;
+sub persistent_key {	# Identify "sameness" of the Perl
+  my @keys = ($Config::Config{sitearchexp}, $^X);
+  push @keys, (-f $^X ? (stat(_))[9] : '--');	# mtime
+  my $dll = eval {OS2::DLLname()};
+  if (defined $dll) {
+    push @keys, $dll;
+    push @keys, (-f $dll ? (stat(_))[9] : '--');	# mtime
+  }
+  join "\n", @keys, '';
+}
+
+#-> sub CPAN::Distribution::persistent_tested_ok ;
+sub persistent_tested_ok {
+  my($self) = @_;
+  return unless $CPAN::Index::BUILD_DIRS and $CPAN::Config->{expire_old_builds};
+  my $dir = $CPAN::Index::BUILD_DIRS->{$self->id};
+  return unless $dir and -d $dir;
+  my $cpan_test_ok = File::Spec->catfile($dir, 'cpantok#');
+  return unless -f $cpan_test_ok;
+  return if $CPAN::Config->{expire_old_builds} > 0
+	    and -M $cpan_test_ok > $CPAN::Config->{expire_old_builds};
+  {   local *T; local $/;
+      open T, $cpan_test_ok and <T> eq $self->persistent_key and close T
+	  or return;
+  }
+  my $date = -M $cpan_test_ok;
+  eval { File::Find::find sub {
+	  -M $_ >= $date
+	    or warn("File `$File::Find::name' newer than $cpan_test_ok: "
+		    . (-M _) . " days vs. $date days\n"),
+	       die 'update'
+	}, $dir ; 1} and return $dir;
+  warn "error scanning $dir: $@" unless $@ =~ /^update\b/;
+  return;
+}
+
+#-> sub CPAN::Distribution::mark_persistent_tested_ok ;
+sub mark_persistent_tested_ok {
+  my($self) = @_;
+  my $dir = $self->{build_dir};
+  return unless -d $dir;
+  my $cpan_test_ok = File::Spec->catfile($dir, 'cpantok#');
+  local *T;
+  open T, "> $cpan_test_ok" or warn("error touching $cpan_test_ok: $!\n"), return;
+  print T $self->persistent_key;		# Something very build-specific
+  close T or warn("error touching $cpan_test_ok: $!\n"), return;
+  $CPAN::Index::BUILD_DIRS ||= {};
+  $CPAN::Index::BUILD_DIRS->{'*new*'} ||= 0;
+  $CPAN::Index::BUILD_DIRS->{'*new*'}++
+    unless exists $CPAN::Index::BUILD_DIRS->{$self->id}
+      and $CPAN::Index::BUILD_DIRS->{$self->id} eq $dir;
+  $CPAN::Index::BUILD_DIRS->{$self->id} = $dir;
+  return 1;
+}
+
+#-> sub CPAN::Distribution::tested_ok ;
+sub tested_ok {
+    my($self) = @_;
+    exists $self->{'make_test'} and $self->{'make_test'} ne 'NO'
+}
+
+#-> sub CPAN::Distribution::mark_tested_ok ;
+sub mark_tested_ok {
+    my($self) = @_;
+    $self->{make} = "YES";
+    $self->{make_test} = "YES";
+    $self->{writemakefile} = "YES";
+    my $c;
+    foreach $c ($self->containsmods) {
+        my $obj = CPAN::Shell->expandany($c);
+        $obj->mark_tested_ok();
+    }
+}
+
 #-> sub CPAN::Distribution::test ;
 sub test {
-    my($self) = @_;
+    my($self, $for) = @_;
+    if ($self->uptodate
+	and not $CPAN::Config->{test_uptodate} =~ /\bdistributions?\b/
+	and not exists $self->{'force_test'}
+	and not exists $self->{'force_update'}
+       ) {
+	$CPAN::Frontend->myprint( $self->id. " is up to date.\n");
+	return;
+    }
+    my $tested_dir = $self->persistent_tested_ok;
+    if ($tested_dir and not $self->{'force_update'} and not $self->{'force_test'}) {
+	 $self->{'build_dir'} = $tested_dir;
+	 $CPAN::Frontend->myprint("Skipping test for " . $self->id . ": test was successful in $tested_dir\n");
+	 $CPAN::META->is_tested($self->{'build_dir'});
+	 $self->mark_tested_ok();
+	 chdir $self->{'build_dir'} or
+	    Carp::croak("Couldn't chdir to $self->{'build_dir'}");
+	 $self->debug("Changed directory to $self->{'build_dir'}")
+	    if $CPAN::DEBUG;
+	 if (my @prereq = $self->unsat_prereq($for or 'test')){
+	   return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner
+	 }
+	 return;
+    }
     $self->make;
     if ($CPAN::Signal){
       delete $self->{force_update};
+      delete $self->{force_test};
       return;
     }
     $CPAN::Frontend->myprint("Running make test\n");
-    if (my @prereq = $self->unsat_prereq){
+    if (my @prereq = $self->unsat_prereq($for or 'test')){
       return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner
     }
   EXCUSE: {
@@ -4739,13 +4963,14 @@ sub test {
         return;
     }
 
-    local $ENV{PERL5LIB} = $ENV{PERL5LIB} || "";
+    local $ENV{PERL5LIB} = $ENV{PERL5LIB} || $ENV{PERLLIB} || "";
     $CPAN::META->set_perl5lib;
     my $system = join " ", $CPAN::Config->{'make'}, "test";
     if (system($system) == 0) {
 	 $CPAN::Frontend->myprint("  $system -- OK\n");
 	 $CPAN::META->is_tested($self->{'build_dir'});
-	 $self->{make_test} = "YES";
+	 $self->mark_tested_ok();
+	 $self->mark_persistent_tested_ok();
     } else {
 	 $self->{make_test} = "NO";
          $self->{badtestcnt}++;
@@ -4785,6 +5010,7 @@ sub clean {
       # object's state back to where it is after untarring.
 
       delete $self->{force_update};
+      delete $self->{force_test};
       delete $self->{install};
       delete $self->{writemakefile};
       delete $self->{make};
@@ -4806,9 +5032,18 @@ make clean did not succeed, marking dire
 #-> sub CPAN::Distribution::install ;
 sub install {
     my($self) = @_;
-    $self->test;
+    if ($self->uptodate
+	and not $CPAN::Config->{install_uptodate} =~ /\bdistributions?\b/
+	and not exists $self->{'force_test'}
+	and not exists $self->{'force_update'}
+       ) {
+	$CPAN::Frontend->myprint( $self->id. " is up to date.\n");
+	return;
+    }
+    $self->test('install');
     if ($CPAN::Signal){
       delete $self->{force_update};
+      delete $self->{force_test};
       return;
     }
     $CPAN::Frontend->myprint("Running make install\n");
@@ -4871,6 +5106,7 @@ sub install {
 	 }
     }
     delete $self->{force_update};
+    delete $self->{force_test};
 }
 
 #-> sub CPAN::Distribution::dir ;
@@ -4993,6 +5229,22 @@ Sorry for the inconvenience.
     @result;
 }
 
+#-> sub CPAN::Bundle::containsdists
+sub containsdists {
+    my($self) = @_;
+    my($elt, %dists);
+    for $elt ($self->contains) {
+	my $what = CPAN::Shell->expandany($elt);
+	$CPAN::Frontend->mywarn("$self->{ID}: $elt does not point anywhere\n"),
+	    next unless defined $what; 
+	my $dist;
+	for $dist ($what->containsdists) {
+	    $dists{$dist}++;
+	}
+    }
+    keys %dists;
+}
+
 #-> sub CPAN::Bundle::find_bundle_file
 sub find_bundle_file {
     my($self,$where,$what) = @_;
@@ -5118,6 +5370,8 @@ explicitly a file $s.
         }
     }
 
+    $self->mark_tested_ok() if $meth eq "test" and not %fail;
+
     # recap with less noise
     if ( $meth eq "install" ) {
 	if (%fail) {
@@ -5168,12 +5422,28 @@ sub make    { shift->rematein('make',@_)
 #-> sub CPAN::Bundle::test ;
 sub test    {
     my $self = shift;
+    if ($self->uptodate
+	and not $CPAN::Config->{test_uptodate} =~ /\bbundles?\b/
+	and not exists $self->{'force_test'}
+	and not exists $self->{'force_update'}
+       ) {
+	$CPAN::Frontend->myprint( $self->id. " is up to date.\n");
+	return;
+    }
     $self->{badtestcnt} ||= 0;
     $self->rematein('test',@_);
 }
 #-> sub CPAN::Bundle::install ;
 sub install {
   my $self = shift;
+  if ($self->uptodate
+	and not $CPAN::Config->{install_uptodate} =~ /\bbundles?\b/
+	and not exists $self->{'force_test'}
+	and not exists $self->{'force_update'}
+       ) {
+	$CPAN::Frontend->myprint( $self->id. " is up to date.\n");
+	return;
+  }
   $self->rematein('install',@_);
 }
 #-> sub CPAN::Bundle::clean ;
@@ -5186,11 +5456,25 @@ sub uptodate {
     my $c;
     foreach $c ($self->contains) {
         my $obj = CPAN::Shell->expandany($c);
-        return 0 unless $obj->uptodate;
+	# unrecognized stuff makes it not uptodate
+        return 0 unless defined $obj and $obj->uptodate;
     }
     return 1;
 }
 
+#-> sub CPAN::Bundle::mark_tested_ok ;
+sub mark_tested_ok {
+    my($self) = @_;
+    $self->{make_test_all} = "YES";
+}
+
+#-> sub CPAN::Module::tested_ok ;
+sub tested_ok {
+    my($self) = @_;
+    exists $self->{make_test_all} and $self->{make_test_all} eq "YES";
+}
+
+
 #-> sub CPAN::Bundle::readme ;
 sub readme  {
     my($self) = @_;
@@ -5451,6 +5735,12 @@ sub cpan_file {
     }
 }
 
+#-> sub CPAN::Module::containsdists
+sub containsdists {
+    my($self) = @_;
+    $self->cpan_file;
+}
+
 #-> sub CPAN::Module::cpan_version ;
 sub cpan_version {
     my $self = shift;
@@ -5468,6 +5758,7 @@ sub cpan_version {
 sub force {
     my($self) = @_;
     $self->{'force_update'}++;
+    $self->{'force_test'}++;
 }
 
 #-> sub CPAN::Module::rematein ;
@@ -5496,6 +5787,7 @@ sub rematein {
     $pack->$meth();
     $pack->unforce if $pack->can("unforce") && exists $self->{'force_update'};
     delete $self->{'force_update'};
+    delete $self->{'force_test'};
 }
 
 #-> sub CPAN::Module::readme ;
@@ -5515,7 +5807,15 @@ sub make   {
 sub test   {
     my $self = shift;
     $self->{badtestcnt} ||= 0;
-    $self->rematein('test',@_);
+    if ($self->uptodate
+	and not ($CPAN::Config->{test_uptodate} =~ /\bmodules?\b/)
+	and not exists $self->{'force_test'}
+	and not exists $self->{'force_update'}
+       ) {
+	$CPAN::Frontend->myprint( $self->id. " is up to date.\n");
+    } else {
+	$self->rematein('test',@_);
+    }
 }
 #-> sub CPAN::Module::uptodate ;
 sub uptodate {
@@ -5538,13 +5838,23 @@ sub uptodate {
     }
     return;
 }
+#-> sub CPAN::Module::mark_tested_ok ;
+sub mark_tested_ok {
+    my($self) = @_;
+    $self->{make_test_dist} = "YES";
+}
+#-> sub CPAN::Module::tested_ok ;
+sub tested_ok {
+    my($self) = @_;
+    exists $self->{make_test_dist} and $self->{make_test_dist} eq "YES";
+}
 #-> sub CPAN::Module::install ;
 sub install {
     my($self) = @_;
     my($doit) = 0;
     if ($self->uptodate
-	&&
-	not exists $self->{'force_update'}
+	and not $CPAN::Config->{install_uptodate} =~ /\bmodules?\b/
+	and not exists $self->{'force_update'}
        ) {
 	$CPAN::Frontend->myprint( $self->id. " is up to date.\n");
     } else {
@@ -6007,7 +6317,7 @@ Batch mode:
 
   use CPAN;
 
-  autobundle, clean, install, make, recompile, test
+  autobundle, clean, install, make, recompile, test, install_tested
 
 =head1 STATUS
 
@@ -6201,6 +6511,11 @@ perl breaks binary compatibility. If one
 is in turn depending on binary compatibility (so you cannot run CPAN
 commands), then you should try the CPAN::Nox module for recovery.
 
+=head2 install_tested()
+
+Installs all the modules successfully tested with this build of perl.
+[Currently works only with persistent index storage enabled.]
+
 =head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution
 
 Although it may be considered internal, the class hierarchy does matter
@@ -6244,7 +6559,14 @@ CPAN::Module, the second by an object of
 
 If you do not enter the shell, the available shell commands are both
 available as methods (C<CPAN::Shell-E<gt>install(...)>) and as
-functions in the calling package (C<install(...)>).
+functions in the calling package (C<install(...)>).  Before calling low-level
+commands it makes sense to initialize components of CPAN you need, e.g.:
+
+  CPAN::Config->load;
+  CPAN::Index::setup_output;
+  CPAN::Index->reload;
+
+high-level commands do such initializations automatically.
 
 There's currently only one class that has a stable interface -
 CPAN::Shell. All commands that are available in the CPAN shell are
@@ -6767,6 +7089,9 @@ defined:
   cpan_home          local directory reserved for this package
   dontload_hash      anonymous hash: modules in the keys will not be
                      loaded by the CPAN::has_inst() routine
+  expire_old_builds  Timeout in days; after this time the module is rebuild
+		     even if it was successfully build, and the build directory
+		     is still present.  -1 means 'never rebuild'.
   gzip		     location of external program gzip
   histfile           file to maintain history between sessions
   histsize           maximum number of lines to keep in histfile
@@ -6774,6 +7099,8 @@ defined:
                      many seconds inactivity. Set to 0 to never break.
   inhibit_startup_message
                      if true, does not print the startup message
+  install_uptodate   what (of modules/distributions/bundles) to install
+                     even if uptodate
   keep_source_where  directory in which to keep the source (if we do)
   make               location of external make program
   make_arg	     arguments that should always be passed to 'make'
@@ -6789,6 +7116,8 @@ defined:
   tar                location of external program tar
   term_is_latin      if true internal UTF-8 is translated to ISO-8859-1
                      (and nonsense for characters outside latin range)
+  test_uptodate      what (of modules/distributions/bundles) to test
+                     even if uptodate
   unzip              location of external program unzip
   urllist	     arrayref to nearby CPAN sites (or equivalent locations)
   wait_list          arrayref to a wait server to try (See CPAN::WAIT)
diff -pru perl-5.8.7-orig/lib/ExtUtils/MakeMaker.pm perl-5.8.7/lib/ExtUtils/MakeMaker.pm
--- perl-5.8.7-orig/lib/ExtUtils/MakeMaker.pm	Mon Jan  5 14:34:58 2004
+++ perl-5.8.7/lib/ExtUtils/MakeMaker.pm	Fri Sep  9 14:23:30 2005
@@ -617,15 +617,15 @@ sub WriteEmptyMakefile {
 
     my %att = @_;
     my $self = MM->new(\%att);
-    if (-f $self->{MAKEFILE_OLD}) {
-      _unlink($self->{MAKEFILE_OLD}) or 
-        warn "unlink $self->{MAKEFILE_OLD}: $!";
-    }
-    if ( -f $self->{MAKEFILE} ) {
-        _rename($self->{MAKEFILE}, $self->{MAKEFILE_OLD}) or
-          warn "rename $self->{MAKEFILE} => $self->{MAKEFILE_OLD}: $!"
+    my $new = $self->{FIRST_MAKEFILE};
+    my $old = $self->{MAKEFILE_OLD};
+    if (-f $old) {
+      _unlink($old) or warn "unlink $old: $!";
     }
-    open MF, '>'.$self->{MAKEFILE} or die "open $self->{MAKEFILE} for write: $!";
+    if ( -f $new ) {
+        _rename($new, $old) or warn "rename $new => $old: $!"
+    }
+    open MF, '>'.$new or die "open $new for write: $!";
     print MF <<'EOP';
 all:
 
@@ -638,7 +638,7 @@ makemakerdflt:
 test:
 
 EOP
-    close MF or die "close $self->{MAKEFILE} for write: $!";
+    close MF or die "close $new for write: $!";
 }
 
 sub check_manifest {
@@ -863,9 +863,10 @@ sub flush {
     my $self = shift;
     my($chunk);
     local *FH;
-    print STDOUT "Writing $self->{MAKEFILE} for $self->{NAME}\n";
+    my($finalname) = $self->{FIRST_MAKEFILE};
+    print STDOUT "Writing $finalname for $self->{NAME}\n";
 
-    unlink($self->{MAKEFILE}, "MakeMaker.tmp", $Is_VMS ? 'Descrip.MMS' : '');
+    unlink($finalname, "MakeMaker.tmp", $Is_VMS ? 'Descrip.MMS' : ());
     open(FH,">MakeMaker.tmp") or die "Unable to open MakeMaker.tmp: $!";
 
     for $chunk (@{$self->{RESULT}}) {
@@ -873,7 +874,6 @@ sub flush {
     }
 
     close FH;
-    my($finalname) = $self->{MAKEFILE};
     _rename("MakeMaker.tmp", $finalname) or
       warn "rename MakeMaker.tmp => $finalname: $!";
     chmod 0644, $finalname unless $Is_VMS;
diff -pru perl-5.8.7-orig/lib/ExtUtils/Manifest.pm perl-5.8.7/lib/ExtUtils/Manifest.pm
--- perl-5.8.7-orig/lib/ExtUtils/Manifest.pm	Mon Jan  5 14:34:58 2004
+++ perl-5.8.7/lib/ExtUtils/Manifest.pm	Fri Sep  9 14:27:52 2005
@@ -33,6 +33,10 @@ my $Filename = __FILE__;
 $DEFAULT_MSKIP = (File::Spec->splitpath($Filename))[1].
                  "$MANIFEST.SKIP";
 
+eval {
+  $DEFAULT_MSKIP = File::Spec->catpath((File::Spec->splitpath($Filename))[0,1],
+				       "$MANIFEST.SKIP");
+};				# is catpath() always available?
 
 =head1 NAME
 
diff -pru perl-5.8.7-orig/lib/ExtUtils/MM_Unix.pm perl-5.8.7/lib/ExtUtils/MM_Unix.pm
--- perl-5.8.7-orig/lib/ExtUtils/MM_Unix.pm	Mon Jan  5 14:34:58 2004
+++ perl-5.8.7/lib/ExtUtils/MM_Unix.pm	Fri Sep  9 14:25:38 2005
@@ -1944,10 +1944,10 @@ sub init_others {	# --- Initialize Other
     $self->{NOOP}               ||= '$(SHELL) -c true';
     $self->{NOECHO}             = '@' unless defined $self->{NOECHO};
 
-    $self->{MAKEFILE}           ||= 'Makefile';
-    $self->{FIRST_MAKEFILE}     ||= $self->{MAKEFILE};
-    $self->{MAKEFILE_OLD}       ||= '$(FIRST_MAKEFILE).old';
-    $self->{MAKE_APERL_FILE}    ||= '$(FIRST_MAKEFILE).aperl';
+    $self->{FIRST_MAKEFILE}     ||= 'Makefile';
+    $self->{MAKEFILE}           ||= $self->{FIRST_MAKEFILE};
+    $self->{MAKEFILE_OLD}       ||= $self->{MAKEFILE}.'.old';
+    $self->{MAKE_APERL_FILE}    ||= $self->{MAKEFILE}.'.aperl';
 
     $self->{SHELL}              ||= $Config{sh} || '/bin/sh';
 
@@ -2972,7 +2972,7 @@ $(FIRST_MAKEFILE) : Makefile.PL $(CONFIG
 	$(NOECHO) $(ECHO) "==> Please rerun the make command.  <=="
 	false
 
-};
+} if -f 'Makefile.PL';
 
     join "", @m;
 }
@@ -3822,6 +3822,7 @@ sub test {
     }
     # note: 'test.pl' name is also hardcoded in init_dirscan()
     my(@m);
+    my $subdirs_test = ($self->{DIR} && @{$self->{DIR}} ? 'subdirs-test' : '');
     push(@m,"
 TEST_VERBOSE=0
 TEST_TYPE=test_\$(LINKTYPE)
@@ -3831,14 +3832,14 @@ TESTDB_SW = -d
 
 testdb :: testdb_\$(LINKTYPE)
 
-test :: \$(TEST_TYPE)
+test :: \$(TEST_TYPE) $subdirs_test
 ");
 
     if ($Is_Win95) {
-        push(@m, map(qq{\t\$(NOECHO) \$(PERLRUN) -e "exit unless -f shift; chdir '$_'; system q{\$(MAKE) test \$(PASTHRU)}" \$(FIRST_MAKEFILE)\n}, @{$self->{DIR}}));
+        push(@m, map(qq{\nsubdirs-test ::\n\t\$(NOECHO) \$(PERLRUN) -e "exit unless -f shift; chdir '$_'; system q{\$(MAKE) -f \$(FIRST_MAKEFILE) test \$(PASTHRU)}" \$(FIRST_MAKEFILE)\n}, @{$self->{DIR}}));
     }
     else {
-        push(@m, map("\t\$(NOECHO) cd $_ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) test \$(PASTHRU)\n", @{$self->{DIR}}));
+        push(@m, map("\nsubdirs-test ::\n\t\$(NOECHO) cd $_ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) -f \$(FIRST_MAKEFILE) test \$(PASTHRU)\n", @{$self->{DIR}}));
     }
 
     push(@m, "\t\$(NOECHO) \$(ECHO) 'No tests defined for \$(NAME) extension.'\n")
diff -pru perl-5.8.7-orig/lib/Test/Harness/Point.pm perl-5.8.7/lib/Test/Harness/Point.pm
--- perl-5.8.7-orig/lib/Test/Harness/Point.pm	Sun Apr 24 08:49:48 2005
+++ perl-5.8.7/lib/Test/Harness/Point.pm	Fri Sep  9 17:49:40 2005
@@ -133,12 +133,12 @@ sub reason          { my $self = shift; 
 sub is_todo {
     my $self = shift;
     my $type = $self->directive_type;
-    return $type && ( $type eq 'todo' );
+    return $type && ( $type =~ /^todo\b/ );
 }
 sub is_skip {
     my $self = shift;
     my $type = $self->directive_type;
-    return $type && ( $type eq 'skip' );
+    return $type && ( $type =~ /^skip\w*\W?$/ ); # "skipped: reason"
 }
 
 sub diagnostics     {
diff -pru perl-5.8.7-orig/lib/Time/Local.t perl-5.8.7/lib/Time/Local.t
--- perl-5.8.7-orig/lib/Time/Local.t	Wed Apr 27 05:37:30 2005
+++ perl-5.8.7/lib/Time/Local.t	Sun Sep  4 02:02:02 2005
@@ -53,7 +53,8 @@ my @neg_time =
      [ 1950, 04, 12, 9, 30, 31 ],
     );
 
-my $neg_epoch_ok = defined ((localtime(-3600))[0]) ? 1 : 0;
+my $neg_epoch_ok =	# take into account systems with unsigned time too
+    (defined ((localtime(-3600))[0]) and (localtime(-3600))[5] == 69) ? 1 : 0;
 
 # use vmsish 'time' makes for oddness around the Unix epoch
 if ($^O eq 'VMS') { 
diff -pru perl-5.8.7-orig/Makefile.SH perl-5.8.7/Makefile.SH
--- perl-5.8.7-orig/Makefile.SH	Sat Feb  5 07:17:44 2005
+++ perl-5.8.7/Makefile.SH	Sun Sep 11 17:42:22 2005
@@ -780,7 +780,12 @@ lib/lib.pm:	miniperl$(EXE_EXT) $(CONFIGP
 	@-rm -f $@
 	$(LDLIBPTH) ./miniperl -Ilib lib/lib_pm.PL
 
-$(unidatafiles): miniperl$(EXE_EXT) $(CONFIGPM) lib/unicore/mktables
+# Without these .PHONY some make -j4 runs mktables several times in parallel
+.PHONY: do_unidatafiles
+
+$(unidatafiles): do_unidatafiles
+
+do_unidatafiles: miniperl$(EXE_EXT) $(CONFIGPM) lib/unicore/mktables
 	cd lib/unicore && $(LDLIBPTH) ../../miniperl -I../../lib mktables -w
 
 extra.pods: miniperl$(EXE_EXT)
diff -pru perl-5.8.7-orig/os2/Makefile.SHs perl-5.8.7/os2/Makefile.SHs
--- perl-5.8.7-orig/os2/Makefile.SHs	Mon Nov 10 13:54:14 2003
+++ perl-5.8.7/os2/Makefile.SHs	Fri Sep  9 14:24:42 2005
@@ -222,6 +222,10 @@ $(AOUT_DYNALOADER_OBJ) : $(DYNALOADER_OB
 $(DYNALOADER_OBJ) : $(DYNALOADER)
 	@sh -c true
 
+# Quick hack to construct directories necessary for /*/% stuff:
+
+$(aout_static_ext) : $(static_ext) $(dynamic_ext)
+
 $(AOUT_LIBPERL) : $(aout_obj) perl$(AOUT_OBJ_EXT)
 	rm -f $@
 	$(AOUT_AR) rcu $@ perl$(AOUT_OBJ_EXT) $(aout_obj)
diff -pru perl-5.8.7-orig/os2/OS2/Process/Process.pm perl-5.8.7/os2/OS2/Process/Process.pm
--- perl-5.8.7-orig/os2/OS2/Process/Process.pm	Thu Sep 11 14:25:38 2003
+++ perl-5.8.7/os2/OS2/Process/Process.pm	Mon Sep 12 01:08:12 2005
@@ -171,6 +171,7 @@ our @EXPORT = qw(
 	_ClipbrdData_set
 	ClipbrdText
 	ClipbrdText_set
+	MemoryRegionSize
 
 	_MessageBox
 	MessageBox
@@ -415,6 +416,8 @@ sub FocusWindow_set_keep_Zorder ($) {
 sub ClipbrdText (@) {
   my $morph = OS2::localMorphPM->new(0);
   OpenClipbrd();
+  my $data = ClipbrdData @_;
+  return unless $data;
   my $txt = unpack 'p', pack 'L', ClipbrdData @_;
   CloseClipbrd();
   $txt;
@@ -573,6 +576,9 @@ sub kbdhStatus_set {
   _kbdStatus_set($o,$h);
 }
 
+#sub DeleteAtom		{ !WinDeleteAtom(@_) }
+sub DeleteAtom		{ !_DeleteAtom(@_) }
+sub DestroyAtomTable    { !_DestroyAtomTable(@_) }
 
 # Autoload methods go after __END__, and are processed by the autosplit program.
 
@@ -1304,6 +1310,16 @@ This function is normally not needed.  N
 
 gets the path of the directory which corresponds to Desktop.
 
+=item 	InvalidateRect
+
+=item	CreateFrameControl
+
+=back
+
+=head2 Control of the PM clipboard
+
+=over
+
 =item ClipbrdText()
 
 gets the content of the clipboard.  An optional argument is the format
@@ -1319,51 +1335,153 @@ is TRUE, will convert newlines to C<"\r\
 argument is the format of the data in the clipboard (defaults to
 C<CF_TEXT>).
 
-=item 	InvalidateRect
+=item	ClipbrdFmtInfo( [$fmt, [ $hab ] ])
 
-=item	CreateFrameControl
+returns the $fmtInfo flags set by the application which filled the
+clipboard.  $fmt defaults to C<CF_TEXT>.
+
+=item	ClipbrdOwner( [ $hab ] )
+
+Returns window handle of the current clipboard owner.
+
+=item	ClipbrdViewer( [ $hab ] )
+
+Returns window handle of the current clipboard viewer.
+
+=item	ClipbrdData( [$fmt, [ $hab ] ])
+
+Returns a handle to clipboard data of the given format as an integer.
+Format defaults to C<CF_TEXT> (in this case the handle is a memory address).
+
+=item	OpenClipbrd( [ $hab ] )
+
+claim read access to the clipboard.  May need a message queue to operate.
+May block until other processes finish dealing with clipboard.
+
+=item	CloseClipbrd( [ $hab ] )
+
+Allow other processes access to clipboard.
+Clipboard should be opened before calling this function.
+
+=item	ClipbrdData_set($data, [$convert_nl, [$fmt, [$fmtInfo, [ $hab] ] ] ] )
+
+Sets the clipboard data of format given by atom $fmt.  Format defaults to
+CF_TEXT.
+
+$fmtInfo should qualify what $data is; it should be either C<CFI_POINTER>,
+or C<CFI_HANDLE> (possibly qualified by C<CFI_OWNERFREE> and C<CFI_OWNERDRAW>
+flags).  It defaults to C<CFI_POINTER> for $fmt being C<CF_TEXT> or
+C<CF_DSPTEXT>, otherwise defaults to C<CFI_HANDLE>.  If format is
+C<CFI_POINTER>, $data should contain the string to copy to clipboard;
+otherwise it should be an integer handle.
 
-=item	ClipbrdFmtInfo
+If $convert_nl is TRUE (the default), C<"\n"> in $data are converted to
+C<"\r\n"> pairs if $fmt is C<CFI_POINTER> (as is the convention for text
+format of the clipboard) unless they are already in such a pair.
 
-=item	ClipbrdOwner
+=item	_ClipbrdData_set($data, [$fmt, [$fmtInfo, [ $hab] ] ] )
 
-=item	ClipbrdViewer
+Sets the clipboard data of format given by atom $fmt.  Format defaults to
+CF_TEXT.  $data should be an address (in givable unnamed shared memory which
+should not be accessed or manipulated after this call) or a handle in a form
+of an integer.
 
-=item	ClipbrdData
+$fmtInfo has the same semantic as for ClipbrdData_set().
 
-=item	OpenClipbrd
+=item	ClipbrdOwner_set( $hwnd, [ $hab ] )
 
-=item	CloseClipbrd
+Sets window handle of the current clipboard owner (window which gets messages
+when content of clipboard is retrieved).
 
-=item	ClipbrdData_set
+=item	ClipbrdViewer_set( $hwnd, [ $hab ] )
 
-=item	ClipbrdOwner_set
+Sets window handle of the current clipboard owner (window which gets messages
+when content of clipboard is changed).
 
-=item	ClipbrdViewer_set
+=item	EnumClipbrdFmts($fmt [, $hab])
 
-=item	EnumClipbrdFmts
+Returns the atom for the format of clipboard after $fmt.  If $fmt is 0, returns
+the first format of clipboard.  Returns 0 if $fmt is the last format.  Example:
 
-=item	EmptyClipbrd
+  OpenClipbrd or die "can't open clipboard: $^E";
+  $fmt = 0;
+  push @formats, AtomName $fmt
+    while $fmt = EnumClipbrdFmts $_;
+  CloseClipbrd or die "can't close clipboard: $^E"
 
-=item	AddAtom
+Clipboard should be opened before calling this function.
 
-=item	FindAtom
+=item	EmptyClipbrd( [ $hab ] )
 
-=item	DeleteAtom
+Remove all the data handles in the clipboard.  Recommended before assigning
+a value to clipboard to remove extraneous formats of data from clipboard.
 
-=item	AtomUsage
+Clipboard should be opened before calling this function.
 
-=item	AtomName
+=item ($size, $flags) = MemoryRegionSize($addr, [$size_lim])
 
-=item	AtomLength
+$addr should be a memory address (encoded as integer).  This call finds
+the largest continuous region of memory belonging to the same memory object
+as $addr, and having the same memory flags as $addr. $flags is the value of
+the memory flag of $addr (see docs of DosQueryMem(3) for details).  If
+optional argumetn $size_lim is given, the search is restricted to the region
+this many bytes long (after $addr).
 
-=item	SystemAtomTable
+($addr and $size are rounded so that all the memory pages containing
+the region are inspected.)
 
-=item	CreateAtomTable
+=back
+
+=head2 Control of the PM atom tables
+
+Low-level methods to access the atom table(s).  $atomtable defaults to 
+the SystemAtomTable().
+
+=over
+
+=item	AddAtom($name, [$atomtable])
+
+Returns the atom; increments the use count unless $name is a name of an
+integer atom.
+
+=item	FindAtom($name, [$atomtable])
+
+Returns the atom if it exists, 0 otherwise (actually, croaks).
+
+=item	DeleteAtom($name, [$atomtable])
+
+Decrements the use count unless $name is a name of an integer atom.
+When count goes to 0, association of the name to an integer is removed.
+(Version with prepended underscore returns 0 on success.)
+
+=item	AtomName($atom, [$atomtable])
 
-=item	DestroyAtomTable
+Returns the name of the atom.  Integer atoms have names of format C<"#ddddd">
+of variable length up to 7 chars.
+
+=item	AtomLength($atom, [$atomtable])
+
+Returns the length of the name of the atom.  Return of 0 means that no
+such atom exists (but usually croaks in such a case).
+
+Integer atoms always return length 6.
+
+=item	AtomUsage($name, [$atomtable])
+
+Returns the usage count of the atom.
+
+=item	SystemAtomTable()
+
+Returns central atom table accessible to any process.
+
+=item	CreateAtomTable( [ $initial, [ $buckets ] ] )
+
+Returns new per-process atom table.  See docs for WinCreateAtomTable(3).
+
+=item	DestroyAtomTable($atomtable)
+
+Dispose of the table. (Version with prepended underscore returns 0 on success.)
 
-Low-level methods to access clipboard and the atom table(s).
 
 =back
 
@@ -1408,12 +1526,14 @@ Add tests for:
 	scrsize
 	scrsize_set
 
-Document and test: Query/SetWindowULong/Short/Ptr, SetWindowBits.
+Document: Query/SetWindowULong/Short/Ptr, SetWindowBits, InvalidateRect,
+CreateFrameControl.
+
+Test: Query/SetWindowULong/Short/Ptr, SetWindowBits.
 InvalidateRect, CreateFrameControl, ClipbrdFmtInfo ClipbrdOwner
 ClipbrdViewer ClipbrdData OpenClipbrd CloseClipbrd ClipbrdData_set
 ClipbrdOwner_set ClipbrdViewer_set EnumClipbrdFmts EmptyClipbrd
-AddAtom FindAtom DeleteAtom AtomUsage AtomName AtomLength
-SystemAtomTable CreateAtomTable DestroyAtomTable
+MemoryRegionSize
 
 Implement SOMETHINGFROMMR.
 
diff -pru perl-5.8.7-orig/os2/OS2/Process/Process.xs perl-5.8.7/os2/OS2/Process/Process.xs
--- perl-5.8.7-orig/os2/OS2/Process/Process.xs	Thu Sep 11 14:25:38 2003
+++ perl-5.8.7/os2/OS2/Process/Process.xs	Mon Sep 12 01:00:08 2005
@@ -324,10 +324,6 @@ DeclWinFunc_CACHE(HWND, SetClipbrdOwner,
 DeclWinFunc_CACHE(ULONG, EnumClipbrdFmts, (HAB hab, ULONG fmt), (hab, fmt));
 DeclWinFunc_CACHE(ATOM, AddAtom, (HATOMTBL hAtomTbl, PCSZ pszAtomName),
 		  (hAtomTbl, pszAtomName));
-DeclWinFunc_CACHE(ATOM, FindAtom, (HATOMTBL hAtomTbl, PCSZ pszAtomName),
-		  (hAtomTbl, pszAtomName));
-DeclWinFunc_CACHE(ATOM, DeleteAtom, (HATOMTBL hAtomTbl, PCSZ pszAtomName),
-		  (hAtomTbl, pszAtomName));
 DeclWinFunc_CACHE(ULONG, QueryAtomUsage, (HATOMTBL hAtomTbl, ATOM atom),
 		  (hAtomTbl, atom));
 DeclWinFunc_CACHE(ULONG, QueryAtomLength, (HATOMTBL hAtomTbl, ATOM atom),
@@ -338,7 +334,6 @@ DeclWinFunc_CACHE(ULONG, QueryAtomName,
 DeclWinFunc_CACHE(HATOMTBL, QuerySystemAtomTable, (VOID), ());
 DeclWinFunc_CACHE(HATOMTBL, CreateAtomTable, (ULONG initial, ULONG buckets),
 		  (initial, buckets));
-DeclWinFunc_CACHE(HATOMTBL, DestroyAtomTable, (HATOMTBL hAtomTbl), (hAtomTbl));
 DeclWinFunc_CACHE(ULONG, MessageBox, (HWND hwndParent, HWND hwndOwner, PCSZ pszText, PCSZ pszCaption, ULONG idWindow, ULONG flStyle), (hwndParent, hwndOwner, pszText, pszCaption, idWindow, flStyle));
 DeclWinFunc_CACHE(ULONG, MessageBox2,
 		  (HWND hwndParent, HWND hwndOwner, PCSZ pszText,
@@ -378,6 +373,14 @@ DeclWinFunc_CACHE_resetError(HWND, GetNe
 DeclWinFunc_CACHE_resetError(BOOL, IsWindowEnabled, (HWND hwnd), (hwnd))
 DeclWinFunc_CACHE_resetError(BOOL, IsWindowVisible, (HWND hwnd), (hwnd))
 DeclWinFunc_CACHE_resetError(BOOL, IsWindowShowing, (HWND hwnd), (hwnd))
+DeclWinFunc_CACHE_resetError(ATOM, FindAtom, (HATOMTBL hAtomTbl, PCSZ pszAtomName),
+			     (hAtomTbl, pszAtomName));
+DeclWinFunc_CACHE_resetError(ATOM, DeleteAtom, (HATOMTBL hAtomTbl, ATOM atom),
+			     (hAtomTbl, atom));
+DeclWinFunc_CACHE_resetError(HATOMTBL, DestroyAtomTable, (HATOMTBL hAtomTbl), (hAtomTbl));
+
+#define _DeleteAtom		DeleteAtom
+#define _DestroyAtomTable	DestroyAtomTable
 
 /* No die()ing on error */
 DeclWinFunc_CACHE_survive(BOOL, IsWindow, (HAB hab, HWND hwnd), (hab, hwnd))
@@ -521,15 +524,22 @@ myWinQueryActiveDesktopPathname()
 SV *
 myWinQueryAtomName(ATOM atom, HATOMTBL hAtomTbl)
 {
-    ULONG len = QueryAtomLength(hAtomTbl, atom);
+  ULONG len = QueryAtomLength(hAtomTbl, atom);
+
+  if (len) {			/* Probably always so... */
     SV *sv = newSVpvn("",0);
     STRLEN n_a;
 
     SvGROW(sv, len + 1);
-    QueryAtomName(hAtomTbl, atom, SvPV(sv, n_a), len);
-    SvCUR_set(sv, len);
-    *SvEND(sv) = 0;
-    return sv;
+    len = QueryAtomName(hAtomTbl, atom, SvPV(sv, n_a), len + 1);
+    if (len) {			/* Probably always so... */
+      SvCUR_set(sv, len);
+      *SvEND(sv) = 0;
+      return sv;
+    }
+    SvREFCNT_dec(sv);
+  }
+  return &PL_sv_undef;
 }
 
 #define myWinQueryClipbrdFmtInfo	QueryClipbrdFmtInfo
@@ -539,26 +549,28 @@ void
 ClipbrdData_set(SV *sv, int convert_nl, unsigned long fmt, unsigned long rgfFmtInfo, HAB hab)
 {
     STRLEN len;
-    char *buf = SvPV_force(sv, len);
+    char *buf;
     char *pByte = 0, *s = buf, c;
-    ULONG nls = 0, rc;
+    ULONG nls = 0, rc, handle;
 
-    if (convert_nl) {
+    if (rgfFmtInfo & CFI_POINTER) {
+      buf = SvPV_force(sv, len);
+      if (convert_nl) {
 	while ((c = *s++)) {
 	    if (c == '\r' && *s == '\n')
 		s++;
 	    else if (c == '\n')
 		nls++;
 	}
-    }
+      }
 
-    if (CheckOSError(DosAllocSharedMem((PPVOID)&pByte, 0, len + nls + 1,
+      if (CheckOSError(DosAllocSharedMem((PPVOID)&pByte, 0, len + nls + 1,
 				       PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE | OBJ_GETTABLE)))
 	croak_with_os2error("ClipbrdData_set: DosAllocSharedMem error");
 
-    if (!nls)
+      if (!nls)
 	memcpy(pByte, buf, len + 1);
-    else {
+      else {
 	char *t = pByte, *e = buf + len;
 
 	while (buf < e) {
@@ -566,14 +578,39 @@ ClipbrdData_set(SV *sv, int convert_nl, 
 	    if (c == '\n' && (t == pByte + 1 || t[-2] != '\r'))
 		t[-1] = '\r', *t++ = '\n';
 	}
+      }
+      handle = (ULONG)pByte;
+    } else {
+      handle = (ULONG)SvUV(sv);
     }
 
-    if (!SetClipbrdData(hab, (ULONG)pByte, fmt, rgfFmtInfo)) {
-	DosFreeMem((PPVOID)&pByte);
+    if (!SetClipbrdData(hab, handle, fmt, rgfFmtInfo)) {
+	if (fmt & CFI_POINTER)
+	    DosFreeMem((PPVOID)&pByte);
 	croak_with_os2error("ClipbrdData_set: WinSetClipbrdData error");
     }
 }
 
+ULONG
+QueryMemoryRegionSize(ULONG addr, ULONG *flagp, ULONG len)
+{
+    ULONG l, f;				/* Modifiable copy */
+    ULONG rc = ERROR_INTERRUPT;
+
+    while ( (l = len, rc == ERROR_INTERRUPT) )
+	rc = DosQueryMem((void *)addr, &l, &f);
+
+    /* We assume this is not about addr */
+/*
+    if (rc == ERROR_INVALID_ADDRESS)
+	return 0xFFFFFFFF;
+*/
+    os2cp_croak(rc,"QueryMemoryRegionSize");
+    if (flagp)
+	*flagp = f;
+    return l;
+}
+
 #if 0
 
 ULONG
@@ -1558,8 +1595,17 @@ FindAtom(char *pszAtomName, HATOMTBL hAt
     C_ARGS: hAtomTbl, pszAtomName
 
 unsigned long
-DeleteAtom(char *pszAtomName, HATOMTBL hAtomTbl = QuerySystemAtomTable())
-    C_ARGS: hAtomTbl, pszAtomName
+_DeleteAtom(ATOM atom, HATOMTBL hAtomTbl = QuerySystemAtomTable())
+    PROTOTYPE: DISABLE
+    C_ARGS: hAtomTbl, atom
+
+#if 0
+
+unsigned long
+WinDeleteAtom(ATOM atom, HATOMTBL hAtomTbl = QuerySystemAtomTable())
+    C_ARGS: hAtomTbl, atom
+
+#endif
 
 void
 Alarm(unsigned long rgfType = WA_ERROR, HWND hwndDesktop = HWND_DESKTOP)
@@ -1604,6 +1650,9 @@ QueryClipbrdData(unsigned long fmt = CF_
     C_ARGS: hab, fmt
     PROTOTYPE: DISABLE
 
+ULONG
+QueryMemoryRegionSize(ULONG addr, OUTLIST ULONG flagp, ULONG len = 0xFFFFFFFF - addr)
+
 unsigned long
 QueryClipbrdViewer(HAB hab = perl_hab_GET())
 
@@ -1626,6 +1675,9 @@ QueryAtomUsage(ATOM atom, HATOMTBL hAtom
 unsigned long
 QueryAtomLength(ATOM atom, HATOMTBL hAtomTbl = QuerySystemAtomTable())
     C_ARGS: hAtomTbl, atom
+   POSTCALL:
+	if (!RETVAL)
+	    XSRETURN_EMPTY;
 
 unsigned long
 QuerySystemAtomTable()
@@ -1638,7 +1690,8 @@ unsigned long
 CreateAtomTable(unsigned long initial = 0, unsigned long buckets = 0)
 
 unsigned long
-DestroyAtomTable(HATOMTBL hAtomTbl)
+_DestroyAtomTable(HATOMTBL hAtomTbl)
+    PROTOTYPE: DISABLE
 
 
 MODULE = OS2::Process		PACKAGE = OS2::Process	PREFIX = myWinQuery
diff -pru perl-5.8.7-orig/os2/os2.c perl-5.8.7/os2/os2.c
--- perl-5.8.7-orig/os2/os2.c	Thu Jan  1 09:53:42 2004
+++ perl-5.8.7/os2/os2.c	Sat Sep 10 14:18:44 2005
@@ -1469,42 +1469,47 @@ do_spawn3(pTHX_ char *cmd, int execf, in
     return rc;
 }
 
+#define ASPAWN_WAIT	0
+#define ASPAWN_EXEC	1
+#define ASPAWN_NOWAIT	2
+
 /* Array spawn/exec.  */
 int
-os2_aspawn4(pTHX_ SV *really, register SV **vmark, register SV **vsp, int execing)
+os2_aspawn_4(pTHX_ SV *really, register SV **args, I32 cnt, int execing)
 {
-    register SV **mark = (SV **)vmark;
-    register SV **sp = (SV **)vsp;
+    register SV **argp = (SV **)args;
+    register SV **last = argp + cnt;
     register char **a;
     int rc;
     int flag = P_WAIT, flag_set = 0;
     STRLEN n_a;
 
-    if (sp > mark) {
-	New(1301,PL_Argv, sp - mark + 3, char*);
+    if (cnt) {
+	New(1301,PL_Argv, cnt + 3, char*); /* 3 extra to expand #! */
 	a = PL_Argv;
 
-	if (mark < sp && SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
-		++mark;
-		flag = SvIVx(*mark);
-		flag_set = 1;
-
-	}
+	if (cnt > 1 && SvNIOKp(*argp) && !SvPOKp(*argp)) {
+	    flag = SvIVx(*argp);
+	    flag_set = 1;
+	} else
+	    --argp;
 
-	while (++mark <= sp) {
-	    if (*mark)
-		*a++ = SvPVx(*mark, n_a);
+	while (++argp < last) {
+	    if (*argp)
+		*a++ = SvPVx(*argp, n_a);
 	    else
 		*a++ = "";
 	}
 	*a = Nullch;
 
 	if ( flag_set && (a == PL_Argv + 1)
-	     && !really && !execing ) { 		/* One arg? */
+	     && !really && execing == ASPAWN_WAIT ) { 		/* One arg? */
 	    rc = do_spawn3(aTHX_ a[-1], EXECF_SPAWN_BYFLAG, flag);
-	} else
-	    rc = do_spawn_ve(aTHX_ really, flag,
-			     (execing ? EXECF_EXEC : EXECF_SPAWN), NULL, 0);
+	} else {
+	    const int execf[3] = {EXECF_SPAWN, EXECF_EXEC, EXECF_SPAWN_NOWAIT};
+	    
+	    rc = do_spawn_ve(aTHX_ really, flag, execf[execing], NULL, 0);
+	}
     } else
     	rc = -1;
     do_execfree();
@@ -1515,14 +1520,14 @@ os2_aspawn4(pTHX_ SV *really, register S
 int
 os2_do_aspawn(pTHX_ SV *really, register SV **vmark, register SV **vsp)
 {
-    return os2_aspawn4(aTHX_ really, vmark, vsp, 0);
+    return os2_aspawn_4(aTHX_ really, vmark + 1, vsp - vmark, ASPAWN_WAIT);
 }
 
 /* Array exec.  */
 bool
 Perl_do_aexec(pTHX_ SV* really, SV** vmark, SV** vsp)
 {
-    return os2_aspawn4(aTHX_ really, vmark, vsp, 1);
+    return os2_aspawn_4(aTHX_ really, vmark + 1, vsp - vmark, ASPAWN_EXEC);
 }
 
 int
@@ -1551,7 +1556,7 @@ os2exec(pTHX_ char *cmd)
 }
 
 PerlIO *
-my_syspopen(pTHX_ char *cmd, char *mode)
+my_syspopen4(pTHX_ char *cmd, char *mode, I32 cnt, SV** args)
 {
 #ifndef USE_POPEN
     int p[2];
@@ -1599,7 +1604,10 @@ my_syspopen(pTHX_ char *cmd, char *mode)
     fcntl(p[this], F_SETFD, FD_CLOEXEC);
     if (newfd != -1)
 	fcntl(newfd, F_SETFD, FD_CLOEXEC);
-    pid = do_spawn_nowait(aTHX_ cmd);
+    if (cnt) {	/* Args: "Real cmd", before first arg, the last, execing */
+	pid = os2_aspawn_4(aTHX_ Nullsv, args, cnt, ASPAWN_NOWAIT);
+    } else
+	pid = do_spawn_nowait(aTHX_ cmd);
     if (newfd == -1)
 	close(*mode == 'r');		/* It was closed initially */
     else if (newfd != (*mode == 'r')) {	/* Probably this check is not needed */
@@ -1630,6 +1638,9 @@ my_syspopen(pTHX_ char *cmd, char *mode)
     PerlIO *res;
     SV *sv;
 
+    if (cnt)
+	Perl_croak(aTHX_ "List form of piped open not implemented");
+
 #  ifdef TRYSHELL
     res = popen(cmd, mode);
 #  else
@@ -1646,6 +1657,12 @@ my_syspopen(pTHX_ char *cmd, char *mode)
 
 #endif /* USE_POPEN */
 
+}
+
+PerlIO *
+my_syspopen(pTHX_ char *cmd, char *mode)
+{
+    return my_syspopen4(aTHX_ cmd, mode, 0, NULL);
 }
 
 /******************************************************************/
diff -pru perl-5.8.7-orig/os2/os2ish.h perl-5.8.7/os2/os2ish.h
--- perl-5.8.7-orig/os2/os2ish.h	Thu Jan  1 13:50:16 2004
+++ perl-5.8.7/os2/os2ish.h	Sat Sep 10 14:10:46 2005
@@ -309,6 +309,7 @@ void *sys_alloc(int size);
 #define TMPPATH1 "plXXXXXX"
 extern const char *tmppath;
 PerlIO *my_syspopen(pTHX_ char *cmd, char *mode);
+PerlIO *my_syspopen4(pTHX_ char *cmd, char *mode, I32 cnt, SV** args);
 /* Cannot prototype with I32 at this point. */
 int my_syspclose(PerlIO *f);
 FILE *my_tmpfile (void);
diff -pru perl-5.8.7-orig/perl.c perl-5.8.7/perl.c
--- perl-5.8.7-orig/perl.c	Fri Apr 22 07:14:26 2005
+++ perl-5.8.7/perl.c	Sun Sep 11 17:09:22 2005
@@ -1235,11 +1235,7 @@ setuid perl scripts securely.\n");
 	 }
 	 /* Can we grab env area too to be used as the area for $0? */
 	 if (PL_origenviron) {
-	      if ((PL_origenviron[0] == s + 1
-#ifdef OS2
-		   || (PL_origenviron[0] == s + 9 && (s += 8))
-#endif 
-		  )
+	      if ((PL_origenviron[0] == s + 1)
 		  ||
 		  (aligned &&
 		   (PL_origenviron[0] >  s &&
@@ -1247,7 +1243,7 @@ setuid perl scripts securely.\n");
 		    INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask)))
 		 )
 	      {
-#ifndef OS2
+#ifndef OS2		/* ENVIRON is read by the kernel too. */
 		   s = PL_origenviron[0];
 		   while (*s) s++;
 #endif
diff -pru perl-5.8.7-orig/t/io/pipe.t perl-5.8.7/t/io/pipe.t
--- perl-5.8.7-orig/t/io/pipe.t	Sat Dec  8 08:25:18 2001
+++ perl-5.8.7/t/io/pipe.t	Fri Sep  9 17:12:02 2005
@@ -10,7 +10,7 @@ BEGIN {
         skip_all("fork required to pipe");
     }
     else {
-        plan(tests => 22);
+        plan(tests => 24);
     }
 }
 
@@ -30,7 +30,7 @@ close PIPE;
 SKIP: {
     # Technically this should be TODO.  Someone try it if you happen to
     # have a vmesa machine.
-    skip "Doesn't work here yet", 4 if $^O eq 'vmesa';
+    skip "Doesn't work here yet", 6 if $^O eq 'vmesa';
 
     if (open(PIPE, "-|")) {
 	while(<PIPE>) {
@@ -49,6 +49,49 @@ SKIP: {
 
     # This has to be *outside* the fork
     next_test() for 1..2;
+
+    my $raw = "abc\nrst\rxyz\r\nfoo\n";
+    if (open(PIPE, "-|")) {
+	$_ = join '', <PIPE>;
+	(my $raw1 = $_) =~ s/not ok \d+ - //;
+	my @r  = map ord, split //, $raw;
+	my @r1 = map ord, split //, $raw1;
+        if ($raw1 eq $raw) {
+	    s/^not (ok \d+ -) .*/$1 '@r1' passes through '-|'\n/s;
+	} else {
+	    s/^(not ok \d+ -) .*/$1 expect '@r', got '@r1'\n/s;
+	}
+	print;
+	close PIPE;        # avoid zombies
+    }
+    else {
+	printf STDOUT "not ok %d - $raw", curr_test();
+        exec $Perl, '-e0';	# Do not run END()...
+    }
+
+    # This has to be *outside* the fork
+    next_test();
+
+    if (open(PIPE, "|-")) {
+	printf PIPE "not ok %d - $raw", curr_test();
+	close PIPE;        # avoid zombies
+    }
+    else {
+	$_ = join '', <STDIN>;
+	(my $raw1 = $_) =~ s/not ok \d+ - //;
+	my @r  = map ord, split //, $raw;
+	my @r1 = map ord, split //, $raw1;
+        if ($raw1 eq $raw) {
+	    s/^not (ok \d+ -) .*/$1 '@r1' passes through '|-'\n/s;
+	} else {
+	    s/^(not ok \d+ -) .*/$1 expect '@r', got '@r1'\n/s;
+	}
+	print;
+        exec $Perl, '-e0';	# Do not run END()...
+    }
+
+    # This has to be *outside* the fork
+    next_test();
 
     SKIP: {
         skip "fork required", 2 unless $Config{d_fork};
diff -pru perl-5.8.7-orig/t/op/stat.t perl-5.8.7/t/op/stat.t
--- perl-5.8.7-orig/t/op/stat.t	Thu Apr  7 09:07:50 2005
+++ perl-5.8.7/t/op/stat.t	Sat Sep 10 16:33:40 2005
@@ -41,7 +41,7 @@ my $Curdir = File::Spec->curdir;
 my $tmpfile = 'Op_stat.tmp';
 my $tmpfile_link = $tmpfile.'2';
 
-
+chmod 0666, $tmpfile;
 1 while unlink $tmpfile;
 open(FOO, ">$tmpfile") || DIE("Can't open temp test file: $!");
 close FOO;
@@ -466,5 +466,6 @@ ok(unlink($f), 'unlink tmp file');
 }
 
 END {
+    chmod 0666, $tmpfile;
     1 while unlink $tmpfile;
 }
diff -pru perl-5.8.7-orig/util.c perl-5.8.7/util.c
--- perl-5.8.7-orig/util.c	Mon May 30 05:44:14 2005
+++ perl-5.8.7/util.c	Sat Sep 10 14:15:20 2005
@@ -2071,8 +2071,12 @@ Perl_my_popen_list(pTHX_ char *mode, int
 	 PerlLIO_close(pp[0]);
     return PerlIO_fdopen(p[This], mode);
 #else
+#  ifdef OS2	/* Same, without fork()ing and all extra overhead... */
+    return my_syspopen4(aTHX_ Nullch, mode, n, args);
+#  else
     Perl_croak(aTHX_ "List form of piped open not implemented");
     return (PerlIO *) NULL;
+#  endif
 #endif
 }
 
@@ -2088,6 +2092,7 @@ Perl_my_popen(pTHX_ char *cmd, char *mod
     I32 doexec = !(*cmd == '-' && cmd[1] == '\0');
     I32 did_pipes = 0;
     int pp[2];
+    PerlIO *res;
 
     PERL_FLUSHALL_FOR_CHILD;
 #ifdef OS2
@@ -2161,6 +2166,14 @@ Perl_my_popen(pTHX_ char *cmd, char *mod
 	    PerlProc__exit(1);
 	}
 #endif	/* defined OS2 */
+
+#ifdef PERLIO_USING_CRLF
+	/* Since we circumvent IO layers when we manipulate low-level
+	   filedescriptors directly, need to manually switch to the
+	   default, binary, low-level mode; see PerlIOBuf_open(). */
+	PerlLIO_setmode((*mode == 'r'), O_BINARY);
+#endif
+
 	/*SUPPRESS 560*/
 	if ((tmpgv = gv_fetchpv("$",TRUE, SVt_PV))) {
 	    SvREADONLY_off(GvSV(tmpgv));
@@ -2221,7 +2234,8 @@ Perl_my_popen(pTHX_ char *cmd, char *mod
     }
     if (did_pipes)
 	 PerlLIO_close(pp[0]);
-    return PerlIO_fdopen(p[This], mode);
+    res = PerlIO_fdopen(p[This], mode);
+    return res;
 }
 #else
 #if defined(atarist) || defined(EPOC)
