This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Additional changes to get C++ a little closer to a clean compile
[perl5.git] / ext / POSIX / POSIX.xs
index 4425f6d..3c7b0b8 100644 (file)
@@ -51,7 +51,7 @@
 #include <unistd.h>
 #endif
 
-/* XXX This comment is just to make I_TERMIO and I_SGTTY visible to 
+/* XXX This comment is just to make I_TERMIO and I_SGTTY visible to
    metaconfig for future extension writers.  We don't use them in POSIX.
    (This is really sneaky :-)  --AD
 */
@@ -61,7 +61,9 @@
 #ifdef I_STDLIB
 #include <stdlib.h>
 #endif
+#ifndef __ultrix__
 #include <string.h>
+#endif
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
@@ -83,6 +85,26 @@ char *tzname[] = { "" , "" };
 #endif
 #endif
 
+#ifndef PERL_UNUSED_DECL
+#  ifdef HASATTRIBUTE
+#    if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER)
+#      define PERL_UNUSED_DECL
+#    else
+#      define PERL_UNUSED_DECL __attribute__((unused))
+#    endif
+#  else
+#    define PERL_UNUSED_DECL
+#  endif
+#endif
+
+#ifndef dNOOP
+#define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#ifndef dVAR
+#define dVAR dNOOP
+#endif
+
 #if defined(__VMS) && !defined(__POSIX_SOURCE)
 #  include <libdef.h>       /* LIB$_INVARG constant */
 #  include <lib$routines.h> /* prototype for lib$ediv() */
@@ -176,7 +198,7 @@ char *tzname[] = { "" , "" };
 #  ifndef HAS_MKFIFO
 #    if defined(OS2) || defined(MACOS_TRADITIONAL)
 #      define mkfifo(a,b) not_here("mkfifo")
-#    else      /* !( defined OS2 ) */ 
+#    else      /* !( defined OS2 ) */
 #      ifndef mkfifo
 #        define mkfifo(path, mode) (mknod((path), (mode) | S_IFIFO, 0))
 #      endif
@@ -187,7 +209,9 @@ char *tzname[] = { "" , "" };
 #    define ttyname(a) (char*)not_here("ttyname")
 #    define tzset() not_here("tzset")
 #  else
-#    include <grp.h>
+#    ifdef I_GRP
+#      include <grp.h>
+#    endif
 #    include <sys/times.h>
 #    ifdef HAS_UNAME
 #      include <sys/utsname.h>
@@ -241,7 +265,7 @@ unsigned long strtoul (const char *, char **, int);
 #endif
 #endif
 #ifndef HAS_FPATHCONF
-#define fpathconf(f,n)         (SysRetLong) not_here("fpathconf")
+#define fpathconf(f,n) (SysRetLong) not_here("fpathconf")
 #endif
 #ifndef HAS_MKTIME
 #define mktime(a) not_here("mktime")
@@ -250,10 +274,10 @@ unsigned long strtoul (const char *, char **, int);
 #define nice(a) not_here("nice")
 #endif
 #ifndef HAS_PATHCONF
-#define pathconf(f,n)  (SysRetLong) not_here("pathconf")
+#define pathconf(f,n)  (SysRetLong) not_here("pathconf")
 #endif
 #ifndef HAS_SYSCONF
-#define sysconf(n)     (SysRetLong) not_here("sysconf")
+#define sysconf(n)     (SysRetLong) not_here("sysconf")
 #endif
 #ifndef HAS_READLINK
 #define readlink(a,b,c) not_here("readlink")
@@ -389,7 +413,6 @@ foreach (C_constant ("POSIX", 'int_macro_int', 'IV', $types, undef, 5, @names) )
 }
 print "#### XS Section:\n";
 print XS_constant ("POSIX", $types);
-__END__
    */
 
   switch (len) {
@@ -563,7 +586,7 @@ new(packname = "POSIX::SigSet", ...)
     CODE:
        {
            int i;
-           New(0, RETVAL, 1, sigset_t);
+           Newx(RETVAL, 1, sigset_t);
            sigemptyset(RETVAL);
            for (i = 1; i < items; i++)
                sigaddset(RETVAL, SvIV(ST(i)));
@@ -600,7 +623,6 @@ sigismember(sigset, sig)
        POSIX::SigSet   sigset
        int             sig
 
-
 MODULE = Termios       PACKAGE = POSIX::Termios        PREFIX = cf
 
 POSIX::Termios
@@ -609,7 +631,7 @@ new(packname = "POSIX::Termios", ...)
     CODE:
        {
 #ifdef I_TERMIOS
-           New(0, RETVAL, 1, struct termios);
+           Newx(RETVAL, 1, struct termios);
 #else
            not_here("termios");
         RETVAL = 0;
@@ -710,7 +732,7 @@ getlflag(termios_ref)
 cc_t
 getcc(termios_ref, ccix)
        POSIX::Termios  termios_ref
-       int             ccix
+       unsigned int    ccix
     CODE:
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
        if (ccix >= NCCS)
@@ -780,7 +802,7 @@ setlflag(termios_ref, lflag)
 void
 setcc(termios_ref, ccix, cc)
        POSIX::Termios  termios_ref
-       int             ccix
+       unsigned int    ccix
        cc_t            cc
     CODE:
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
@@ -840,10 +862,12 @@ int_macro_int(sv, iv)
 
 int
 isalnum(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalnum(*s))
                RETVAL = 0;
@@ -852,10 +876,12 @@ isalnum(charstring)
 
 int
 isalpha(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalpha(*s))
                RETVAL = 0;
@@ -864,10 +890,12 @@ isalpha(charstring)
 
 int
 iscntrl(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!iscntrl(*s))
                RETVAL = 0;
@@ -876,10 +904,12 @@ iscntrl(charstring)
 
 int
 isdigit(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isdigit(*s))
                RETVAL = 0;
@@ -888,10 +918,12 @@ isdigit(charstring)
 
 int
 isgraph(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isgraph(*s))
                RETVAL = 0;
@@ -900,10 +932,12 @@ isgraph(charstring)
 
 int
 islower(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!islower(*s))
                RETVAL = 0;
@@ -912,10 +946,12 @@ islower(charstring)
 
 int
 isprint(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isprint(*s))
                RETVAL = 0;
@@ -924,10 +960,12 @@ isprint(charstring)
 
 int
 ispunct(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!ispunct(*s))
                RETVAL = 0;
@@ -936,10 +974,12 @@ ispunct(charstring)
 
 int
 isspace(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isspace(*s))
                RETVAL = 0;
@@ -948,10 +988,12 @@ isspace(charstring)
 
 int
 isupper(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isupper(*s))
                RETVAL = 0;
@@ -960,10 +1002,12 @@ isupper(charstring)
 
 int
 isxdigit(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + SvCUR(ST(0));
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isxdigit(*s))
                RETVAL = 0;
@@ -989,6 +1033,7 @@ localeconv()
 #ifdef HAS_LOCALECONV
        struct lconv *lcbuf;
        RETVAL = newHV();
+       sv_2mortal((SV*)RETVAL);
        if ((lcbuf = localeconv())) {
            /* the strings */
            if (lcbuf->decimal_point && *lcbuf->decimal_point)
@@ -1015,7 +1060,7 @@ localeconv()
            if (lcbuf->mon_thousands_sep && *lcbuf->mon_thousands_sep)
                hv_store(RETVAL, "mon_thousands_sep", 17,
                    newSVpv(lcbuf->mon_thousands_sep, 0), 0);
-#endif                    
+#endif
 #ifndef NO_LOCALECONV_MON_GROUPING
            if (lcbuf->mon_grouping && *lcbuf->mon_grouping)
                hv_store(RETVAL, "mon_grouping", 12,
@@ -1203,6 +1248,7 @@ sigaction(sig, optaction, oldaction = 0)
 # interface look beautiful, which is hard.
 
        {
+           dVAR;
            POSIX__SigAction action;
            GV *siggv = gv_fetchpv("SIG", TRUE, SVt_PVHV);
            struct sigaction act;
@@ -1212,10 +1258,38 @@ sigaction(sig, optaction, oldaction = 0)
            sigset_t osset;
            POSIX__SigSet sigset;
            SV** svp;
-           SV** sigsvp = hv_fetch(GvHVn(siggv),
-                                PL_sig_name[sig],
-                                strlen(PL_sig_name[sig]),
-                                TRUE);
+           SV** sigsvp;
+
+            if (sig < 0) {
+                croak("Negative signals are not allowed");
+            }
+
+           if (sig == 0 && SvPOK(ST(0))) {
+               const char *s = SvPVX_const(ST(0));
+               int i = whichsig(s);
+
+               if (i < 0 && memEQ(s, "SIG", 3))
+                   i = whichsig(s + 3);
+               if (i < 0) {
+                   if (ckWARN(WARN_SIGNAL))
+                       Perl_warner(aTHX_ packWARN(WARN_SIGNAL),
+                                    "No such signal: SIG%s", s);
+                   XSRETURN_UNDEF;
+               }
+               else
+                   sig = i;
+            }
+#ifdef NSIG
+           if (sig > NSIG) { /* NSIG - 1 is still okay. */
+               Perl_warner(aTHX_ packWARN(WARN_SIGNAL),
+                            "No such signal: %d", sig);
+               XSRETURN_UNDEF;
+           }
+#endif
+           sigsvp = hv_fetch(GvHVn(siggv),
+                             PL_sig_name[sig],
+                             strlen(PL_sig_name[sig]),
+                             TRUE);
 
            /* Check optaction and set action */
            if(SvTRUE(optaction)) {
@@ -1247,7 +1321,7 @@ sigaction(sig, optaction, oldaction = 0)
 
            /* Remember old disposition if desired. */
            if (oldaction) {
-               svp = hv_fetch(oldaction, "HANDLER", 7, TRUE);
+               svp = hv_fetchs(oldaction, "HANDLER", TRUE);
                if(!svp)
                    croak("Can't supply an oldaction without a HANDLER");
                if(SvTRUE(*sigsvp)) { /* TBD: what if "0"? */
@@ -1260,48 +1334,66 @@ sigaction(sig, optaction, oldaction = 0)
                if(RETVAL == -1)
                    XSRETURN_UNDEF;
                /* Get back the mask. */
-               svp = hv_fetch(oldaction, "MASK", 4, TRUE);
+               svp = hv_fetchs(oldaction, "MASK", TRUE);
                if (sv_isa(*svp, "POSIX::SigSet")) {
                    IV tmp = SvIV((SV*)SvRV(*svp));
                    sigset = INT2PTR(sigset_t*, tmp);
                }
                else {
-                   New(0, sigset, 1, sigset_t);
+                   Newx(sigset, 1, sigset_t);
                    sv_setptrobj(*svp, sigset, "POSIX::SigSet");
                }
                *sigset = oact.sa_mask;
 
                /* Get back the flags. */
-               svp = hv_fetch(oldaction, "FLAGS", 5, TRUE);
+               svp = hv_fetchs(oldaction, "FLAGS", TRUE);
                sv_setiv(*svp, oact.sa_flags);
+
+               /* Get back whether the old handler used safe signals. */
+               svp = hv_fetchs(oldaction, "SAFE", TRUE);
+               sv_setiv(*svp,
+               /* compare incompatible pointers by casting to integer */
+                   PTR2nat(oact.sa_handler) == PTR2nat(PL_csighandlerp));
            }
 
            if (action) {
-               /* Vector new handler through %SIG.  (We always use sighandler
-                  for the C signal handler, which reads %SIG to dispatch.) */
-               svp = hv_fetch(action, "HANDLER", 7, FALSE);
+               /* Safe signals use "csighandler", which vectors through the
+                  PL_sighandlerp pointer when it's safe to do so.
+                  (BTW, "csighandler" is very different from "sighandler".) */
+               svp = hv_fetchs(action, "SAFE", FALSE);
+               act.sa_handler =
+                       DPTR2FPTR(
+                           void (*)(int),
+                           (*svp && SvTRUE(*svp))
+                               ? PL_csighandlerp : PL_sighandlerp
+                       );
+
+               /* Vector new Perl handler through %SIG.
+                  (The core signal handlers read %SIG to dispatch.) */
+               svp = hv_fetchs(action, "HANDLER", FALSE);
                if (!svp)
                    croak("Can't supply an action without a HANDLER");
                sv_setsv(*sigsvp, *svp);
-               mg_set(*sigsvp);        /* handles DEFAULT and IGNORE */
+
+               /* This call actually calls sigaction() with almost the
+                  right settings, including appropriate interpretation
+                  of DEFAULT and IGNORE.  However, why are we doing
+                  this when we're about to do it again just below?  XXX */
+               mg_set(*sigsvp);
+
+               /* And here again we duplicate -- DEFAULT/IGNORE checking. */
                if(SvPOK(*svp)) {
-                       char *s=SvPVX(*svp);
+                       const char *s=SvPVX_const(*svp);
                        if(strEQ(s,"IGNORE")) {
                                act.sa_handler = SIG_IGN;
                        }
                        else if(strEQ(s,"DEFAULT")) {
                                act.sa_handler = SIG_DFL;
                        }
-                       else {
-                               act.sa_handler = PL_sighandlerp;
-                       }
-               }
-               else {
-                       act.sa_handler = PL_sighandlerp;
                }
 
                /* Set up any desired mask. */
-               svp = hv_fetch(action, "MASK", 4, FALSE);
+               svp = hv_fetchs(action, "MASK", FALSE);
                if (svp && sv_isa(*svp, "POSIX::SigSet")) {
                    IV tmp = SvIV((SV*)SvRV(*svp));
                    sigset = INT2PTR(sigset_t*, tmp);
@@ -1311,7 +1403,7 @@ sigaction(sig, optaction, oldaction = 0)
                    sigemptyset(& act.sa_mask);
 
                /* Set up any desired flags. */
-               svp = hv_fetch(action, "FLAGS", 5, FALSE);
+               svp = hv_fetchs(action, "FLAGS", FALSE);
                act.sa_flags = svp ? SvIV(*svp) : 0;
 
                /* Don't worry about cleaning up *sigsvp if this fails,
@@ -1320,8 +1412,8 @@ sigaction(sig, optaction, oldaction = 0)
                 * essentially meaningless anyway.
                 */
                RETVAL = sigaction(sig, & act, (struct sigaction *)0);
-               if(RETVAL == -1)
-                   XSRETURN_UNDEF;
+               if(RETVAL == -1)
+                   XSRETURN_UNDEF;
            }
 
            LEAVE;
@@ -1337,20 +1429,25 @@ sigpending(sigset)
 SysRet
 sigprocmask(how, sigset, oldsigset = 0)
        int                     how
-       POSIX::SigSet           sigset
+       POSIX::SigSet           sigset = NO_INIT
        POSIX::SigSet           oldsigset = NO_INIT
 INIT:
-       if ( items < 3 ) {
-           oldsigset = 0;
+       if (! SvOK(ST(1))) {
+           sigset = NULL;
+       } else if (sv_isa(ST(1), "POSIX::SigSet")) {
+           IV tmp = SvIV((SV*)SvRV(ST(1)));
+           sigset = INT2PTR(POSIX__SigSet,tmp);
+       } else {
+           croak("sigset is not of type POSIX::SigSet");
        }
-       else if (sv_derived_from(ST(2), "POSIX::SigSet")) {
+
+       if (items < 3 || ! SvOK(ST(2))) {
+           oldsigset = NULL;
+       } else if (sv_isa(ST(2), "POSIX::SigSet")) {
            IV tmp = SvIV((SV*)SvRV(ST(2)));
            oldsigset = INT2PTR(POSIX__SigSet,tmp);
-       }
-       else {
-           New(0, oldsigset, 1, sigset_t);
-           sigemptyset(oldsigset);
-           sv_setref_pv(ST(2), "POSIX::SigSet", (void*)oldsigset);
+       } else {
+           croak("oldsigset is not of type POSIX::SigSet");
        }
 
 SysRet
@@ -1386,7 +1483,7 @@ lseek(fd, offset, whence)
     OUTPUT:
        RETVAL
 
-SV *
+void
 nice(incr)
        int             incr
     PPCODE:
@@ -1418,7 +1515,7 @@ read(fd, buffer, nbytes)
         char *          buffer = sv_grow( sv_buffer, nbytes+1 );
     CLEANUP:
         if (RETVAL >= 0) {
-            SvCUR(sv_buffer) = RETVAL;
+            SvCUR_set(sv_buffer, RETVAL);
             SvPOK_only(sv_buffer);
             *SvEND(sv_buffer) = '\0';
             SvTAINTED_on(sv_buffer);
@@ -1563,10 +1660,12 @@ strtoul(str, base = 0)
        char *unparsed;
     PPCODE:
        num = strtoul(str, &unparsed, base);
-       if (num <= IV_MAX)
-           PUSHs(sv_2mortal(newSViv((IV)num)));
-       else
+#if IVSIZE <= LONGSIZE
+       if (num > IV_MAX)
            PUSHs(sv_2mortal(newSVnv((double)num)));
+       else
+#endif
+           PUSHs(sv_2mortal(newSViv((IV)num)));
        if (GIMME == G_ARRAY) {
            EXTEND(SP, 1);
            if (unparsed)
@@ -1584,7 +1683,7 @@ strxfrm(src)
           STRLEN dstlen;
           char *p = SvPV(src,srclen);
           srclen++;
-          ST(0) = sv_2mortal(NEWSV(800,srclen*4+1));
+          ST(0) = sv_2mortal(newSV(srclen*4+1));
           dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)srclen);
           if (dstlen > srclen) {
               dstlen++;
@@ -1592,7 +1691,7 @@ strxfrm(src)
               strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
               dstlen--;
           }
-          SvCUR(ST(0)) = dstlen;
+          SvCUR_set(ST(0), dstlen);
            SvPOK_only(ST(0));
        }
 
@@ -1751,7 +1850,18 @@ access(filename, mode)
 
 char *
 ctermid(s = 0)
-       char *          s = 0;
+       char *          s = 0;
+    CODE:
+#ifdef HAS_CTERMID_R
+       s = safemalloc((size_t) L_ctermid);
+#endif
+       RETVAL = ctermid(s);
+    OUTPUT:
+       RETVAL
+    CLEANUP:
+#ifdef HAS_CTERMID_R
+       Safefree(s);
+#endif
 
 char *
 cuserid(s = 0)
@@ -1773,10 +1883,24 @@ pause()
 SysRet
 setgid(gid)
        Gid_t           gid
+    CLEANUP:
+#ifndef WIN32
+       if (RETVAL >= 0) {
+           PL_gid  = getgid();
+           PL_egid = getegid();
+       }
+#endif
 
 SysRet
 setuid(uid)
        Uid_t           uid
+    CLEANUP:
+#ifndef WIN32
+       if (RETVAL >= 0) {
+           PL_uid  = getuid();
+           PL_euid = geteuid();
+       }
+#endif
 
 SysRetLong
 sysconf(name)
@@ -1795,3 +1919,18 @@ getcwd()
        XSprePUSH; PUSHTARG;
       }
 
+SysRet
+lchown(uid, gid, path)
+       Uid_t           uid
+       Gid_t           gid
+       char *          path
+    CODE:
+#ifdef HAS_LCHOWN
+       /* yes, the order of arguments is different,
+        * but consistent with CORE::chown() */
+       RETVAL = lchown(path, uid, gid);
+#else
+       RETVAL = not_here("lchown");
+#endif
+    OUTPUT:
+       RETVAL