This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use Mode_t.
[perl5.git] / pp_sys.c
index d841d04..f469ed0 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -1,6 +1,6 @@
 /*    pp_sys.c
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, 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.
  */
 
 #include "EXTERN.h"
+#define PERL_IN_PP_SYS_C
 #include "perl.h"
 
+#ifdef I_SHADOW
+/* Shadow password support for solaris - pdo@cs.umd.edu
+ * Not just Solaris: at least HP-UX, IRIX, Linux.
+ * the API is from SysV. --jhi */
+#include <shadow.h>
+#endif
+
 /* XXX If this causes problems, set i_unistd=undef in the hint file.  */
 #ifdef I_UNISTD
 # include <unistd.h>
@@ -38,6 +46,9 @@ extern "C" int syscall(unsigned long,...);
 
 #if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
 # include <sys/socket.h>
+# if defined(USE_SOCKS) && defined(I_SOCKS)
+#   include <socks.h>
+# endif 
 # ifdef I_NETDB
 #  include <netdb.h>
 # endif
@@ -56,7 +67,10 @@ extern "C" int syscall(unsigned long,...);
 
 /* XXX Configure test needed.
    h_errno might not be a simple 'int', especially for multi-threaded
-   applications.  HOST_NOT_FOUND is typically defined in <netdb.h>.
+   applications, see "extern int errno in perl.h".  Creating such
+   a test requires taking into account the differences between
+   compiling multithreaded and singlethreaded ($ccflags et al).
+   HOST_NOT_FOUND is typically defined in <netdb.h>.
 */
 #if defined(HOST_NOT_FOUND) && !defined(h_errno)
 extern int h_errno;
@@ -66,20 +80,24 @@ extern int h_errno;
 # ifdef I_PWD
 #  include <pwd.h>
 # else
-    struct passwd *getpwnam _((char *));
-    struct passwd *getpwuid _((Uid_t));
+    struct passwd *getpwnam (char *);
+    struct passwd *getpwuid (Uid_t);
+# endif
+# ifdef HAS_GETPWENT
+  struct passwd *getpwent (void);
 # endif
-  struct passwd *getpwent _((void));
 #endif
 
 #ifdef HAS_GROUP
 # ifdef I_GRP
 #  include <grp.h>
 # else
-    struct group *getgrnam _((char *));
-    struct group *getgrgid _((Gid_t));
+    struct group *getgrnam (char *);
+    struct group *getgrgid (Gid_t);
+# endif
+# ifdef HAS_GETGRENT
+    struct group *getgrent (void);
 # endif
-    struct group *getgrent _((void));
 #endif
 
 #ifdef I_UTIME
@@ -110,10 +128,6 @@ extern int h_errno;
 #  endif
 #endif
 
-#if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
-static int dooneliner _((char *cmd, char *filename));
-#endif
-
 #ifdef HAS_CHSIZE
 # ifdef my_chsize  /* Probably #defined to Perl_my_chsize in embed.h */
 #   undef my_chsize
@@ -144,7 +158,7 @@ static int dooneliner _((char *cmd, char *filename));
 #  endif /* no flock() or fcntl(F_SETLK,...) */
 
 #  ifdef FLOCK
-     static int FLOCK _((int, int));
+     static int FLOCK (int, int);
 
     /*
      * These are the flock() constants.  Since this sytems doesn't have
@@ -166,24 +180,135 @@ static int dooneliner _((char *cmd, char *filename));
 
 #endif /* no flock() */
 
-#ifndef MAXPATHLEN
-#  ifdef PATH_MAX
-#    define MAXPATHLEN PATH_MAX
-#  else
-#    define MAXPATHLEN 1024
-#  endif
-#endif
-
 #define ZBTLEN 10
 static char zero_but_true[ZBTLEN + 1] = "0 but true";
 
-/* Pushy I/O. */
+#if defined(I_SYS_ACCESS) && !defined(R_OK)
+#  include <sys/access.h>
+#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
+
+/* F_OK unused: if stat() cannot find it... */
+
+#if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESS) && defined(EFF_ONLY_OK) && !defined(NO_EFF_ONLY_OK)
+    /* Digital UNIX (when the EFF_ONLY_OK gets fixed), UnixWare */
+#   define PERL_EFF_ACCESS_R_OK(p) (access((p), R_OK | EFF_ONLY_OK))
+#   define PERL_EFF_ACCESS_W_OK(p) (access((p), W_OK | EFF_ONLY_OK))
+#   define PERL_EFF_ACCESS_X_OK(p) (access((p), X_OK | EFF_ONLY_OK))
+#endif
+
+#if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_EACCESS)
+#   if defined(I_SYS_SECURITY)
+#       include <sys/security.h>
+#   endif
+    /* XXX Configure test needed for eaccess */
+#   ifdef ACC_SELF
+        /* HP SecureWare */
+#       define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK, ACC_SELF))
+#       define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK, ACC_SELF))
+#       define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK, ACC_SELF))
+#   else
+        /* SCO */
+#       define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK))
+#       define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK))
+#       define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK))
+#   endif
+#endif
+
+#if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESSX) && defined(ACC_SELF)
+    /* AIX */
+#   define PERL_EFF_ACCESS_R_OK(p) (accessx((p), R_OK, ACC_SELF))
+#   define PERL_EFF_ACCESS_W_OK(p) (accessx((p), W_OK, ACC_SELF))
+#   define PERL_EFF_ACCESS_X_OK(p) (accessx((p), X_OK, ACC_SELF))
+#endif
+
+#if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESS)      \
+    && (defined(HAS_SETREUID) || defined(HAS_SETRESUID)                \
+       || defined(HAS_SETREGID) || defined(HAS_SETRESGID))
+/* The Hard Way. */
+STATIC int
+S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
+{
+    Uid_t ruid = getuid();
+    Uid_t euid = geteuid();
+    Gid_t rgid = getgid();
+    Gid_t egid = getegid();
+    int res;
+
+    MUTEX_LOCK(&PL_cred_mutex);
+#if !defined(HAS_SETREUID) && !defined(HAS_SETRESUID)
+    Perl_croak(aTHX_ "switching effective uid is not implemented");
+#else
+#ifdef HAS_SETREUID
+    if (setreuid(euid, ruid))
+#else
+#ifdef HAS_SETRESUID
+    if (setresuid(euid, ruid, (Uid_t)-1))
+#endif
+#endif
+       Perl_croak(aTHX_ "entering effective uid failed");
+#endif
+
+#if !defined(HAS_SETREGID) && !defined(HAS_SETRESGID)
+    Perl_croak(aTHX_ "switching effective gid is not implemented");
+#else
+#ifdef HAS_SETREGID
+    if (setregid(egid, rgid))
+#else
+#ifdef HAS_SETRESGID
+    if (setresgid(egid, rgid, (Gid_t)-1))
+#endif
+#endif
+       Perl_croak(aTHX_ "entering effective gid failed");
+#endif
+
+    res = access(path, mode);
+
+#ifdef HAS_SETREUID
+    if (setreuid(ruid, euid))
+#else
+#ifdef HAS_SETRESUID
+    if (setresuid(ruid, euid, (Uid_t)-1))
+#endif
+#endif
+       Perl_croak(aTHX_ "leaving effective uid failed");
+
+#ifdef HAS_SETREGID
+    if (setregid(rgid, egid))
+#else
+#ifdef HAS_SETRESGID
+    if (setresgid(rgid, egid, (Gid_t)-1))
+#endif
+#endif
+       Perl_croak(aTHX_ "leaving effective gid failed");
+    MUTEX_UNLOCK(&PL_cred_mutex);
+
+    return res;
+}
+#   define PERL_EFF_ACCESS_R_OK(p) (emulate_eaccess((p), R_OK))
+#   define PERL_EFF_ACCESS_W_OK(p) (emulate_eaccess((p), W_OK))
+#   define PERL_EFF_ACCESS_X_OK(p) (emulate_eaccess((p), X_OK))
+#endif
+
+#if !defined(PERL_EFF_ACCESS_R_OK)
+STATIC int
+S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
+{
+    Perl_croak(aTHX_ "switching effective uid is not implemented");
+    /*NOTREACHED*/
+    return -1;
+}
+#endif
 
 PP(pp_backtick)
 {
     djSP; dTARGET;
     PerlIO *fp;
-    char *tmps = POPp;
+    STRLEN n_a;
+    char *tmps = POPpx;
     I32 gimme = GIMME_V;
 
     TAINT_PROPER("``");
@@ -207,7 +332,7 @@ PP(pp_backtick)
            SV *sv;
 
            for (;;) {
-               sv = NEWSV(56, 80);
+               sv = NEWSV(56, 79);
                if (sv_gets(sv, fp, 0) == Nullch) {
                    SvREFCNT_dec(sv);
                    break;
@@ -235,27 +360,29 @@ PP(pp_backtick)
 PP(pp_glob)
 {
     OP *result;
+    tryAMAGICunTARGET(iter, -1);
+
     ENTER;
 
 #ifndef VMS
-    if (tainting) {
+    if (PL_tainting) {
        /*
         * The external globbing program may use things we can't control,
         * so for security reasons we must assume the worst.
         */
        TAINT;
-       taint_proper(no_security, "glob");
+       taint_proper(PL_no_security, "glob");
     }
 #endif /* !VMS */
 
-    SAVESPTR(last_in_gv);      /* We don't want this to be permanent. */
-    last_in_gv = (GV*)*stack_sp--;
+    SAVESPTR(PL_last_in_gv);   /* We don't want this to be permanent. */
+    PL_last_in_gv = (GV*)*PL_stack_sp--;
 
-    SAVESPTR(rs);              /* This is not permanent, either. */
-    rs = sv_2mortal(newSVpv("", 1));
+    SAVESPTR(PL_rs);           /* This is not permanent, either. */
+    PL_rs = sv_2mortal(newSVpvn("\000", 1));
 #ifndef DOSISH
 #ifndef CSH
-    *SvPVX(rs) = '\n';
+    *SvPVX(PL_rs) = '\n';
 #endif /* !CSH */
 #endif /* !DOSISH */
 
@@ -264,40 +391,49 @@ PP(pp_glob)
     return result;
 }
 
+#if 0          /* XXX never used! */
 PP(pp_indread)
 {
-    last_in_gv = gv_fetchpv(SvPVx(GvSV((GV*)(*stack_sp--)), na), TRUE,SVt_PVIO);
+    STRLEN n_a;
+    PL_last_in_gv = gv_fetchpv(SvPVx(GvSV((GV*)(*PL_stack_sp--)), n_a), TRUE,SVt_PVIO);
     return do_readline();
 }
+#endif
 
 PP(pp_rcatline)
 {
-    last_in_gv = cGVOP->op_gv;
+    PL_last_in_gv = cGVOP->op_gv;
     return do_readline();
 }
 
 PP(pp_warn)
 {
     djSP; dMARK;
+    SV *tmpsv;
     char *tmps;
+    STRLEN len;
     if (SP - MARK != 1) {
        dTARGET;
-       do_join(TARG, &sv_no, MARK, SP);
-       tmps = SvPV(TARG, na);
+       do_join(TARG, &PL_sv_no, MARK, SP);
+       tmpsv = TARG;
        SP = MARK + 1;
     }
     else {
-       tmps = SvPV(TOPs, na);
+       tmpsv = TOPs;
     }
-    if (!tmps || !*tmps) {
-       (void)SvUPGRADE(ERRSV, SVt_PV);
-       if (SvPOK(ERRSV) && SvCUR(ERRSV))
-           sv_catpv(ERRSV, "\t...caught");
-       tmps = SvPV(ERRSV, na);
-    }
-    if (!tmps || !*tmps)
-       tmps = "Warning: something's wrong";
-    warn("%s", tmps);
+    tmps = SvPV(tmpsv, len);
+    if (!tmps || !len) {
+       SV *error = ERRSV;
+       (void)SvUPGRADE(error, SVt_PV);
+       if (SvPOK(error) && SvCUR(error))
+           sv_catpv(error, "\t...caught");
+       tmpsv = error;
+       tmps = SvPV(tmpsv, len);
+    }
+    if (!tmps || !len)
+       tmpsv = sv_2mortal(newSVpvn("Warning: something's wrong", 26));
+
+    Perl_warn(aTHX_ "%_", tmpsv);
     RETSETYES;
 }
 
@@ -305,24 +441,57 @@ PP(pp_die)
 {
     djSP; dMARK;
     char *tmps;
+    SV *tmpsv;
+    STRLEN len;
+    bool multiarg = 0;
     if (SP - MARK != 1) {
        dTARGET;
-       do_join(TARG, &sv_no, MARK, SP);
-       tmps = SvPV(TARG, na);
+       do_join(TARG, &PL_sv_no, MARK, SP);
+       tmpsv = TARG;
+       tmps = SvPV(tmpsv, len);
+       multiarg = 1;
        SP = MARK + 1;
     }
     else {
-       tmps = SvPV(TOPs, na);
+       tmpsv = TOPs;
+       tmps = SvROK(tmpsv) ? Nullch : SvPV(tmpsv, len);
     }
-    if (!tmps || !*tmps) {
-       (void)SvUPGRADE(ERRSV, SVt_PV);
-       if (SvPOK(ERRSV) && SvCUR(ERRSV))
-           sv_catpv(ERRSV, "\t...propagated");
-       tmps = SvPV(ERRSV, na);
+    if (!tmps || !len) {
+       SV *error = ERRSV;
+       (void)SvUPGRADE(error, SVt_PV);
+       if (multiarg ? SvROK(error) : SvROK(tmpsv)) {
+           if (!multiarg)
+               SvSetSV(error,tmpsv);
+           else if (sv_isobject(error)) {
+               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));
+                   EXTEND(SP, 3);
+                   PUSHMARK(SP);
+                   PUSHs(error);
+                   PUSHs(file);
+                   PUSHs(line);
+                   PUTBACK;
+                   call_sv((SV*)GvCV(gv),
+                           G_SCALAR|G_EVAL|G_KEEPERR);
+                   sv_setsv(error,*PL_stack_sp--);
+               }
+           }
+           DIE(aTHX_ Nullch);
+       }
+       else {
+           if (SvPOK(error) && SvCUR(error))
+               sv_catpv(error, "\t...propagated");
+           tmpsv = error;
+           tmps = SvPV(tmpsv, len);
+       }
     }
-    if (!tmps || !*tmps)
-       tmps = "Died";
-    DIE("%s", tmps);
+    if (!tmps || !len)
+       tmpsv = sv_2mortal(newSVpvn("Died", 4));
+
+    DIE(aTHX_ "%_", tmpsv);
 }
 
 /* I/O. */
@@ -332,24 +501,62 @@ 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))
-       DIE(no_usym, "filehandle");
+       DIE(aTHX_ PL_no_usym, "filehandle");
     if (MAXARG <= 1)
        sv = GvSV(TOPs);
     gv = (GV*)POPs;
     if (!isGV(gv))
-       DIE(no_usym, "filehandle");
+       DIE(aTHX_ PL_no_usym, "filehandle");
     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')) {
+       PUSHMARK(SP);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
+       XPUSHs(sv);
+       if (have_name)
+           XPUSHs(name);
+       PUTBACK;
+       ENTER;
+       call_method("OPEN", G_SCALAR);
+       LEAVE;
+       SPAGAIN;
+       RETURN;
+    }
+
     tmps = SvPV(sv, len);
-    if (do_open(gv, tmps, len, FALSE, 0, 0, Nullfp))
-       PUSHi( (I32)forkprocess );
-    else if (forkprocess == 0)         /* we are a new child */
+    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);
     else
        RETPUSHUNDEF;
@@ -363,16 +570,16 @@ PP(pp_close)
     MAGIC *mg;
 
     if (MAXARG == 0)
-       gv = defoutgv;
+       gv = PL_defoutgv;
     else
        gv = (GV*)POPs;
 
-    if (SvRMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q'))) {
+    if (mg = SvTIED_mg((SV*)gv, 'q')) {
        PUSHMARK(SP);
-       XPUSHs(mg->mg_obj);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
        PUTBACK;
        ENTER;
-       perl_call_method("CLOSE", G_SCALAR);
+       call_method("CLOSE", G_SCALAR);
        LEAVE;
        SPAGAIN;
        RETURN;
@@ -399,7 +606,7 @@ PP(pp_pipe_op)
        goto badexit;
 
     if (SvTYPE(rgv) != SVt_PVGV || SvTYPE(wgv) != SVt_PVGV)
-       DIE(no_usym, "filehandle");
+       DIE(aTHX_ PL_no_usym, "filehandle");
     rstio = GvIOn(rgv);
     wstio = GvIOn(wgv);
 
@@ -424,13 +631,16 @@ PP(pp_pipe_op)
        else PerlLIO_close(fd[1]);
        goto badexit;
     }
-
+#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;
 
 badexit:
     RETPUSHUNDEF;
 #else
-    DIE(no_func, "pipe");
+    DIE(aTHX_ PL_no_func, "pipe");
 #endif
 }
 
@@ -440,9 +650,23 @@ PP(pp_fileno)
     GV *gv;
     IO *io;
     PerlIO *fp;
+    MAGIC  *mg;
+
     if (MAXARG < 1)
        RETPUSHUNDEF;
     gv = (GV*)POPs;
+
+    if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
+       PUSHMARK(SP);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
+       PUTBACK;
+       ENTER;
+       call_method("FILENO", G_SCALAR);
+       LEAVE;
+       SPAGAIN;
+       RETURN;
+    }
+
     if (!gv || !(io = GvIO(gv)) || !(fp = IoIFP(io)))
        RETPUSHUNDEF;
     PUSHi(PerlIO_fileno(fp));
@@ -452,7 +676,7 @@ PP(pp_fileno)
 PP(pp_umask)
 {
     djSP; dTARGET;
-    int anum;
+    Mode_t anum;
 
 #ifdef HAS_UMASK
     if (MAXARG < 1) {
@@ -464,7 +688,12 @@ PP(pp_umask)
     TAINT_PROPER("umask");
     XPUSHi(anum);
 #else
-    DIE(no_func, "Unsupported function umask");
+    /* Only DIE if trying to restrict permissions on `user' (self).
+     * Otherwise it's harmless and more useful to just return undef
+     * since 'group' and 'other' concepts probably don't exist here. */
+    if (MAXARG >= 1 && (POPi & 0700))
+       DIE(aTHX_ "umask not implemented");
+    XPUSHs(&PL_sv_undef);
 #endif
     RETURN;
 }
@@ -475,11 +704,23 @@ PP(pp_binmode)
     GV *gv;
     IO *io;
     PerlIO *fp;
+    MAGIC *mg;
 
     if (MAXARG < 1)
        RETPUSHUNDEF;
 
-    gv = (GV*)POPs;
+    gv = (GV*)POPs; 
+
+    if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
+       PUSHMARK(SP);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
+       PUTBACK;
+       ENTER;
+       call_method("BINMODE", G_SCALAR);
+       LEAVE;
+       SPAGAIN;
+       RETURN;
+    }
 
     EXTEND(SP, 1);
     if (!(io = GvIO(gv)) || !(fp = IoIFP(io)))
@@ -500,10 +741,11 @@ PP(pp_tie)
     HV* stash;
     GV *gv;
     SV *sv;
-    I32 markoff = MARK - stack_base;
+    I32 markoff = MARK - PL_stack_base;
     char *methname;
     int how = 'P';
     U32 items;
+    STRLEN n_a;
 
     varsv = *++MARK;
     switch(SvTYPE(varsv)) {
@@ -525,42 +767,42 @@ PP(pp_tie)
     items = SP - MARK++;
     if (sv_isobject(*MARK)) {
        ENTER;
-       PUSHSTACK(SI_MAGIC);
+       PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
        EXTEND(SP,items);
        while (items--)
            PUSHs(*MARK++);
        PUTBACK;
-       perl_call_method(methname, G_SCALAR);
+       call_method(methname, G_SCALAR);
     } 
     else {
-       /* Not clear why we don't call perl_call_method here too.
+       /* Not clear why we don't call call_method here too.
         * perhaps to get different error message ?
         */
        stash = gv_stashsv(*MARK, FALSE);
        if (!stash || !(gv = gv_fetchmethod(stash, methname))) {
-           DIE("Can't locate object method \"%s\" via package \"%s\"",
-                methname, SvPV(*MARK,na));                   
+           DIE(aTHX_ "Can't locate object method \"%s\" via package \"%s\"",
+                methname, SvPV(*MARK,n_a));                   
        }
        ENTER;
-       PUSHSTACK(SI_MAGIC);
+       PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
        EXTEND(SP,items);
        while (items--)
            PUSHs(*MARK++);
        PUTBACK;
-       perl_call_sv((SV*)GvCV(gv), G_SCALAR);
+       call_sv((SV*)GvCV(gv), G_SCALAR);
     }
     SPAGAIN;
 
     sv = TOPs;
-    POPSTACK();
+    POPSTACK;
     if (sv_isobject(sv)) {
-       sv_unmagic(varsv, how);            
-       sv_magic(varsv, sv, how, Nullch, 0);
+       sv_unmagic(varsv, how);
+       sv_magic(varsv, (SvRV(sv) == varsv ? Nullsv : sv), how, Nullch, 0);
     }
     LEAVE;
-    SP = stack_base + markoff;
+    SP = PL_stack_base + markoff;
     PUSHs(sv);
     RETURN;
 }
@@ -568,47 +810,43 @@ PP(pp_tie)
 PP(pp_untie)
 {
     djSP;
-    SV * sv ;
-    sv = POPs;          
+    SV *sv = POPs;
+    char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) ? 'P' : 'q';
 
-    if (dowarn) {
+    if (ckWARN(WARN_UNTIE)) {
         MAGIC * mg ;
-        if (SvMAGICAL(sv)) {
-            if (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
-                mg = mg_find(sv, 'P') ;
-            else
-                mg = mg_find(sv, 'q') ;
-    
+        if (mg = SvTIED_mg(sv, how)) {
+#ifdef IV_IS_QUAD
             if (mg && SvREFCNT(SvRV(mg->mg_obj)) > 1)  
-               warn("untie attempted while %lu inner references still exist",
-                       (unsigned long)SvREFCNT(SvRV(mg->mg_obj)) - 1 ) ;
+               Perl_warner(aTHX_ WARN_UNTIE,
+                   "untie attempted while %" PERL_PRIu64 " inner references still exist",
+                   (UV)SvREFCNT(SvRV(mg->mg_obj)) - 1 ) ;
+#else
+            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 ) ;
+#endif
         }
     }
  
-    if (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
-       sv_unmagic(sv, 'P');
-    else
-       sv_unmagic(sv, 'q');
+    sv_unmagic(sv, how);
     RETPUSHYES;
 }
 
 PP(pp_tied)
 {
     djSP;
-    SV * sv ;
-    MAGIC * mg ;
+    SV *sv = POPs;
+    char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) ? 'P' : 'q';
+    MAGIC *mg;
 
-    sv = POPs;
-    if (SvMAGICAL(sv)) {
-        if (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
-            mg = mg_find(sv, 'P') ;
-        else
-            mg = mg_find(sv, 'q') ;
-
-        if (mg)  {
-            PUSHs(sv_2mortal(newSVsv(mg->mg_obj))) ; 
-            RETURN ;
-       }
+    if (mg = SvTIED_mg(sv, how)) {
+       SV *osv = SvTIED_obj(sv, mg);
+       if (osv == mg->mg_obj)
+           osv = sv_mortalcopy(osv);
+       PUSHs(osv);
+       RETURN;
     }
     RETPUSHUNDEF;
 }
@@ -624,15 +862,15 @@ PP(pp_dbmopen)
 
     hv = (HV*)POPs;
 
-    sv = sv_mortalcopy(&sv_no);
+    sv = sv_mortalcopy(&PL_sv_no);
     sv_setpv(sv, "AnyDBM_File");
     stash = gv_stashsv(sv, FALSE);
     if (!stash || !(gv = gv_fetchmethod(stash, "TIEHASH"))) {
        PUTBACK;
-       perl_require_pv("AnyDBM_File.pm");
+       require_pv("AnyDBM_File.pm");
        SPAGAIN;
        if (!(gv = gv_fetchmethod(stash, "TIEHASH")))
-           DIE("No dbm on this machine");
+           DIE(aTHX_ "No dbm on this machine");
     }
 
     ENTER;
@@ -647,7 +885,7 @@ PP(pp_dbmopen)
        PUSHs(sv_2mortal(newSViv(O_RDWR)));
     PUSHs(right);
     PUTBACK;
-    perl_call_sv((SV*)GvCV(gv), G_SCALAR);
+    call_sv((SV*)GvCV(gv), G_SCALAR);
     SPAGAIN;
 
     if (!sv_isobject(TOPs)) {
@@ -658,7 +896,7 @@ PP(pp_dbmopen)
        PUSHs(sv_2mortal(newSViv(O_RDONLY)));
        PUSHs(right);
        PUTBACK;
-       perl_call_sv((SV*)GvCV(gv), G_SCALAR);
+       call_sv((SV*)GvCV(gv), G_SCALAR);
        SPAGAIN;
     }
 
@@ -672,7 +910,7 @@ PP(pp_dbmopen)
 
 PP(pp_dbmclose)
 {
-    return pp_untie(ARGS);
+    return pp_untie();
 }
 
 PP(pp_sselect)
@@ -683,13 +921,14 @@ PP(pp_sselect)
     register I32 j;
     register char *s;
     register SV *sv;
-    double value;
+    NV value;
     I32 maxlen = 0;
     I32 nfound;
     struct timeval timebuf;
     struct timeval *tbuf = &timebuf;
     I32 growsize;
     char *fd_sets[4];
+    STRLEN n_a;
 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
        I32 masksize;
        I32 offset;
@@ -712,23 +951,29 @@ PP(pp_sselect)
            maxlen = j;
     }
 
+/* little endians can use vecs directly */
 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
-#if defined(__linux__) || defined(OS2)
+#  if SELECT_MIN_BITS > 1
+    /* 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
+     * on (sets/tests/clears bits) is 32 bits.  */
+    growsize = maxlen + (SELECT_MIN_BITS/8 - (maxlen % (SELECT_MIN_BITS/8)));
+#  else
     growsize = sizeof(fd_set);
-#else
-    growsize = maxlen;         /* little endians can use vecs directly */
-#endif
-#else
-#ifdef NFDBITS
+#  endif
+# else
+#  ifdef NFDBITS
 
-#ifndef NBBY
-#define NBBY 8
-#endif
+#    ifndef NBBY
+#     define NBBY 8
+#    endif
 
     masksize = NFDBITS / NBBY;
-#else
+#  else
     masksize = sizeof(long);   /* documented int, everyone seems to use long */
-#endif
+#  endif
     growsize = maxlen + (masksize - (maxlen % masksize));
     Zero(&fd_sets[0], 4, char*);
 #endif
@@ -739,7 +984,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
@@ -752,7 +997,7 @@ PP(pp_sselect)
            continue;
        }
        else if (!SvPOK(sv))
-           SvPV_force(sv,na);  /* force string conversion */
+           SvPV_force(sv,n_a); /* force string conversion */
        j = SvLEN(sv);
        if (j < growsize) {
            Sv_Grow(sv, growsize);
@@ -798,26 +1043,26 @@ PP(pp_sselect)
 
     PUSHi(nfound);
     if (GIMME == G_ARRAY && tbuf) {
-       value = (double)(timebuf.tv_sec) +
-               (double)(timebuf.tv_usec) / 1000000.0;
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       value = (NV)(timebuf.tv_sec) +
+               (NV)(timebuf.tv_usec) / 1000000.0;
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setnv(sv, value);
     }
     RETURN;
 #else
-    DIE("select not implemented");
+    DIE(aTHX_ "select not implemented");
 #endif
 }
 
 void
-setdefout(GV *gv)
+Perl_setdefout(pTHX_ GV *gv)
 {
     dTHR;
     if (gv)
        (void)SvREFCNT_inc(gv);
-    if (defoutgv)
-       SvREFCNT_dec(defoutgv);
-    defoutgv = gv;
+    if (PL_defoutgv)
+       SvREFCNT_dec(PL_defoutgv);
+    PL_defoutgv = gv;
 }
 
 PP(pp_select)
@@ -826,18 +1071,18 @@ PP(pp_select)
     GV *newdefout, *egv;
     HV *hv;
 
-    newdefout = (op->op_private > 0) ? ((GV *) POPs) : (GV *) NULL;
+    newdefout = (PL_op->op_private > 0) ? ((GV *) POPs) : (GV *) NULL;
 
-    egv = GvEGV(defoutgv);
+    egv = GvEGV(PL_defoutgv);
     if (!egv)
-       egv = defoutgv;
+       egv = PL_defoutgv;
     hv = GvSTASH(egv);
     if (! hv)
-       XPUSHs(&sv_undef);
+       XPUSHs(&PL_sv_undef);
     else {
        GV **gvp = (GV**)hv_fetch(hv, GvNAME(egv), GvNAMELEN(egv), FALSE);
        if (gvp && *gvp == egv) {
-           gv_efullname3(TARG, defoutgv, Nullch);
+           gv_efullname3(TARG, PL_defoutgv, Nullch);
            XPUSHTARG;
        }
        else {
@@ -861,19 +1106,19 @@ PP(pp_getc)
     MAGIC *mg;
 
     if (MAXARG <= 0)
-       gv = stdingv;
+       gv = PL_stdingv;
     else
        gv = (GV*)POPs;
     if (!gv)
-       gv = argvgv;
+       gv = PL_argvgv;
 
-    if (SvRMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q'))) {
+    if (mg = SvTIED_mg((SV*)gv, 'q')) {
        I32 gimme = GIMME_V;
        PUSHMARK(SP);
-       XPUSHs(mg->mg_obj);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
        PUTBACK;
        ENTER;
-       perl_call_method("GETC", gimme);
+       call_method("GETC", gimme);
        LEAVE;
        SPAGAIN;
        if (gimme == G_SCALAR)
@@ -891,11 +1136,11 @@ PP(pp_getc)
 
 PP(pp_read)
 {
-    return pp_sysread(ARGS);
+    return pp_sysread();
 }
 
-static OP *
-doform(CV *cv, GV *gv, OP *retop)
+STATIC OP *
+S_doform(pTHX_ CV *cv, GV *gv, OP *retop)
 {
     dTHR;
     register PERL_CONTEXT *cx;
@@ -907,10 +1152,10 @@ doform(CV *cv, GV *gv, OP *retop)
     SAVETMPS;
 
     push_return(retop);
-    PUSHBLOCK(cx, CXt_SUB, stack_sp);
+    PUSHBLOCK(cx, CXt_SUB, PL_stack_sp);
     PUSHFORMAT(cx);
-    SAVESPTR(curpad);
-    curpad = AvARRAY((AV*)svp[1]);
+    SAVESPTR(PL_curpad);
+    PL_curpad = AvARRAY((AV*)svp[1]);
 
     setdefout(gv);         /* locally select filehandle so $% et al work */
     return CvSTART(cv);
@@ -925,11 +1170,11 @@ PP(pp_enterwrite)
     CV *cv;
 
     if (MAXARG == 0)
-       gv = defoutgv;
+       gv = PL_defoutgv;
     else {
        gv = (GV*)POPs;
        if (!gv)
-           gv = defoutgv;
+           gv = PL_defoutgv;
     }
     EXTEND(SP, 1);
     io = GvIO(gv);
@@ -946,15 +1191,15 @@ PP(pp_enterwrite)
        if (fgv) {
            SV *tmpsv = sv_newmortal();
            gv_efullname3(tmpsv, fgv, Nullch);
-           DIE("Undefined format \"%s\" called",SvPVX(tmpsv));
+           DIE(aTHX_ "Undefined format \"%s\" called",SvPVX(tmpsv));
        }
-       DIE("Not a format reference");
+       DIE(aTHX_ "Not a format reference");
     }
     if (CvCLONE(cv))
        cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
 
     IoFLAGS(io) &= ~IOf_DIDTOP;
-    return doform(cv,gv,op->op_next);
+    return doform(cv,gv,PL_op->op_next);
 }
 
 PP(pp_leavewrite)
@@ -969,9 +1214,9 @@ PP(pp_leavewrite)
     register PERL_CONTEXT *cx;
 
     DEBUG_f(PerlIO_printf(Perl_debug_log, "left=%ld, todo=%ld\n",
-         (long)IoLINES_LEFT(io), (long)FmLINES(formtarget)));
-    if (IoLINES_LEFT(io) < FmLINES(formtarget) &&
-       formtarget != toptarget)
+         (long)IoLINES_LEFT(io), (long)FmLINES(PL_formtarget)));
+    if (IoLINES_LEFT(io) < FmLINES(PL_formtarget) &&
+       PL_formtarget != PL_toptarget)
     {
        GV *fgv;
        CV *cv;
@@ -982,7 +1227,7 @@ PP(pp_leavewrite)
            if (!IoTOP_NAME(io)) {
                if (!IoFMT_NAME(io))
                    IoFMT_NAME(io) = savepv(GvNAME(gv));
-               topname = sv_2mortal(newSVpvf("%s_TOP", IoFMT_NAME(io)));
+               topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%s_TOP", IoFMT_NAME(io)));
                topgv = gv_fetchpv(SvPVX(topname), FALSE, SVt_PVFM);
                if ((topgv && GvFORM(topgv)) ||
                  !gv_fetchpv("top",FALSE,SVt_PVFM))
@@ -999,7 +1244,7 @@ PP(pp_leavewrite)
        }
        if (IoFLAGS(io) & IOf_DIDTOP) { /* Oh dear.  It still doesn't fit. */
            I32 lines = IoLINES_LEFT(io);
-           char *s = SvPVX(formtarget);
+           char *s = SvPVX(PL_formtarget);
            if (lines <= 0)             /* Yow, header didn't even fit!!! */
                goto forget_top;
            while (lines-- > 0) {
@@ -1009,64 +1254,69 @@ PP(pp_leavewrite)
                s++;
            }
            if (s) {
-               PerlIO_write(ofp, SvPVX(formtarget), s - SvPVX(formtarget));
-               sv_chop(formtarget, s);
-               FmLINES(formtarget) -= IoLINES_LEFT(io);
+               PerlIO_write(ofp, SvPVX(PL_formtarget), s - SvPVX(PL_formtarget));
+               sv_chop(PL_formtarget, s);
+               FmLINES(PL_formtarget) -= IoLINES_LEFT(io);
            }
        }
        if (IoLINES_LEFT(io) >= 0 && IoPAGE(io) > 0)
-           PerlIO_write(ofp, SvPVX(formfeed), SvCUR(formfeed));
+           PerlIO_write(ofp, SvPVX(PL_formfeed), SvCUR(PL_formfeed));
        IoLINES_LEFT(io) = IoPAGE_LEN(io);
        IoPAGE(io)++;
-       formtarget = toptarget;
+       PL_formtarget = PL_toptarget;
        IoFLAGS(io) |= IOf_DIDTOP;
        fgv = IoTOP_GV(io);
        if (!fgv)
-           DIE("bad top format reference");
+           DIE(aTHX_ "bad top format reference");
        cv = GvFORM(fgv);
        if (!cv) {
            SV *tmpsv = sv_newmortal();
            gv_efullname3(tmpsv, fgv, Nullch);
-           DIE("Undefined top format \"%s\" called",SvPVX(tmpsv));
+           DIE(aTHX_ "Undefined top format \"%s\" called",SvPVX(tmpsv));
        }
        if (CvCLONE(cv))
            cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
-       return doform(cv,gv,op);
+       return doform(cv,gv,PL_op);
     }
 
   forget_top:
-    POPBLOCK(cx,curpm);
+    POPBLOCK(cx,PL_curpm);
     POPFORMAT(cx);
     LEAVE;
 
     fp = IoOFP(io);
     if (!fp) {
-       if (dowarn) {
+       if (ckWARN2(WARN_CLOSED,WARN_IO)) {
+           SV* sv = sv_newmortal();
+           gv_efullname3(sv, gv, Nullch);
            if (IoIFP(io))
-               warn("Filehandle only opened for input");
-           else
-               warn("Write on closed filehandle");
+               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 %s", SvPV_nolen(sv));
        }
-       PUSHs(&sv_no);
+       PUSHs(&PL_sv_no);
     }
     else {
-       if ((IoLINES_LEFT(io) -= FmLINES(formtarget)) < 0) {
-           if (dowarn)
-               warn("page overflow");
+       if ((IoLINES_LEFT(io) -= FmLINES(PL_formtarget)) < 0) {
+           if (ckWARN(WARN_IO))
+               Perl_warner(aTHX_ WARN_IO, "page overflow");
        }
-       if (!PerlIO_write(ofp, SvPVX(formtarget), SvCUR(formtarget)) ||
+       if (!PerlIO_write(ofp, SvPVX(PL_formtarget), SvCUR(PL_formtarget)) ||
                PerlIO_error(fp))
-           PUSHs(&sv_no);
+           PUSHs(&PL_sv_no);
        else {
-           FmLINES(formtarget) = 0;
-           SvCUR_set(formtarget, 0);
-           *SvEND(formtarget) = '\0';
+           FmLINES(PL_formtarget) = 0;
+           SvCUR_set(PL_formtarget, 0);
+           *SvEND(PL_formtarget) = '\0';
            if (IoFLAGS(io) & IOf_FLUSH)
                (void)PerlIO_flush(fp);
-           PUSHs(&sv_yes);
+           PUSHs(&PL_sv_yes);
        }
     }
-    formtarget = bodytarget;
+    PL_formtarget = PL_bodytarget;
     PUTBACK;
     return pop_return();
 }
@@ -1079,13 +1329,14 @@ PP(pp_prtf)
     PerlIO *fp;
     SV *sv;
     MAGIC *mg;
+    STRLEN n_a;
 
-    if (op->op_flags & OPf_STACKED)
+    if (PL_op->op_flags & OPf_STACKED)
        gv = (GV*)*++MARK;
     else
-       gv = defoutgv;
+       gv = PL_defoutgv;
 
-    if (SvRMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q'))) {
+    if (mg = SvTIED_mg((SV*)gv, 'q')) {
        if (MARK == ORIGMARK) {
            MEXTEND(SP, 1);
            ++MARK;
@@ -1093,10 +1344,10 @@ PP(pp_prtf)
            ++SP;
        }
        PUSHMARK(MARK - 1);
-       *MARK = mg->mg_obj;
+       *MARK = SvTIED_obj((SV*)gv, mg);
        PUTBACK;
        ENTER;
-       perl_call_method("PRINTF", G_SCALAR);
+       call_method("PRINTF", G_SCALAR);
        LEAVE;
        SPAGAIN;
        MARK = ORIGMARK + 1;
@@ -1107,31 +1358,29 @@ PP(pp_prtf)
 
     sv = NEWSV(0,0);
     if (!(io = GvIO(gv))) {
-       if (dowarn) {
-           gv_fullname3(sv, gv, Nullch);
-           warn("Filehandle %s never opened", SvPV(sv,na));
+       if (ckWARN(WARN_UNOPENED)) {
+           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 (dowarn)  {
-           gv_fullname3(sv, gv, Nullch);
+       if (ckWARN2(WARN_CLOSED,WARN_IO))  {
+           gv_efullname3(sv, gv, Nullch);
            if (IoIFP(io))
-               warn("Filehandle %s opened only for input", SvPV(sv,na));
-           else
-               warn("printf on closed filehandle %s", SvPV(sv,na));
+               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));
        }
        SETERRNO(EBADF,IoIFP(io)?RMS$_FAC:RMS$_IFI);
        goto just_say_no;
     }
     else {
-#ifdef USE_LOCALE_NUMERIC
-       if (op->op_private & OPpLOCALE)
-           SET_NUMERIC_LOCAL();
-       else
-           SET_NUMERIC_STANDARD();
-#endif
        do_sprintf(sv, SP - MARK, MARK + 1);
        if (!do_print(sv, fp))
            goto just_say_no;
@@ -1142,13 +1391,13 @@ PP(pp_prtf)
     }
     SvREFCNT_dec(sv);
     SP = ORIGMARK;
-    PUSHs(&sv_yes);
+    PUSHs(&PL_sv_yes);
     RETURN;
 
   just_say_no:
     SvREFCNT_dec(sv);
     SP = ORIGMARK;
-    PUSHs(&sv_undef);
+    PUSHs(&PL_sv_undef);
     RETURN;
 }
 
@@ -1169,13 +1418,15 @@ PP(pp_sysopen)
     sv = POPs;
     gv = (GV *)POPs;
 
+    /* Need TIEHANDLE method ? */
+
     tmps = SvPV(sv, len);
     if (do_open(gv, tmps, len, TRUE, mode, perm, Nullfp)) {
        IoLINES(GvIOp(gv)) = 0;
-       PUSHs(&sv_yes);
+       PUSHs(&PL_sv_yes);
     }
     else {
-       PUSHs(&sv_undef);
+       PUSHs(&PL_sv_undef);
     }
     RETURN;
 }
@@ -1194,15 +1445,15 @@ PP(pp_sysread)
     MAGIC *mg;
 
     gv = (GV*)*++MARK;
-    if ((op->op_type == OP_READ || op->op_type == OP_SYSREAD) &&
-       SvRMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q')))
+    if ((PL_op->op_type == OP_READ || PL_op->op_type == OP_SYSREAD) &&
+       (mg = SvTIED_mg((SV*)gv, 'q')))
     {
        SV *sv;
        
        PUSHMARK(MARK-1);
-       *MARK = mg->mg_obj;
+       *MARK = SvTIED_obj((SV*)gv, mg);
        ENTER;
-       perl_call_method("READ", G_SCALAR);
+       call_method("READ", G_SCALAR);
        LEAVE;
        SPAGAIN;
        sv = POPs;
@@ -1219,7 +1470,7 @@ PP(pp_sysread)
     buffer = SvPV_force(bufsv, blen);
     length = SvIVx(*++MARK);
     if (length < 0)
-       DIE("Negative length");
+       DIE(aTHX_ "Negative length");
     SETERRNO(0,0);
     if (MARK < SP)
        offset = SvIVx(*++MARK);
@@ -1229,13 +1480,21 @@ PP(pp_sysread)
     if (!io || !IoIFP(io))
        goto say_undef;
 #ifdef HAS_SOCKET
-    if (op->op_type == OP_RECV) {
+    if (PL_op->op_type == OP_RECV) {
        char namebuf[MAXPATHLEN];
-#if defined(VMS_DO_SOCKETS) && defined(DECCRTL_SOCKETS)
+#if (defined(VMS_DO_SOCKETS) && defined(DECCRTL_SOCKETS)) || defined(MPE)
        bufsize = sizeof (struct sockaddr_in);
 #else
        bufsize = sizeof namebuf;
 #endif
+#ifdef OS2     /* At least Warp3+IAK: only the first byte of bufsize set */
+       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,
@@ -1255,12 +1514,12 @@ PP(pp_sysread)
        RETURN;
     }
 #else
-    if (op->op_type == OP_RECV)
-       DIE(no_sock_func, "recv");
+    if (PL_op->op_type == OP_RECV)
+       DIE(aTHX_ PL_no_sock_func, "recv");
 #endif
     if (offset < 0) {
        if (-offset > blen)
-           DIE("Offset outside string");
+           DIE(aTHX_ "Offset outside string");
        offset += blen;
     }
     bufsize = SvCUR(bufsv);
@@ -1268,8 +1527,18 @@ PP(pp_sysread)
     if (offset > bufsize) { /* Zero any newly allocated space */
        Zero(buffer+bufsize, offset-bufsize, char);
     }
-    if (op->op_type == OP_SYSREAD) {
-       length = PerlLIO_read(PerlIO_fileno(IoIFP(io)), buffer+offset, length);
+    if (PL_op->op_type == OP_SYSREAD) {
+#ifdef PERL_SOCK_SYSREAD_IS_RECV
+       if (IoTYPE(io) == 's') {
+           length = PerlSock_recv(PerlIO_fileno(IoIFP(io)),
+                                  buffer+offset, length, 0);
+       }
+       else
+#endif
+       {
+           length = PerlLIO_read(PerlIO_fileno(IoIFP(io)),
+                                 buffer+offset, length);
+       }
     }
     else
 #ifdef HAS_SOCKET__bad_code_maybe
@@ -1285,9 +1554,23 @@ PP(pp_sysread)
     }
     else
 #endif
+    {
        length = PerlIO_read(IoIFP(io), buffer+offset, length);
-    if (length < 0)
+       /* fread() returns 0 on both error and EOF */
+       if (length == 0 && PerlIO_error(IoIFP(io)))
+           length = -1;
+    }
+    if (length < 0) {
+       if (IoTYPE(io) == '>' || IoIFP(io) == PerlIO_stdout()
+           || IoIFP(io) == PerlIO_stderr())
+       {
+           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);
@@ -1306,7 +1589,16 @@ PP(pp_sysread)
 
 PP(pp_syswrite)
 {
-    return pp_send(ARGS);
+    djSP;
+    int items = (SP - PL_stack_base) - TOPMARK;
+    if (items == 2) {
+       SV *sv;
+        EXTEND(SP, 1);
+       sv = sv_2mortal(newSViv(sv_len(*SP)));
+       PUSHs(sv);
+        PUTBACK;
+    }
+    return pp_send();
 }
 
 PP(pp_send)
@@ -1322,15 +1614,13 @@ PP(pp_send)
     MAGIC *mg;
 
     gv = (GV*)*++MARK;
-    if (op->op_type == OP_SYSWRITE &&
-       SvRMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q')))
-    {
+    if (PL_op->op_type == OP_SYSWRITE && (mg = SvTIED_mg((SV*)gv, 'q'))) {
        SV *sv;
        
        PUSHMARK(MARK-1);
-       *MARK = mg->mg_obj;
+       *MARK = SvTIED_obj((SV*)gv, mg);
        ENTER;
-       perl_call_method("WRITE", G_SCALAR);
+       call_method("WRITE", G_SCALAR);
        LEAVE;
        SPAGAIN;
        sv = POPs;
@@ -1344,32 +1634,42 @@ PP(pp_send)
     buffer = SvPV(bufsv, blen);
     length = SvIVx(*++MARK);
     if (length < 0)
-       DIE("Negative length");
+       DIE(aTHX_ "Negative length");
     SETERRNO(0,0);
     io = GvIO(gv);
     if (!io || !IoIFP(io)) {
        length = -1;
-       if (dowarn) {
-           if (op->op_type == OP_SYSWRITE)
-               warn("Syswrite on closed filehandle");
+       if (ckWARN(WARN_CLOSED)) {
+           if (PL_op->op_type == OP_SYSWRITE)
+               Perl_warner(aTHX_ WARN_CLOSED, "Syswrite on closed filehandle");
            else
-               warn("Send on closed socket");
+               Perl_warner(aTHX_ WARN_CLOSED, "Send on closed socket");
        }
     }
-    else if (op->op_type == OP_SYSWRITE) {
+    else if (PL_op->op_type == OP_SYSWRITE) {
        if (MARK < SP) {
            offset = SvIVx(*++MARK);
            if (offset < 0) {
                if (-offset > blen)
-                   DIE("Offset outside string");
+                   DIE(aTHX_ "Offset outside string");
                offset += blen;
            } else if (offset >= blen && blen > 0)
-               DIE("Offset outside string");
+               DIE(aTHX_ "Offset outside string");
        } else
            offset = 0;
        if (length > blen - offset)
            length = blen - offset;
-       length = PerlLIO_write(PerlIO_fileno(IoIFP(io)), buffer+offset, length);
+#ifdef PERL_SOCK_SYSWRITE_IS_SEND
+       if (IoTYPE(io) == 's') {
+           length = PerlSock_send(PerlIO_fileno(IoIFP(io)),
+                                  buffer+offset, length, 0);
+       }
+       else
+#endif
+       {
+           length = PerlLIO_write(PerlIO_fileno(IoIFP(io)),
+                                  buffer+offset, length);
+       }
     }
 #ifdef HAS_SOCKET
     else if (SP > MARK) {
@@ -1384,7 +1684,7 @@ PP(pp_send)
 
 #else
     else
-       DIE(no_sock_func, "send");
+       DIE(aTHX_ PL_no_sock_func, "send");
 #endif
     if (length < 0)
        goto say_undef;
@@ -1399,18 +1699,31 @@ PP(pp_send)
 
 PP(pp_recv)
 {
-    return pp_sysread(ARGS);
+    return pp_sysread();
 }
 
 PP(pp_eof)
 {
     djSP;
     GV *gv;
+    MAGIC *mg;
 
     if (MAXARG <= 0)
-       gv = last_in_gv;
+       gv = PL_last_in_gv;
     else
-       gv = last_in_gv = (GV*)POPs;
+       gv = PL_last_in_gv = (GV*)POPs;
+
+    if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
+       PUSHMARK(SP);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
+       PUTBACK;
+       ENTER;
+       call_method("EOF", G_SCALAR);
+       LEAVE;
+       SPAGAIN;
+       RETURN;
+    }
+
     PUSHs(boolSV(!gv || do_eof(gv)));
     RETURN;
 }
@@ -1418,19 +1731,32 @@ PP(pp_eof)
 PP(pp_tell)
 {
     djSP; dTARGET;
-    GV *gv;
+    GV *gv;     
+    MAGIC *mg;
 
     if (MAXARG <= 0)
-       gv = last_in_gv;
+       gv = PL_last_in_gv;
     else
-       gv = last_in_gv = (GV*)POPs;
+       gv = PL_last_in_gv = (GV*)POPs;
+
+    if (gv && (mg = SvTIED_mg((SV*)gv, 'q'))) {
+       PUSHMARK(SP);
+       XPUSHs(SvTIED_obj((SV*)gv, mg));
+       PUTBACK;
+       ENTER;
+       call_method("TELL", G_SCALAR);
+       LEAVE;
+       SPAGAIN;
+       RETURN;
+    }
+
     PUSHi( do_tell(gv) );
     RETURN;
 }
 
 PP(pp_seek)
 {
-    return pp_sysseek(ARGS);
+    return pp_sysseek();
 }
 
 PP(pp_sysseek)
@@ -1438,16 +1764,31 @@ PP(pp_sysseek)
     djSP;
     GV *gv;
     int whence = POPi;
-    long offset = POPl;
+    Off_t offset = POPl;
+    MAGIC *mg;
+
+    gv = PL_last_in_gv = (GV*)POPs;
+
+    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)));
+       PUTBACK;
+       ENTER;
+       call_method("SEEK", G_SCALAR);
+       LEAVE;
+       SPAGAIN;
+       RETURN;
+    }
 
-    gv = last_in_gv = (GV*)POPs;
-    if (op->op_type == OP_SEEK)
+    if (PL_op->op_type == OP_SEEK)
        PUSHs(boolSV(do_seek(gv, offset, whence)));
     else {
-       long n = do_sysseek(gv, offset, whence);
-       PUSHs((n < 0) ? &sv_undef
+       Off_t n = do_sysseek(gv, offset, whence);
+       PUSHs((n < 0) ? &PL_sv_undef
              : sv_2mortal(n ? newSViv((IV)n)
-                          : newSVpv(zero_but_true, ZBTLEN)));
+                          : newSVpvn(zero_but_true, ZBTLEN)));
     }
     RETURN;
 }
@@ -1458,11 +1799,12 @@ PP(pp_truncate)
     Off_t len = (Off_t)POPn;
     int result = 1;
     GV *tmpgv;
+    STRLEN n_a;
 
     SETERRNO(0,0);
 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) || defined(F_FREESP)
-    if (op->op_flags & OPf_SPECIAL) {
-       tmpgv = gv_fetchpv(POPp, FALSE, SVt_PVIO);
+    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)) ||
@@ -1476,6 +1818,7 @@ PP(pp_truncate)
     else {
        SV *sv = POPs;
        char *name;
+       STRLEN n_a;
 
        if (SvTYPE(sv) == SVt_PVGV) {
            tmpgv = (GV*)sv;            /* *main::FRED for example */
@@ -1486,7 +1829,7 @@ PP(pp_truncate)
            goto do_ftruncate;
        }
 
-       name = SvPV(sv, na);
+       name = SvPV(sv, n_a);
        TAINT_PROPER("truncate");
 #ifdef HAS_TRUNCATE
        if (truncate(name, len) < 0)
@@ -1511,13 +1854,13 @@ PP(pp_truncate)
        SETERRNO(EBADF,RMS$_IFI);
     RETPUSHUNDEF;
 #else
-    DIE("truncate not implemented");
+    DIE(aTHX_ "truncate not implemented");
 #endif
 }
 
 PP(pp_fcntl)
 {
-    return pp_ioctl(ARGS);
+    return pp_ioctl();
 }
 
 PP(pp_ioctl)
@@ -1525,7 +1868,7 @@ PP(pp_ioctl)
     djSP; dTARGET;
     SV *argsv = POPs;
     unsigned int func = U_I(POPn);
-    int optype = op->op_type;
+    int optype = PL_op->op_type;
     char *s;
     IV retval;
     GV *gv = (GV*)POPs;
@@ -1557,9 +1900,9 @@ PP(pp_ioctl)
 
     if (optype == OP_IOCTL)
 #ifdef HAS_IOCTL
-       retval = ioctl(PerlIO_fileno(IoIFP(io)), func, s);
+       retval = PerlLIO_ioctl(PerlIO_fileno(IoIFP(io)), func, s);
 #else
-       DIE("ioctl is not implemented");
+       DIE(aTHX_ "ioctl is not implemented");
 #endif
     else
 #ifdef HAS_FCNTL
@@ -1569,13 +1912,13 @@ PP(pp_ioctl)
        retval = fcntl(PerlIO_fileno(IoIFP(io)), func, s);
 #endif 
 #else
-       DIE("fcntl is not implemented");
+       DIE(aTHX_ "fcntl is not implemented");
 #endif
 
     if (SvPOK(argsv)) {
        if (s[SvCUR(argsv)] != 17)
-           DIE("Possible memory corruption: %s overflowed 3rd argument",
-               op_name[optype]);
+           DIE(aTHX_ "Possible memory corruption: %s overflowed 3rd argument",
+               PL_op_name[optype]);
        s[SvCUR(argsv)] = 0;            /* put our null back */
        SvSETMAGIC(argsv);              /* Assume it has changed */
     }
@@ -1602,7 +1945,7 @@ PP(pp_flock)
 #ifdef FLOCK
     argtype = POPi;
     if (MAXARG <= 0)
-       gv = last_in_gv;
+       gv = PL_last_in_gv;
     else
        gv = (GV*)POPs;
     if (gv && GvIO(gv))
@@ -1611,14 +1954,14 @@ PP(pp_flock)
        fp = Nullfp;
     if (fp) {
        (void)PerlIO_flush(fp);
-       value = (I32)(FLOCK(PerlIO_fileno(fp), argtype) >= 0);
+       value = (I32)(PerlLIO_flock(PerlIO_fileno(fp), argtype) >= 0);
     }
     else
        value = 0;
     PUSHi(value);
     RETURN;
 #else
-    DIE(no_func, "flock()");
+    DIE(aTHX_ PL_no_func, "flock()");
 #endif
 }
 
@@ -1662,7 +2005,7 @@ PP(pp_socket)
 
     RETPUSHYES;
 #else
-    DIE(no_sock_func, "socket");
+    DIE(aTHX_ PL_no_sock_func, "socket");
 #endif
 }
 
@@ -1712,7 +2055,7 @@ PP(pp_sockpair)
 
     RETPUSHYES;
 #else
-    DIE(no_sock_func, "socketpair");
+    DIE(aTHX_ PL_no_sock_func, "socketpair");
 #endif
 }
 
@@ -1720,29 +2063,58 @@ PP(pp_bind)
 {
     djSP;
 #ifdef HAS_SOCKET
+#ifdef MPE /* Requires PRIV mode to bind() to ports < 1024 */
+    extern GETPRIVMODE();
+    extern GETUSERMODE();
+#endif
     SV *addrsv = POPs;
     char *addr;
     GV *gv = (GV*)POPs;
     register IO *io = GvIOn(gv);
     STRLEN len;
+    int bind_ok = 0;
+#ifdef MPE
+    int mpeprivmode = 0;
+#endif
 
     if (!io || !IoIFP(io))
        goto nuts;
 
     addr = SvPV(addrsv, len);
     TAINT_PROPER("bind");
-    if (PerlSock_bind(PerlIO_fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
+#ifdef MPE /* Deal with MPE bind() peculiarities */
+    if (((struct sockaddr *)addr)->sa_family == AF_INET) {
+        /* The address *MUST* stupidly be zero. */
+        ((struct sockaddr_in *)addr)->sin_addr.s_addr = INADDR_ANY;
+        /* PRIV mode is required to bind() to ports < 1024. */
+        if (((struct sockaddr_in *)addr)->sin_port < 1024 &&
+            ((struct sockaddr_in *)addr)->sin_port > 0) {
+            GETPRIVMODE(); /* If this fails, we are aborted by MPE/iX. */
+           mpeprivmode = 1;
+       }
+    }
+#endif /* MPE */
+    if (PerlSock_bind(PerlIO_fileno(IoIFP(io)),
+                     (struct sockaddr *)addr, len) >= 0)
+       bind_ok = 1;
+
+#ifdef MPE /* Switch back to USER mode */
+    if (mpeprivmode)
+       GETUSERMODE();
+#endif /* MPE */
+
+    if (bind_ok)
        RETPUSHYES;
     else
        RETPUSHUNDEF;
 
 nuts:
-    if (dowarn)
-       warn("bind() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "bind() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
-    DIE(no_sock_func, "bind");
+    DIE(aTHX_ PL_no_sock_func, "bind");
 #endif
 }
 
@@ -1767,12 +2139,12 @@ PP(pp_connect)
        RETPUSHUNDEF;
 
 nuts:
-    if (dowarn)
-       warn("connect() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "connect() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
-    DIE(no_sock_func, "connect");
+    DIE(aTHX_ PL_no_sock_func, "connect");
 #endif
 }
 
@@ -1793,12 +2165,12 @@ PP(pp_listen)
        RETPUSHUNDEF;
 
 nuts:
-    if (dowarn)
-       warn("listen() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "listen() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
-    DIE(no_sock_func, "listen");
+    DIE(aTHX_ PL_no_sock_func, "listen");
 #endif
 }
 
@@ -1847,15 +2219,15 @@ PP(pp_accept)
     RETURN;
 
 nuts:
-    if (dowarn)
-       warn("accept() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "accept() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
 
 badexit:
     RETPUSHUNDEF;
 
 #else
-    DIE(no_sock_func, "accept");
+    DIE(aTHX_ PL_no_sock_func, "accept");
 #endif
 }
 
@@ -1874,21 +2246,21 @@ PP(pp_shutdown)
     RETURN;
 
 nuts:
-    if (dowarn)
-       warn("shutdown() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "shutdown() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
     RETPUSHUNDEF;
 #else
-    DIE(no_sock_func, "shutdown");
+    DIE(aTHX_ PL_no_sock_func, "shutdown");
 #endif
 }
 
 PP(pp_gsockopt)
 {
 #ifdef HAS_SOCKET
-    return pp_ssockopt(ARGS);
+    return pp_ssockopt();
 #else
-    DIE(no_sock_func, "getsockopt");
+    DIE(aTHX_ PL_no_sock_func, "getsockopt");
 #endif
 }
 
@@ -1896,7 +2268,7 @@ PP(pp_ssockopt)
 {
     djSP;
 #ifdef HAS_SOCKET
-    int optype = op->op_type;
+    int optype = PL_op->op_type;
     SV *sv;
     int fd;
     unsigned int optname;
@@ -1935,40 +2307,41 @@ PP(pp_ssockopt)
            char *buf;
            int aint;
            if (SvPOKp(sv)) {
-               buf = SvPV(sv, na);
-               len = na;
+               STRLEN l;
+               buf = SvPV(sv, l);
+               len = l;
            }
-           else if (SvOK(sv)) {
+           else {
                aint = (int)SvIV(sv);
                buf = (char*)&aint;
                len = sizeof(int);
            }
            if (PerlSock_setsockopt(fd, lvl, optname, buf, len) < 0)
                goto nuts2;
-           PUSHs(&sv_yes);
+           PUSHs(&PL_sv_yes);
        }
        break;
     }
     RETURN;
 
 nuts:
-    if (dowarn)
-       warn("[gs]etsockopt() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "[gs]etsockopt() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
 nuts2:
     RETPUSHUNDEF;
 
 #else
-    DIE(no_sock_func, "setsockopt");
+    DIE(aTHX_ PL_no_sock_func, "setsockopt");
 #endif
 }
 
 PP(pp_getsockname)
 {
 #ifdef HAS_SOCKET
-    return pp_getpeername(ARGS);
+    return pp_getpeername();
 #else
-    DIE(no_sock_func, "getsockname");
+    DIE(aTHX_ PL_no_sock_func, "getsockname");
 #endif
 }
 
@@ -1976,7 +2349,7 @@ PP(pp_getpeername)
 {
     djSP;
 #ifdef HAS_SOCKET
-    int optype = op->op_type;
+    int optype = PL_op->op_type;
     SV *sv;
     int fd;
     GV *gv = (GV*)POPs;
@@ -2025,14 +2398,14 @@ PP(pp_getpeername)
     RETURN;
 
 nuts:
-    if (dowarn)
-       warn("get{sock, peer}name() on closed fd");
+    if (ckWARN(WARN_CLOSED))
+       Perl_warner(aTHX_ WARN_CLOSED, "get{sock, peer}name() on closed fd");
     SETERRNO(EBADF,SS$_IVCHAN);
 nuts2:
     RETPUSHUNDEF;
 
 #else
-    DIE(no_sock_func, "getpeername");
+    DIE(aTHX_ PL_no_sock_func, "getpeername");
 #endif
 }
 
@@ -2040,7 +2413,7 @@ nuts2:
 
 PP(pp_lstat)
 {
-    return pp_stat(ARGS);
+    return pp_stat();
 }
 
 PP(pp_stat)
@@ -2049,18 +2422,19 @@ PP(pp_stat)
     GV *tmpgv;
     I32 gimme;
     I32 max = 13;
+    STRLEN n_a;
 
-    if (op->op_flags & OPf_REF) {
+    if (PL_op->op_flags & OPf_REF) {
        tmpgv = cGVOP->op_gv;
       do_fstat:
-       if (tmpgv != defgv) {
-           laststype = OP_STAT;
-           statgv = tmpgv;
-           sv_setpv(statname, "");
-           laststatval = (GvIO(tmpgv) && IoIFP(GvIOp(tmpgv))
-               ? PerlLIO_fstat(PerlIO_fileno(IoIFP(GvIOn(tmpgv))), &statcache) : -1);
+       if (tmpgv != PL_defgv) {
+           PL_laststype = OP_STAT;
+           PL_statgv = tmpgv;
+           sv_setpv(PL_statname, "");
+           PL_laststatval = (GvIO(tmpgv) && IoIFP(GvIOp(tmpgv))
+               ? PerlLIO_fstat(PerlIO_fileno(IoIFP(GvIOn(tmpgv))), &PL_statcache) : -1);
        }
-       if (laststatval < 0)
+       if (PL_laststatval < 0)
            max = 0;
     }
     else {
@@ -2073,18 +2447,18 @@ PP(pp_stat)
            tmpgv = (GV*)SvRV(sv);
            goto do_fstat;
        }
-       sv_setpv(statname, SvPV(sv,na));
-       statgv = Nullgv;
+       sv_setpv(PL_statname, SvPV(sv,n_a));
+       PL_statgv = Nullgv;
 #ifdef HAS_LSTAT
-       laststype = op->op_type;
-       if (op->op_type == OP_LSTAT)
-           laststatval = PerlLIO_lstat(SvPV(statname, na), &statcache);
+       PL_laststype = PL_op->op_type;
+       if (PL_op->op_type == OP_LSTAT)
+           PL_laststatval = PerlLIO_lstat(SvPV(PL_statname, n_a), &PL_statcache);
        else
 #endif
-           laststatval = PerlLIO_stat(SvPV(statname, na), &statcache);
-       if (laststatval < 0) {
-           if (dowarn && strchr(SvPV(statname, na), '\n'))
-               warn(warn_nl, "stat");
+           PL_laststatval = PerlLIO_stat(SvPV(PL_statname, n_a), &PL_statcache);
+       if (PL_laststatval < 0) {
+           if (ckWARN(WARN_NEWLINE) && strchr(SvPV(PL_statname, n_a), '\n'))
+               Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "stat");
            max = 0;
        }
     }
@@ -2098,33 +2472,33 @@ PP(pp_stat)
     if (max) {
        EXTEND(SP, max);
        EXTEND_MORTAL(max);
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_dev)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_ino)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_mode)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_nlink)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_uid)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_gid)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_dev)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ino)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_mode)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_nlink)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_uid)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_gid)));
 #ifdef USE_STAT_RDEV
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_rdev)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_rdev)));
 #else
-       PUSHs(sv_2mortal(newSVpv("", 0)));
+       PUSHs(sv_2mortal(newSVpvn("", 0)));
 #endif
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_size)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_size)));
 #ifdef BIG_TIME
-       PUSHs(sv_2mortal(newSVnv((U32)statcache.st_atime)));
-       PUSHs(sv_2mortal(newSVnv((U32)statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSVnv((U32)statcache.st_ctime)));
+       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)));
 #else
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_atime)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSViv((I32)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)statcache.st_blksize)));
-       PUSHs(sv_2mortal(newSViv((I32)statcache.st_blocks)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_blksize)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_blocks)));
 #else
-       PUSHs(sv_2mortal(newSVpv("", 0)));
-       PUSHs(sv_2mortal(newSVpv("", 0)));
+       PUSHs(sv_2mortal(newSVpvn("", 0)));
+       PUSHs(sv_2mortal(newSVpvn("", 0)));
 #endif
     }
     RETURN;
@@ -2132,73 +2506,169 @@ PP(pp_stat)
 
 PP(pp_ftrread)
 {
-    I32 result = my_stat(ARGS);
+    I32 result;
     djSP;
+#if defined(HAS_ACCESS) && defined(R_OK)
+    STRLEN n_a;
+    if ((PL_hints & HINT_FILETEST_ACCESS) && SvPOK(TOPs)) {
+       result = access(TOPpx, R_OK);
+       if (result == 0)
+           RETPUSHYES;
+       if (result < 0)
+           RETPUSHUNDEF;
+       RETPUSHNO;
+    }
+    else
+       result = my_stat();
+#else
+    result = my_stat();
+#endif
+    SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (cando(S_IRUSR, 0, &statcache))
+    if (cando(S_IRUSR, 0, &PL_statcache))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftrwrite)
 {
-    I32 result = my_stat(ARGS);
+    I32 result;
     djSP;
+#if defined(HAS_ACCESS) && defined(W_OK)
+    STRLEN n_a;
+    if ((PL_hints & HINT_FILETEST_ACCESS) && SvPOK(TOPs)) {
+       result = access(TOPpx, W_OK);
+       if (result == 0)
+           RETPUSHYES;
+       if (result < 0)
+           RETPUSHUNDEF;
+       RETPUSHNO;
+    }
+    else
+       result = my_stat();
+#else
+    result = my_stat();
+#endif
+    SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (cando(S_IWUSR, 0, &statcache))
+    if (cando(S_IWUSR, 0, &PL_statcache))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftrexec)
 {
-    I32 result = my_stat(ARGS);
+    I32 result;
     djSP;
+#if defined(HAS_ACCESS) && defined(X_OK)
+    STRLEN n_a;
+    if ((PL_hints & HINT_FILETEST_ACCESS) && SvPOK(TOPs)) {
+       result = access(TOPpx, X_OK);
+       if (result == 0)
+           RETPUSHYES;
+       if (result < 0)
+           RETPUSHUNDEF;
+       RETPUSHNO;
+    }
+    else
+       result = my_stat();
+#else
+    result = my_stat();
+#endif
+    SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (cando(S_IXUSR, 0, &statcache))
+    if (cando(S_IXUSR, 0, &PL_statcache))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_fteread)
 {
-    I32 result = my_stat(ARGS);
+    I32 result;
     djSP;
+#ifdef PERL_EFF_ACCESS_R_OK
+    STRLEN n_a;
+    if ((PL_hints & HINT_FILETEST_ACCESS) && SvPOK(TOPs)) {
+       result = PERL_EFF_ACCESS_R_OK(TOPpx);
+       if (result == 0)
+           RETPUSHYES;
+       if (result < 0)
+           RETPUSHUNDEF;
+       RETPUSHNO;
+    }
+    else
+       result = my_stat();
+#else
+    result = my_stat();
+#endif
+    SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (cando(S_IRUSR, 1, &statcache))
+    if (cando(S_IRUSR, 1, &PL_statcache))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftewrite)
 {
-    I32 result = my_stat(ARGS);
+    I32 result;
     djSP;
+#ifdef PERL_EFF_ACCESS_W_OK
+    STRLEN n_a;
+    if ((PL_hints & HINT_FILETEST_ACCESS) && SvPOK(TOPs)) {
+       result = PERL_EFF_ACCESS_W_OK(TOPpx);
+       if (result == 0)
+           RETPUSHYES;
+       if (result < 0)
+           RETPUSHUNDEF;
+       RETPUSHNO;
+    }
+    else
+       result = my_stat();
+#else
+    result = my_stat();
+#endif
+    SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (cando(S_IWUSR, 1, &statcache))
+    if (cando(S_IWUSR, 1, &PL_statcache))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_fteexec)
 {
-    I32 result = my_stat(ARGS);
+    I32 result;
     djSP;
+#ifdef PERL_EFF_ACCESS_X_OK
+    STRLEN n_a;
+    if ((PL_hints & HINT_FILETEST_ACCESS) && SvPOK(TOPs)) {
+       result = PERL_EFF_ACCESS_X_OK(TOPpx);
+       if (result == 0)
+           RETPUSHYES;
+       if (result < 0)
+           RETPUSHUNDEF;
+       RETPUSHNO;
+    }
+    else
+       result = my_stat();
+#else
+    result = my_stat();
+#endif
+    SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (cando(S_IXUSR, 1, &statcache))
+    if (cando(S_IXUSR, 1, &PL_statcache))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftis)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
@@ -2207,144 +2677,144 @@ PP(pp_ftis)
 
 PP(pp_fteowned)
 {
-    return pp_ftrowned(ARGS);
+    return pp_ftrowned();
 }
 
 PP(pp_ftrowned)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (statcache.st_uid == (op->op_type == OP_FTEOWNED ? euid : uid) )
+    if (PL_statcache.st_uid == (PL_op->op_type == OP_FTEOWNED ? PL_euid : PL_uid) )
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftzero)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (!statcache.st_size)
+    if (!PL_statcache.st_size)
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftsize)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHi(statcache.st_size);
+    PUSHi(PL_statcache.st_size);
     RETURN;
 }
 
 PP(pp_ftmtime)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)basetime - (I32)statcache.st_mtime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_mtime) / 86400.0 );
     RETURN;
 }
 
 PP(pp_ftatime)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)basetime - (I32)statcache.st_atime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_atime) / 86400.0 );
     RETURN;
 }
 
 PP(pp_ftctime)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)basetime - (I32)statcache.st_ctime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_ctime) / 86400.0 );
     RETURN;
 }
 
 PP(pp_ftsock)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISSOCK(statcache.st_mode))
+    if (S_ISSOCK(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftchr)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISCHR(statcache.st_mode))
+    if (S_ISCHR(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftblk)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISBLK(statcache.st_mode))
+    if (S_ISBLK(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftfile)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISREG(statcache.st_mode))
+    if (S_ISREG(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftdir)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISDIR(statcache.st_mode))
+    if (S_ISDIR(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftpipe)
 {
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISFIFO(statcache.st_mode))
+    if (S_ISFIFO(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
 
 PP(pp_ftlink)
 {
-    I32 result = my_lstat(ARGS);
+    I32 result = my_lstat();
     djSP;
     if (result < 0)
        RETPUSHUNDEF;
-    if (S_ISLNK(statcache.st_mode))
+    if (S_ISLNK(PL_statcache.st_mode))
        RETPUSHYES;
     RETPUSHNO;
 }
@@ -2353,11 +2823,11 @@ PP(pp_ftsuid)
 {
     djSP;
 #ifdef S_ISUID
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (statcache.st_mode & S_ISUID)
+    if (PL_statcache.st_mode & S_ISUID)
        RETPUSHYES;
 #endif
     RETPUSHNO;
@@ -2367,11 +2837,11 @@ PP(pp_ftsgid)
 {
     djSP;
 #ifdef S_ISGID
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (statcache.st_mode & S_ISGID)
+    if (PL_statcache.st_mode & S_ISGID)
        RETPUSHYES;
 #endif
     RETPUSHNO;
@@ -2381,11 +2851,11 @@ PP(pp_ftsvtx)
 {
     djSP;
 #ifdef S_ISVTX
-    I32 result = my_stat(ARGS);
+    I32 result = my_stat();
     SPAGAIN;
     if (result < 0)
        RETPUSHUNDEF;
-    if (statcache.st_mode & S_ISVTX)
+    if (PL_statcache.st_mode & S_ISVTX)
        RETPUSHYES;
 #endif
     RETPUSHNO;
@@ -2397,15 +2867,16 @@ PP(pp_fttty)
     int fd;
     GV *gv;
     char *tmps = Nullch;
+    STRLEN n_a;
 
-    if (op->op_flags & OPf_REF)
+    if (PL_op->op_flags & OPf_REF)
        gv = cGVOP->op_gv;
     else if (isGV(TOPs))
        gv = (GV*)POPs;
     else if (SvROK(TOPs) && isGV(SvRV(TOPs)))
        gv = (GV*)SvRV(POPs);
     else
-       gv = gv_fetchpv(tmps = POPp, FALSE, SVt_PVIO);
+       gv = gv_fetchpv(tmps = POPpx, FALSE, SVt_PVIO);
 
     if (GvIO(gv) && IoIFP(GvIOp(gv)))
        fd = PerlIO_fileno(IoIFP(GvIOp(gv)));
@@ -2437,8 +2908,9 @@ PP(pp_fttext)
     register IO *io;
     register SV *sv;
     GV *gv;
+    STRLEN n_a;
 
-    if (op->op_flags & OPf_REF)
+    if (PL_op->op_flags & OPf_REF)
        gv = cGVOP->op_gv;
     else if (isGV(TOPs))
        gv = (GV*)POPs;
@@ -2449,28 +2921,28 @@ PP(pp_fttext)
 
     if (gv) {
        EXTEND(SP, 1);
-       if (gv == defgv) {
-           if (statgv)
-               io = GvIO(statgv);
+       if (gv == PL_defgv) {
+           if (PL_statgv)
+               io = GvIO(PL_statgv);
            else {
-               sv = statname;
+               sv = PL_statname;
                goto really_filename;
            }
        }
        else {
-           statgv = gv;
-           laststatval = -1;
-           sv_setpv(statname, "");
-           io = GvIO(statgv);
+           PL_statgv = gv;
+           PL_laststatval = -1;
+           sv_setpv(PL_statname, "");
+           io = GvIO(PL_statgv);
        }
        if (io && IoIFP(io)) {
            if (! PerlIO_has_base(IoIFP(io)))
-               DIE("-T and -B not implemented on filehandles");
-           laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &statcache);
-           if (laststatval < 0)
+               DIE(aTHX_ "-T and -B not implemented on filehandles");
+           PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache);
+           if (PL_laststatval < 0)
                RETPUSHUNDEF;
-           if (S_ISDIR(statcache.st_mode))     /* handle NFS glitch */
-               if (op->op_type == OP_FTTEXT)
+           if (S_ISDIR(PL_statcache.st_mode))  /* handle NFS glitch */
+               if (PL_op->op_type == OP_FTTEXT)
                    RETPUSHNO;
                else
                    RETPUSHYES;
@@ -2488,8 +2960,8 @@ PP(pp_fttext)
                len = 512;
        }
        else {
-           if (dowarn)
-               warn("Test on unopened file <%s>",
+           if (ckWARN(WARN_UNOPENED))
+               Perl_warner(aTHX_ WARN_UNOPENED, "Test on unopened file <%s>",
                  GvENAME(cGVOP->op_gv));
            SETERRNO(EBADF,RMS$_IFI);
            RETPUSHUNDEF;
@@ -2498,26 +2970,26 @@ PP(pp_fttext)
     else {
        sv = POPs;
       really_filename:
-       statgv = Nullgv;
-       laststatval = -1;
-       sv_setpv(statname, SvPV(sv, na));
+       PL_statgv = Nullgv;
+       PL_laststatval = -1;
+       sv_setpv(PL_statname, SvPV(sv, n_a));
 #ifdef HAS_OPEN3
-       i = PerlLIO_open3(SvPV(sv, na), O_RDONLY, 0);
+       i = PerlLIO_open3(SvPV(sv, n_a), O_RDONLY, 0);
 #else
-       i = PerlLIO_open(SvPV(sv, na), 0);
+       i = PerlLIO_open(SvPV(sv, n_a), 0);
 #endif
        if (i < 0) {
-           if (dowarn && strchr(SvPV(sv, na), '\n'))
-               warn(warn_nl, "open");
+           if (ckWARN(WARN_NEWLINE) && strchr(SvPV(sv, n_a), '\n'))
+               Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
            RETPUSHUNDEF;
        }
-       laststatval = PerlLIO_fstat(i, &statcache);
-       if (laststatval < 0)
+       PL_laststatval = PerlLIO_fstat(i, &PL_statcache);
+       if (PL_laststatval < 0)
            RETPUSHUNDEF;
        len = PerlLIO_read(i, tbuf, 512);
        (void)PerlLIO_close(i);
        if (len <= 0) {
-           if (S_ISDIR(statcache.st_mode) && op->op_type == OP_FTTEXT)
+           if (S_ISDIR(PL_statcache.st_mode) && PL_op->op_type == OP_FTTEXT)
                RETPUSHNO;              /* special case NFS directories */
            RETPUSHYES;         /* null file is anything */
        }
@@ -2532,15 +3004,20 @@ PP(pp_fttext)
            odd += len;
            break;
        }
+#ifdef EBCDIC
+        else if (!(isPRINT(*s) || isSPACE(*s))) 
+            odd++;
+#else
        else if (*s & 128)
            odd++;
        else if (*s < 32 &&
          *s != '\n' && *s != '\r' && *s != '\b' &&
          *s != '\t' && *s != '\f' && *s != 27)
            odd++;
+#endif
     }
 
-    if ((odd * 3 > len) == (op->op_type == OP_FTTEXT)) /* allow 1/3 odd */
+    if ((odd * 3 > len) == (PL_op->op_type == OP_FTTEXT)) /* allow 1/3 odd */
        RETPUSHNO;
     else
        RETPUSHYES;
@@ -2548,7 +3025,7 @@ PP(pp_fttext)
 
 PP(pp_ftbinary)
 {
-    return pp_fttext(ARGS);
+    return pp_fttext();
 }
 
 /* File calls. */
@@ -2558,26 +3035,27 @@ PP(pp_chdir)
     djSP; dTARGET;
     char *tmps;
     SV **svp;
+    STRLEN n_a;
 
     if (MAXARG < 1)
        tmps = Nullch;
     else
-       tmps = POPp;
+       tmps = POPpx;
     if (!tmps || !*tmps) {
-       svp = hv_fetch(GvHVn(envgv), "HOME", 4, FALSE);
+       svp = hv_fetch(GvHVn(PL_envgv), "HOME", 4, FALSE);
        if (svp)
-           tmps = SvPV(*svp, na);
+           tmps = SvPV(*svp, n_a);
     }
     if (!tmps || !*tmps) {
-       svp = hv_fetch(GvHVn(envgv), "LOGDIR", 6, FALSE);
+       svp = hv_fetch(GvHVn(PL_envgv), "LOGDIR", 6, FALSE);
        if (svp)
-           tmps = SvPV(*svp, na);
+           tmps = SvPV(*svp, n_a);
     }
 #ifdef VMS
     if (!tmps || !*tmps) {
-       svp = hv_fetch(GvHVn(envgv), "SYS$LOGIN", 9, FALSE);
+       svp = hv_fetch(GvHVn(PL_envgv), "SYS$LOGIN", 9, FALSE);
        if (svp)
-           tmps = SvPV(*svp, na);
+           tmps = SvPV(*svp, n_a);
     }
 #endif
     TAINT_PROPER("chdir");
@@ -2585,7 +3063,7 @@ PP(pp_chdir)
 #ifdef VMS
     /* Clear the DEFAULT element of ENV so we'll get the new value
      * in the future. */
-    hv_delete(GvHVn(envgv),"DEFAULT",7,G_DISCARD);
+    hv_delete(GvHVn(PL_envgv),"DEFAULT",7,G_DISCARD);
 #endif
     RETURN;
 }
@@ -2595,12 +3073,12 @@ PP(pp_chown)
     djSP; dMARK; dTARGET;
     I32 value;
 #ifdef HAS_CHOWN
-    value = (I32)apply(op->op_type, MARK, SP);
+    value = (I32)apply(PL_op->op_type, MARK, SP);
     SP = MARK;
     PUSHi(value);
     RETURN;
 #else
-    DIE(no_func, "Unsupported function chown");
+    DIE(aTHX_ PL_no_func, "Unsupported function chown");
 #endif
 }
 
@@ -2609,12 +3087,13 @@ PP(pp_chroot)
     djSP; dTARGET;
     char *tmps;
 #ifdef HAS_CHROOT
-    tmps = POPp;
+    STRLEN n_a;
+    tmps = POPpx;
     TAINT_PROPER("chroot");
     PUSHi( chroot(tmps) >= 0 );
     RETURN;
 #else
-    DIE(no_func, "chroot");
+    DIE(aTHX_ PL_no_func, "chroot");
 #endif
 }
 
@@ -2622,7 +3101,7 @@ PP(pp_unlink)
 {
     djSP; dMARK; dTARGET;
     I32 value;
-    value = (I32)apply(op->op_type, MARK, SP);
+    value = (I32)apply(PL_op->op_type, MARK, SP);
     SP = MARK;
     PUSHi(value);
     RETURN;
@@ -2632,7 +3111,7 @@ PP(pp_chmod)
 {
     djSP; dMARK; dTARGET;
     I32 value;
-    value = (I32)apply(op->op_type, MARK, SP);
+    value = (I32)apply(PL_op->op_type, MARK, SP);
     SP = MARK;
     PUSHi(value);
     RETURN;
@@ -2642,7 +3121,7 @@ PP(pp_utime)
 {
     djSP; dMARK; dTARGET;
     I32 value;
-    value = (I32)apply(op->op_type, MARK, SP);
+    value = (I32)apply(PL_op->op_type, MARK, SP);
     SP = MARK;
     PUSHi(value);
     RETURN;
@@ -2652,18 +3131,19 @@ PP(pp_rename)
 {
     djSP; dTARGET;
     int anum;
+    STRLEN n_a;
 
-    char *tmps2 = POPp;
-    char *tmps = SvPV(TOPs, na);
+    char *tmps2 = POPpx;
+    char *tmps = SvPV(TOPs, n_a);
     TAINT_PROPER("rename");
 #ifdef HAS_RENAME
-    anum = rename(tmps, tmps2);
+    anum = PerlLIO_rename(tmps, tmps2);
 #else
-    if (!(anum = PerlLIO_stat(tmps, &statbuf))) {
+    if (!(anum = PerlLIO_stat(tmps, &PL_statbuf))) {
        if (same_dirent(tmps2, tmps))   /* can always rename to same name */
            anum = 1;
        else {
-           if (euid || PerlLIO_stat(tmps2, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
+           if (PL_euid || PerlLIO_stat(tmps2, &PL_statbuf) < 0 || !S_ISDIR(PL_statbuf.st_mode))
                (void)UNLINK(tmps2);
            if (!(anum = link(tmps, tmps2)))
                anum = UNLINK(tmps);
@@ -2678,12 +3158,13 @@ PP(pp_link)
 {
     djSP; dTARGET;
 #ifdef HAS_LINK
-    char *tmps2 = POPp;
-    char *tmps = SvPV(TOPs, na);
+    STRLEN n_a;
+    char *tmps2 = POPpx;
+    char *tmps = SvPV(TOPs, n_a);
     TAINT_PROPER("link");
     SETi( link(tmps, tmps2) >= 0 );
 #else
-    DIE(no_func, "Unsupported function link");
+    DIE(aTHX_ PL_no_func, "Unsupported function link");
 #endif
     RETURN;
 }
@@ -2692,13 +3173,14 @@ PP(pp_symlink)
 {
     djSP; dTARGET;
 #ifdef HAS_SYMLINK
-    char *tmps2 = POPp;
-    char *tmps = SvPV(TOPs, na);
+    STRLEN n_a;
+    char *tmps2 = POPpx;
+    char *tmps = SvPV(TOPs, n_a);
     TAINT_PROPER("symlink");
     SETi( symlink(tmps, tmps2) >= 0 );
     RETURN;
 #else
-    DIE(no_func, "symlink");
+    DIE(aTHX_ PL_no_func, "symlink");
 #endif
 }
 
@@ -2709,11 +3191,12 @@ PP(pp_readlink)
     char *tmps;
     char buf[MAXPATHLEN];
     int len;
+    STRLEN n_a;
 
 #ifndef INCOMPLETE_TAINTS
     TAINT;
 #endif
-    tmps = POPp;
+    tmps = POPpx;
     len = readlink(tmps, buf, sizeof buf);
     EXTEND(SP, 1);
     if (len < 0)
@@ -2727,10 +3210,8 @@ PP(pp_readlink)
 }
 
 #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
-static int
-dooneliner(cmd, filename)
-char *cmd;
-char *filename;
+STATIC int
+S_dooneliner(pTHX_ char *cmd, char *filename)
 {
     char *save_filename = filename;
     char *cmdline;
@@ -2751,7 +3232,7 @@ char *filename;
 
     if (myfp) {
        SV *tmpsv = sv_newmortal();
-       /* Need to save/restore 'rs' ?? */
+       /* Need to save/restore 'PL_rs' ?? */
        s = sv_gets(tmpsv, myfp, 0);
        (void)PerlProc_pclose(myfp);
        if (s != Nullch) {
@@ -2800,8 +3281,8 @@ char *filename;
            return 0;
        }
        else {  /* some mkdirs return no failure indication */
-           anum = (PerlLIO_stat(save_filename, &statbuf) >= 0);
-           if (op->op_type == OP_RMDIR)
+           anum = (PerlLIO_stat(save_filename, &PL_statbuf) >= 0);
+           if (PL_op->op_type == OP_RMDIR)
                anum = !anum;
            if (anum)
                SETERRNO(0,0);
@@ -2822,7 +3303,8 @@ PP(pp_mkdir)
 #ifndef HAS_MKDIR
     int oldumask;
 #endif
-    char *tmps = SvPV(TOPs, na);
+    STRLEN n_a;
+    char *tmps = SvPV(TOPs, n_a);
 
     TAINT_PROPER("mkdir");
 #ifdef HAS_MKDIR
@@ -2840,8 +3322,9 @@ PP(pp_rmdir)
 {
     djSP; dTARGET;
     char *tmps;
+    STRLEN n_a;
 
-    tmps = POPp;
+    tmps = POPpx;
     TAINT_PROPER("rmdir");
 #ifdef HAS_RMDIR
     XPUSHi( PerlDir_rmdir(tmps) >= 0 );
@@ -2857,7 +3340,8 @@ PP(pp_open_dir)
 {
     djSP;
 #if defined(Direntry_t) && defined(HAS_READDIR)
-    char *dirname = POPp;
+    STRLEN n_a;
+    char *dirname = POPpx;
     GV *gv = (GV*)POPs;
     register IO *io = GvIOn(gv);
 
@@ -2875,7 +3359,7 @@ nope:
        SETERRNO(EBADF,RMS$_DIR);
     RETPUSHUNDEF;
 #else
-    DIE(no_dir_func, "opendir");
+    DIE(aTHX_ PL_no_dir_func, "opendir");
 #endif
 }
 
@@ -2884,7 +3368,7 @@ PP(pp_readdir)
     djSP;
 #if defined(Direntry_t) && defined(HAS_READDIR)
 #ifndef I_DIRENT
-    Direntry_t *readdir _((DIR *));
+    Direntry_t *readdir (DIR *);
 #endif
     register Direntry_t *dp;
     GV *gv = (GV*)POPs;
@@ -2898,7 +3382,7 @@ PP(pp_readdir)
        /*SUPPRESS 560*/
        while (dp = (Direntry_t *)PerlDir_read(IoDIRP(io))) {
 #ifdef DIRNAMLEN
-           sv = newSVpv(dp->d_name, dp->d_namlen);
+           sv = newSVpvn(dp->d_name, dp->d_namlen);
 #else
            sv = newSVpv(dp->d_name, 0);
 #endif
@@ -2912,7 +3396,7 @@ PP(pp_readdir)
        if (!(dp = (Direntry_t *)PerlDir_read(IoDIRP(io))))
            goto nope;
 #ifdef DIRNAMLEN
-       sv = newSVpv(dp->d_name, dp->d_namlen);
+       sv = newSVpvn(dp->d_name, dp->d_namlen);
 #else
        sv = newSVpv(dp->d_name, 0);
 #endif
@@ -2931,7 +3415,7 @@ nope:
     else
        RETPUSHUNDEF;
 #else
-    DIE(no_dir_func, "readdir");
+    DIE(aTHX_ PL_no_dir_func, "readdir");
 #endif
 }
 
@@ -2939,8 +3423,12 @@ PP(pp_telldir)
 {
     djSP; dTARGET;
 #if defined(HAS_TELLDIR) || defined(telldir)
-# ifdef NEED_TELLDIR_PROTO /* XXX does _anyone_ need this? --AD 2/20/1998 */
-    long telldir _((DIR *));
+ /* XXX does _anyone_ need this? --AD 2/20/1998 */
+ /* XXX netbsd still seemed to.
+    XXX HAS_TELLDIR_PROTO is new style, NEED_TELLDIR_PROTO is old style.
+    --JHI 1999-Feb-02 */
+# if !defined(HAS_TELLDIR_PROTO) || defined(NEED_TELLDIR_PROTO)
+    long telldir (DIR *);
 # endif
     GV *gv = (GV*)POPs;
     register IO *io = GvIOn(gv);
@@ -2955,7 +3443,7 @@ nope:
        SETERRNO(EBADF,RMS$_ISI);
     RETPUSHUNDEF;
 #else
-    DIE(no_dir_func, "telldir");
+    DIE(aTHX_ PL_no_dir_func, "telldir");
 #endif
 }
 
@@ -2978,7 +3466,7 @@ nope:
        SETERRNO(EBADF,RMS$_ISI);
     RETPUSHUNDEF;
 #else
-    DIE(no_dir_func, "seekdir");
+    DIE(aTHX_ PL_no_dir_func, "seekdir");
 #endif
 }
 
@@ -2999,7 +3487,7 @@ nope:
        SETERRNO(EBADF,RMS$_ISI);
     RETPUSHUNDEF;
 #else
-    DIE(no_dir_func, "rewinddir");
+    DIE(aTHX_ PL_no_dir_func, "rewinddir");
 #endif
 }
 
@@ -3029,7 +3517,7 @@ nope:
        SETERRNO(EBADF,RMS$_IFI);
     RETPUSHUNDEF;
 #else
-    DIE(no_dir_func, "closedir");
+    DIE(aTHX_ PL_no_dir_func, "closedir");
 #endif
 }
 
@@ -3039,10 +3527,11 @@ PP(pp_fork)
 {
 #ifdef HAS_FORK
     djSP; dTARGET;
-    int childpid;
+    Pid_t childpid;
     GV *tmpgv;
 
     EXTEND(SP, 1);
+    PERL_FLUSHALL_FOR_CHILD;
     childpid = fork();
     if (childpid < 0)
        RETSETUNDEF;
@@ -3050,12 +3539,12 @@ PP(pp_fork)
        /*SUPPRESS 560*/
        if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV))
            sv_setiv(GvSV(tmpgv), (IV)getpid());
-       hv_clear(pidstatus);    /* no kids, so don't wait for 'em */
+       hv_clear(PL_pidstatus); /* no kids, so don't wait for 'em */
     }
     PUSHi(childpid);
     RETURN;
 #else
-    DIE(no_func, "Unsupported function fork");
+    DIE(aTHX_ PL_no_func, "Unsupported function fork");
 #endif
 }
 
@@ -3063,7 +3552,7 @@ PP(pp_wait)
 {
 #if !defined(DOSISH) || defined(OS2) || defined(WIN32)
     djSP; dTARGET;
-    int childpid;
+    Pid_t childpid;
     int argflags;
 
     childpid = wait4pid(-1, &argflags, 0);
@@ -3071,7 +3560,7 @@ PP(pp_wait)
     XPUSHi(childpid);
     RETURN;
 #else
-    DIE(no_func, "Unsupported function wait");
+    DIE(aTHX_ PL_no_func, "Unsupported function wait");
 #endif
 }
 
@@ -3079,7 +3568,7 @@ PP(pp_waitpid)
 {
 #if !defined(DOSISH) || defined(OS2) || defined(WIN32)
     djSP; dTARGET;
-    int childpid;
+    Pid_t childpid;
     int optype;
     int argflags;
 
@@ -3090,7 +3579,7 @@ PP(pp_waitpid)
     SETi(childpid);
     RETURN;
 #else
-    DIE(no_func, "Unsupported function waitpid");
+    DIE(aTHX_ PL_no_func, "Unsupported function waitpid");
 #endif
 }
 
@@ -3098,29 +3587,41 @@ PP(pp_system)
 {
     djSP; dMARK; dORIGMARK; dTARGET;
     I32 value;
-    int childpid;
+    Pid_t childpid;
     int result;
     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 (tainting) {
-           char *junk = SvPV(TOPs, na);
+       if (PL_tainting) {
+           char *junk = SvPV(TOPs, n_a);
            TAINT_ENV();
            TAINT_PROPER("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 {
@@ -3131,28 +3632,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))
+                   Perl_croak(aTHX_ "panic: kid popen errno read");
+               errno = errkid;         /* Propagate errno from kid */
+               STATUS_CURRENT = -1;
+           }
+       }
        PUSHi(STATUS_CURRENT);
        RETURN;
     }
-    if (op->op_flags & OPf_STACKED) {
+    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), na));
+       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 (op->op_flags & OPf_STACKED) {
+    if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
        value = (I32)do_aspawn(really, (void **)MARK, (void **)SP);
     }
     else if (SP - MARK != 1)
        value = (I32)do_aspawn(Nullsv, (void **)MARK, (void **)SP);
     else {
-       value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), na));
+       value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), n_a));
     }
     STATUS_NATIVE_SET(value);
     do_execfree();
@@ -3166,8 +3693,10 @@ PP(pp_exec)
 {
     djSP; dMARK; dORIGMARK; dTARGET;
     I32 value;
+    STRLEN n_a;
 
-    if (op->op_flags & OPf_STACKED) {
+    PERL_FLUSHALL_FOR_CHILD;
+    if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
        value = (I32)do_aexec(really, MARK, SP);
     }
@@ -3175,18 +3704,30 @@ PP(pp_exec)
 #ifdef VMS
        value = (I32)vms_do_aexec(Nullsv, MARK, SP);
 #else
+#  ifdef __OPEN_VM
+       {
+          (void ) do_aspawn(Nullsv, MARK, SP);
+          value = 0;
+       }
+#  else
        value = (I32)do_aexec(Nullsv, MARK, SP);
+#  endif
 #endif
     else {
-       if (tainting) {
-           char *junk = SvPV(*SP, na);
+       if (PL_tainting) {
+           char *junk = SvPV(*SP, n_a);
            TAINT_ENV();
            TAINT_PROPER("exec");
        }
 #ifdef VMS
-       value = (I32)vms_do_exec(SvPVx(sv_mortalcopy(*SP), na));
+       value = (I32)vms_do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
 #else
-       value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), na));
+#  ifdef __OPEN_VM
+       (void) do_spawn(SvPVx(sv_mortalcopy(*SP), n_a));
+       value = 0;
+#  else
+       value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
+#  endif
 #endif
     }
     SP = ORIGMARK;
@@ -3199,12 +3740,12 @@ PP(pp_kill)
     djSP; dMARK; dTARGET;
     I32 value;
 #ifdef HAS_KILL
-    value = (I32)apply(op->op_type, MARK, SP);
+    value = (I32)apply(PL_op->op_type, MARK, SP);
     SP = MARK;
     PUSHi(value);
     RETURN;
 #else
-    DIE(no_func, "Unsupported function kill");
+    DIE(aTHX_ PL_no_func, "Unsupported function kill");
 #endif
 }
 
@@ -3215,7 +3756,7 @@ PP(pp_getppid)
     XPUSHi( getppid() );
     RETURN;
 #else
-    DIE(no_func, "getppid");
+    DIE(aTHX_ PL_no_func, "getppid");
 #endif
 }
 
@@ -3234,13 +3775,13 @@ PP(pp_getpgrp)
     value = (I32)BSD_GETPGRP(pid);
 #else
     if (pid != 0 && pid != getpid())
-       DIE("POSIX getpgrp can't take an argument");
+       DIE(aTHX_ "POSIX getpgrp can't take an argument");
     value = (I32)getpgrp();
 #endif
     XPUSHi(value);
     RETURN;
 #else
-    DIE(no_func, "getpgrp()");
+    DIE(aTHX_ PL_no_func, "getpgrp()");
 #endif
 }
 
@@ -3264,12 +3805,12 @@ PP(pp_setpgrp)
     SETi( BSD_SETPGRP(pid, pgrp) >= 0 );
 #else
     if ((pgrp != 0 && pgrp != getpid()) || (pid != 0 && pid != getpid()))
-       DIE("POSIX setpgrp can't take an argument");
+       DIE(aTHX_ "POSIX setpgrp can't take an argument");
     SETi( setpgrp() >= 0 );
 #endif /* USE_BSDPGRP */
     RETURN;
 #else
-    DIE(no_func, "setpgrp()");
+    DIE(aTHX_ PL_no_func, "setpgrp()");
 #endif
 }
 
@@ -3284,7 +3825,7 @@ PP(pp_getpriority)
     SETi( getpriority(which, who) );
     RETURN;
 #else
-    DIE(no_func, "getpriority()");
+    DIE(aTHX_ PL_no_func, "getpriority()");
 #endif
 }
 
@@ -3302,7 +3843,7 @@ PP(pp_setpriority)
     SETi( setpriority(which, who, niceval) >= 0 );
     RETURN;
 #else
-    DIE(no_func, "setpriority()");
+    DIE(aTHX_ PL_no_func, "setpriority()");
 #endif
 }
 
@@ -3340,23 +3881,23 @@ PP(pp_tms)
     djSP;
 
 #ifndef HAS_TIMES
-    DIE("times not implemented");
+    DIE(aTHX_ "times not implemented");
 #else
     EXTEND(SP, 4);
 
 #ifndef VMS
-    (void)times(&timesbuf);
+    (void)PerlProc_times(&PL_timesbuf);
 #else
-    (void)times((tbuffer_t *)&timesbuf);  /* time.h uses different name for */
-                                          /* struct tms, though same data   */
-                                          /* is returned.                   */
+    (void)PerlProc_times((tbuffer_t *)&PL_timesbuf);  /* time.h uses different name for */
+                                                   /* struct tms, though same data   */
+                                                   /* is returned.                   */
 #endif
 
-    PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_utime)/HZ)));
+    PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_utime)/HZ)));
     if (GIMME == G_ARRAY) {
-       PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_stime)/HZ)));
-       PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_cutime)/HZ)));
-       PUSHs(sv_2mortal(newSVnv(((double)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 */
@@ -3364,7 +3905,7 @@ PP(pp_tms)
 
 PP(pp_localtime)
 {
-    return pp_gmtime(ARGS);
+    return pp_gmtime();
 }
 
 PP(pp_gmtime)
@@ -3385,7 +3926,7 @@ PP(pp_gmtime)
        when = (Time_t)SvIVx(POPs);
 #endif
 
-    if (op->op_type == OP_LOCALTIME)
+    if (PL_op->op_type == OP_LOCALTIME)
        tmbuf = localtime(&when);
     else
        tmbuf = gmtime(&when);
@@ -3397,7 +3938,7 @@ PP(pp_gmtime)
        SV *tsv;
        if (!tmbuf)
            RETPUSHUNDEF;
-       tsv = newSVpvf("%s %s %2d %02d:%02d:%02d %d",
+       tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %d",
                       dayname[tmbuf->tm_wday],
                       monname[tmbuf->tm_mon],
                       tmbuf->tm_mday,
@@ -3408,15 +3949,15 @@ PP(pp_gmtime)
        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;
 }
@@ -3431,10 +3972,10 @@ PP(pp_alarm)
     EXTEND(SP, 1);
     if (anum < 0)
        RETPUSHUNDEF;
-    PUSHi((I32)anum);
+    PUSHi(anum);
     RETURN;
 #else
-    DIE(no_func, "Unsupported function alarm");
+    DIE(aTHX_ PL_no_func, "Unsupported function alarm");
 #endif
 }
 
@@ -3447,10 +3988,10 @@ PP(pp_sleep)
 
     (void)time(&lasttime);
     if (MAXARG < 1)
-       Pause();
+       PerlProc_pause();
     else {
        duration = POPi;
-       sleep((unsigned int)duration);
+       PerlProc_sleep((unsigned int)duration);
     }
     (void)time(&when);
     XPUSHi(when - lasttime);
@@ -3461,29 +4002,29 @@ PP(pp_sleep)
 
 PP(pp_shmget)
 {
-    return pp_semget(ARGS);
+    return pp_semget();
 }
 
 PP(pp_shmctl)
 {
-    return pp_semctl(ARGS);
+    return pp_semctl();
 }
 
 PP(pp_shmread)
 {
-    return pp_shmwrite(ARGS);
+    return pp_shmwrite();
 }
 
 PP(pp_shmwrite)
 {
 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
     djSP; dMARK; dTARGET;
-    I32 value = (I32)(do_shmio(op->op_type, MARK, SP) >= 0);
+    I32 value = (I32)(do_shmio(PL_op->op_type, MARK, SP) >= 0);
     SP = MARK;
     PUSHi(value);
     RETURN;
 #else
-    return pp_semget(ARGS);
+    return pp_semget();
 #endif
 }
 
@@ -3491,12 +4032,12 @@ PP(pp_shmwrite)
 
 PP(pp_msgget)
 {
-    return pp_semget(ARGS);
+    return pp_semget();
 }
 
 PP(pp_msgctl)
 {
-    return pp_semctl(ARGS);
+    return pp_semctl();
 }
 
 PP(pp_msgsnd)
@@ -3508,7 +4049,7 @@ PP(pp_msgsnd)
     PUSHi(value);
     RETURN;
 #else
-    return pp_semget(ARGS);
+    return pp_semget();
 #endif
 }
 
@@ -3521,7 +4062,7 @@ PP(pp_msgrcv)
     PUSHi(value);
     RETURN;
 #else
-    return pp_semget(ARGS);
+    return pp_semget();
 #endif
 }
 
@@ -3531,14 +4072,14 @@ PP(pp_semget)
 {
 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
     djSP; dMARK; dTARGET;
-    int anum = do_ipcget(op->op_type, MARK, SP);
+    int anum = do_ipcget(PL_op->op_type, MARK, SP);
     SP = MARK;
     if (anum == -1)
        RETPUSHUNDEF;
     PUSHi(anum);
     RETURN;
 #else
-    DIE("System V IPC is not implemented on this machine");
+    DIE(aTHX_ "System V IPC is not implemented on this machine");
 #endif
 }
 
@@ -3546,7 +4087,7 @@ PP(pp_semctl)
 {
 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
     djSP; dMARK; dTARGET;
-    int anum = do_ipcctl(op->op_type, MARK, SP);
+    int anum = do_ipcctl(PL_op->op_type, MARK, SP);
     SP = MARK;
     if (anum == -1)
        RETSETUNDEF;
@@ -3558,7 +4099,7 @@ PP(pp_semctl)
     }
     RETURN;
 #else
-    return pp_semget(ARGS);
+    return pp_semget();
 #endif
 }
 
@@ -3571,7 +4112,7 @@ PP(pp_semop)
     PUSHi(value);
     RETURN;
 #else
-    return pp_semget(ARGS);
+    return pp_semget();
 #endif
 }
 
@@ -3580,18 +4121,18 @@ PP(pp_semop)
 PP(pp_ghbyname)
 {
 #ifdef HAS_GETHOSTBYNAME
-    return pp_ghostent(ARGS);
+    return pp_ghostent();
 #else
-    DIE(no_sock_func, "gethostbyname");
+    DIE(aTHX_ PL_no_sock_func, "gethostbyname");
 #endif
 }
 
 PP(pp_ghbyaddr)
 {
 #ifdef HAS_GETHOSTBYADDR
-    return pp_ghostent(ARGS);
+    return pp_ghostent();
 #else
-    DIE(no_sock_func, "gethostbyaddr");
+    DIE(aTHX_ PL_no_sock_func, "gethostbyaddr");
 #endif
 }
 
@@ -3599,7 +4140,7 @@ PP(pp_ghostent)
 {
     djSP;
 #if defined(HAS_GETHOSTBYNAME) || defined(HAS_GETHOSTBYADDR) || defined(HAS_GETHOSTENT)
-    I32 which = op->op_type;
+    I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;
 #ifndef HAS_GETHOST_PROTOS /* XXX Do we need individual probes? */
@@ -3609,13 +4150,14 @@ PP(pp_ghostent)
 #endif
     struct hostent *hent;
     unsigned long len;
+    STRLEN n_a;
 
     EXTEND(SP, 10);
     if (which == OP_GHBYNAME)
 #ifdef HAS_GETHOSTBYNAME
-       hent = PerlSock_gethostbyname(POPp);
+       hent = PerlSock_gethostbyname(POPpx);
 #else
-       DIE(no_sock_func, "gethostbyname");
+       DIE(aTHX_ PL_no_sock_func, "gethostbyname");
 #endif
     else if (which == OP_GHBYADDR) {
 #ifdef HAS_GETHOSTBYADDR
@@ -3626,14 +4168,14 @@ PP(pp_ghostent)
 
        hent = PerlSock_gethostbyaddr(addr, (Netdb_hlen_t) addrlen, addrtype);
 #else
-       DIE(no_sock_func, "gethostbyaddr");
+       DIE(aTHX_ PL_no_sock_func, "gethostbyaddr");
 #endif
     }
     else
 #ifdef HAS_GETHOSTENT
        hent = PerlSock_gethostent();
 #else
-       DIE(no_sock_func, "gethostent");
+       DIE(aTHX_ PL_no_sock_func, "gethostent");
 #endif
 
 #ifdef HOST_NOT_FOUND
@@ -3655,51 +4197,51 @@ PP(pp_ghostent)
     }
 
     if (hent) {
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, (char*)hent->h_name);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        for (elem = hent->h_aliases; elem && *elem; elem++) {
            sv_catpv(sv, *elem);
            if (elem[1])
                sv_catpvn(sv, " ", 1);
        }
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)hent->h_addrtype);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        len = hent->h_length;
        sv_setiv(sv, (IV)len);
 #ifdef h_addr
        for (elem = hent->h_addr_list; elem && *elem; elem++) {
-           XPUSHs(sv = sv_mortalcopy(&sv_no));
+           XPUSHs(sv = sv_mortalcopy(&PL_sv_no));
            sv_setpvn(sv, *elem, len);
        }
 #else
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        if (hent->h_addr)
            sv_setpvn(sv, hent->h_addr, len);
 #endif /* h_addr */
     }
     RETURN;
 #else
-    DIE(no_sock_func, "gethostent");
+    DIE(aTHX_ PL_no_sock_func, "gethostent");
 #endif
 }
 
 PP(pp_gnbyname)
 {
 #ifdef HAS_GETNETBYNAME
-    return pp_gnetent(ARGS);
+    return pp_gnetent();
 #else
-    DIE(no_sock_func, "getnetbyname");
+    DIE(aTHX_ PL_no_sock_func, "getnetbyname");
 #endif
 }
 
 PP(pp_gnbyaddr)
 {
 #ifdef HAS_GETNETBYADDR
-    return pp_gnetent(ARGS);
+    return pp_gnetent();
 #else
-    DIE(no_sock_func, "getnetbyaddr");
+    DIE(aTHX_ PL_no_sock_func, "getnetbyaddr");
 #endif
 }
 
@@ -3707,7 +4249,7 @@ PP(pp_gnetent)
 {
     djSP;
 #if defined(HAS_GETNETBYNAME) || defined(HAS_GETNETBYADDR) || defined(HAS_GETNETENT)
-    I32 which = op->op_type;
+    I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;
 #ifndef HAS_GETNET_PROTOS /* XXX Do we need individual probes? */
@@ -3716,12 +4258,13 @@ PP(pp_gnetent)
     struct netent *PerlSock_getnetent(void);
 #endif
     struct netent *nent;
+    STRLEN n_a;
 
     if (which == OP_GNBYNAME)
 #ifdef HAS_GETNETBYNAME
-       nent = PerlSock_getnetbyname(POPp);
+       nent = PerlSock_getnetbyname(POPpx);
 #else
-        DIE(no_sock_func, "getnetbyname");
+        DIE(aTHX_ PL_no_sock_func, "getnetbyname");
 #endif
     else if (which == OP_GNBYADDR) {
 #ifdef HAS_GETNETBYADDR
@@ -3729,14 +4272,14 @@ PP(pp_gnetent)
        Netdb_net_t addr = (Netdb_net_t) U_L(POPn);
        nent = PerlSock_getnetbyaddr(addr, addrtype);
 #else
-       DIE(no_sock_func, "getnetbyaddr");
+       DIE(aTHX_ PL_no_sock_func, "getnetbyaddr");
 #endif
     }
     else
 #ifdef HAS_GETNETENT
        nent = PerlSock_getnetent();
 #else
-        DIE(no_sock_func, "getnetent");
+        DIE(aTHX_ PL_no_sock_func, "getnetent");
 #endif
 
     EXTEND(SP, 4);
@@ -3752,41 +4295,41 @@ PP(pp_gnetent)
     }
 
     if (nent) {
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, nent->n_name);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        for (elem = nent->n_aliases; elem && *elem; elem++) {
            sv_catpv(sv, *elem);
            if (elem[1])
                sv_catpvn(sv, " ", 1);
        }
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)nent->n_addrtype);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)nent->n_net);
     }
 
     RETURN;
 #else
-    DIE(no_sock_func, "getnetent");
+    DIE(aTHX_ PL_no_sock_func, "getnetent");
 #endif
 }
 
 PP(pp_gpbyname)
 {
 #ifdef HAS_GETPROTOBYNAME
-    return pp_gprotoent(ARGS);
+    return pp_gprotoent();
 #else
-    DIE(no_sock_func, "getprotobyname");
+    DIE(aTHX_ PL_no_sock_func, "getprotobyname");
 #endif
 }
 
 PP(pp_gpbynumber)
 {
 #ifdef HAS_GETPROTOBYNUMBER
-    return pp_gprotoent(ARGS);
+    return pp_gprotoent();
 #else
-    DIE(no_sock_func, "getprotobynumber");
+    DIE(aTHX_ PL_no_sock_func, "getprotobynumber");
 #endif
 }
 
@@ -3794,7 +4337,7 @@ PP(pp_gprotoent)
 {
     djSP;
 #if defined(HAS_GETPROTOBYNAME) || defined(HAS_GETPROTOBYNUMBER) || defined(HAS_GETPROTOENT)
-    I32 which = op->op_type;
+    I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;  
 #ifndef HAS_GETPROTO_PROTOS /* XXX Do we need individual probes? */
@@ -3803,24 +4346,25 @@ PP(pp_gprotoent)
     struct protoent *PerlSock_getprotoent(void);
 #endif
     struct protoent *pent;
+    STRLEN n_a;
 
     if (which == OP_GPBYNAME)
 #ifdef HAS_GETPROTOBYNAME
-       pent = PerlSock_getprotobyname(POPp);
+       pent = PerlSock_getprotobyname(POPpx);
 #else
-       DIE(no_sock_func, "getprotobyname");
+       DIE(aTHX_ PL_no_sock_func, "getprotobyname");
 #endif
     else if (which == OP_GPBYNUMBER)
 #ifdef HAS_GETPROTOBYNUMBER
        pent = PerlSock_getprotobynumber(POPi);
 #else
-    DIE(no_sock_func, "getprotobynumber");
+    DIE(aTHX_ PL_no_sock_func, "getprotobynumber");
 #endif
     else
 #ifdef HAS_GETPROTOENT
        pent = PerlSock_getprotoent();
 #else
-       DIE(no_sock_func, "getprotoent");
+       DIE(aTHX_ PL_no_sock_func, "getprotoent");
 #endif
 
     EXTEND(SP, 3);
@@ -3836,39 +4380,39 @@ PP(pp_gprotoent)
     }
 
     if (pent) {
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, pent->p_name);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        for (elem = pent->p_aliases; elem && *elem; elem++) {
            sv_catpv(sv, *elem);
            if (elem[1])
                sv_catpvn(sv, " ", 1);
        }
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)pent->p_proto);
     }
 
     RETURN;
 #else
-    DIE(no_sock_func, "getprotoent");
+    DIE(aTHX_ PL_no_sock_func, "getprotoent");
 #endif
 }
 
 PP(pp_gsbyname)
 {
 #ifdef HAS_GETSERVBYNAME
-    return pp_gservent(ARGS);
+    return pp_gservent();
 #else
-    DIE(no_sock_func, "getservbyname");
+    DIE(aTHX_ PL_no_sock_func, "getservbyname");
 #endif
 }
 
 PP(pp_gsbyport)
 {
 #ifdef HAS_GETSERVBYPORT
-    return pp_gservent(ARGS);
+    return pp_gservent();
 #else
-    DIE(no_sock_func, "getservbyport");
+    DIE(aTHX_ PL_no_sock_func, "getservbyport");
 #endif
 }
 
@@ -3876,7 +4420,7 @@ PP(pp_gservent)
 {
     djSP;
 #if defined(HAS_GETSERVBYNAME) || defined(HAS_GETSERVBYPORT) || defined(HAS_GETSERVENT)
-    I32 which = op->op_type;
+    I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;
 #ifndef HAS_GETSERV_PROTOS /* XXX Do we need individual probes? */
@@ -3885,23 +4429,24 @@ PP(pp_gservent)
     struct servent *PerlSock_getservent(void);
 #endif
     struct servent *sent;
+    STRLEN n_a;
 
     if (which == OP_GSBYNAME) {
 #ifdef HAS_GETSERVBYNAME
-       char *proto = POPp;
-       char *name = POPp;
+       char *proto = POPpx;
+       char *name = POPpx;
 
        if (proto && !*proto)
            proto = Nullch;
 
        sent = PerlSock_getservbyname(name, proto);
 #else
-       DIE(no_sock_func, "getservbyname");
+       DIE(aTHX_ PL_no_sock_func, "getservbyname");
 #endif
     }
     else if (which == OP_GSBYPORT) {
 #ifdef HAS_GETSERVBYPORT
-       char *proto = POPp;
+       char *proto = POPpx;
        unsigned short port = POPu;
 
 #ifdef HAS_HTONS
@@ -3909,14 +4454,14 @@ PP(pp_gservent)
 #endif
        sent = PerlSock_getservbyport(port, proto);
 #else
-       DIE(no_sock_func, "getservbyport");
+       DIE(aTHX_ PL_no_sock_func, "getservbyport");
 #endif
     }
     else
 #ifdef HAS_GETSERVENT
        sent = PerlSock_getservent();
 #else
-       DIE(no_sock_func, "getservent");
+       DIE(aTHX_ PL_no_sock_func, "getservent");
 #endif
 
     EXTEND(SP, 4);
@@ -3937,27 +4482,27 @@ PP(pp_gservent)
     }
 
     if (sent) {
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, sent->s_name);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        for (elem = sent->s_aliases; elem && *elem; elem++) {
            sv_catpv(sv, *elem);
            if (elem[1])
                sv_catpvn(sv, " ", 1);
        }
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef HAS_NTOHS
-       sv_setiv(sv, (IV)ntohs(sent->s_port));
+       sv_setiv(sv, (IV)PerlSock_ntohs(sent->s_port));
 #else
        sv_setiv(sv, (IV)(sent->s_port));
 #endif
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, sent->s_proto);
     }
 
     RETURN;
 #else
-    DIE(no_sock_func, "getservent");
+    DIE(aTHX_ PL_no_sock_func, "getservent");
 #endif
 }
 
@@ -3965,10 +4510,10 @@ PP(pp_shostent)
 {
     djSP;
 #ifdef HAS_SETHOSTENT
-    sethostent(TOPi);
+    PerlSock_sethostent(TOPi);
     RETSETYES;
 #else
-    DIE(no_sock_func, "sethostent");
+    DIE(aTHX_ PL_no_sock_func, "sethostent");
 #endif
 }
 
@@ -3976,10 +4521,10 @@ PP(pp_snetent)
 {
     djSP;
 #ifdef HAS_SETNETENT
-    setnetent(TOPi);
+    PerlSock_setnetent(TOPi);
     RETSETYES;
 #else
-    DIE(no_sock_func, "setnetent");
+    DIE(aTHX_ PL_no_sock_func, "setnetent");
 #endif
 }
 
@@ -3987,10 +4532,10 @@ PP(pp_sprotoent)
 {
     djSP;
 #ifdef HAS_SETPROTOENT
-    setprotoent(TOPi);
+    PerlSock_setprotoent(TOPi);
     RETSETYES;
 #else
-    DIE(no_sock_func, "setprotoent");
+    DIE(aTHX_ PL_no_sock_func, "setprotoent");
 #endif
 }
 
@@ -3998,10 +4543,10 @@ PP(pp_sservent)
 {
     djSP;
 #ifdef HAS_SETSERVENT
-    setservent(TOPi);
+    PerlSock_setservent(TOPi);
     RETSETYES;
 #else
-    DIE(no_sock_func, "setservent");
+    DIE(aTHX_ PL_no_sock_func, "setservent");
 #endif
 }
 
@@ -4013,7 +4558,7 @@ PP(pp_ehostent)
     EXTEND(SP,1);
     RETPUSHYES;
 #else
-    DIE(no_sock_func, "endhostent");
+    DIE(aTHX_ PL_no_sock_func, "endhostent");
 #endif
 }
 
@@ -4025,7 +4570,7 @@ PP(pp_enetent)
     EXTEND(SP,1);
     RETPUSHYES;
 #else
-    DIE(no_sock_func, "endnetent");
+    DIE(aTHX_ PL_no_sock_func, "endnetent");
 #endif
 }
 
@@ -4037,7 +4582,7 @@ PP(pp_eprotoent)
     EXTEND(SP,1);
     RETPUSHYES;
 #else
-    DIE(no_sock_func, "endprotoent");
+    DIE(aTHX_ PL_no_sock_func, "endprotoent");
 #endif
 }
 
@@ -4049,43 +4594,64 @@ PP(pp_eservent)
     EXTEND(SP,1);
     RETPUSHYES;
 #else
-    DIE(no_sock_func, "endservent");
+    DIE(aTHX_ PL_no_sock_func, "endservent");
 #endif
 }
 
 PP(pp_gpwnam)
 {
 #ifdef HAS_PASSWD
-    return pp_gpwent(ARGS);
+    return pp_gpwent();
 #else
-    DIE(no_func, "getpwnam");
+    DIE(aTHX_ PL_no_func, "getpwnam");
 #endif
 }
 
 PP(pp_gpwuid)
 {
 #ifdef HAS_PASSWD
-    return pp_gpwent(ARGS);
+    return pp_gpwent();
 #else
-    DIE(no_func, "getpwuid");
+    DIE(aTHX_ PL_no_func, "getpwuid");
 #endif
 }
 
 PP(pp_gpwent)
 {
     djSP;
-#ifdef HAS_PASSWD
-    I32 which = op->op_type;
+#if defined(HAS_PASSWD) && defined(HAS_GETPWENT)
+    I32 which = PL_op->op_type;
     register SV *sv;
     struct passwd *pwent;
+    STRLEN n_a;
+#if defined(HAS_GETSPENT) || defined(HAS_GETSPNAM)
+    struct spwd *spwent = NULL;
+#endif
 
     if (which == OP_GPWNAM)
-       pwent = getpwnam(POPp);
+       pwent = getpwnam(POPpx);
     else if (which == OP_GPWUID)
        pwent = getpwuid(POPi);
     else
        pwent = (struct passwd *)getpwent();
 
+#ifdef HAS_GETSPNAM
+    if (which == OP_GPWNAM) {
+       if (pwent)
+           spwent = getspnam(pwent->pw_name);
+    }
+#  ifdef HAS_GETSPUID /* AFAIK there isn't any anywhere. --jhi */ 
+    else if (which == OP_GPWUID) {
+       if (pwent)
+           spwent = getspnam(pwent->pw_name);
+    }
+#  endif
+#  ifdef HAS_GETSPENT
+    else
+       spwent = (struct spwd *)getspent();
+#  endif
+#endif
+
     EXTEND(SP, 10);
     if (GIMME != G_ARRAY) {
        PUSHs(sv = sv_newmortal());
@@ -4099,105 +4665,135 @@ PP(pp_gpwent)
     }
 
     if (pwent) {
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, pwent->pw_name);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+#ifdef PWPASSWD
+#   if defined(HAS_GETSPENT) || defined(HAS_GETSPNAM)
+      if (spwent)
+              sv_setpv(sv, spwent->sp_pwdp);
+      else
+              sv_setpv(sv, pwent->pw_passwd);
+#   else
        sv_setpv(sv, pwent->pw_passwd);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+#   endif
+#endif
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)pwent->pw_uid);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)pwent->pw_gid);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       /* pw_change, pw_quota, and pw_age are mutually exclusive. */
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef PWCHANGE
        sv_setiv(sv, (IV)pwent->pw_change);
 #else
-#ifdef PWQUOTA
+#   ifdef PWQUOTA
        sv_setiv(sv, (IV)pwent->pw_quota);
-#else
-#ifdef PWAGE
+#   else
+#       ifdef PWAGE
        sv_setpv(sv, pwent->pw_age);
+#       endif
+#   endif
 #endif
-#endif
-#endif
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       /* pw_class and pw_comment are mutually exclusive. */
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef PWCLASS
        sv_setpv(sv, pwent->pw_class);
 #else
-#ifdef PWCOMMENT
+#   ifdef PWCOMMENT
        sv_setpv(sv, pwent->pw_comment);
+#   endif
 #endif
-#endif
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+#ifdef PWGECOS
        sv_setpv(sv, pwent->pw_gecos);
+#endif
 #ifndef INCOMPLETE_TAINTS
+       /* pw_gecos is tainted because user himself can diddle with it. */
        SvTAINTED_on(sv);
 #endif
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, pwent->pw_dir);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, pwent->pw_shell);
+
 #ifdef PWEXPIRE
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)pwent->pw_expire);
 #endif
     }
     RETURN;
 #else
-    DIE(no_func, "getpwent");
+    DIE(aTHX_ PL_no_func, "getpwent");
 #endif
 }
 
 PP(pp_spwent)
 {
     djSP;
-#if defined(HAS_PASSWD) && !defined(CYGWIN32)
+#if defined(HAS_PASSWD) && defined(HAS_SETPWENT) && !defined(CYGWIN)
     setpwent();
+#   ifdef HAS_SETSPENT
+    setspent();
+#   endif
     RETPUSHYES;
 #else
-    DIE(no_func, "setpwent");
+    DIE(aTHX_ PL_no_func, "setpwent");
 #endif
 }
 
 PP(pp_epwent)
 {
     djSP;
-#ifdef HAS_PASSWD
+#if defined(HAS_PASSWD) && defined(HAS_ENDPWENT)
     endpwent();
+#   ifdef HAS_ENDSPENT
+    endspent();
+#   endif
     RETPUSHYES;
 #else
-    DIE(no_func, "endpwent");
+    DIE(aTHX_ PL_no_func, "endpwent");
 #endif
 }
 
 PP(pp_ggrnam)
 {
 #ifdef HAS_GROUP
-    return pp_ggrent(ARGS);
+    return pp_ggrent();
 #else
-    DIE(no_func, "getgrnam");
+    DIE(aTHX_ PL_no_func, "getgrnam");
 #endif
 }
 
 PP(pp_ggrgid)
 {
 #ifdef HAS_GROUP
-    return pp_ggrent(ARGS);
+    return pp_ggrent();
 #else
-    DIE(no_func, "getgrgid");
+    DIE(aTHX_ PL_no_func, "getgrgid");
 #endif
 }
 
 PP(pp_ggrent)
 {
     djSP;
-#ifdef HAS_GROUP
-    I32 which = op->op_type;
+#if defined(HAS_GROUP) && defined(HAS_GETGRENT)
+    I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;
     struct group *grent;
+    STRLEN n_a;
 
     if (which == OP_GGRNAM)
-       grent = (struct group *)getgrnam(POPp);
+       grent = (struct group *)getgrnam(POPpx);
     else if (which == OP_GGRGID)
        grent = (struct group *)getgrgid(POPi);
     else
@@ -4216,13 +4812,18 @@ PP(pp_ggrent)
     }
 
     if (grent) {
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setpv(sv, grent->gr_name);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+#ifdef GRPASSWD
        sv_setpv(sv, grent->gr_passwd);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+#endif
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        sv_setiv(sv, (IV)grent->gr_gid);
-       PUSHs(sv = sv_mortalcopy(&sv_no));
+
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        for (elem = grent->gr_mem; elem && *elem; elem++) {
            sv_catpv(sv, *elem);
            if (elem[1])
@@ -4232,29 +4833,29 @@ PP(pp_ggrent)
 
     RETURN;
 #else
-    DIE(no_func, "getgrent");
+    DIE(aTHX_ PL_no_func, "getgrent");
 #endif
 }
 
 PP(pp_sgrent)
 {
     djSP;
-#ifdef HAS_GROUP
+#if defined(HAS_GROUP) && defined(HAS_SETGRENT)
     setgrent();
     RETPUSHYES;
 #else
-    DIE(no_func, "setgrent");
+    DIE(aTHX_ PL_no_func, "setgrent");
 #endif
 }
 
 PP(pp_egrent)
 {
     djSP;
-#ifdef HAS_GROUP
+#if defined(HAS_GROUP) && defined(HAS_ENDGRENT)
     endgrent();
     RETPUSHYES;
 #else
-    DIE(no_func, "endgrent");
+    DIE(aTHX_ PL_no_func, "endgrent");
 #endif
 }
 
@@ -4264,12 +4865,12 @@ PP(pp_getlogin)
 #ifdef HAS_GETLOGIN
     char *tmps;
     EXTEND(SP, 1);
-    if (!(tmps = getlogin()))
+    if (!(tmps = PerlProc_getlogin()))
        RETPUSHUNDEF;
     PUSHp(tmps, strlen(tmps));
     RETURN;
 #else
-    DIE(no_func, "getlogin");
+    DIE(aTHX_ PL_no_func, "getlogin");
 #endif
 }
 
@@ -4277,15 +4878,16 @@ PP(pp_getlogin)
 
 PP(pp_syscall)
 {
-#ifdef HAS_SYSCALL   
+#ifdef HAS_SYSCALL
     djSP; dMARK; dORIGMARK; dTARGET;
     register I32 items = SP - MARK;
     unsigned long a[20];
     register I32 i = 0;
     I32 retval = -1;
     MAGIC *mg;
+    STRLEN n_a;
 
-    if (tainting) {
+    if (PL_tainting) {
        while (++MARK <= SP) {
            if (SvTAINTED(*MARK)) {
                TAINT;
@@ -4303,18 +4905,18 @@ PP(pp_syscall)
     while (++MARK <= SP) {
        if (SvNIOK(*MARK) || !i)
            a[i++] = SvIV(*MARK);
-       else if (*MARK == &sv_undef)
+       else if (*MARK == &PL_sv_undef)
            a[i++] = 0;
        else 
-           a[i++] = (unsigned long)SvPV_force(*MARK, na);
+           a[i++] = (unsigned long)SvPV_force(*MARK, n_a);
        if (i > 15)
            break;
     }
     switch (items) {
     default:
-       DIE("Too many args to syscall");
+       DIE(aTHX_ "Too many args to syscall");
     case 0:
-       DIE("Too few args to syscall");
+       DIE(aTHX_ "Too few args to syscall");
     case 1:
        retval = syscall(a[0]);
        break;
@@ -4368,7 +4970,7 @@ PP(pp_syscall)
     PUSHi(retval);
     RETURN;
 #else
-    DIE(no_func, "syscall");
+    DIE(aTHX_ PL_no_func, "syscall");
 #endif
 }
 
@@ -4436,9 +5038,7 @@ fcntl_emulate_flock(int fd, int operation)
 # endif
 
 static int
-lockf_emulate_flock (fd, operation)
-int fd;
-int operation;
+lockf_emulate_flock(int fd, int operation)
 {
     int i;
     int save_errno;
@@ -4491,4 +5091,3 @@ int operation;
 }
 
 #endif /* LOCKF_EMULATE_FLOCK */
-