This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
make perldoc use the pod2man from the same version (from
[perl5.git] / pp_sys.c
index 483ddce..00de34a 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -1,6 +1,6 @@
 /*    pp_sys.c
  *
- *    Copyright (c) 1991-1999, Larry Wall
+ *    Copyright (c) 1991-2000, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
 /* Shadow password support for solaris - pdo@cs.umd.edu
  * Not just Solaris: at least HP-UX, IRIX, Linux.
  * the API is from SysV. --jhi */
+#ifdef __hpux__
+/* There is a MAXINT coming from <shadow.h> <- <hpsecurity.h> <- <values.h>
+ * and another MAXINT from "perl.h" <- <sys/param.h>. */ 
+#undef MAXINT
+#endif
 #include <shadow.h>
 #endif
 
@@ -72,7 +77,7 @@ extern "C" int syscall(unsigned long,...);
    compiling multithreaded and singlethreaded ($ccflags et al).
    HOST_NOT_FOUND is typically defined in <netdb.h>.
 */
-#if defined(HOST_NOT_FOUND) && !defined(h_errno)
+#if defined(HOST_NOT_FOUND) && !defined(h_errno) && !defined(__CYGWIN__)
 extern int h_errno;
 #endif
 
@@ -107,27 +112,12 @@ extern int h_errno;
 #    include <utime.h>
 #  endif
 #endif
-#ifdef I_FCNTL
-#include <fcntl.h>
-#endif
-#ifdef I_SYS_FILE
-#include <sys/file.h>
-#endif
 
 /* Put this after #includes because fork and vfork prototypes may conflict. */
 #ifndef HAS_VFORK
 #   define vfork fork
 #endif
 
-/* Put this after #includes because <unistd.h> defines _XOPEN_*. */
-#ifndef Sock_size_t
-#  if _XOPEN_VERSION >= 5 || defined(_XOPEN_SOURCE_EXTENDED) || defined(__GLIBC__)
-#    define Sock_size_t Size_t
-#  else
-#    define Sock_size_t int
-#  endif
-#endif
-
 #ifdef HAS_CHSIZE
 # ifdef my_chsize  /* Probably #defined to Perl_my_chsize in embed.h */
 #   undef my_chsize
@@ -187,6 +177,10 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true";
 #  include <sys/access.h>
 #endif
 
+#if defined(HAS_FCNTL) && defined(F_SETFD) && !defined(FD_CLOEXEC)
+#  define FD_CLOEXEC 1         /* NeXT needs this */
+#endif
+
 #undef PERL_EFF_ACCESS_R_OK    /* EFFective uid/gid ACCESS R_OK */
 #undef PERL_EFF_ACCESS_W_OK
 #undef PERL_EFF_ACCESS_X_OK
@@ -230,7 +224,7 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true";
        || defined(HAS_SETREGID) || defined(HAS_SETRESGID))
 /* The Hard Way. */
 STATIC int
-S_emulate_eaccess(pTHX_ const char* path, int mode)
+S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
 {
     Uid_t ruid = getuid();
     Uid_t euid = geteuid();
@@ -238,7 +232,7 @@ S_emulate_eaccess(pTHX_ const char* path, int mode)
     Gid_t egid = getegid();
     int res;
 
-    MUTEX_LOCK(&PL_cred_mutex);
+    LOCK_CRED_MUTEX;
 #if !defined(HAS_SETREUID) && !defined(HAS_SETRESUID)
     Perl_croak(aTHX_ "switching effective uid is not implemented");
 #else
@@ -284,7 +278,7 @@ S_emulate_eaccess(pTHX_ const char* path, int mode)
 #endif
 #endif
        Perl_croak(aTHX_ "leaving effective gid failed");
-    MUTEX_UNLOCK(&PL_cred_mutex);
+    UNLOCK_CRED_MUTEX;
 
     return res;
 }
@@ -295,7 +289,7 @@ S_emulate_eaccess(pTHX_ const char* path, int mode)
 
 #if !defined(PERL_EFF_ACCESS_R_OK)
 STATIC int
-S_emulate_eaccess(pTHX_ const char* path, int mode)
+S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
 {
     Perl_croak(aTHX_ "switching effective uid is not implemented");
     /*NOTREACHED*/
@@ -310,9 +304,14 @@ PP(pp_backtick)
     STRLEN n_a;
     char *tmps = POPpx;
     I32 gimme = GIMME_V;
+    char *mode = "r";
 
     TAINT_PROPER("``");
-    fp = PerlProc_popen(tmps, "r");
+    if (PL_op->op_private & OPpOPEN_IN_RAW)
+       mode = "rb";
+    else if (PL_op->op_private & OPpOPEN_IN_CRLF)
+       mode = "rt";
+    fp = PerlProc_popen(tmps, mode);
     if (fp) {
        if (gimme == G_VOID) {
            char tmpbuf[256];
@@ -362,6 +361,10 @@ PP(pp_glob)
     OP *result;
     tryAMAGICunTARGET(iter, -1);
 
+    /* Note that we only ever get here if File::Glob fails to load
+     * without at the same time croaking, for some reason, or if
+     * perl was built with PERL_EXTERNAL_GLOB */
+
     ENTER;
 
 #ifndef VMS
@@ -402,7 +405,7 @@ PP(pp_indread)
 
 PP(pp_rcatline)
 {
-    PL_last_in_gv = cGVOP->op_gv;
+    PL_last_in_gv = cGVOP_gv;
     return do_readline();
 }
 
@@ -433,7 +436,7 @@ PP(pp_warn)
     if (!tmps || !len)
        tmpsv = sv_2mortal(newSVpvn("Warning: something's wrong", 26));
 
-    Perl_warn(aTHX_ "%_", tmpsv);
+    Perl_warn(aTHX_ "%"SVf, tmpsv);
     RETSETYES;
 }
 
@@ -466,8 +469,8 @@ PP(pp_die)
                HV *stash = SvSTASH(SvRV(error));
                GV *gv = gv_fetchmethod(stash, "PROPAGATE");
                if (gv) {
-                   SV *file = sv_2mortal(newSVsv(GvSV(PL_curcop->cop_filegv)));
-                   SV *line = sv_2mortal(newSViv(PL_curcop->cop_line));
+                   SV *file = sv_2mortal(newSVpv(CopFILE(PL_curcop),0));
+                   SV *line = sv_2mortal(newSVuv(CopLINE(PL_curcop)));
                    EXTEND(SP, 3);
                    PUSHMARK(SP);
                    PUSHs(error);
@@ -491,7 +494,7 @@ PP(pp_die)
     if (!tmps || !len)
        tmpsv = sv_2mortal(newSVpvn("Died", 4));
 
-    DIE(aTHX_ "%_", tmpsv);
+    DIE(aTHX_ "%"SVf, tmpsv);
 }
 
 /* I/O. */
@@ -501,10 +504,16 @@ PP(pp_open)
     djSP; dTARGET;
     GV *gv;
     SV *sv;
+    SV *name;
+    I32 have_name = 0;
     char *tmps;
     STRLEN len;
     MAGIC *mg;
 
+    if (MAXARG > 2) {
+       name = POPs;
+       have_name = 1;
+    }
     if (MAXARG > 1)
        sv = POPs;
     if (!isGV(TOPs))
@@ -517,26 +526,12 @@ PP(pp_open)
     if (GvIOp(gv))
        IoFLAGS(GvIOp(gv)) &= ~IOf_UNTAINT;
 
-#if 0 /* no undef means tmpfile() yet */
-    if (sv == &PL_sv_undef) {
-#ifdef PerlIO
-       PerlIO *fp = PerlIO_tmpfile();
-#else
-       PerlIO *fp = tmpfile();
-#endif                   
-       if (fp != Nullfp && do_open(gv, "+>&", 3, FALSE, 0, 0, fp)) 
-           PUSHi( (I32)PL_forkprocess );
-       else
-           RETPUSHUNDEF;
-       RETURN;
-    }   
-#endif /* no undef means tmpfile() yet */
-
-
-    if (mg = SvTIED_mg((SV*)gv, 'q')) {
+    if ((mg = SvTIED_mg((SV*)gv, 'q'))) {
        PUSHMARK(SP);
        XPUSHs(SvTIED_obj((SV*)gv, mg));
        XPUSHs(sv);
+       if (have_name)
+           XPUSHs(name);
        PUTBACK;
        ENTER;
        call_method("OPEN", G_SCALAR);
@@ -546,7 +541,7 @@ PP(pp_open)
     }
 
     tmps = SvPV(sv, len);
-    if (do_open(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp))
+    if (do_open9(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp, name, have_name))
        PUSHi( (I32)PL_forkprocess );
     else if (PL_forkprocess == 0)              /* we are a new child */
        PUSHi(0);
@@ -566,7 +561,7 @@ PP(pp_close)
     else
        gv = (GV*)POPs;
 
-    if (mg = SvTIED_mg((SV*)gv, 'q')) {
+    if ((mg = SvTIED_mg((SV*)gv, 'q'))) {
        PUSHMARK(SP);
        XPUSHs(SvTIED_obj((SV*)gv, mg));
        PUTBACK;
@@ -697,15 +692,20 @@ PP(pp_binmode)
     IO *io;
     PerlIO *fp;
     MAGIC *mg;
+    SV *discp = Nullsv;
 
     if (MAXARG < 1)
        RETPUSHUNDEF;
+    if (MAXARG > 1)
+       discp = POPs;
 
     gv = (GV*)POPs; 
 
     if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
        PUSHMARK(SP);
        XPUSHs(SvTIED_obj((SV*)gv, mg));
+       if (discp)
+           XPUSHs(discp);
        PUTBACK;
        ENTER;
        call_method("BINMODE", G_SCALAR);
@@ -718,13 +718,12 @@ PP(pp_binmode)
     if (!(io = GvIO(gv)) || !(fp = IoIFP(io)))
        RETPUSHUNDEF;
 
-    if (do_binmode(fp,IoTYPE(io),TRUE)) 
+    if (do_binmode(fp,IoTYPE(io),mode_from_discipline(discp))) 
        RETPUSHYES;
     else
        RETPUSHUNDEF;
 }
 
-
 PP(pp_tie)
 {
     djSP;
@@ -807,11 +806,11 @@ PP(pp_untie)
 
     if (ckWARN(WARN_UNTIE)) {
         MAGIC * mg ;
-        if (mg = SvTIED_mg(sv, how)) {
+        if ((mg = SvTIED_mg(sv, how))) {
             if (mg && SvREFCNT(SvRV(mg->mg_obj)) > 1)  
                Perl_warner(aTHX_ WARN_UNTIE,
-                   "untie attempted while %lu inner references still exist",
-                   (unsigned long)SvREFCNT(SvRV(mg->mg_obj)) - 1 ) ;
+                   "untie attempted while %"UVuf" inner references still exist",
+                   (UV)SvREFCNT(SvRV(mg->mg_obj)) - 1 ) ;
         }
     }
  
@@ -826,7 +825,7 @@ PP(pp_tied)
     char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) ? 'P' : 'q';
     MAGIC *mg;
 
-    if (mg = SvTIED_mg(sv, how)) {
+    if ((mg = SvTIED_mg(sv, how))) {
        SV *osv = SvTIED_obj(sv, mg);
        if (osv == mg->mg_obj)
            osv = sv_mortalcopy(osv);
@@ -865,9 +864,9 @@ PP(pp_dbmopen)
     PUSHs(sv);
     PUSHs(left);
     if (SvIV(right))
-       PUSHs(sv_2mortal(newSViv(O_RDWR|O_CREAT)));
+       PUSHs(sv_2mortal(newSVuv(O_RDWR|O_CREAT)));
     else
-       PUSHs(sv_2mortal(newSViv(O_RDWR)));
+       PUSHs(sv_2mortal(newSVuv(O_RDWR)));
     PUSHs(right);
     PUTBACK;
     call_sv((SV*)GvCV(gv), G_SCALAR);
@@ -878,7 +877,7 @@ PP(pp_dbmopen)
        PUSHMARK(SP);
        PUSHs(sv);
        PUSHs(left);
-       PUSHs(sv_2mortal(newSViv(O_RDONLY)));
+       PUSHs(sv_2mortal(newSVuv(O_RDONLY)));
        PUSHs(right);
        PUTBACK;
        call_sv((SV*)GvCV(gv), G_SCALAR);
@@ -906,7 +905,7 @@ PP(pp_sselect)
     register I32 j;
     register char *s;
     register SV *sv;
-    double value;
+    NV value;
     I32 maxlen = 0;
     I32 nfound;
     struct timeval timebuf;
@@ -942,7 +941,7 @@ PP(pp_sselect)
     /* If SELECT_MIN_BITS is greater than one we most probably will want
      * to align the sizes with SELECT_MIN_BITS/8 because for example
      * in many little-endian (Intel, Alpha) systems (Linux, OS/2, Digital
-     * UNIX, Solaris, NeXT, Rhapsody) the smallest quantum select() operates
+     * UNIX, Solaris, NeXT, Darwin) the smallest quantum select() operates
      * on (sets/tests/clears bits) is 32 bits.  */
     growsize = maxlen + (SELECT_MIN_BITS/8 - (maxlen % (SELECT_MIN_BITS/8)));
 #  else
@@ -969,7 +968,7 @@ PP(pp_sselect)
        if (value < 0.0)
            value = 0.0;
        timebuf.tv_sec = (long)value;
-       value -= (double)timebuf.tv_sec;
+       value -= (NV)timebuf.tv_sec;
        timebuf.tv_usec = (long)(value * 1000000.0);
     }
     else
@@ -1028,8 +1027,8 @@ PP(pp_sselect)
 
     PUSHi(nfound);
     if (GIMME == G_ARRAY && tbuf) {
-       value = (double)(timebuf.tv_sec) +
-               (double)(timebuf.tv_usec) / 1000000.0;
+       value = (NV)(timebuf.tv_sec) +
+               (NV)(timebuf.tv_usec) / 1000000.0;
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setnv(sv, value);
     }
@@ -1090,14 +1089,12 @@ PP(pp_getc)
     GV *gv;
     MAGIC *mg;
 
-    if (MAXARG <= 0)
+    if (MAXARG == 0)
        gv = PL_stdingv;
     else
        gv = (GV*)POPs;
-    if (!gv)
-       gv = PL_argvgv;
 
-    if (mg = SvTIED_mg((SV*)gv, 'q')) {
+    if ((mg = SvTIED_mg((SV*)gv, 'q'))) {
        I32 gimme = GIMME_V;
        PUSHMARK(SP);
        XPUSHs(SvTIED_obj((SV*)gv, mg));
@@ -1137,9 +1134,9 @@ S_doform(pTHX_ CV *cv, GV *gv, OP *retop)
     SAVETMPS;
 
     push_return(retop);
-    PUSHBLOCK(cx, CXt_SUB, PL_stack_sp);
+    PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp);
     PUSHFORMAT(cx);
-    SAVESPTR(PL_curpad);
+    SAVEVPTR(PL_curpad);
     PL_curpad = AvARRAY((AV*)svp[1]);
 
     setdefout(gv);         /* locally select filehandle so $% et al work */
@@ -1272,10 +1269,15 @@ PP(pp_leavewrite)
     fp = IoOFP(io);
     if (!fp) {
        if (ckWARN2(WARN_CLOSED,WARN_IO)) {
-           if (IoIFP(io))
-               Perl_warner(aTHX_ WARN_IO, "Filehandle only opened for input");
+           if (IoIFP(io)) {
+               SV* sv = sv_newmortal();
+               gv_efullname3(sv, gv, Nullch);
+               Perl_warner(aTHX_ WARN_IO,
+                           "Filehandle %s opened only for input",
+                           SvPV_nolen(sv));
+           }
            else if (ckWARN(WARN_CLOSED))
-               Perl_warner(aTHX_ WARN_CLOSED, "Write on closed filehandle");
+               report_closed_fh(gv, io, "write", "filehandle");
        }
        PUSHs(&PL_sv_no);
     }
@@ -1316,7 +1318,7 @@ PP(pp_prtf)
     else
        gv = PL_defoutgv;
 
-    if (mg = SvTIED_mg((SV*)gv, 'q')) {
+    if ((mg = SvTIED_mg((SV*)gv, 'q'))) {
        if (MARK == ORIGMARK) {
            MEXTEND(SP, 1);
            ++MARK;
@@ -1339,21 +1341,23 @@ PP(pp_prtf)
     sv = NEWSV(0,0);
     if (!(io = GvIO(gv))) {
        if (ckWARN(WARN_UNOPENED)) {
-           gv_fullname3(sv, gv, Nullch);
-           Perl_warner(aTHX_ WARN_UNOPENED, "Filehandle %s never opened", SvPV(sv,n_a));
+           gv_efullname3(sv, gv, Nullch);
+           Perl_warner(aTHX_ WARN_UNOPENED,
+                       "Filehandle %s never opened", SvPV(sv,n_a));
        }
        SETERRNO(EBADF,RMS$_IFI);
        goto just_say_no;
     }
     else if (!(fp = IoOFP(io))) {
        if (ckWARN2(WARN_CLOSED,WARN_IO))  {
-           gv_fullname3(sv, gv, Nullch);
-           if (IoIFP(io))
-               Perl_warner(aTHX_ WARN_IO, "Filehandle %s opened only for input",
-                       SvPV(sv,n_a));
+           if (IoIFP(io)) {
+               gv_efullname3(sv, gv, Nullch);
+               Perl_warner(aTHX_ WARN_IO,
+                           "Filehandle %s opened only for input",
+                           SvPV(sv,n_a));
+           }
            else if (ckWARN(WARN_CLOSED))
-               Perl_warner(aTHX_ WARN_CLOSED, "printf on closed filehandle %s",
-                       SvPV(sv,n_a));
+               report_closed_fh(gv, io, "printf", "filehandle");
        }
        SETERRNO(EBADF,IoIFP(io)?RMS$_FAC:RMS$_IFI);
        goto just_say_no;
@@ -1469,6 +1473,10 @@ PP(pp_sysread)
        if (bufsize >= 256)
            bufsize = 255;
 #endif
+#ifdef OS2     /* At least Warp3+IAK: only the first byte of bufsize set */
+       if (bufsize >= 256)
+           bufsize = 255;
+#endif
        buffer = SvGROW(bufsv, length+1);
        /* 'offset' means 'flags' here */
        length = PerlSock_recvfrom(PerlIO_fileno(IoIFP(io)), buffer, length, offset,
@@ -1534,8 +1542,17 @@ PP(pp_sysread)
        if (length == 0 && PerlIO_error(IoIFP(io)))
            length = -1;
     }
-    if (length < 0)
+    if (length < 0) {
+       if ((IoTYPE(io) == '>' || IoIFP(io) == PerlIO_stdout()
+           || IoIFP(io) == PerlIO_stderr()) && ckWARN(WARN_IO))
+       {
+           SV* sv = sv_newmortal();
+           gv_efullname3(sv, gv, Nullch);
+           Perl_warner(aTHX_ WARN_IO, "Filehandle %s opened only for output",
+                       SvPV_nolen(sv));
+       }
        goto say_undef;
+    }
     SvCUR_set(bufsv, length+offset);
     *SvEND(bufsv) = '\0';
     (void)SvPOK_only(bufsv);
@@ -1571,10 +1588,11 @@ PP(pp_send)
     djSP; dMARK; dORIGMARK; dTARGET;
     GV *gv;
     IO *io;
-    int offset;
     SV *bufsv;
     char *buffer;
-    int length;
+    Size_t length;
+    SSize_t retval;
+    IV offset;
     STRLEN blen;
     MAGIC *mg;
 
@@ -1597,18 +1615,22 @@ PP(pp_send)
        goto say_undef;
     bufsv = *++MARK;
     buffer = SvPV(bufsv, blen);
-    length = SvIVx(*++MARK);
-    if (length < 0)
+#if Size_t_size > IVSIZE
+    length = (Size_t)SvNVx(*++MARK);
+#else
+    length = (Size_t)SvIVx(*++MARK);
+#endif
+    if ((SSize_t)length < 0)
        DIE(aTHX_ "Negative length");
     SETERRNO(0,0);
     io = GvIO(gv);
     if (!io || !IoIFP(io)) {
-       length = -1;
+       retval = -1;
        if (ckWARN(WARN_CLOSED)) {
            if (PL_op->op_type == OP_SYSWRITE)
-               Perl_warner(aTHX_ WARN_CLOSED, "Syswrite on closed filehandle");
+               report_closed_fh(gv, io, "syswrite", "filehandle");
            else
-               Perl_warner(aTHX_ WARN_CLOSED, "Send on closed socket");
+               report_closed_fh(gv, io, "send", "socket");
        }
     }
     else if (PL_op->op_type == OP_SYSWRITE) {
@@ -1626,13 +1648,14 @@ PP(pp_send)
            length = blen - offset;
 #ifdef PERL_SOCK_SYSWRITE_IS_SEND
        if (IoTYPE(io) == 's') {
-           length = PerlSock_send(PerlIO_fileno(IoIFP(io)),
+           retval = PerlSock_send(PerlIO_fileno(IoIFP(io)),
                                   buffer+offset, length, 0);
        }
        else
 #endif
        {
-           length = PerlLIO_write(PerlIO_fileno(IoIFP(io)),
+           /* See the note at doio.c:do_print about filesize limits. --jhi */
+           retval = PerlLIO_write(PerlIO_fileno(IoIFP(io)),
                                   buffer+offset, length);
        }
     }
@@ -1641,20 +1664,24 @@ PP(pp_send)
        char *sockbuf;
        STRLEN mlen;
        sockbuf = SvPVx(*++MARK, mlen);
-       length = PerlSock_sendto(PerlIO_fileno(IoIFP(io)), buffer, blen, length,
-                               (struct sockaddr *)sockbuf, mlen);
+       retval = PerlSock_sendto(PerlIO_fileno(IoIFP(io)), buffer, blen,
+                                length, (struct sockaddr *)sockbuf, mlen);
     }
     else
-       length = PerlSock_send(PerlIO_fileno(IoIFP(io)), buffer, blen, length);
+       retval = PerlSock_send(PerlIO_fileno(IoIFP(io)), buffer, blen, length);
 
 #else
     else
        DIE(aTHX_ PL_no_sock_func, "send");
 #endif
-    if (length < 0)
+    if (retval < 0)
        goto say_undef;
     SP = ORIGMARK;
-    PUSHi(length);
+#if Size_t_size > IVSIZE
+    PUSHn(retval);
+#else
+    PUSHi(retval);
+#endif
     RETURN;
 
   say_undef:
@@ -1673,10 +1700,28 @@ PP(pp_eof)
     GV *gv;
     MAGIC *mg;
 
-    if (MAXARG <= 0)
-       gv = PL_last_in_gv;
+    if (MAXARG == 0) {
+       if (PL_op->op_flags & OPf_SPECIAL) {    /* eof() */
+           IO *io;
+           gv = PL_last_in_gv = PL_argvgv;
+           io = GvIO(gv);
+           if (io && !IoIFP(io)) {
+               if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) {
+                   IoLINES(io) = 0;
+                   IoFLAGS(io) &= ~IOf_START;
+                   do_open(gv, "-", 1, FALSE, O_RDONLY, 0, Nullfp);
+                   sv_setpvn(GvSV(gv), "-", 1);
+                   SvSETMAGIC(GvSV(gv));
+               }
+               else if (!nextargv(gv))
+                   RETPUSHYES;
+           }
+       }
+       else
+           gv = PL_last_in_gv;                 /* eof */
+    }
     else
-       gv = PL_last_in_gv = (GV*)POPs;
+       gv = PL_last_in_gv = (GV*)POPs;         /* eof(FH) */
 
     if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
        PUSHMARK(SP);
@@ -1699,7 +1744,7 @@ PP(pp_tell)
     GV *gv;     
     MAGIC *mg;
 
-    if (MAXARG <= 0)
+    if (MAXARG == 0)
        gv = PL_last_in_gv;
     else
        gv = PL_last_in_gv = (GV*)POPs;
@@ -1715,7 +1760,11 @@ PP(pp_tell)
        RETURN;
     }
 
+#if LSEEKSIZE > IVSIZE
+    PUSHn( do_tell(gv) );
+#else
     PUSHi( do_tell(gv) );
+#endif
     RETURN;
 }
 
@@ -1729,7 +1778,11 @@ PP(pp_sysseek)
     djSP;
     GV *gv;
     int whence = POPi;
-    Off_t offset = POPl;
+#if LSEEKSIZE > IVSIZE
+    Off_t offset = (Off_t)SvNVx(POPs);
+#else
+    Off_t offset = (Off_t)SvIVx(POPs);
+#endif
     MAGIC *mg;
 
     gv = PL_last_in_gv = (GV*)POPs;
@@ -1737,8 +1790,12 @@ PP(pp_sysseek)
     if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
        PUSHMARK(SP);
        XPUSHs(SvTIED_obj((SV*)gv, mg));
-       XPUSHs(sv_2mortal(newSViv((IV) offset)));
-       XPUSHs(sv_2mortal(newSViv((IV) whence)));
+#if LSEEKSIZE > IVSIZE
+       XPUSHs(sv_2mortal(newSVnv((NV) offset)));
+#else
+       XPUSHs(sv_2mortal(newSViv(offset)));
+#endif
+       XPUSHs(sv_2mortal(newSViv(whence)));
        PUTBACK;
        ENTER;
        call_method("SEEK", G_SCALAR);
@@ -1750,10 +1807,19 @@ PP(pp_sysseek)
     if (PL_op->op_type == OP_SEEK)
        PUSHs(boolSV(do_seek(gv, offset, whence)));
     else {
-       Off_t n = do_sysseek(gv, offset, whence);
-       PUSHs((n < 0) ? &PL_sv_undef
-             : sv_2mortal(n ? newSViv((IV)n)
-                          : newSVpvn(zero_but_true, ZBTLEN)));
+       Off_t sought = do_sysseek(gv, offset, whence);
+        if (sought < 0)
+            PUSHs(&PL_sv_undef);
+        else {
+            SV* sv = sought ?
+#if LSEEKSIZE > IVSIZE
+                newSVnv((NV)sought)
+#else
+                newSViv(sought)
+#endif
+                : newSVpvn(zero_but_true, ZBTLEN);
+            PUSHs(sv_2mortal(sv));
+        }
     }
     RETURN;
 }
@@ -1761,24 +1827,41 @@ PP(pp_sysseek)
 PP(pp_truncate)
 {
     djSP;
-    Off_t len = (Off_t)POPn;
+    /* There seems to be no consensus on the length type of truncate()
+     * and ftruncate(), both off_t and size_t have supporters. In
+     * general one would think that when using large files, off_t is
+     * at least as wide as size_t, so using an off_t should be okay. */
+    /* XXX Configure probe for the length type of *truncate() needed XXX */
+    Off_t len;
     int result = 1;
     GV *tmpgv;
     STRLEN n_a;
 
+#if Size_t_size > IVSIZE
+    len = (Off_t)POPn;
+#else
+    len = (Off_t)POPi;
+#endif
+    /* Checking for length < 0 is problematic as the type might or
+     * might not be signed: if it is not, clever compilers will moan. */ 
+    /* XXX Configure probe for the signedness of the length type of *truncate() needed? XXX */
     SETERRNO(0,0);
 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) || defined(F_FREESP)
     if (PL_op->op_flags & OPf_SPECIAL) {
        tmpgv = gv_fetchpv(POPpx, FALSE, SVt_PVIO);
     do_ftruncate:
        TAINT_PROPER("truncate");
-       if (!GvIO(tmpgv) || !IoIFP(GvIOp(tmpgv)) ||
+       if (!GvIO(tmpgv) || !IoIFP(GvIOp(tmpgv)))
+           result = 0;
+       else {
+           PerlIO_flush(IoIFP(GvIOp(tmpgv)));
 #ifdef HAS_TRUNCATE
-         ftruncate(PerlIO_fileno(IoIFP(GvIOn(tmpgv))), len) < 0)
+           if (ftruncate(PerlIO_fileno(IoIFP(GvIOn(tmpgv))), len) < 0)
 #else 
-         my_chsize(PerlIO_fileno(IoIFP(GvIOn(tmpgv))), len) < 0)
+           if (my_chsize(PerlIO_fileno(IoIFP(GvIOn(tmpgv))), len) < 0)
 #endif
-           result = 0;
+               result = 0;
+       }
     }
     else {
        SV *sv = POPs;
@@ -1858,7 +1941,7 @@ PP(pp_ioctl)
     }
     else {
        retval = SvIV(argsv);
-       s = (char*)retval;              /* ouch */
+       s = INT2PTR(char*,retval);              /* ouch */
     }
 
     TAINT_PROPER(optype == OP_IOCTL ? "ioctl" : "fcntl");
@@ -1909,7 +1992,7 @@ PP(pp_flock)
 
 #ifdef FLOCK
     argtype = POPi;
-    if (MAXARG <= 0)
+    if (MAXARG == 0)
        gv = PL_last_in_gv;
     else
        gv = (GV*)POPs;
@@ -1921,8 +2004,12 @@ PP(pp_flock)
        (void)PerlIO_flush(fp);
        value = (I32)(PerlLIO_flock(PerlIO_fileno(fp), argtype) >= 0);
     }
-    else
+    else {
        value = 0;
+       SETERRNO(EBADF,RMS$_IFI);
+       if (ckWARN(WARN_CLOSED))
+           report_closed_fh(gv, GvIO(gv), "flock", "filehandle");
+    }
     PUSHi(value);
     RETURN;
 #else
@@ -1967,6 +2054,9 @@ PP(pp_socket)
        if (!IoIFP(io) && !IoOFP(io)) PerlLIO_close(fd);
        RETPUSHUNDEF;
     }
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+    fcntl(fd, F_SETFD, fd > PL_maxsysfd);      /* ensure close-on-exec */
+#endif
 
     RETPUSHYES;
 #else
@@ -2017,6 +2107,10 @@ PP(pp_sockpair)
        if (!IoIFP(io2) && !IoOFP(io2)) PerlLIO_close(fd[1]);
        RETPUSHUNDEF;
     }
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+    fcntl(fd[0],F_SETFD,fd[0] > PL_maxsysfd);  /* ensure close-on-exec */
+    fcntl(fd[1],F_SETFD,fd[1] > PL_maxsysfd);  /* ensure close-on-exec */
+#endif
 
     RETPUSHYES;
 #else
@@ -2075,7 +2169,7 @@ PP(pp_bind)
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "bind() on closed fd");
+       report_closed_fh(gv, io, "bind", "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
@@ -2105,7 +2199,7 @@ PP(pp_connect)
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "connect() on closed fd");
+       report_closed_fh(gv, io, "connect", "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
@@ -2131,7 +2225,7 @@ PP(pp_listen)
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "listen() on closed fd");
+       report_closed_fh(gv, io, "listen", "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
@@ -2179,13 +2273,16 @@ PP(pp_accept)
        if (!IoIFP(nstio) && !IoOFP(nstio)) PerlLIO_close(fd);
        goto badexit;
     }
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+    fcntl(fd, F_SETFD, fd > PL_maxsysfd);      /* ensure close-on-exec */
+#endif
 
     PUSHp((char *)&saddr, len);
     RETURN;
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "accept() on closed fd");
+       report_closed_fh(ggv, ggv ? GvIO(ggv) : 0, "accept", "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
 
 badexit:
@@ -2212,7 +2309,7 @@ PP(pp_shutdown)
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "shutdown() on closed fd");
+       report_closed_fh(gv, io, "shutdown", "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
@@ -2291,7 +2388,9 @@ PP(pp_ssockopt)
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "[gs]etsockopt() on closed fd");
+       report_closed_fh(gv, io,
+                        optype == OP_GSOCKOPT ? "getsockopt" : "setsockopt",
+                        "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
 nuts2:
     RETPUSHUNDEF;
@@ -2364,7 +2463,10 @@ PP(pp_getpeername)
 
 nuts:
     if (ckWARN(WARN_CLOSED))
-       Perl_warner(aTHX_ WARN_CLOSED, "get{sock, peer}name() on closed fd");
+       report_closed_fh(gv, io,
+                        optype == OP_GETSOCKNAME ? "getsockname"
+                                                 : "getpeername",
+                        "socket");
     SETERRNO(EBADF,SS$_IVCHAN);
 nuts2:
     RETPUSHUNDEF;
@@ -2390,7 +2492,7 @@ PP(pp_stat)
     STRLEN n_a;
 
     if (PL_op->op_flags & OPf_REF) {
-       tmpgv = cGVOP->op_gv;
+       tmpgv = cGVOP_gv;
       do_fstat:
        if (tmpgv != PL_defgv) {
            PL_laststype = OP_STAT;
@@ -2437,30 +2539,50 @@ PP(pp_stat)
     if (max) {
        EXTEND(SP, max);
        EXTEND_MORTAL(max);
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_dev)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_ino)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_mode)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_nlink)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_uid)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_gid)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_dev)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ino)));
+       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_mode)));
+       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_nlink)));
+#if Uid_t_size > IVSIZE
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_uid)));
+#else
+#   if Uid_t_sign <= 0
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_uid)));
+#   else
+       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_uid)));
+#   endif
+#endif
+#if Gid_t_size > IVSIZE 
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_gid)));
+#else
+#   if Gid_t_sign <= 0
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_gid)));
+#   else
+       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_gid)));
+#   endif
+#endif
 #ifdef USE_STAT_RDEV
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_rdev)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_rdev)));
 #else
        PUSHs(sv_2mortal(newSVpvn("", 0)));
 #endif
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_size)));
+#if Off_t_size > IVSIZE
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_size)));
+#else
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_size)));
+#endif
 #ifdef BIG_TIME
-       PUSHs(sv_2mortal(newSVnv((U32)PL_statcache.st_atime)));
-       PUSHs(sv_2mortal(newSVnv((U32)PL_statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSVnv((U32)PL_statcache.st_ctime)));
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_atime)));
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_mtime)));
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_ctime)));
 #else
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_atime)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_ctime)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_atime)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_mtime)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ctime)));
 #endif
 #ifdef USE_STAT_BLOCKS
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_blksize)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_blocks)));
+       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_blksize)));
+       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_blocks)));
 #else
        PUSHs(sv_2mortal(newSVpvn("", 0)));
        PUSHs(sv_2mortal(newSVpvn("", 0)));
@@ -2651,7 +2773,8 @@ PP(pp_ftrowned)
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (PL_statcache.st_uid == (PL_op->op_type == OP_FTEOWNED ? PL_euid : PL_uid) )
+    if (PL_statcache.st_uid == (PL_op->op_type == OP_FTEOWNED ?
+                               PL_euid : PL_uid) )
        RETPUSHYES;
     RETPUSHNO;
 }
@@ -2662,7 +2785,7 @@ PP(pp_ftzero)
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (!PL_statcache.st_size)
+    if (PL_statcache.st_size == 0)
        RETPUSHYES;
     RETPUSHNO;
 }
@@ -2673,7 +2796,11 @@ PP(pp_ftsize)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
+#if Off_t_size > IVSIZE
+    PUSHn(PL_statcache.st_size);
+#else
     PUSHi(PL_statcache.st_size);
+#endif
     RETURN;
 }
 
@@ -2683,7 +2810,7 @@ PP(pp_ftmtime)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)PL_basetime - (I32)PL_statcache.st_mtime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_mtime) / 86400.0 );
     RETURN;
 }
 
@@ -2693,7 +2820,7 @@ PP(pp_ftatime)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)PL_basetime - (I32)PL_statcache.st_atime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_atime) / 86400.0 );
     RETURN;
 }
 
@@ -2703,7 +2830,7 @@ PP(pp_ftctime)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)PL_basetime - (I32)PL_statcache.st_ctime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_ctime) / 86400.0 );
     RETURN;
 }
 
@@ -2835,7 +2962,7 @@ PP(pp_fttty)
     STRLEN n_a;
 
     if (PL_op->op_flags & OPf_REF)
-       gv = cGVOP->op_gv;
+       gv = cGVOP_gv;
     else if (isGV(TOPs))
        gv = (GV*)POPs;
     else if (SvROK(TOPs) && isGV(SvRV(TOPs)))
@@ -2874,9 +3001,10 @@ PP(pp_fttext)
     register SV *sv;
     GV *gv;
     STRLEN n_a;
+    PerlIO *fp;
 
     if (PL_op->op_flags & OPf_REF)
-       gv = cGVOP->op_gv;
+       gv = cGVOP_gv;
     else if (isGV(TOPs))
        gv = (GV*)POPs;
     else if (SvROK(TOPs) && isGV(SvRV(TOPs)))
@@ -2925,9 +3053,11 @@ PP(pp_fttext)
                len = 512;
        }
        else {
-           if (ckWARN(WARN_UNOPENED))
+           if (ckWARN(WARN_UNOPENED)) {
+               gv = cGVOP_gv;
                Perl_warner(aTHX_ WARN_UNOPENED, "Test on unopened file <%s>",
-                 GvENAME(cGVOP->op_gv));
+                           GvENAME(gv));
+           }
            SETERRNO(EBADF,RMS$_IFI);
            RETPUSHUNDEF;
        }
@@ -2938,21 +3068,19 @@ PP(pp_fttext)
        PL_statgv = Nullgv;
        PL_laststatval = -1;
        sv_setpv(PL_statname, SvPV(sv, n_a));
-#ifdef HAS_OPEN3
-       i = PerlLIO_open3(SvPV(sv, n_a), O_RDONLY, 0);
-#else
-       i = PerlLIO_open(SvPV(sv, n_a), 0);
-#endif
-       if (i < 0) {
+       if (!(fp = PerlIO_open(SvPVX(PL_statname), "r"))) {
            if (ckWARN(WARN_NEWLINE) && strchr(SvPV(sv, n_a), '\n'))
                Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
            RETPUSHUNDEF;
        }
-       PL_laststatval = PerlLIO_fstat(i, &PL_statcache);
-       if (PL_laststatval < 0)
+       PL_laststatval = PerlLIO_fstat(PerlIO_fileno(fp), &PL_statcache);
+       if (PL_laststatval < 0) {
+           (void)PerlIO_close(fp);
            RETPUSHUNDEF;
-       len = PerlLIO_read(i, tbuf, 512);
-       (void)PerlLIO_close(i);
+       }
+       do_binmode(fp, '<', O_BINARY);
+       len = PerlIO_read(fp, tbuf, sizeof(tbuf));
+       (void)PerlIO_close(fp);
        if (len <= 0) {
            if (S_ISDIR(PL_statcache.st_mode) && PL_op->op_type == OP_FTTEXT)
                RETPUSHNO;              /* special case NFS directories */
@@ -2964,6 +3092,12 @@ PP(pp_fttext)
     /* now scan s to look for textiness */
     /*   XXX ASCII dependent code */
 
+#if defined(DOSISH) || defined(USEMYBINMODE)
+    /* ignore trailing ^Z on short files */
+    if (len && len < sizeof(tbuf) && tbuf[len-1] == 26)
+       --len;
+#endif
+
     for (i = 0; i < len; i++, s++) {
        if (!*s) {                      /* null never allowed in text */
            odd += len;
@@ -2973,8 +3107,29 @@ PP(pp_fttext)
         else if (!(isPRINT(*s) || isSPACE(*s))) 
             odd++;
 #else
-       else if (*s & 128)
+       else if (*s & 128) {
+#ifdef USE_LOCALE
+           if ((PL_op->op_private & OPpLOCALE) && isALPHA_LC(*s))
+               continue;
+#endif
+           /* utf8 characters don't count as odd */
+           if (*s & 0x40) {
+               int ulen = UTF8SKIP(s);
+               if (ulen < len - i) {
+                   int j;
+                   for (j = 1; j < ulen; j++) {
+                       if ((s[j] & 0xc0) != 0x80)
+                           goto not_utf8;
+                   }
+                   --ulen;     /* loop does extra increment */
+                   s += ulen;
+                   i += ulen;
+                   continue;
+               }
+           }
+         not_utf8:
            odd++;
+       }
        else if (*s < 32 &&
          *s != '\n' && *s != '\r' && *s != '\b' &&
          *s != '\t' && *s != '\f' && *s != 27)
@@ -3127,7 +3282,7 @@ PP(pp_link)
     char *tmps2 = POPpx;
     char *tmps = SvPV(TOPs, n_a);
     TAINT_PROPER("link");
-    SETi( link(tmps, tmps2) >= 0 );
+    SETi( PerlLIO_link(tmps, tmps2) >= 0 );
 #else
     DIE(aTHX_ PL_no_func, "Unsupported function link");
 #endif
@@ -3264,12 +3419,19 @@ S_dooneliner(pTHX_ char *cmd, char *filename)
 PP(pp_mkdir)
 {
     djSP; dTARGET;
-    int mode = POPi;
+    int mode;
 #ifndef HAS_MKDIR
     int oldumask;
 #endif
     STRLEN n_a;
-    char *tmps = SvPV(TOPs, n_a);
+    char *tmps;
+
+    if (MAXARG > 1)
+       mode = POPi;
+    else
+       mode = 0777;
+
+    tmps = SvPV(TOPs, n_a);
 
     TAINT_PROPER("mkdir");
 #ifdef HAS_MKDIR
@@ -3345,14 +3507,15 @@ PP(pp_readdir)
 
     if (GIMME == G_ARRAY) {
        /*SUPPRESS 560*/
-       while (dp = (Direntry_t *)PerlDir_read(IoDIRP(io))) {
+       while ((dp = (Direntry_t *)PerlDir_read(IoDIRP(io)))) {
 #ifdef DIRNAMLEN
            sv = newSVpvn(dp->d_name, dp->d_namlen);
 #else
            sv = newSVpv(dp->d_name, 0);
 #endif
 #ifndef INCOMPLETE_TAINTS
-           SvTAINTED_on(sv);
+           if (!(IoFLAGS(io) & IOf_UNTAINT))
+               SvTAINTED_on(sv);
 #endif
            XPUSHs(sv_2mortal(sv));
        }
@@ -3366,7 +3529,8 @@ PP(pp_readdir)
        sv = newSVpv(dp->d_name, 0);
 #endif
 #ifndef INCOMPLETE_TAINTS
-       SvTAINTED_on(sv);
+       if (!(IoFLAGS(io) & IOf_UNTAINT))
+           SvTAINTED_on(sv);
 #endif
        XPUSHs(sv_2mortal(sv));
     }
@@ -3502,20 +3666,31 @@ PP(pp_fork)
        RETSETUNDEF;
     if (!childpid) {
        /*SUPPRESS 560*/
-       if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV))
-           sv_setiv(GvSV(tmpgv), (IV)getpid());
+       if ((tmpgv = gv_fetchpv("$", TRUE, SVt_PV)))
+           sv_setiv(GvSV(tmpgv), (IV)PerlProc_getpid());
        hv_clear(PL_pidstatus); /* no kids, so don't wait for 'em */
     }
     PUSHi(childpid);
     RETURN;
 #else
+#  if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
+    djSP; dTARGET;
+    Pid_t childpid;
+
+    EXTEND(SP, 1);
+    PERL_FLUSHALL_FOR_CHILD;
+    childpid = PerlProc_fork();
+    PUSHi(childpid);
+    RETURN;
+#  else
     DIE(aTHX_ PL_no_func, "Unsupported function fork");
+#  endif
 #endif
 }
 
 PP(pp_wait)
 {
-#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32)
+#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL) 
     djSP; dTARGET;
     Pid_t childpid;
     int argflags;
@@ -3531,7 +3706,7 @@ PP(pp_wait)
 
 PP(pp_waitpid)
 {
-#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32)
+#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL) 
     djSP; dTARGET;
     Pid_t childpid;
     int optype;
@@ -3557,6 +3732,8 @@ PP(pp_system)
     int status;
     Sigsave_t ihand,qhand;     /* place to save signals during system() */
     STRLEN n_a;
+    I32 did_pipes = 0;
+    int pp[2];
 
     if (SP - MARK == 1) {
        if (PL_tainting) {
@@ -3567,16 +3744,24 @@ PP(pp_system)
     }
     PERL_FLUSHALL_FOR_CHILD;
 #if (defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(OS2)
+    if (PerlProc_pipe(pp) >= 0)
+       did_pipes = 1;
     while ((childpid = vfork()) == -1) {
        if (errno != EAGAIN) {
            value = -1;
            SP = ORIGMARK;
            PUSHi(value);
+           if (did_pipes) {
+               PerlLIO_close(pp[0]);
+               PerlLIO_close(pp[1]);
+           }
            RETURN;
        }
        sleep(5);
     }
     if (childpid > 0) {
+       if (did_pipes)
+           PerlLIO_close(pp[1]);
        rsignal_save(SIGINT, SIG_IGN, &ihand);
        rsignal_save(SIGQUIT, SIG_IGN, &qhand);
        do {
@@ -3587,28 +3772,54 @@ PP(pp_system)
        STATUS_NATIVE_SET(result == -1 ? -1 : status);
        do_execfree();  /* free any memory child malloced on vfork */
        SP = ORIGMARK;
+       if (did_pipes) {
+           int errkid;
+           int n = 0, n1;
+
+           while (n < sizeof(int)) {
+               n1 = PerlLIO_read(pp[0],
+                                 (void*)(((char*)&errkid)+n),
+                                 (sizeof(int)) - n);
+               if (n1 <= 0)
+                   break;
+               n += n1;
+           }
+           PerlLIO_close(pp[0]);
+           if (n) {                    /* Error */
+               if (n != sizeof(int))
+                   DIE(aTHX_ "panic: kid popen errno read");
+               errno = errkid;         /* Propagate errno from kid */
+               STATUS_CURRENT = -1;
+           }
+       }
        PUSHi(STATUS_CURRENT);
        RETURN;
     }
+    if (did_pipes) {
+       PerlLIO_close(pp[0]);
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+       fcntl(pp[1], F_SETFD, FD_CLOEXEC);
+#endif
+    }
     if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
-       value = (I32)do_aexec(really, MARK, SP);
+       value = (I32)do_aexec5(really, MARK, SP, pp[1], did_pipes);
     }
     else if (SP - MARK != 1)
-       value = (I32)do_aexec(Nullsv, MARK, SP);
+       value = (I32)do_aexec5(Nullsv, MARK, SP, pp[1], did_pipes);
     else {
-       value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
+       value = (I32)do_exec3(SvPVx(sv_mortalcopy(*SP), n_a), pp[1], did_pipes);
     }
     PerlProc__exit(-1);
 #else /* ! FORK or VMS or OS/2 */
     if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
-       value = (I32)do_aspawn(aTHX_ really, (void **)MARK, (void **)SP);
+       value = (I32)do_aspawn(really, (void **)MARK, (void **)SP);
     }
     else if (SP - MARK != 1)
-       value = (I32)do_aspawn(aTHX_ Nullsv, (void **)MARK, (void **)SP);
+       value = (I32)do_aspawn(Nullsv, (void **)MARK, (void **)SP);
     else {
-       value = (I32)do_spawn(aTHX_ SvPVx(sv_mortalcopy(*SP), n_a));
+       value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), n_a));
     }
     STATUS_NATIVE_SET(value);
     do_execfree();
@@ -3635,7 +3846,7 @@ PP(pp_exec)
 #else
 #  ifdef __OPEN_VM
        {
-          (void ) do_aspawn(aTHX_ Nullsv, MARK, SP);
+          (void ) do_aspawn(Nullsv, MARK, SP);
           value = 0;
        }
 #  else
@@ -3652,13 +3863,19 @@ PP(pp_exec)
        value = (I32)vms_do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
 #else
 #  ifdef __OPEN_VM
-       (void) do_spawn(aTHX_ SvPVx(sv_mortalcopy(*SP), n_a));
+       (void) do_spawn(SvPVx(sv_mortalcopy(*SP), n_a));
        value = 0;
 #  else
        value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
 #  endif
 #endif
     }
+
+#if !defined(HAS_FORK) && defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
+    if (value >= 0)
+       my_exit(value);
+#endif
+
     SP = ORIGMARK;
     PUSHi(value);
     RETURN;
@@ -3693,21 +3910,21 @@ PP(pp_getpgrp)
 {
 #ifdef HAS_GETPGRP
     djSP; dTARGET;
-    int pid;
-    I32 value;
+    Pid_t pid;
+    Pid_t pgrp;
 
     if (MAXARG < 1)
        pid = 0;
     else
        pid = SvIVx(POPs);
 #ifdef BSD_GETPGRP
-    value = (I32)BSD_GETPGRP(pid);
+    pgrp = (I32)BSD_GETPGRP(pid);
 #else
-    if (pid != 0 && pid != getpid())
+    if (pid != 0 && pid != PerlProc_getpid())
        DIE(aTHX_ "POSIX getpgrp can't take an argument");
-    value = (I32)getpgrp();
+    pgrp = getpgrp();
 #endif
-    XPUSHi(value);
+    XPUSHi(pgrp);
     RETURN;
 #else
     DIE(aTHX_ PL_no_func, "getpgrp()");
@@ -3718,8 +3935,8 @@ PP(pp_setpgrp)
 {
 #ifdef HAS_SETPGRP
     djSP; dTARGET;
-    int pgrp;
-    int pid;
+    Pid_t pgrp;
+    Pid_t pid;
     if (MAXARG < 2) {
        pgrp = 0;
        pid = 0;
@@ -3733,8 +3950,11 @@ PP(pp_setpgrp)
 #ifdef BSD_SETPGRP
     SETi( BSD_SETPGRP(pid, pgrp) >= 0 );
 #else
-    if ((pgrp != 0 && pgrp != getpid()) || (pid != 0 && pid != getpid()))
-       DIE(aTHX_ "POSIX setpgrp can't take an argument");
+    if ((pgrp != 0 && pgrp != PerlProc_getpid())
+       || (pid != 0 && pid != PerlProc_getpid()))
+    {
+       DIE(aTHX_ "setpgrp can't take arguments");
+    }
     SETi( setpgrp() >= 0 );
 #endif /* USE_BSDPGRP */
     RETURN;
@@ -3822,11 +4042,11 @@ PP(pp_tms)
                                                    /* is returned.                   */
 #endif
 
-    PUSHs(sv_2mortal(newSVnv(((double)PL_timesbuf.tms_utime)/HZ)));
+    PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_utime)/HZ)));
     if (GIMME == G_ARRAY) {
-       PUSHs(sv_2mortal(newSVnv(((double)PL_timesbuf.tms_stime)/HZ)));
-       PUSHs(sv_2mortal(newSVnv(((double)PL_timesbuf.tms_cutime)/HZ)));
-       PUSHs(sv_2mortal(newSVnv(((double)PL_timesbuf.tms_cstime)/HZ)));
+       PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_stime)/HZ)));
+       PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_cutime)/HZ)));
+       PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_cstime)/HZ)));
     }
     RETURN;
 #endif /* HAS_TIMES */
@@ -3863,30 +4083,29 @@ PP(pp_gmtime)
     EXTEND(SP, 9);
     EXTEND_MORTAL(9);
     if (GIMME != G_ARRAY) {
-       dTARGET;
        SV *tsv;
        if (!tmbuf)
            RETPUSHUNDEF;
        tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %d",
-                      dayname[tmbuf->tm_wday],
-                      monname[tmbuf->tm_mon],
-                      tmbuf->tm_mday,
-                      tmbuf->tm_hour,
-                      tmbuf->tm_min,
-                      tmbuf->tm_sec,
-                      tmbuf->tm_year + 1900);
+                           dayname[tmbuf->tm_wday],
+                           monname[tmbuf->tm_mon],
+                           tmbuf->tm_mday,
+                           tmbuf->tm_hour,
+                           tmbuf->tm_min,
+                           tmbuf->tm_sec,
+                           tmbuf->tm_year + 1900);
        PUSHs(sv_2mortal(tsv));
     }
     else if (tmbuf) {
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_sec)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_min)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_hour)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mday)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mon)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_year)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_wday)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_yday)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_isdst)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_sec)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_min)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_hour)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_mday)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_mon)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_year)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_wday)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_yday)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_isdst)));
     }
     RETURN;
 }
@@ -3901,7 +4120,7 @@ PP(pp_alarm)
     EXTEND(SP, 1);
     if (anum < 0)
        RETPUSHUNDEF;
-    PUSHi((I32)anum);
+    PUSHi(anum);
     RETURN;
 #else
     DIE(aTHX_ PL_no_func, "Unsupported function alarm");
@@ -4548,12 +4767,12 @@ PP(pp_gpwuid)
 PP(pp_gpwent)
 {
     djSP;
-#if defined(HAS_PASSWD) && defined(HAS_GETPWENT)
+#ifdef HAS_PASSWD
     I32 which = PL_op->op_type;
     register SV *sv;
     struct passwd *pwent;
     STRLEN n_a;
-#ifdef HAS_GETSPENT
+#if defined(HAS_GETSPENT) || defined(HAS_GETSPNAM)
     struct spwd *spwent = NULL;
 #endif
 
@@ -4562,7 +4781,11 @@ PP(pp_gpwent)
     else if (which == OP_GPWUID)
        pwent = getpwuid(POPi);
     else
+#ifdef HAS_GETPWENT
        pwent = (struct passwd *)getpwent();
+#else
+       DIE(aTHX_ PL_no_func, "getpwent");
+#endif
 
 #ifdef HAS_GETSPNAM
     if (which == OP_GPWNAM) {
@@ -4575,8 +4798,10 @@ PP(pp_gpwent)
            spwent = getspnam(pwent->pw_name);
     }
 #  endif
+#  ifdef HAS_GETSPENT
     else
        spwent = (struct spwd *)getspent();
+#  endif
 #endif
 
     EXTEND(SP, 10);
@@ -4584,7 +4809,11 @@ PP(pp_gpwent)
        PUSHs(sv = sv_newmortal());
        if (pwent) {
            if (which == OP_GPWNAM)
+#if Uid_t_sign <= 0
                sv_setiv(sv, (IV)pwent->pw_uid);
+#else
+               sv_setuv(sv, (UV)pwent->pw_uid);
+#endif
            else
                sv_setpv(sv, pwent->pw_name);
        }
@@ -4597,7 +4826,7 @@ PP(pp_gpwent)
 
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef PWPASSWD
-#   ifdef HAS_GETSPENT
+#   if defined(HAS_GETSPENT) || defined(HAS_GETSPNAM)
       if (spwent)
               sv_setpv(sv, spwent->sp_pwdp);
       else
@@ -4606,13 +4835,24 @@ PP(pp_gpwent)
        sv_setpv(sv, pwent->pw_passwd);
 #   endif
 #endif
+#ifndef INCOMPLETE_TAINTS
+       /* passwd is tainted because user himself can diddle with it. */
+       SvTAINTED_on(sv);
+#endif
 
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+#if Uid_t_sign <= 0
        sv_setiv(sv, (IV)pwent->pw_uid);
+#else
+       sv_setuv(sv, (UV)pwent->pw_uid);
+#endif
 
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+#if Uid_t_sign <= 0
        sv_setiv(sv, (IV)pwent->pw_gid);
-
+#else
+       sv_setuv(sv, (UV)pwent->pw_gid);
+#endif
        /* pw_change, pw_quota, and pw_age are mutually exclusive. */
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef PWCHANGE
@@ -4651,6 +4891,10 @@ PP(pp_gpwent)
 
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, pwent->pw_shell);
+#ifndef INCOMPLETE_TAINTS
+       /* pw_shell is tainted because user himself can diddle with it. */
+       SvTAINTED_on(sv);
+#endif
 
 #ifdef PWEXPIRE
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
@@ -4666,7 +4910,7 @@ PP(pp_gpwent)
 PP(pp_spwent)
 {
     djSP;
-#if defined(HAS_PASSWD) && defined(HAS_SETPWENT) && !defined(CYGWIN32)
+#if defined(HAS_PASSWD) && defined(HAS_SETPWENT)
     setpwent();
 #   ifdef HAS_SETSPENT
     setspent();
@@ -4712,7 +4956,7 @@ PP(pp_ggrgid)
 PP(pp_ggrent)
 {
     djSP;
-#if defined(HAS_GROUP) && defined(HAS_GETGRENT)
+#ifdef HAS_GROUP
     I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;
@@ -4724,7 +4968,11 @@ PP(pp_ggrent)
     else if (which == OP_GGRGID)
        grent = (struct group *)getgrgid(POPi);
     else
+#ifdef HAS_GETGRENT
        grent = (struct group *)getgrent();
+#else
+        DIE(aTHX_ PL_no_func, "getgrent");
+#endif
 
     EXTEND(SP, 4);
     if (GIMME != G_ARRAY) {
@@ -4811,7 +5059,6 @@ PP(pp_syscall)
     unsigned long a[20];
     register I32 i = 0;
     I32 retval = -1;
-    MAGIC *mg;
     STRLEN n_a;
 
     if (PL_tainting) {
@@ -4927,7 +5174,7 @@ fcntl_emulate_flock(int fd, int operation)
        return -1;
     }
     flock.l_whence = SEEK_SET;
-    flock.l_start = flock.l_len = 0L;
+    flock.l_start = flock.l_len = (Off_t)0;
  
     return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock);
 }