5.003_08: OS/2-specific bugs/enhancements
Ilya Zakharevich [Sun, 24 Nov 1996 11:47:25 +0000 (06:47 -0500)]
This patch modifies the following files:
hints/os2.sh
New flags added.
os2/Changes
Documentation...
os2/Makefile.SHs
perl_init_i18nl10n is now in main list of symbols.
os2/OS2/PrfDB/PrfDB.pm
@ISA corrected.
os2/os2.c
reliable signals used, popen not used any more.
May work under OS/2 2.1 again.
README.os2
misprints and minor additions.

p5p-msgid: <199611241147.GAA00490@monk.mps.ohio-state.edu>

README.os2
hints/os2.sh
os2/Changes
os2/Makefile.SHs
os2/OS2/PrfDB/PrfDB.pm
os2/os2.c

index bbadbf6..34e6e08 100644 (file)
@@ -4,7 +4,7 @@ specially designed to be readable as is.
 
 =head1 NAME
 
-perlos2 - Perl under OS/2, Win0.31, Win0.95 and WinNT.
+perlos2 - Perl under OS/2, DOS, Win0.3*, Win0.95 and WinNT.
 
 =head1 SYNOPSIS
 
@@ -18,6 +18,10 @@ One can read this document in the following formats:
 to list some (not all may be available simultaneously), or it may
 be read I<as is>: either as F<README.os2>, or F<pod/perlos2.pod>.
 
+To read the F<.INF> version of documentation (B<very> recommended)
+outside of OS/2, one needs an IBM's reader (may be available on IBM
+ftp sites (?)  (URL anyone?)) or shipped with PC DOS 7.0.
+
 =cut
 
 Contents
@@ -33,7 +37,7 @@ Contents
          -  Starting Perl programs under OS/2 
          -  Starting OS/2 programs under Perl 
        Frequently asked questions 
-         -  I cannot run extenal programs 
+         -  I cannot run external programs 
          -  I cannot embed perl into my program, or use perl.dll from my program.   
        INSTALLATION 
          -  Automatic binary installation 
@@ -85,7 +89,7 @@ Contents
          -  TMP or TEMP 
        Evolution 
          -  Priorities 
-         -  DLL name mungling 
+         -  DLL name mangling 
          -  Threading 
          -  Calls to external programs 
        AUTHOR 
@@ -96,7 +100,7 @@ Contents
 =head2 Target
 
 The target is to make OS/2 the best supported platform for
-using/building/developping Perl and I<Perl applications>, as well as
+using/building/developing Perl and I<Perl applications>, as well as
 make Perl the best language to use under OS/2.
 
 The current state is quite close to this target. Known limitations:
@@ -117,7 +121,7 @@ to use PM code in your application (like the forthcoming Perl/Tk).
 
 There is no simple way to access B<WPS> objects. The only way I know
 is via C<OS2::REXX> extension (see L<OS2::REXX>), and we do not have access to
-convinience methods of B<Object REXX>. (Is it possible at all? I know
+convenience methods of B<Object REXX>. (Is it possible at all? I know
 of no B<Object-REXX> API.)
 
 =back
@@ -129,7 +133,7 @@ Please keep this list up-to-date by informing me about other items.
 Since OS/2 port of perl uses a remarkable B<EMX> environment, it can
 run (and build extensions, and - possibly - be build itself) under any
 environment which can run EMX. The current list is DOS,
-DOS-inside-OS/2, Win0.31, Win0.95 and WinNT. Out of many perl flavors,
+DOS-inside-OS/2, Win0.3*, Win0.95 and WinNT. Out of many perl flavors,
 only one works, see L<"perl_.exe">.
 
 Note that not all features of Perl are available under these
@@ -146,10 +150,11 @@ Cf. L<Prerequisites>.
 
 B<EMX> runtime is required (may be substituted by B<RSX>). Note that
 it is possible to make F<perl_.exe> to run under DOS without any
-external support by binding F<emx.exe> to it, see L<emxbind>. Note
+external support by binding F<emx.exe>/F<rsx.exe> to it, see L<emxbind>. Note
 that under DOS for best results one should use B<RSX> runtime, which
 has much more functions working (like C<fork>, C<popen> and so on). In
-fact B<RSX> is required if there is no C<VCPI> present.
+fact B<RSX> is required if there is no C<VCPI> present. Note the
+B<RSX> requires C<DPMI>.
 
 Only the latest runtime is supported, currently C<0.9c>.
 
@@ -160,12 +165,19 @@ One can get different parts of B<EMX> from, say
 
 The runtime component should have the name F<emxrt.zip>.
 
+B<NOTE>. It is enough to have F<emx.exe>/F<rsx.exe> on your path. One
+does not need to specify them explicitly (though this
+
+  emx perl_.exe -de 0
+
+will work as well.)
+
 =item B<RSX>
 
-To run Perl on C<DPMS> platforms one needs B<RSX> runtime. This is
-needed under DOS-inside-OS/2, Win0.31, Win0.95 and WinNT (see 
-L<"Other OSes">). I do not know whether B<RSX> would work with C<VCPI>
-only, as B<EMX> would.
+To run Perl on C<DPMI> platforms one needs B<RSX> runtime. This is
+needed under DOS-inside-OS/2, Win0.3*, Win0.95 and WinNT (see 
+L<"Other OSes">). B<RSX> would not work with C<VCPI>
+only, as B<EMX> would, it requires C<DMPI>.
 
 Having B<RSX> and the latest F<sh.exe> one gets a fully functional
 B<*nix>-ish environment under DOS, say, C<fork>, C<``> and
@@ -241,10 +253,10 @@ and C<-x> switches - see L<perlrun>, and cmdref about C<extproc>:
 
 or whatever method you prefer.
 
-There are also endless possibilites to use I<executable extensions> of
+There are also endless possibilities to use I<executable extensions> of
 B<4OS2>, I<associations> of B<WPS> and so on... However, if you use
 *nixish shell (like F<sh.exe> supplied in the binary distribution),
-you need follow the syntax specified in L<perlrun/"Switches">.
+you need to follow the syntax specified in L<perlrun/"Switches">.
 
 =head2 Starting OS/2 programs under Perl
 
@@ -265,7 +277,7 @@ meta-characters.
 
 =head1 Frequently asked questions
 
-=head2 I cannot run extenal programs
+=head2 I cannot run external programs
 
 =over 4
 
@@ -278,7 +290,7 @@ L<Starting OS/2 programs under Perl>.
 
 Do you try to run I<internal> shell commands, like C<`copy a b`>
 (internal for F<cmd.exe>), or C<`glob a*b`> (internal for ksh)? You
-need to specify your shell explicitely, like C<`cmd /c copy a b`>,
+need to specify your shell explicitly, like C<`cmd /c copy a b`>,
 since Perl cannot deduce which commands are internal to your shell.
 
 =back
@@ -301,19 +313,19 @@ I had reports it does not work. Somebody would need to fix it.
 
 =head2 C<``> and pipe-C<open> do not work under DOS.
 
-This may a variant of just L<"I cannot run extenal programs">, or a
+This may a variant of just L<"I cannot run external programs">, or a
 deeper problem. Basically: you I<need> B<RSX> (see L<"Prerequisites">)
-for these commands to work, and you need a port of F<sh.exe> which
+for these commands to work, and you may need a port of F<sh.exe> which
 understands command arguments. One of such ports is listed in
 L<"Prerequisites"> under B<RSX>.
 
-I do not know whether C<DPMI> is required.
+C<DPMI> is required for B<RSX>.
 
 =head1 INSTALLATION
 
 =head2 Automatic binary installation
 
-The most convinient way of installing perl is via perl installer
+The most convenient way of installing perl is via perl installer
 F<install.exe>. Just follow the instructions, and 99% of the
 installation blues would go away. 
 
@@ -355,7 +367,7 @@ data, please keep me informed if you find one.
 
 =head2 Manual binary installation
 
-As of version 5.00305, OS/2 perl binary distribution comes splitted
+As of version 5.00305, OS/2 perl binary distribution comes split
 into 11 components. Unfortunately, to enable configurable binary
 installation, the file paths in the C<zip> files are not absolute, but
 relative to some directory.
@@ -364,7 +376,9 @@ Note that the extraction with the stored paths is still necessary
 (default with C<unzip>, specify C<-d> to C<pkunzip>). However, you
 need to know where to extract the files. You need also to manually
 change entries in F<Config.sys> to reflect where did you put the
-files. 
+files. Note that if you have some primitive unzipper (like
+C<pkunzip>), you may get a lot of warnings/errors during
+unzipping. Upgrade to C<(w)unzip>.
 
 Below is the sample of what to do to reproduce the configuration on my
 machine:
@@ -449,7 +463,7 @@ This directory should better be on C<BOOKSHELF>.
 
   unzip perl_sh.zip -d f:/bin
 
-This is used by perl to run external commands which explicitely
+This is used by perl to run external commands which explicitly
 require shell, like the commands using I<redirection> and I<shell
 metacharacters>. It is also used instead of explicit F</bin/sh>.
 
@@ -485,7 +499,7 @@ identical) Perl documentation in the following formats:
 
 =head2 OS/2 F<.INF> file
 
-Most probably the most convinient form. View it as
+Most probably the most convenient form. View it as
 
   view perl
   view perl perlfunc
@@ -515,7 +529,7 @@ installed, and B<GNU> C<groff> installed, you may use
        perldoc less
        perldoc ExtUtils::MakeMaker
 
-to access the perl documention in the text form (note that you may get
+to access the perl documentation in the text form (note that you may get
 better results using perl manpages).
 
 Alternately, try running pod2text on F<.pod> files.
@@ -556,7 +570,7 @@ directory, and go ahead with reading docs, like this:
 
        explore file:///f:/perllib/lib/pod/perl.html
 
-Alternatively you may be able to get these docs prebuild from C<CPAN>.
+Alternatively you may be able to get these docs prebuilt from C<CPAN>.
 
 =head2 B<GNU> C<info> files
 
@@ -619,12 +633,12 @@ but may be not installed due to customization. If typing
   link386
 
 shows you do not have it, do I<Selective install>, and choose C<Link
-object modules> in I<Optional system utilites/More>. If you get into
+object modules> in I<Optional system utilities/More>. If you get into
 C<link386>, press C<Ctrl-C>.
 
 =head2 Getting perl source
 
-You need to fetch the latest perl source (including developpers
+You need to fetch the latest perl source (including developers
 releases). With some probability it is located in 
 
   http://www.perl.com/CPAN/src/5.0
@@ -633,7 +647,7 @@ releases). With some probability it is located in
 If not, you may need to dig in the indices to find it in the directory
 of the current maintainer.
 
-Quick cycle of developpers release may break the OS/2 build time to
+Quick cycle of developers release may break the OS/2 build time to
 time, looking into 
 
   http://www.perl.com/CPAN/ports/os2/ilyaz/
@@ -710,7 +724,7 @@ Now run
 
   make test
 
-Some tests (5..7) should fail. Some perl invocations should end in a
+Some tests (4..6) should fail. Some perl invocations should end in a
 segfault (system error C<SYS3175>). To get finer error reports, 
 
   cd t
@@ -724,13 +738,20 @@ The report you get may look like
   lib/io_pipe.t     3   768     6   ??       %  ??
   lib/io_sock.t     3   768     5   ??       %  ??
   op/stat.t                    56    5   8.93%  3-4, 20, 35, 39
-  Failed 4/118 test scripts, 96.61% okay. 27/2445 subtests failed, 98.90% okay.
+  Failed 4/140 test scripts, 97.14% okay. 27/2937 subtests failed, 99.08% okay.
 
 Note that using `make test' target two more tests may fail: C<op/exec:1>
 because of (mis)feature of C<pdksh>, and C<lib/posix:15>, which checks
 that the buffers are not flushed on C<_exit> (this is a bug in the test
 which assumes that tty output is buffered).
 
+I submitted a patch to B<EMX> which makes it possible to fork() with EMX 
+dynamic libraries loaded, which makes F<lib/io*> tests pass. This means
+that soon the number of failing tests may decrease yet more.
+
+However, the test F<lib/io_udp.t> is disabled, since it never ends, I
+do not know why.
+
 The reasons for failed tests are:
 
 =over 8
@@ -861,7 +882,7 @@ test and install by
 Manually put F<perl_.exe> to a location on your C<PATH>.
 
 Since C<perl_> has the extensions prebuilt, it does not suffer from
-the I<dynamic extensions + fork()> syndrom, thus the failing tests
+the I<dynamic extensions + fork()> syndrome, thus the failing tests
 look like
 
   Failed Test  Status Wstat Total Fail  Failed  List of failed
@@ -911,7 +932,7 @@ You use an old version of C<GNU> make. See L<Prerequisites>.
 
 Note that these functions are compatible with *nix, not with the older
 ports of '94 - 95. The priorities are absolute, go from 32 to -95,
-lower is quickier. 0 is the default priority.
+lower is quicker. 0 is the default priority.
 
 =head2 C<system()>
 
@@ -926,7 +947,7 @@ modules provide access to additional numeric argument for C<system>,
 to DLLs having functions with REXX signature and to REXX runtime, to
 OS/2 databases in the F<.INI> format, and to Extended Attributes.
 
-Two additional extensions by Andread Kaiser, C<OS2::UPM>, and
+Two additional extensions by Andreas Kaiser, C<OS2::UPM>, and
 C<OS2::FTP>, are included into my ftp directory, mirrored on CPAN.
 
 =head2 Prebuilt methods:
@@ -939,7 +960,7 @@ used by C<File::Copy::copy>, see L<File::Copy/copy>.
 
 =item C<DynaLoader::mod2fname>
 
-used by C<DynaLoader> for DLL name mungling.
+used by C<DynaLoader> for DLL name mangling.
 
 =item  C<Cwd::current_drive()>
 
@@ -1017,7 +1038,7 @@ Note that C<kill -9> does not work with the current version of EMX.
 
 =item
 
-Since F<sh.exe> is used for globbing (see L<perlfunc/glob>), the bugs
+Since F<sh.exe> is used for globing (see L<perlfunc/glob>), the bugs
 of F<sh.exe> plague perl as well. 
 
 In particular, uppercase letters do not work in C<[...]>-patterns with
@@ -1033,7 +1054,7 @@ Perl modifies some standard C library calls in the following ways:
 
 =item C<popen>
 
-C<my_popen> always uses F<sh.exe>, cf. L<"PERL_SH_DIR">.
+C<my_popen> uses F<sh.exe> if shell is required, cf. L<"PERL_SH_DIR">.
 
 =item C<tmpnam>
 
@@ -1042,7 +1063,7 @@ C<tempnam>.
 
 =item C<tmpfile>
 
-If the current directory is not writable, it is created using modified
+If the current directory is not writable, file is created using modified
 C<tmpnam>, so there may be a race condition.
 
 =item C<ctermid>
@@ -1057,7 +1078,7 @@ C<os2_stat> special-cases F</dev/tty> and F</dev/con>.
 
 =head1 Perl flavors
 
-Because of ideosyncrasies of OS/2 one cannot have all the eggs in the
+Because of idiosyncrasies of OS/2 one cannot have all the eggs in the
 same basket (though C<EMX> environment tries hard to overcome this
 limitations, so the situation may somehow improve). There are 4
 executables for Perl provided by the distribution:
@@ -1070,7 +1091,8 @@ library F<perl.dll>, and with dynamic B<CRT> DLL. This executable is a
 C<VIO> application.
 
 It can load perl dynamic extensions, and it can fork(). Unfortunately,
-currently it cannot fork() with dynamic extensions loaded.
+with the current version of B<EMX> it cannot fork() with dynamic
+extensions loaded (may be fixed by patches to B<EMX>).
 
 B<Note.> Keep in mind that fork() is needed to open a pipe to yourself.
 
@@ -1092,7 +1114,7 @@ hint files should be necessary to achieve this.
 
 I<This is also the only executable with does not require OS/2.> The
 friends locked into C<M$> world would appreciate the fact that this
-executable runs under DOS, Win0.31, Win0.95 and WinNT with an
+executable runs under DOS, Win0.3*, Win0.95 and WinNT with an
 appropriate extender. See L<"Other OSes">.
 
 =head2 F<perl__.exe>
@@ -1127,7 +1149,7 @@ L<perldiag/"Not a perl script">,
 L<perldiag/"No Perl script found in input">), it should know when a
 program I<is a Perl>. There is some naming convention which allows
 Perl to distinguish correct lines from wrong ones. The above names are
-almost the only names allowed by this convension which do not contain
+almost the only names allowed by this convention which do not contain
 digits (which have absolutely different semantics).
 
 =head2 Why dynamic linking?
@@ -1137,14 +1159,14 @@ library has its advantages, but this would not substantiate the
 additional work to make it compile. The reason is stupid-but-quick
 "hard" dynamic linking used by OS/2.
 
-The address tables of DLLs are patches only once, when they are
-loaded. The addresses of entry points into DLLs are guarantied to be
+The address tables of DLLs are patched only once, when they are
+loaded. The addresses of entry points into DLLs are guaranteed to be
 the same for all programs which use the same DLL, which reduces the
 amount of runtime patching - once DLL is loaded, its code is
 read-only.
 
 While this allows some performance advantages, this makes life
-terrible for developpers, since the above scheme makes it impossible
+terrible for developers, since the above scheme makes it impossible
 for a DLL to be resolved to a symbol in the .EXE file, since this
 would need a DLL to have different relocations tables for the
 executables which use it.
@@ -1155,7 +1177,7 @@ internal evaluation stack. The solution is that the main code of
 interpreter should be contained in a DLL, and the F<.EXE> file just loads
 this DLL into memory and supplies command-arguments.
 
-This I<greately> increases the load time for the application (as well as
+This I<greatly> increases the load time for the application (as well as
 the number of problems during compilation). Since interpreter is in a DLL,
 the C<CRT> is basically forced to reside in a DLL as well (otherwise
 extensions would not be able to use C<CRT>).
@@ -1241,7 +1263,7 @@ Here we list major changes which could make you by surprise.
 C<setpriority> and C<getpriority> are not compatible with earlier
 ports by Andreas Kaiser. See C<"setpriority, getpriority">.
 
-=head2 DLL name mungling
+=head2 DLL name mangling
 
 With the release 5.003_01 the dynamically loadable libraries
 should be rebuilt. In particular, DLLs are now created with the names
@@ -1260,7 +1282,7 @@ Needed to compile C<Perl/Tk> for C<XFreeOS/2> out-of-the-box.
 =head2 Calls to external programs
 
 Due to a popular demand the perl external program calling has been
-changed wrt Andread Kaiser's port.  I<If> perl needs to call an
+changed wrt Andreas Kaiser's port.  I<If> perl needs to call an
 external program I<via shell>, the F<f:/bin/sh.exe> will be called, or
 whatever is the override, see L<"PERL_SH_DIR">.
 
@@ -1278,16 +1300,19 @@ with F<cmd.exe> as a shell, thus I picked up C<sh.exe>. Thus assures almost
 B<Disadvantages:> currently F<sh.exe> of C<pdksh> calls external programs
 via fork()/exec(), and there is I<no> functioning exec() on
 OS/2. exec() is emulated by EMX by asyncroneous call while the caller
-waits for child completion (to pretend that the pid did not change). This
+waits for child completion (to pretend that the C<pid> did not change). This
 means that 1 I<extra> copy of F<sh.exe> is made active via fork()/exec(),
 which may lead to some resources taken from the system (even if we do
 not count extra work needed for fork()ing).
 
-One can always start F<cmd.exe> explicitely via
+Note that this a lesser issue now when we do not spawn F<sh.exe>
+unless needed (metachars found).
+
+One can always start F<cmd.exe> explicitly via
 
   system 'cmd', '/c', 'mycmd', 'arg1', 'arg2', ...
 
-If you need to use F<cmd.exe>, and do not want to hand-edit thousends of your
+If you need to use F<cmd.exe>, and do not want to hand-edit thousands of your
 scripts, the long-term solution proposed on p5-p is to have a directive
 
   use OS2::Cmd;
@@ -1306,7 +1331,7 @@ cannot test it.
 
 OS/2 extensions
 ~~~~~~~~~~~~~~~
-I include 3 extensions by Andread Kaiser, OS2::REXX, OS2::UPM, and OS2::FTP, 
+I include 3 extensions by Andreas Kaiser, OS2::REXX, OS2::UPM, and OS2::FTP, 
 into my ftp directory, mirrored on CPAN. I made
 some minor changes needed to compile them by standard tools. I cannot 
 test UPM and FTP, so I will appreciate your feedback. Other extensions
index 9d81b24..59087e3 100644 (file)
@@ -64,8 +64,8 @@ fi
 aout_ldflags="$aout_ldflags"
 
 aout_d_fork='define'
-aout_ccflags='-DDOSISH -DPERL_IS_AOUT -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS'
-aout_cppflags='-DDOSISH -DPERL_IS_AOUT -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS'
+aout_ccflags='-DPERL_CORE -DDOSISH -DPERL_IS_AOUT -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS -DTWO_POT_OPTIMIZE -DPERL_EMERGENCY_SBRK'
+aout_cppflags='-DPERL_CORE -DDOSISH -DPERL_IS_AOUT -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS -DTWO_POT_OPTIMIZE -DPERL_EMERGENCY_SBRK'
 aout_use_clib='c'
 aout_usedl='undef'
 aout_archobjs="os2.o dl_os2.o"
@@ -105,7 +105,7 @@ else
     # Recursive regmatch may eat 2.5M of stack alone.
     ldflags='-Zexe -Zomf -Zmt -Zcrtdll -Zstack 32000'
     if [ $emxcrtrev -ge 50 ]; then 
-       ccflags='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS'
+       ccflags='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS -DTWO_POT_OPTIMIZE -DPERL_EMERGENCY_SBRK'
     else
        ccflags='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS -DEMX_BAD_SBRK'
     fi
index 2bd48b2..f4a0e30 100644 (file)
@@ -112,3 +112,9 @@ after 5.003_07:
        Tested that popen works under DOS with modified PDKSH and RSX.
        File::Copy works under DOS.
        MakeMaker modified to work under DOS (perlmain.c.tmp and sh -c true).
+
+after 5.003_08:
+       OS2::PrfDB exports symbols as documented;
+       should work on OS/2 2.1 again.
+       uses reliable signals when spawing.
+       do not use popen() any more - no intermediate shell unless needed.
index c498706..b4ac75e 100644 (file)
@@ -16,7 +16,7 @@ AOUT_LIBPERL  = libperl$aout_lib_ext
 AOUT_CLDFLAGS  = $aout_ldflags
 
 AOUT_LIBPERL_DLL       = libperl_dll$aout_lib_ext
-AOUT_CCCMD_DLL = \$(CC) -DDOSISH -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS -g
+AOUT_CCCMD_DLL = \$(CC) -DDOSISH -DOS2=2 -DEMBED -I. -DPACK_MALLOC -DDEBUGGING_MSTATS -DTWO_POT_OPTIMIZE -DPERL_EMERGENCY_SBRK
 AOUT_CLDFLAGS_DLL      = -Zexe -Zmt -Zcrtdll
 
 !GROK!THIS!
@@ -48,7 +48,6 @@ perl5.def: perl.linkexp
        echo '  "dlopen"'                               >>$@
        echo '  "dlsym"'                                >>$@
        echo '  "dlerror"'                              >>$@
-       echo '  "perl_init_i18nl10n"'                   >>$@
        echo '  "my_tmpfile"'                           >>$@
        echo '  "my_tmpnam"'                            >>$@
 !NO!SUBS!
index d404c8b..41d7dba 100644 (file)
@@ -34,7 +34,7 @@ sub SystemIni {
 
 use vars qw{$debug @ISA};
 use Tie::Hash;
-@ISA = qw{Tie::Hash};
+push @ISA, qw{Tie::Hash};
 
 # Internal structure 0 => HINI, 1 => array of entries, 2 => iterator.
 
index f192dd6..a35b706 100644 (file)
--- a/os2/os2.c
+++ b/os2/os2.c
 #include <errno.h>
 #include <limits.h>
 #include <process.h>
+#include <fcntl.h>
 
 #include "EXTERN.h"
 #include "perl.h"
 
 /*****************************************************************************/
+/* 2.1 would not resolve symbols on demand, and has no ExtLIBPATH. */
+static PFN ExtFCN[2];                  /* Labeled by ord below. */
+static USHORT loadOrd[2] = { 874, 873 }; /* Query=874, Set=873. */
+#define ORD_QUERY_ELP  0
+#define ORD_SET_ELP    1
+
+APIRET
+loadByOrd(ULONG ord)
+{
+    if (ExtFCN[ord] == NULL) {
+       static HMODULE hdosc = 0;
+       BYTE buf[20];
+       PFN fcn;
+       APIRET rc;
+
+       if ((!hdosc && CheckOSError(DosLoadModule(buf, sizeof buf, 
+                                                 "doscalls", &hdosc)))
+           || CheckOSError(DosQueryProcAddr(hdosc, loadOrd[ord], NULL, &fcn)))
+           die("This version of OS/2 does not support doscalls.%i", 
+               loadOrd[ord]);
+       ExtFCN[ord] = fcn;
+    } 
+    if ((long)ExtFCN[ord] == -1) die("panic queryaddr");
+}
+
 /* priorities */
 static signed char priors[] = {0, 1, 3, 2}; /* Last two interchanged,
                                               self inverse. */
@@ -130,6 +156,23 @@ getpriority(int which /* ignored */, int pid)
 
 /*****************************************************************************/
 /* spawn */
+typedef void (*Sigfunc) _((int));
+
+static
+Sigfunc rsignal(signo,handler)
+int signo;
+Sigfunc handler;
+{
+    struct sigaction act,oact;
+    
+    act.sa_handler = handler;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    if (sigaction(signo, &act, &oact) < 0)
+       return(SIG_ERR);
+    else
+       return(oact.sa_handler);
+}
 
 static int
 result(int flag, int pid)
@@ -146,22 +189,22 @@ result(int flag, int pid)
                return pid;
 
 #ifdef __EMX__
-       ihand = signal(SIGINT, SIG_IGN);
-       qhand = signal(SIGQUIT, SIG_IGN);
+       ihand = rsignal(SIGINT, SIG_IGN);
+       qhand = rsignal(SIGQUIT, SIG_IGN);
        do {
            r = wait4pid(pid, &status, 0);
        } while (r == -1 && errno == EINTR);
-       signal(SIGINT, ihand);
-       signal(SIGQUIT, qhand);
+       rsignal(SIGINT, ihand);
+       rsignal(SIGQUIT, qhand);
 
        statusvalue = (U16)status;
        if (r < 0)
                return -1;
        return status & 0xFFFF;
 #else
-       ihand = signal(SIGINT, SIG_IGN);
+       ihand = rsignal(SIGINT, SIG_IGN);
        r = DosWaitChild(DCWA_PROCESS, DCWW_WAIT, &res, &rpid, pid);
-       signal(SIGINT, ihand);
+       rsignal(SIGINT, ihand);
        statusvalue = res.codeResult << 8 | res.codeTerminate;
        if (r)
                return -1;
@@ -226,6 +269,7 @@ register SV **sp;
 #define EXECF_SPAWN 0
 #define EXECF_EXEC 1
 #define EXECF_TRUEEXEC 2
+#define EXECF_SPAWN_NOWAIT 3
 
 int
 do_spawn2(cmd, execf)
@@ -292,6 +336,8 @@ int execf;
                 return execl(shell,shell,copt,cmd,(char*)0);
            else if (execf == EXECF_EXEC)
                 return spawnl(P_OVERLAY,shell,shell,copt,cmd,(char*)0);
+           else if (execf == EXECF_SPAWN_NOWAIT)
+                return spawnl(P_NOWAIT,shell,shell,copt,cmd,(char*)0);
            /* In the ak code internal P_NOWAIT is P_WAIT ??? */
            rc = result(P_WAIT,
                        spawnl(P_NOWAIT,shell,shell,copt,cmd,(char*)0));
@@ -322,6 +368,8 @@ int execf;
            rc = execvp(Argv[0],Argv);
        else if (execf == EXECF_EXEC)
            rc = spawnvp(P_OVERLAY,Argv[0],Argv);
+       else if (execf == EXECF_SPAWN_NOWAIT)
+           rc = spawnvp(P_NOWAIT,Argv[0],Argv);
         else
            rc = result(P_WAIT, spawnvp(P_NOWAIT,Argv[0],Argv));
        if (rc < 0 && dowarn)
@@ -343,6 +391,13 @@ char *cmd;
     return do_spawn2(cmd, EXECF_SPAWN);
 }
 
+int
+do_spawn_nowait(cmd)
+char *cmd;
+{
+    return do_spawn2(cmd, EXECF_SPAWN_NOWAIT);
+}
+
 bool
 do_exec(cmd)
 char *cmd;
@@ -362,22 +417,74 @@ my_syspopen(cmd,mode)
 char   *cmd;
 char   *mode;
 {
+#ifndef USE_POPEN
+
+    int p[2];
+    register I32 this, that, newfd;
+    register I32 pid, rc;
     PerlIO *res;
     SV *sv;
+    
+    if (pipe(p) < 0)
+       return Nullfp;
+    /* `this' is what we use in the parent, `that' in the child. */
+    this = (*mode == 'w');
+    that = !this;
+    if (tainting) {
+       taint_env();
+       taint_proper("Insecure %s%s", "EXEC");
+    }
+    /* Now we need to spawn the child. */
+    newfd = dup(*mode == 'r');         /* Preserve std* */
+    if (p[that] != (*mode == 'r')) {
+       dup2(p[that], *mode == 'r');
+       close(p[that]);
+    }
+    /* Where is `this' and newfd now? */
+    fcntl(p[this], F_SETFD, FD_CLOEXEC);
+    fcntl(newfd, F_SETFD, FD_CLOEXEC);
+    pid = do_spawn_nowait(cmd);
+    if (newfd != (*mode == 'r')) {
+       dup2(newfd, *mode == 'r');      /* Return std* back. */
+       close(newfd);
+    }
+    close(p[that]);
+    if (pid == -1) {
+       close(p[this]);
+       return NULL;
+    }
+    if (p[that] < p[this]) {
+       dup2(p[this], p[that]);
+       close(p[this]);
+       p[this] = p[that];
+    }
+    sv = *av_fetch(fdpid,p[this],TRUE);
+    (void)SvUPGRADE(sv,SVt_IV);
+    SvIVX(sv) = pid;
+    forkprocess = pid;
+    return PerlIO_fdopen(p[this], mode);
 
-#ifdef TRYSHELL
+#else  /* USE_POPEN */
+
+    PerlIO *res;
+    SV *sv;
+
+#  ifdef TRYSHELL
     res = popen(cmd, mode);
-#else
+#  else
     char *shell = getenv("EMXSHELL");
 
     my_setenv("EMXSHELL", SH_PATH);
     res = popen(cmd, mode);
     my_setenv("EMXSHELL", shell);
-#endif 
+#  endif 
     sv = *av_fetch(fdpid, PerlIO_fileno(res), TRUE);
     (void)SvUPGRADE(sv,SVt_IV);
     SvIVX(sv) = -1;                    /* A cooky. */
     return res;
+
+#endif /* USE_POPEN */
+
 }
 
 /******************************************************************/
@@ -890,15 +997,23 @@ XS(XS_Cwd_sys_abspath)
     }
     XSRETURN(1);
 }
+typedef APIRET (*PELP)(PSZ path, ULONG type);
+
+APIRET
+ExtLIBPATH(ULONG ord, PSZ path, ULONG type)
+{
+    loadByOrd(ord);                    /* Guarantied to load or die! */
+    return (*(PELP)ExtFCN[ord])(path, type);
+}
 
-#define extLibpath(type)                                       \
-    (CheckOSError(DosQueryExtLIBPATH(to, ((type) ? END_LIBPATH \
-                                         : BEGIN_LIBPATH)))    \
+#define extLibpath(type)                                               \
+    (CheckOSError(ExtLIBPATH(ORD_QUERY_ELP, to, ((type) ? END_LIBPATH  \
+                                                : BEGIN_LIBPATH)))     \
      ? NULL : to )
 
 #define extLibpath_set(p,type)                                         \
-    (!CheckOSError(DosSetExtLIBPATH((p), ((type) ? END_LIBPATH \
-                                         : BEGIN_LIBPATH))))
+    (!CheckOSError(ExtLIBPATH(ORD_SET_ELP, (p), ((type) ? END_LIBPATH  \
+                                                : BEGIN_LIBPATH))))
 
 XS(XS_Cwd_extLibpath)
 {