summaryrefslogtreecommitdiffstats
path: root/contrib/perl5/ext/POSIX/POSIX.xs
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/perl5/ext/POSIX/POSIX.xs')
-rw-r--r--contrib/perl5/ext/POSIX/POSIX.xs73
1 files changed, 61 insertions, 12 deletions
diff --git a/contrib/perl5/ext/POSIX/POSIX.xs b/contrib/perl5/ext/POSIX/POSIX.xs
index 6958c00..15e026e 100644
--- a/contrib/perl5/ext/POSIX/POSIX.xs
+++ b/contrib/perl5/ext/POSIX/POSIX.xs
@@ -10,8 +10,6 @@
# undef open
# undef setmode
# define open PerlLIO_open3
-# undef TAINT_PROPER
-# define TAINT_PROPER(a)
#endif
#include <ctype.h>
#ifdef I_DIRENT /* XXX maybe better to just rely on perl.h? */
@@ -2569,7 +2567,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)));
@@ -2581,7 +2579,7 @@ void
DESTROY(sigset)
POSIX::SigSet sigset
CODE:
- safefree((char *)sigset);
+ Safefree(sigset);
SysRet
sigaddset(sigset, sig)
@@ -2615,7 +2613,7 @@ 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;
@@ -2629,7 +2627,7 @@ DESTROY(termios_ref)
POSIX::Termios termios_ref
CODE:
#ifdef I_TERMIOS
- safefree((char *)termios_ref);
+ Safefree(termios_ref);
#else
not_here("termios");
#endif
@@ -3181,10 +3179,11 @@ sigaction(sig, action, oldaction = 0)
sig_name[sig],
strlen(sig_name[sig]),
TRUE);
+ STRLEN n_a;
/* Remember old handler name if desired. */
if (oldaction) {
- char *hand = SvPVx(*sigsvp, PL_na);
+ char *hand = SvPVx(*sigsvp, n_a);
svp = hv_fetch(oldaction, "HANDLER", 7, TRUE);
sv_setpv(*svp, *hand ? hand : "DEFAULT");
}
@@ -3195,7 +3194,7 @@ 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, PL_na));
+ sv_setpv(*sigsvp, SvPV(*svp, n_a));
mg_set(*sigsvp); /* handles DEFAULT and IGNORE */
act.sa_handler = sighandler;
@@ -3234,7 +3233,7 @@ sigaction(sig, action, oldaction = 0)
sigset = (sigset_t*) tmp;
}
else {
- sigset = (sigset_t*)safemalloc(sizeof(sigset_t));
+ New(0, sigset, 1, sigset_t);
sv_setptrobj(*svp, sigset, "POSIX::SigSet");
}
*sigset = oact.sa_mask;
@@ -3256,7 +3255,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 = (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)
@@ -3591,7 +3603,7 @@ mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
RETVAL
char *
-strftime(fmt, sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
+strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
char * fmt
int sec
int min
@@ -3617,8 +3629,45 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
mytm.tm_wday = wday;
mytm.tm_yday = yday;
mytm.tm_isdst = isdst;
+ (void) mktime(&mytm);
len = strftime(tmpbuf, sizeof tmpbuf, fmt, &mytm);
- ST(0) = sv_2mortal(newSVpv(tmpbuf, len));
+ /*
+ ** 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(newSVpv(buf, buflen));
+ Safefree(buf);
+ } else {
+ ST(0) = sv_2mortal(newSVpv(tmpbuf, len));
+ }
+ }
}
void
OpenPOWER on IntegriCloud