X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FPOSIX%2FPOSIX.xs;h=f079b7b257a46ac4b50f08b59bdda3987f3df75d;hb=8fa7f3676ed75809365905727fbae97dc8767f29;hp=16217f09367bb1de22ea0f71d0effcc46fed9515;hpb=5bc28da93666e223bb56098f72517273bc8bcbf9;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs index 16217f0..f079b7b 100644 --- a/ext/POSIX/POSIX.xs +++ b/ext/POSIX/POSIX.xs @@ -8,7 +8,7 @@ #define PERLIO_NOT_STDIO 1 #include "perl.h" #include "XSUB.h" -#if defined(PERL_OBJECT) || defined(PERL_CAPI) +#if defined(PERL_OBJECT) || defined(PERL_CAPI) || defined(PERL_IMPLICIT_SYS) # undef signal # undef open # undef setmode @@ -38,6 +38,10 @@ #include #endif +#ifdef I_UNISTD +#include +#endif + /* 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 @@ -55,8 +59,21 @@ #ifdef I_UNISTD #include #endif +#ifdef MACOS_TRADITIONAL +#undef fdopen +#endif #include +#ifdef HAS_TZNAME +# if !defined(WIN32) && !defined(__CYGWIN__) +extern char *tzname[]; +# endif +#else +#if !defined(WIN32) || (defined(__MINGW32__) && !defined(tzname)) +char *tzname[] = { "" , "" }; +#endif +#endif + #if defined(__VMS) && !defined(__POSIX_SOURCE) # include /* LIB$_INVARG constant */ # include /* prototype for lib$ediv() */ @@ -80,7 +97,7 @@ /* The non-POSIX CRTL times() has void return type, so we just get the current time directly */ - clock_t vms_times(struct tms *PL_bufptr) { + clock_t vms_times(struct tms *bufptr) { dTHX; clock_t retval; /* Get wall time and convert to 10 ms intervals to @@ -101,14 +118,13 @@ _ckvmssts(lib$ediv(&divisor,vmstime,(long int *)&retval,&remainder)); # endif /* Fill in the struct tms using the CRTL routine . . .*/ - times((tbuffer_t *)PL_bufptr); + times((tbuffer_t *)bufptr); return (clock_t) retval; } # define times(t) vms_times(t) #else -#if defined (CYGWIN) +#if defined (__CYGWIN__) # define tzname _tzname -# undef MB_CUR_MAX /* XXX: bug in b20.1 */ #endif #if defined (WIN32) # undef mkfifo @@ -143,7 +159,7 @@ #else # ifndef HAS_MKFIFO -# ifdef OS2 +# if defined(OS2) || defined(MACOS_TRADITIONAL) # define mkfifo(a,b) not_here("mkfifo") # else /* !( defined OS2 ) */ # ifndef mkfifo @@ -152,12 +168,17 @@ # endif # endif /* !HAS_MKFIFO */ -# include -# include -# ifdef HAS_UNAME -# include +# ifdef MACOS_TRADITIONAL +# define ttyname(a) (char*)not_here("ttyname") +# define tzset() not_here("tzset") +# else +# include +# include +# ifdef HAS_UNAME +# include +# endif +# include # endif -# include # ifdef I_UTIME # include # endif @@ -289,57 +310,13 @@ unsigned long strtoul (const char *, char **, int); #define localeconv() not_here("localeconv") #endif -#ifdef HAS_TZNAME -# ifndef WIN32 -extern char *tzname[]; -# endif -#else -#if !defined(WIN32) || (defined(__MINGW32__) && !defined(tzname)) -char *tzname[] = { "" , "" }; -#endif -#endif - -/* XXX struct tm on some systems (SunOS4/BSD) contains extra (non POSIX) - * fields for which we don't have Configure support yet: - * char *tm_zone; -- abbreviation of timezone name - * long tm_gmtoff; -- offset from GMT in seconds - * To workaround core dumps from the uninitialised tm_zone we get the - * system to give us a reasonable struct to copy. This fix means that - * strftime uses the tm_zone and tm_gmtoff values returned by - * localtime(time()). That should give the desired result most of the - * time. But probably not always! - * - * This is a temporary workaround to be removed once Configure - * support is added and NETaa14816 is considered in full. - * It does not address tzname aspects of NETaa14816. - */ -#ifdef HAS_GNULIBC -# ifndef STRUCT_TM_HASZONE -# define STRUCT_TM_HASZONE -# endif -#endif - -#ifdef STRUCT_TM_HASZONE -static void -init_tm(struct tm *ptm) /* see mktime, strftime and asctime */ -{ - Time_t now; - (void)time(&now); - Copy(localtime(&now), ptm, 1, struct tm); -} - -#else -# define init_tm(ptm) -#endif - - #ifdef HAS_LONG_DOUBLE -# if LONG_DOUBLESIZE > DOUBLESIZE +# if LONG_DOUBLESIZE > NVSIZE # undef HAS_LONG_DOUBLE /* XXX until we figure out how to use them */ # endif #endif -#ifndef HAS_LONG_DOUBLE +#ifndef HAS_LONG_DOUBLE #ifdef LDBL_MAX #undef LDBL_MAX #endif @@ -359,11 +336,7 @@ not_here(char *s) } static -#if defined(HAS_LONG_DOUBLE) && (LONG_DOUBLESIZE > DOUBLESIZE) -long double -#else -double -#endif +NV constant(char *name, int arg) { errno = 0; @@ -1322,6 +1295,11 @@ constant(char *name, int arg) break; case 'H': if (strEQ(name, "HUGE_VAL")) +#if defined(USE_LONG_DOUBLE) && defined(HUGE_VALL) + /* HUGE_VALL is admittedly non-POSIX but if we are using long doubles + * we might as well use long doubles. --jhi */ + return HUGE_VALL; +#endif #ifdef HUGE_VAL return HUGE_VAL; #else @@ -2096,9 +2074,9 @@ constant(char *name, int arg) #else goto not_there; #endif - if (strEQ(name, "STRERR_FILENO")) -#ifdef STRERR_FILENO - return STRERR_FILENO; + if (strEQ(name, "STDERR_FILENO")) +#ifdef STDERR_FILENO + return STDERR_FILENO; #else goto not_there; #endif @@ -2571,6 +2549,17 @@ not_there: return 0; } +static void +restore_sigmask(sigset_t *ossetp) +{ + /* Fortunately, restoring the signal mask can't fail, because + * there's nothing we can do about it if it does -- we're not + * supposed to return -1 from sigaction unless the disposition + * was unaffected. + */ + (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0); +} + MODULE = SigSet PACKAGE = POSIX::SigSet PREFIX = sig POSIX::SigSet @@ -2810,7 +2799,7 @@ setcc(termios_ref, ccix, cc) MODULE = POSIX PACKAGE = POSIX -double +NV constant(name,arg) char * name int arg @@ -2966,7 +2955,7 @@ localeconv() #ifdef HAS_LOCALECONV struct lconv *lcbuf; RETVAL = newHV(); - if (lcbuf = localeconv()) { + if ((lcbuf = localeconv())) { /* the strings */ if (lcbuf->decimal_point && *lcbuf->decimal_point) hv_store(RETVAL, "decimal_point", 13, @@ -3099,78 +3088,78 @@ setlocale(category, locale = 0) RETVAL -double +NV acos(x) - double x + NV x -double +NV asin(x) - double x + NV x -double +NV atan(x) - double x + NV x -double +NV ceil(x) - double x + NV x -double +NV cosh(x) - double x + NV x -double +NV floor(x) - double x + NV x -double +NV fmod(x,y) - double x - double y + NV x + NV y void frexp(x) - double x + NV x PPCODE: int expvar; /* (We already know stack is long enough.) */ PUSHs(sv_2mortal(newSVnv(frexp(x,&expvar)))); PUSHs(sv_2mortal(newSViv(expvar))); -double +NV ldexp(x,exp) - double x + NV x int exp -double +NV log10(x) - double x + NV x void modf(x) - double x + NV x PPCODE: - double intvar; + NV intvar; /* (We already know stack is long enough.) */ - PUSHs(sv_2mortal(newSVnv(modf(x,&intvar)))); + PUSHs(sv_2mortal(newSVnv(Perl_modf(x,&intvar)))); PUSHs(sv_2mortal(newSVnv(intvar))); -double +NV sinh(x) - double x + NV x -double +NV tan(x) - double x + NV x -double +NV tanh(x) - double x + NV x SysRet -sigaction(sig, action, oldaction = 0) +sigaction(sig, optaction, oldaction = 0) int sig - POSIX::SigAction action + SV * optaction POSIX::SigAction oldaction CODE: #ifdef WIN32 @@ -3179,25 +3168,75 @@ sigaction(sig, action, oldaction = 0) # This code is really grody because we're trying to make the signal # interface look beautiful, which is hard. - if (!PL_siggv) - gv_fetchpv("SIG", TRUE, SVt_PVHV); - { + POSIX__SigAction action; + GV *siggv = gv_fetchpv("SIG", TRUE, SVt_PVHV); struct sigaction act; struct sigaction oact; + sigset_t sset; + sigset_t osset; POSIX__SigSet sigset; SV** svp; - SV** sigsvp = hv_fetch(GvHVn(PL_siggv), + SV** sigsvp = hv_fetch(GvHVn(siggv), PL_sig_name[sig], strlen(PL_sig_name[sig]), TRUE); - STRLEN n_a; - /* Remember old handler name if desired. */ + /* Check optaction and set action */ + if(SvTRUE(optaction)) { + if(sv_isa(optaction, "POSIX::SigAction")) + action = (HV*)SvRV(optaction); + else + croak("action is not of type POSIX::SigAction"); + } + else { + action=0; + } + + /* sigaction() is supposed to look atomic. In particular, any + * signal handler invoked during a sigaction() call should + * see either the old or the new disposition, and not something + * in between. We use sigprocmask() to make it so. + */ + sigfillset(&sset); + RETVAL=sigprocmask(SIG_BLOCK, &sset, &osset); + if(RETVAL == -1) + XSRETURN(1); + ENTER; + /* Restore signal mask no matter how we exit this block. */ + SAVEDESTRUCTOR(restore_sigmask, &osset); + + RETVAL=-1; /* In case both oldaction and action are 0. */ + + /* Remember old disposition if desired. */ if (oldaction) { - char *hand = SvPVx(*sigsvp, n_a); svp = hv_fetch(oldaction, "HANDLER", 7, TRUE); - sv_setpv(*svp, *hand ? hand : "DEFAULT"); + if(!svp) + croak("Can't supply an oldaction without a HANDLER"); + if(SvTRUE(*sigsvp)) { /* TBD: what if "0"? */ + sv_setsv(*svp, *sigsvp); + } + else { + sv_setpv(*svp, "DEFAULT"); + } + RETVAL = sigaction(sig, (struct sigaction *)0, & oact); + if(RETVAL == -1) + XSRETURN(1); + /* Get back the mask. */ + svp = hv_fetch(oldaction, "MASK", 4, 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); + sv_setptrobj(*svp, sigset, "POSIX::SigSet"); + } + *sigset = oact.sa_mask; + + /* Get back the flags. */ + svp = hv_fetch(oldaction, "FLAGS", 5, TRUE); + sv_setiv(*svp, oact.sa_flags); } if (action) { @@ -3206,16 +3245,29 @@ sigaction(sig, action, oldaction = 0) svp = hv_fetch(action, "HANDLER", 7, FALSE); if (!svp) croak("Can't supply an action without a HANDLER"); - sv_setpv(*sigsvp, SvPV(*svp, n_a)); + sv_setsv(*sigsvp, *svp); mg_set(*sigsvp); /* handles DEFAULT and IGNORE */ - act.sa_handler = PL_sighandlerp; + if(SvPOK(*svp)) { + char *s=SvPVX(*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); if (svp && sv_isa(*svp, "POSIX::SigSet")) { - unsigned long tmp; - tmp = (unsigned long)SvNV((SV*)SvRV(*svp)); - sigset = (sigset_t*) tmp; + IV tmp = SvIV((SV*)SvRV(*svp)); + sigset = INT2PTR(sigset_t*, tmp); act.sa_mask = *sigset; } else @@ -3224,36 +3276,16 @@ sigaction(sig, action, oldaction = 0) /* Set up any desired flags. */ svp = hv_fetch(action, "FLAGS", 5, FALSE); act.sa_flags = svp ? SvIV(*svp) : 0; - } - /* Now work around sigaction oddities */ - if (action && oldaction) - RETVAL = sigaction(sig, & act, & oact); - else if (action) + /* Don't worry about cleaning up *sigsvp if this fails, + * because that means we tried to disposition a + * nonblockable signal, in which case *sigsvp is + * essentially meaningless anyway. + */ RETVAL = sigaction(sig, & act, (struct sigaction *)0); - else if (oldaction) - RETVAL = sigaction(sig, (struct sigaction *)0, & oact); - else - RETVAL = -1; - - if (oldaction) { - /* Get back the mask. */ - svp = hv_fetch(oldaction, "MASK", 4, TRUE); - if (sv_isa(*svp, "POSIX::SigSet")) { - unsigned long tmp; - tmp = (unsigned long)SvNV((SV*)SvRV(*svp)); - sigset = (sigset_t*) tmp; - } - else { - New(0, 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); - sv_setiv(*svp, oact.sa_flags); } + + LEAVE; } #endif OUTPUT: @@ -3313,7 +3345,7 @@ SysRet nice(incr) int incr -int +void pipe() PPCODE: int fds[2]; @@ -3356,7 +3388,7 @@ tcsetpgrp(fd, pgrp_id) int fd pid_t pgrp_id -int +void uname() PPCODE: #ifdef HAS_UNAME @@ -3490,7 +3522,7 @@ strtoul(str, base = 0) PUSHs(&PL_sv_undef); } -SV * +void strxfrm(src) SV * src CODE: @@ -3625,7 +3657,10 @@ mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0) OUTPUT: RETVAL -char * +#XXX: if $xsubpp::WantOptimize is always the default +# sv_setpv(TARG, ...) could be used rather than +# ST(0) = sv_2mortal(newSVpv(...)) +void strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1) char * fmt int sec @@ -3639,57 +3674,10 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1) int isdst CODE: { - char tmpbuf[128]; - struct tm mytm; - int len; - init_tm(&mytm); /* XXX workaround - see init_tm() above */ - mytm.tm_sec = sec; - mytm.tm_min = min; - mytm.tm_hour = hour; - mytm.tm_mday = mday; - mytm.tm_mon = mon; - mytm.tm_year = year; - mytm.tm_wday = wday; - mytm.tm_yday = yday; - mytm.tm_isdst = isdst; - (void) mktime(&mytm); - len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm); - /* - ** The following is needed to handle to the situation where - ** tmpbuf overflows. Basically we want to allocate a buffer - ** and try repeatedly. The reason why it is so complicated - ** is that getting a return value of 0 from strftime can indicate - ** one of the following: - ** 1. buffer overflowed, - ** 2. illegal conversion specifier, or - ** 3. the format string specifies nothing to be returned(not - ** an error). This could be because format is an empty string - ** or it specifies %p that yields an empty string in some locale. - ** If there is a better way to make it portable, go ahead by - ** all means. - */ - if ( ( len > 0 && len < sizeof(tmpbuf) ) - || ( len == 0 && strlen(fmt) == 0 ) ) { - ST(0) = sv_2mortal(newSVpv(tmpbuf, len)); - } else { - /* Possibly buf overflowed - try again with a bigger buf */ - int bufsize = strlen(fmt) + sizeof(tmpbuf); - char* buf; - int buflen; - - New(0, buf, bufsize, char); - while( buf ) { - buflen = strftime(buf, bufsize, fmt, &mytm); - if ( buflen > 0 && buflen < bufsize ) break; - bufsize *= 2; - Renew(buf, bufsize, char); - } - if ( buf ) { - ST(0) = sv_2mortal(newSVpvn(buf, buflen)); - Safefree(buf); - } else { - ST(0) = sv_2mortal(newSVpvn(tmpbuf, len)); - } + char *buf = my_strftime(fmt, sec, min, hour, mday, mon, year, wday, yday, isdst); + if (buf) { + ST(0) = sv_2mortal(newSVpv(buf, 0)); + Safefree(buf); } } @@ -3729,6 +3717,14 @@ pathconf(filename, name) SysRet pause() +SysRet +setgid(gid) + Gid_t gid + +SysRet +setuid(uid) + Uid_t uid + SysRetLong sysconf(name) int name @@ -3736,3 +3732,40 @@ sysconf(name) char * ttyname(fd) int fd + +char * +getcwd() + PPCODE: +#ifdef HAS_GETCWD + char * buf; + int buflen = 128; + + New(0, buf, buflen, char); + /* Many getcwd()s know how to automatically allocate memory + * for the directory if the buffer argument is NULL but... + * (1) we cannot assume all getcwd()s do that + * (2) this may interfere with Perl's malloc + * So let's not. --jhi */ + while ((getcwd(buf, buflen) == NULL) && errno == ERANGE) { + buflen += 128; + if (buflen > MAXPATHLEN) { + Safefree(buf); + buf = NULL; + break; + } + Renew(buf, buflen, char); + } + if (buf) { + PUSHs(sv_2mortal(newSVpv(buf, 0))); + Safefree(buf); + } + else + PUSHs(&PL_sv_undef); +#else + require_pv("Cwd.pm"); + /* Module require may have grown the stack */ + SPAGAIN; + PUSHMARK(sp); + PUTBACK; + XSRETURN(call_pv("Cwd::cwd", GIMME_V)); +#endif