X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FPOSIX%2FPOSIX.xs;h=f079b7b257a46ac4b50f08b59bdda3987f3df75d;hb=8fa7f3676ed75809365905727fbae97dc8767f29;hp=d3714557ecf19ca994c4800e70d90f5dec82f0f4;hpb=39e571d41067215a80f26089b260f1418caeb36b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs index d371455..f079b7b 100644 --- a/ext/POSIX/POSIX.xs +++ b/ext/POSIX/POSIX.xs @@ -1,7 +1,19 @@ +#ifdef WIN32 +#define _POSIX_ +#endif + +#define PERL_NO_GET_CONTEXT + #include "EXTERN.h" #define PERLIO_NOT_STDIO 1 #include "perl.h" #include "XSUB.h" +#if defined(PERL_OBJECT) || defined(PERL_CAPI) || defined(PERL_IMPLICIT_SYS) +# undef signal +# undef open +# undef setmode +# define open PerlLIO_open3 +#endif #include #ifdef I_DIRENT /* XXX maybe better to just rely on perl.h? */ #include @@ -20,12 +32,16 @@ #endif #include #include -#ifdef I_STDARG #include -#endif + #ifdef I_STDDEF #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 @@ -40,9 +56,24 @@ #include #include #include -#include /* see hints/sunos_4_1.sh */ +#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() */ @@ -51,7 +82,7 @@ # define pid_t int /* old versions of DECC miss this in types.h */ # endif -# undef mkfifo /* #defined in perl.h */ +# undef mkfifo # define mkfifo(a,b) (not_here("mkfifo"),-1) # define tzset() not_here("tzset") @@ -67,6 +98,7 @@ /* The non-POSIX CRTL times() has void return type, so we just get the current time directly */ clock_t vms_times(struct tms *bufptr) { + dTHX; clock_t retval; /* Get wall time and convert to 10 ms intervals to * produce the return value that the POSIX standard expects */ @@ -91,16 +123,67 @@ } # define times(t) vms_times(t) #else -# include -# include -# ifdef HAS_UNAME -# include +#if defined (__CYGWIN__) +# define tzname _tzname +#endif +#if defined (WIN32) +# undef mkfifo +# define mkfifo(a,b) not_here("mkfifo") +# define ttyname(a) (char*)not_here("ttyname") +# define sigset_t long +# define pid_t long +# ifdef __BORLANDC__ +# define tzname _tzname +# endif +# ifdef _MSC_VER +# define mode_t short +# endif +# ifdef __MINGW32__ +# define mode_t short +# ifndef tzset +# define tzset() not_here("tzset") +# endif +# ifndef _POSIX_OPEN_MAX +# define _POSIX_OPEN_MAX FOPEN_MAX /* XXX bogus ? */ +# endif +# endif +# define sigaction(a,b,c) not_here("sigaction") +# define sigpending(a) not_here("sigpending") +# define sigprocmask(a,b,c) not_here("sigprocmask") +# define sigsuspend(a) not_here("sigsuspend") +# define sigemptyset(a) not_here("sigemptyset") +# define sigaddset(a,b) not_here("sigaddset") +# define sigdelset(a,b) not_here("sigdelset") +# define sigfillset(a) not_here("sigfillset") +# define sigismember(a,b) not_here("sigismember") +#else + +# ifndef HAS_MKFIFO +# if defined(OS2) || defined(MACOS_TRADITIONAL) +# define mkfifo(a,b) not_here("mkfifo") +# else /* !( defined OS2 ) */ +# ifndef mkfifo +# define mkfifo(path, mode) (mknod((path), (mode) | S_IFIFO, 0)) +# endif +# endif +# endif /* !HAS_MKFIFO */ + +# 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 -#endif +#endif /* WIN32 */ +#endif /* __VMS */ typedef int SysRet; typedef long SysRetLong; @@ -127,10 +210,10 @@ typedef struct termios* POSIX__Termios; #endif /* Possibly needed prototypes */ -char *cuserid _((char *)); -double strtod _((const char *, char **)); -long strtol _((const char *, char **, int)); -unsigned long strtoul _((const char *, char **, int)); +char *cuserid (char *); +double strtod (const char *, char **); +long strtol (const char *, char **, int); +unsigned long strtoul (const char *, char **, int); #ifndef HAS_CUSERID #define cuserid(a) (char *) not_here("cuserid") @@ -227,42 +310,13 @@ unsigned long strtoul _((const char *, char **, int)); #define localeconv() not_here("localeconv") #endif -#ifdef HAS_TZNAME -extern char *tzname[]; -#else -char *tzname[] = { "" , "" }; -#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 STRUCT_TM_HASZONE -static void -init_tm(ptm) /* see mktime, strftime and asctime */ - struct tm *ptm; -{ - Time_t now; - (void)time(&now); - Copy(localtime(&now), ptm, 1, struct tm); -} - -#else -# define init_tm(ptm) +#ifdef HAS_LONG_DOUBLE +# if LONG_DOUBLESIZE > NVSIZE +# undef HAS_LONG_DOUBLE /* XXX until we figure out how to use them */ +# endif #endif - -#ifndef HAS_LONG_DOUBLE /* XXX What to do about long doubles? */ +#ifndef HAS_LONG_DOUBLE #ifdef LDBL_MAX #undef LDBL_MAX #endif @@ -281,7 +335,8 @@ not_here(char *s) return -1; } -static double +static +NV constant(char *name, int arg) { errno = 0; @@ -749,6 +804,8 @@ constant(char *name, int arg) #else goto not_there; #endif + break; + case 'L': if (strEQ(name, "ELOOP")) #ifdef ELOOP return ELOOP; @@ -1238,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 @@ -1446,9 +1508,10 @@ constant(char *name, int arg) #else goto not_there; #endif - if (strEQ(name, "L_tmpname")) -#ifdef L_tmpname - return L_tmpname; + /* L_tmpnam[e] was a typo--retained for compatibility */ + if (strEQ(name, "L_tmpname") || strEQ(name, "L_tmpnam")) +#ifdef L_tmpnam + return L_tmpnam; #else goto not_there; #endif @@ -2011,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 @@ -2242,55 +2305,55 @@ constant(char *name, int arg) case '_': if (strnEQ(name, "_PC_", 4)) { if (strEQ(name, "_PC_CHOWN_RESTRICTED")) -#ifdef _PC_CHOWN_RESTRICTED +#if defined(_PC_CHOWN_RESTRICTED) || HINT_SC_EXIST return _PC_CHOWN_RESTRICTED; #else goto not_there; #endif if (strEQ(name, "_PC_LINK_MAX")) -#ifdef _PC_LINK_MAX +#if defined(_PC_LINK_MAX) || HINT_SC_EXIST return _PC_LINK_MAX; #else goto not_there; #endif if (strEQ(name, "_PC_MAX_CANON")) -#ifdef _PC_MAX_CANON +#if defined(_PC_MAX_CANON) || HINT_SC_EXIST return _PC_MAX_CANON; #else goto not_there; #endif if (strEQ(name, "_PC_MAX_INPUT")) -#ifdef _PC_MAX_INPUT +#if defined(_PC_MAX_INPUT) || HINT_SC_EXIST return _PC_MAX_INPUT; #else goto not_there; #endif if (strEQ(name, "_PC_NAME_MAX")) -#ifdef _PC_NAME_MAX +#if defined(_PC_NAME_MAX) || HINT_SC_EXIST return _PC_NAME_MAX; #else goto not_there; #endif if (strEQ(name, "_PC_NO_TRUNC")) -#ifdef _PC_NO_TRUNC +#if defined(_PC_NO_TRUNC) || HINT_SC_EXIST return _PC_NO_TRUNC; #else goto not_there; #endif if (strEQ(name, "_PC_PATH_MAX")) -#ifdef _PC_PATH_MAX +#if defined(_PC_PATH_MAX) || HINT_SC_EXIST return _PC_PATH_MAX; #else goto not_there; #endif if (strEQ(name, "_PC_PIPE_BUF")) -#ifdef _PC_PIPE_BUF +#if defined(_PC_PIPE_BUF) || HINT_SC_EXIST return _PC_PIPE_BUF; #else goto not_there; #endif if (strEQ(name, "_PC_VDISABLE")) -#ifdef _PC_VDISABLE +#if defined(_PC_VDISABLE) || HINT_SC_EXIST return _PC_VDISABLE; #else goto not_there; @@ -2416,61 +2479,61 @@ constant(char *name, int arg) } if (strnEQ(name, "_SC_", 4)) { if (strEQ(name, "_SC_ARG_MAX")) -#ifdef _SC_ARG_MAX +#if defined(_SC_ARG_MAX) || HINT_SC_EXIST return _SC_ARG_MAX; #else goto not_there; #endif if (strEQ(name, "_SC_CHILD_MAX")) -#ifdef _SC_CHILD_MAX +#if defined(_SC_CHILD_MAX) || HINT_SC_EXIST return _SC_CHILD_MAX; #else goto not_there; #endif if (strEQ(name, "_SC_CLK_TCK")) -#ifdef _SC_CLK_TCK +#if defined(_SC_CLK_TCK) || HINT_SC_EXIST return _SC_CLK_TCK; #else goto not_there; #endif if (strEQ(name, "_SC_JOB_CONTROL")) -#ifdef _SC_JOB_CONTROL +#if defined(_SC_JOB_CONTROL) || HINT_SC_EXIST return _SC_JOB_CONTROL; #else goto not_there; #endif if (strEQ(name, "_SC_NGROUPS_MAX")) -#ifdef _SC_NGROUPS_MAX +#if defined(_SC_NGROUPS_MAX) || HINT_SC_EXIST return _SC_NGROUPS_MAX; #else goto not_there; #endif if (strEQ(name, "_SC_OPEN_MAX")) -#ifdef _SC_OPEN_MAX +#if defined(_SC_OPEN_MAX) || HINT_SC_EXIST return _SC_OPEN_MAX; #else goto not_there; #endif if (strEQ(name, "_SC_SAVED_IDS")) -#ifdef _SC_SAVED_IDS +#if defined(_SC_SAVED_IDS) || HINT_SC_EXIST return _SC_SAVED_IDS; #else goto not_there; #endif if (strEQ(name, "_SC_STREAM_MAX")) -#ifdef _SC_STREAM_MAX +#if defined(_SC_STREAM_MAX) || HINT_SC_EXIST return _SC_STREAM_MAX; #else goto not_there; #endif if (strEQ(name, "_SC_TZNAME_MAX")) -#ifdef _SC_TZNAME_MAX +#if defined(_SC_TZNAME_MAX) || HINT_SC_EXIST return _SC_TZNAME_MAX; #else goto not_there; #endif if (strEQ(name, "_SC_VERSION")) -#ifdef _SC_VERSION +#if defined(_SC_VERSION) || HINT_SC_EXIST return _SC_VERSION; #else goto not_there; @@ -2486,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 @@ -2494,7 +2568,7 @@ new(packname = "POSIX::SigSet", ...) CODE: { int i; - RETVAL = (sigset_t*)safemalloc(sizeof(sigset_t)); + New(0, RETVAL, 1, sigset_t); sigemptyset(RETVAL); for (i = 1; i < items; i++) sigaddset(RETVAL, SvIV(ST(i))); @@ -2506,7 +2580,7 @@ void DESTROY(sigset) POSIX::SigSet sigset CODE: - safefree((char *)sigset); + Safefree(sigset); SysRet sigaddset(sigset, sig) @@ -2540,9 +2614,10 @@ new(packname = "POSIX::Termios", ...) CODE: { #ifdef I_TERMIOS - RETVAL = (struct termios*)safemalloc(sizeof(struct termios)); + New(0, RETVAL, 1, struct termios); #else not_here("termios"); + RETVAL = 0; #endif } OUTPUT: @@ -2553,7 +2628,7 @@ DESTROY(termios_ref) POSIX::Termios termios_ref CODE: #ifdef I_TERMIOS - safefree((char *)termios_ref); + Safefree(termios_ref); #else not_here("termios"); #endif @@ -2592,7 +2667,8 @@ getiflag(termios_ref) #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */ RETVAL = termios_ref->c_iflag; #else - not_here("getiflag"); + not_here("getiflag"); + RETVAL = 0; #endif OUTPUT: RETVAL @@ -2604,7 +2680,8 @@ getoflag(termios_ref) #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */ RETVAL = termios_ref->c_oflag; #else - not_here("getoflag"); + not_here("getoflag"); + RETVAL = 0; #endif OUTPUT: RETVAL @@ -2616,7 +2693,8 @@ getcflag(termios_ref) #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */ RETVAL = termios_ref->c_cflag; #else - not_here("getcflag"); + not_here("getcflag"); + RETVAL = 0; #endif OUTPUT: RETVAL @@ -2628,7 +2706,8 @@ getlflag(termios_ref) #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */ RETVAL = termios_ref->c_lflag; #else - not_here("getlflag"); + not_here("getlflag"); + RETVAL = 0; #endif OUTPUT: RETVAL @@ -2643,7 +2722,8 @@ getcc(termios_ref, ccix) croak("Bad getcc subscript"); RETVAL = termios_ref->c_cc[ccix]; #else - not_here("getcc"); + not_here("getcc"); + RETVAL = 0; #endif OUTPUT: RETVAL @@ -2719,7 +2799,7 @@ setcc(termios_ref, ccix, cc) MODULE = POSIX PACKAGE = POSIX -double +NV constant(name,arg) char * name int arg @@ -2729,7 +2809,7 @@ isalnum(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isalnum(*s)) RETVAL = 0; @@ -2741,7 +2821,7 @@ isalpha(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isalpha(*s)) RETVAL = 0; @@ -2753,7 +2833,7 @@ iscntrl(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!iscntrl(*s)) RETVAL = 0; @@ -2765,7 +2845,7 @@ isdigit(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isdigit(*s)) RETVAL = 0; @@ -2777,7 +2857,7 @@ isgraph(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isgraph(*s)) RETVAL = 0; @@ -2789,7 +2869,7 @@ islower(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!islower(*s)) RETVAL = 0; @@ -2801,7 +2881,7 @@ isprint(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isprint(*s)) RETVAL = 0; @@ -2813,7 +2893,7 @@ ispunct(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!ispunct(*s)) RETVAL = 0; @@ -2825,7 +2905,7 @@ isspace(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isspace(*s)) RETVAL = 0; @@ -2837,7 +2917,7 @@ isupper(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isupper(*s)) RETVAL = 0; @@ -2849,7 +2929,7 @@ isxdigit(charstring) unsigned char * charstring CODE: unsigned char *s = charstring; - unsigned char *e = s + na; /* "na" set by typemap side effect */ + unsigned char *e = s + PL_na; /* "PL_na" set by typemap side effect */ for (RETVAL = 1; RETVAL && s < e; s++) if (!isxdigit(*s)) RETVAL = 0; @@ -2875,8 +2955,7 @@ localeconv() #ifdef HAS_LOCALECONV struct lconv *lcbuf; RETVAL = newHV(); - SET_NUMERIC_LOCAL(); - if (lcbuf = localeconv()) { + if ((lcbuf = localeconv())) { /* the strings */ if (lcbuf->decimal_point && *lcbuf->decimal_point) hv_store(RETVAL, "decimal_point", 13, @@ -2884,9 +2963,11 @@ localeconv() if (lcbuf->thousands_sep && *lcbuf->thousands_sep) hv_store(RETVAL, "thousands_sep", 13, newSVpv(lcbuf->thousands_sep, 0), 0); +#ifndef NO_LOCALECONV_GROUPING if (lcbuf->grouping && *lcbuf->grouping) hv_store(RETVAL, "grouping", 8, newSVpv(lcbuf->grouping, 0), 0); +#endif if (lcbuf->int_curr_symbol && *lcbuf->int_curr_symbol) hv_store(RETVAL, "int_curr_symbol", 15, newSVpv(lcbuf->int_curr_symbol, 0), 0); @@ -2901,9 +2982,11 @@ localeconv() hv_store(RETVAL, "mon_thousands_sep", 17, newSVpv(lcbuf->mon_thousands_sep, 0), 0); #endif +#ifndef NO_LOCALECONV_MON_GROUPING if (lcbuf->mon_grouping && *lcbuf->mon_grouping) hv_store(RETVAL, "mon_grouping", 12, newSVpv(lcbuf->mon_grouping, 0), 0); +#endif if (lcbuf->positive_sign && *lcbuf->positive_sign) hv_store(RETVAL, "positive_sign", 13, newSVpv(lcbuf->positive_sign, 0), 0); @@ -2963,7 +3046,7 @@ setlocale(category, locale = 0) else #endif newctype = RETVAL; - perl_new_ctype(newctype); + new_ctype(newctype); } #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE @@ -2980,7 +3063,7 @@ setlocale(category, locale = 0) else #endif newcoll = RETVAL; - perl_new_collate(newcoll); + new_collate(newcoll); } #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC @@ -2997,7 +3080,7 @@ setlocale(category, locale = 0) else #endif newnum = RETVAL; - perl_new_numeric(newnum); + new_numeric(newnum); } #endif /* USE_LOCALE_NUMERIC */ } @@ -3005,102 +3088,155 @@ 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 + RETVAL = not_here("sigaction"); +#else # This code is really grody because we're trying to make the signal # interface look beautiful, which is hard. - if (!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(siggv), - sig_name[sig], - strlen(sig_name[sig]), + PL_sig_name[sig], + strlen(PL_sig_name[sig]), TRUE); - /* 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, na); 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) { @@ -3109,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, na)); + sv_setsv(*sigsvp, *svp); mg_set(*sigsvp); /* handles DEFAULT and IGNORE */ - act.sa_handler = sighandler; + 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 @@ -3127,37 +3276,18 @@ 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 { - sigset = (sigset_t*)safemalloc(sizeof(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: RETVAL @@ -3169,7 +3299,20 @@ SysRet sigprocmask(how, sigset, oldsigset = 0) int how POSIX::SigSet sigset - POSIX::SigSet oldsigset + POSIX::SigSet oldsigset = NO_INIT +INIT: + if ( items < 3 ) { + oldsigset = 0; + } + else if (sv_derived_from(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); + } SysRet sigsuspend(signal_mask) @@ -3202,12 +3345,12 @@ SysRet nice(incr) int incr -int +void pipe() PPCODE: int fds[2]; if (pipe(fds) != -1) { - EXTEND(sp,2); + EXTEND(SP,2); PUSHs(sv_2mortal(newSViv(fds[0]))); PUSHs(sv_2mortal(newSViv(fds[1]))); } @@ -3245,13 +3388,13 @@ tcsetpgrp(fd, pgrp_id) int fd pid_t pgrp_id -int +void uname() PPCODE: #ifdef HAS_UNAME struct utsname buf; if (uname(&buf) >= 0) { - EXTEND(sp, 5); + EXTEND(SP, 5); PUSHs(sv_2mortal(newSVpv(buf.sysname, 0))); PUSHs(sv_2mortal(newSVpv(buf.nodename, 0))); PUSHs(sv_2mortal(newSVpv(buf.release, 0))); @@ -3268,9 +3411,18 @@ write(fd, buffer, nbytes) char * buffer size_t nbytes -char * -tmpnam(s = 0) - char * s = 0; +SV * +tmpnam() + PREINIT: + STRLEN i; + int len; + CODE: + RETVAL = newSVpvn("", 0); + SvGROW(RETVAL, L_tmpnam); + len = strlen(tmpnam(SvPV(RETVAL, i))); + SvCUR_set(RETVAL, len); + OUTPUT: + RETVAL void abort() @@ -3319,11 +3471,11 @@ strtod(str) num = strtod(str, &unparsed); PUSHs(sv_2mortal(newSVnv(num))); if (GIMME == G_ARRAY) { - EXTEND(sp, 1); + EXTEND(SP, 1); if (unparsed) PUSHs(sv_2mortal(newSViv(strlen(unparsed)))); else - PUSHs(&sv_undef); + PUSHs(&PL_sv_undef); } void @@ -3335,16 +3487,18 @@ strtol(str, base = 0) char *unparsed; PPCODE: num = strtol(str, &unparsed, base); - if (num >= IV_MIN && num <= IV_MAX) - PUSHs(sv_2mortal(newSViv((IV)num))); - else +#if IVSIZE <= LONGSIZE + if (num < IV_MIN || num > IV_MAX) PUSHs(sv_2mortal(newSVnv((double)num))); + else +#endif + PUSHs(sv_2mortal(newSViv((IV)num))); if (GIMME == G_ARRAY) { - EXTEND(sp, 1); + EXTEND(SP, 1); if (unparsed) PUSHs(sv_2mortal(newSViv(strlen(unparsed)))); else - PUSHs(&sv_undef); + PUSHs(&PL_sv_undef); } void @@ -3361,14 +3515,14 @@ strtoul(str, base = 0) else PUSHs(sv_2mortal(newSVnv((double)num))); if (GIMME == G_ARRAY) { - EXTEND(sp, 1); + EXTEND(SP, 1); if (unparsed) PUSHs(sv_2mortal(newSViv(strlen(unparsed)))); else - PUSHs(&sv_undef); + PUSHs(&PL_sv_undef); } -SV * +void strxfrm(src) SV * src CODE: @@ -3462,7 +3616,7 @@ times() struct tms tms; clock_t realtime; realtime = times( &tms ); - EXTEND(sp,5); + EXTEND(SP,5); PUSHs( sv_2mortal( newSViv( (IV) realtime ) ) ); PUSHs( sv_2mortal( newSViv( (IV) tms.tms_utime ) ) ); PUSHs( sv_2mortal( newSViv( (IV) tms.tms_stime ) ) ); @@ -3503,8 +3657,11 @@ mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0) OUTPUT: RETVAL -char * -strftime(fmt, sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0) +#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 int min @@ -3517,21 +3674,11 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0) 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; - len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm); - ST(0) = sv_2mortal(newSVpv(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); + } } void @@ -3540,9 +3687,9 @@ tzset() void tzname() PPCODE: - EXTEND(sp,2); - PUSHs(sv_2mortal(newSVpv(tzname[0],strlen(tzname[0])))); - PUSHs(sv_2mortal(newSVpv(tzname[1],strlen(tzname[1])))); + EXTEND(SP,2); + PUSHs(sv_2mortal(newSVpvn(tzname[0],strlen(tzname[0])))); + PUSHs(sv_2mortal(newSVpvn(tzname[1],strlen(tzname[1])))); SysRet access(filename, mode) @@ -3570,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 @@ -3577,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