This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
note about AVf_*
[perl5.git] / pp_sys.c
index c608ab5..5271a86 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -187,6 +187,10 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true";
 #  include <sys/access.h>
 #endif
 
+#if defined(HAS_FCNTL) && defined(F_SETFD) && !defined(FD_CLOEXEC)
+#  define FD_CLOEXEC 1         /* NeXT needs this */
+#endif
+
 #undef PERL_EFF_ACCESS_R_OK    /* EFFective uid/gid ACCESS R_OK */
 #undef PERL_EFF_ACCESS_W_OK
 #undef PERL_EFF_ACCESS_X_OK
@@ -230,7 +234,7 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true";
        || defined(HAS_SETREGID) || defined(HAS_SETRESGID))
 /* The Hard Way. */
 STATIC int
-S_emulate_eaccess(pTHX_ const char* path, int mode)
+S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
 {
     Uid_t ruid = getuid();
     Uid_t euid = geteuid();
@@ -295,7 +299,7 @@ S_emulate_eaccess(pTHX_ const char* path, int mode)
 
 #if !defined(PERL_EFF_ACCESS_R_OK)
 STATIC int
-S_emulate_eaccess(pTHX_ const char* path, int mode)
+S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
 {
     Perl_croak(aTHX_ "switching effective uid is not implemented");
     /*NOTREACHED*/
@@ -501,10 +505,16 @@ PP(pp_open)
     djSP; dTARGET;
     GV *gv;
     SV *sv;
+    SV *name;
+    I32 have_name = 0;
     char *tmps;
     STRLEN len;
     MAGIC *mg;
 
+    if (MAXARG > 2) {
+       name = POPs;
+       have_name = 1;
+    }
     if (MAXARG > 1)
        sv = POPs;
     if (!isGV(TOPs))
@@ -537,6 +547,8 @@ PP(pp_open)
        PUSHMARK(SP);
        XPUSHs(SvTIED_obj((SV*)gv, mg));
        XPUSHs(sv);
+       if (have_name)
+           XPUSHs(name);
        PUTBACK;
        ENTER;
        call_method("OPEN", G_SCALAR);
@@ -546,7 +558,7 @@ PP(pp_open)
     }
 
     tmps = SvPV(sv, len);
-    if (do_open(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp))
+    if (do_open9(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp, name, have_name))
        PUSHi( (I32)PL_forkprocess );
     else if (PL_forkprocess == 0)              /* we are a new child */
        PUSHi(0);
@@ -808,10 +820,17 @@ PP(pp_untie)
     if (ckWARN(WARN_UNTIE)) {
         MAGIC * mg ;
         if (mg = SvTIED_mg(sv, how)) {
+#ifdef IV_IS_QUAD
+            if (mg && 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
         }
     }
  
@@ -1546,8 +1565,8 @@ PP(pp_sysread)
            length = -1;
     }
     if (length < 0) {
-       if (IoTYPE(io) == '>' || IoIFP(io) == PerlIO_stdout()
-           || IoIFP(io) == PerlIO_stderr())
+       if ((IoTYPE(io) == '>' || IoIFP(io) == PerlIO_stdout()
+           || IoIFP(io) == PerlIO_stderr()) && ckWARN(WARN_IO))
        {
            SV* sv = sv_newmortal();
            gv_efullname3(sv, gv, Nullch);
@@ -1652,6 +1671,7 @@ PP(pp_send)
        else
 #endif
        {
+           /* See the note at doio.c:do_print about filesize limits. --jhi */
            length = PerlLIO_write(PerlIO_fileno(IoIFP(io)),
                                   buffer+offset, length);
        }
@@ -1749,7 +1769,7 @@ PP(pp_sysseek)
     djSP;
     GV *gv;
     int whence = POPi;
-    Off_t offset = POPl;
+    Off_t offset = (Off_t)SvIVx(POPs);
     MAGIC *mg;
 
     gv = PL_last_in_gv = (GV*)POPs;
@@ -1878,7 +1898,7 @@ PP(pp_ioctl)
     }
     else {
        retval = SvIV(argsv);
-       s = (char*)retval;              /* ouch */
+       s = (char*)PTR_CAST retval;             /* ouch */
     }
 
     TAINT_PROPER(optype == OP_IOCTL ? "ioctl" : "fcntl");
@@ -2457,30 +2477,30 @@ PP(pp_stat)
     if (max) {
        EXTEND(SP, max);
        EXTEND_MORTAL(max);
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_dev)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_ino)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_mode)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_nlink)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_uid)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_gid)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_dev)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ino)));
+       PUSHs(sv_2mortal(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)PL_statcache.st_rdev)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_rdev)));
 #else
        PUSHs(sv_2mortal(newSVpvn("", 0)));
 #endif
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_size)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_size)));
 #ifdef BIG_TIME
-       PUSHs(sv_2mortal(newSVnv((U32)PL_statcache.st_atime)));
-       PUSHs(sv_2mortal(newSVnv((U32)PL_statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSVnv((U32)PL_statcache.st_ctime)));
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_atime)));
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_mtime)));
+       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_ctime)));
 #else
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_atime)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_ctime)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_atime)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_mtime)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ctime)));
 #endif
 #ifdef USE_STAT_BLOCKS
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_blksize)));
-       PUSHs(sv_2mortal(newSViv((I32)PL_statcache.st_blocks)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_blksize)));
+       PUSHs(sv_2mortal(newSViv(PL_statcache.st_blocks)));
 #else
        PUSHs(sv_2mortal(newSVpvn("", 0)));
        PUSHs(sv_2mortal(newSVpvn("", 0)));
@@ -2703,7 +2723,7 @@ PP(pp_ftmtime)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)PL_basetime - (I32)PL_statcache.st_mtime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_mtime) / 86400.0 );
     RETURN;
 }
 
@@ -2713,7 +2733,7 @@ PP(pp_ftatime)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)PL_basetime - (I32)PL_statcache.st_atime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_atime) / 86400.0 );
     RETURN;
 }
 
@@ -2723,7 +2743,7 @@ PP(pp_ftctime)
     djSP; dTARGET;
     if (result < 0)
        RETPUSHUNDEF;
-    PUSHn( ((I32)PL_basetime - (I32)PL_statcache.st_ctime) / 86400.0 );
+    PUSHn( (PL_basetime - PL_statcache.st_ctime) / 86400.0 );
     RETURN;
 }
 
@@ -3535,7 +3555,7 @@ PP(pp_fork)
 
 PP(pp_wait)
 {
-#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32)
+#if !defined(DOSISH) || defined(OS2) || defined(WIN32)
     djSP; dTARGET;
     Pid_t childpid;
     int argflags;
@@ -3551,7 +3571,7 @@ PP(pp_wait)
 
 PP(pp_waitpid)
 {
-#if !defined(DOSISH) || defined(OS2) || defined(WIN32) || defined(CYGWIN32)
+#if !defined(DOSISH) || defined(OS2) || defined(WIN32)
     djSP; dTARGET;
     Pid_t childpid;
     int optype;
@@ -3577,6 +3597,8 @@ PP(pp_system)
     int status;
     Sigsave_t ihand,qhand;     /* place to save signals during system() */
     STRLEN n_a;
+    I32 did_pipes = 0;
+    int pp[2];
 
     if (SP - MARK == 1) {
        if (PL_tainting) {
@@ -3587,16 +3609,24 @@ PP(pp_system)
     }
     PERL_FLUSHALL_FOR_CHILD;
 #if (defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(OS2)
+    if (PerlProc_pipe(pp) >= 0)
+       did_pipes = 1;
     while ((childpid = vfork()) == -1) {
        if (errno != EAGAIN) {
            value = -1;
            SP = ORIGMARK;
            PUSHi(value);
+           if (did_pipes) {
+               PerlLIO_close(pp[0]);
+               PerlLIO_close(pp[1]);
+           }
            RETURN;
        }
        sleep(5);
     }
     if (childpid > 0) {
+       if (did_pipes)
+           PerlLIO_close(pp[1]);
        rsignal_save(SIGINT, SIG_IGN, &ihand);
        rsignal_save(SIGQUIT, SIG_IGN, &qhand);
        do {
@@ -3607,28 +3637,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 (did_pipes) {
+       PerlLIO_close(pp[0]);
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+       fcntl(pp[1], F_SETFD, FD_CLOEXEC);
+#endif
+    }
     if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
-       value = (I32)do_aexec(really, MARK, SP);
+       value = (I32)do_aexec5(really, MARK, SP, pp[1], did_pipes);
     }
     else if (SP - MARK != 1)
-       value = (I32)do_aexec(Nullsv, MARK, SP);
+       value = (I32)do_aexec5(Nullsv, MARK, SP, pp[1], did_pipes);
     else {
-       value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
+       value = (I32)do_exec3(SvPVx(sv_mortalcopy(*SP), n_a), pp[1], did_pipes);
     }
     PerlProc__exit(-1);
 #else /* ! FORK or VMS or OS/2 */
     if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
-       value = (I32)do_aspawn(aTHX_ really, (void **)MARK, (void **)SP);
+       value = (I32)do_aspawn(really, (void **)MARK, (void **)SP);
     }
     else if (SP - MARK != 1)
-       value = (I32)do_aspawn(aTHX_ Nullsv, (void **)MARK, (void **)SP);
+       value = (I32)do_aspawn(Nullsv, (void **)MARK, (void **)SP);
     else {
-       value = (I32)do_spawn(aTHX_ SvPVx(sv_mortalcopy(*SP), n_a));
+       value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), n_a));
     }
     STATUS_NATIVE_SET(value);
     do_execfree();
@@ -3655,7 +3711,7 @@ PP(pp_exec)
 #else
 #  ifdef __OPEN_VM
        {
-          (void ) do_aspawn(aTHX_ Nullsv, MARK, SP);
+          (void ) do_aspawn(Nullsv, MARK, SP);
           value = 0;
        }
 #  else
@@ -3672,7 +3728,7 @@ PP(pp_exec)
        value = (I32)vms_do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
 #else
 #  ifdef __OPEN_VM
-       (void) do_spawn(aTHX_ SvPVx(sv_mortalcopy(*SP), n_a));
+       (void) do_spawn(SvPVx(sv_mortalcopy(*SP), n_a));
        value = 0;
 #  else
        value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), n_a));
@@ -3713,21 +3769,21 @@ PP(pp_getpgrp)
 {
 #ifdef HAS_GETPGRP
     djSP; dTARGET;
-    int pid;
-    I32 value;
+    Pid_t pid;
+    Pid_t pgrp;
 
     if (MAXARG < 1)
        pid = 0;
     else
        pid = SvIVx(POPs);
 #ifdef BSD_GETPGRP
-    value = (I32)BSD_GETPGRP(pid);
+    pgrp = (I32)BSD_GETPGRP(pid);
 #else
     if (pid != 0 && pid != getpid())
        DIE(aTHX_ "POSIX getpgrp can't take an argument");
-    value = (I32)getpgrp();
+    pgrp = getpgrp();
 #endif
-    XPUSHi(value);
+    XPUSHi(pgrp);
     RETURN;
 #else
     DIE(aTHX_ PL_no_func, "getpgrp()");
@@ -3738,8 +3794,8 @@ PP(pp_setpgrp)
 {
 #ifdef HAS_SETPGRP
     djSP; dTARGET;
-    int pgrp;
-    int pid;
+    Pid_t pgrp;
+    Pid_t pid;
     if (MAXARG < 2) {
        pgrp = 0;
        pid = 0;
@@ -3888,25 +3944,25 @@ PP(pp_gmtime)
        if (!tmbuf)
            RETPUSHUNDEF;
        tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %d",
-                      dayname[tmbuf->tm_wday],
-                      monname[tmbuf->tm_mon],
-                      tmbuf->tm_mday,
-                      tmbuf->tm_hour,
-                      tmbuf->tm_min,
-                      tmbuf->tm_sec,
-                      tmbuf->tm_year + 1900);
+                           dayname[tmbuf->tm_wday],
+                           monname[tmbuf->tm_mon],
+                           tmbuf->tm_mday,
+                           tmbuf->tm_hour,
+                           tmbuf->tm_min,
+                           tmbuf->tm_sec,
+                           tmbuf->tm_year + 1900);
        PUSHs(sv_2mortal(tsv));
     }
     else if (tmbuf) {
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_sec)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_min)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_hour)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mday)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mon)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_year)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_wday)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_yday)));
-       PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_isdst)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_sec)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_min)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_hour)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_mday)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_mon)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_year)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_wday)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_yday)));
+       PUSHs(sv_2mortal(newSViv(tmbuf->tm_isdst)));
     }
     RETURN;
 }
@@ -3921,7 +3977,7 @@ PP(pp_alarm)
     EXTEND(SP, 1);
     if (anum < 0)
        RETPUSHUNDEF;
-    PUSHi((I32)anum);
+    PUSHi(anum);
     RETURN;
 #else
     DIE(aTHX_ PL_no_func, "Unsupported function alarm");
@@ -4573,7 +4629,7 @@ PP(pp_gpwent)
     register SV *sv;
     struct passwd *pwent;
     STRLEN n_a;
-#ifdef HAS_GETSPENT
+#if defined(HAS_GETSPENT) || defined(HAS_GETSPNAM)
     struct spwd *spwent = NULL;
 #endif
 
@@ -4595,8 +4651,10 @@ PP(pp_gpwent)
            spwent = getspnam(pwent->pw_name);
     }
 #  endif
+#  ifdef HAS_GETSPENT
     else
        spwent = (struct spwd *)getspent();
+#  endif
 #endif
 
     EXTEND(SP, 10);
@@ -4617,7 +4675,7 @@ PP(pp_gpwent)
 
        PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef PWPASSWD
-#   ifdef HAS_GETSPENT
+#   if defined(HAS_GETSPENT) || defined(HAS_GETSPNAM)
       if (spwent)
               sv_setpv(sv, spwent->sp_pwdp);
       else
@@ -4686,7 +4744,7 @@ PP(pp_gpwent)
 PP(pp_spwent)
 {
     djSP;
-#if defined(HAS_PASSWD) && defined(HAS_SETPWENT) && !defined(CYGWIN32)
+#if defined(HAS_PASSWD) && defined(HAS_SETPWENT)
     setpwent();
 #   ifdef HAS_SETSPENT
     setspent();
@@ -4947,7 +5005,7 @@ fcntl_emulate_flock(int fd, int operation)
        return -1;
     }
     flock.l_whence = SEEK_SET;
-    flock.l_start = flock.l_len = 0L;
+    flock.l_start = flock.l_len = (Off_t)0;
  
     return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock);
 }