#include "EXTERN.h"
+#define PERLIO_NOT_STDIO 1
#include "perl.h"
#include "XSUB.h"
#include <ctype.h>
#include <dirent.h>
#endif
#include <errno.h>
-#include <fcntl.h>
#ifdef I_FLOAT
#include <float.h>
#endif
-#include <grp.h>
#ifdef I_LIMITS
#include <limits.h>
#endif
#endif
#include <string.h>
#include <sys/stat.h>
-#include <sys/times.h>
#include <sys/types.h>
-#ifdef HAS_UNAME
-#include <sys/utsname.h>
-#endif
-#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
-#ifdef I_UTIME
-#include <utime.h>
+#if defined(__VMS) && !defined(__POSIX_SOURCE)
+# include <file.h> /* == fcntl.h for DECC; no fcntl.h for VAXC */
+# include <libdef.h> /* LIB$_INVARG constant */
+# include <lib$routines.h> /* prototype for lib$ediv() */
+# include <starlet.h> /* prototype for sys$gettim() */
+
+# undef mkfifo /* #defined in perl.h */
+# define mkfifo(a,b) (not_here("mkfifo"),-1)
+# define tzset() not_here("tzset")
+
+ /* The default VMS emulation of Unix signals isn't very POSIXish */
+ typedef int sigset_t;
+# define sigpending(a) (not_here("sigpending"),0)
+
+ /* sigset_t is atomic under VMS, so these routines are easy */
+ int sigemptyset(sigset_t *set) {
+ if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+ *set = 0; return 0;
+ }
+ int sigfillset(sigset_t *set) {
+ int i;
+ if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+ for (i = 0; i < NSIG; i++) *set |= (1 << i);
+ return 0;
+ }
+ int sigaddset(sigset_t *set, int sig) {
+ if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+ if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
+ *set |= (1 << (sig - 1));
+ return 0;
+ }
+ int sigdelset(sigset_t *set, int sig) {
+ if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+ if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
+ *set &= ~(1 << (sig - 1));
+ return 0;
+ }
+ int sigismember(sigset_t *set, int sig) {
+ if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+ if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
+ *set & (1 << (sig - 1));
+ }
+ /* The tools for sigprocmask() are there, just not the routine itself */
+# ifndef SIG_UNBLOCK
+# define SIG_UNBLOCK 1
+# endif
+# ifndef SIG_BLOCK
+# define SIG_BLOCK 2
+# endif
+# ifndef SIG_SETMASK
+# define SIG_SETMASK 3
+# endif
+ int sigprocmask(int how, sigset_t *set, sigset_t *oset) {
+ if (!set || !oset) {
+ set_errno(EFAULT); set_vaxc_errno(SS$_ACCVIO);
+ return -1;
+ }
+ switch (how) {
+ case SIG_SETMASK:
+ *oset = sigsetmask(*set);
+ break;
+ case SIG_BLOCK:
+ *oset = sigblock(*set);
+ break;
+ case SIG_UNBLOCK:
+ *oset = sigblock(0);
+ sigsetmask(*oset & ~*set);
+ break;
+ default:
+ set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
+ return -1;
+ }
+ return 0;
+ }
+# define sigaction sigvec
+# define sa_flags sv_onstack
+# define sa_handler sv_handler
+# define sa_mask sv_mask
+# define sigsuspend(set) sigpause(*set)
+
+ /* The POSIX notion of ttyname() is better served by getname() under VMS */
+ static char ttnambuf[64];
+# define ttyname(fd) (isatty(fd) > 0 ? getname(fd,ttnambuf,0) : NULL)
+
+ /* The non-POSIX CRTL times() has void return type, so we just get the
+ current time directly */
+ clock_t vms_times(struct tms *bufptr) {
+ clock_t retval;
+ /* Get wall time and convert to 10 ms intervals to
+ * produce the return value that the POSIX standard expects */
+# if defined(__DECC) && defined (__ALPHA)
+# include <ints.h>
+ uint64 vmstime;
+ _ckvmssts(sys$gettim(&vmstime));
+ vmstime /= 100000;
+ retval = vmstime & 0x7fffffff;
+# else
+ /* (Older hw or ccs don't have an atomic 64-bit type, so we
+ * juggle 32-bit ints (and a float) to produce a time_t result
+ * with minimal loss of information.) */
+ long int vmstime[2],remainder,divisor = 100000;
+ _ckvmssts(sys$gettim((unsigned long int *)vmstime));
+ vmstime[1] &= 0x7fff; /* prevent overflow in EDIV */
+ _ckvmssts(lib$ediv(&divisor,vmstime,(long int *)&retval,&remainder));
+# endif
+ /* Fill in the struct tms using the CRTL routine . . .*/
+ times((tbuffer_t *)bufptr);
+ return (clock_t) retval;
+ }
+# define times(t) vms_times(t)
+#else
+# include <fcntl.h>
+# include <grp.h>
+# include <sys/times.h>
+# ifdef HAS_UNAME
+# include <sys/utsname.h>
+# endif
+# include <sys/wait.h>
+# ifdef I_UTIME
+# include <utime.h>
+# endif
#endif
-typedef FILE * InputStream;
-typedef FILE * OutputStream;
typedef int SysRet;
typedef long SysRetLong;
typedef sigset_t* POSIX__SigSet;
/* Possibly needed prototypes */
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")
#ifndef HAS_STRCOLL
#define strcoll(s1,s2) not_here("strcoll")
#endif
+#ifndef HAS_STRTOD
+#define strtod(s1,s2) not_here("strtod")
+#endif
+#ifndef HAS_STRTOL
+#define strtol(s1,s2,b) not_here("strtol")
+#endif
+#ifndef HAS_STRTOUL
+#define strtoul(s1,s2,b) not_here("strtoul")
+#endif
#ifndef HAS_STRXFRM
#define strxfrm(s1,s2,n) not_here("strxfrm")
#endif
#define waitpid(a,b,c) not_here("waitpid")
#endif
-#ifndef HAS_FGETPOS
-#define fgetpos(a,b) not_here("fgetpos")
-#endif
-#ifndef HAS_FSETPOS
-#define fsetpos(a,b) not_here("fsetpos")
-#endif
-
#ifndef HAS_MBLEN
#ifndef mblen
#define mblen(a,b) not_here("mblen")
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)
+#endif
+
+
#ifndef HAS_LONG_DOUBLE /* XXX What to do about long doubles? */
#ifdef LDBL_MAX
#undef LDBL_MAX
#endif
break;
}
- if (strEQ(name, "_IOFBF"))
-#ifdef _IOFBF
- return _IOFBF;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "_IOLBF"))
-#ifdef _IOLBF
- return _IOLBF;
-#else
- goto not_there;
-#endif
- if (strEQ(name, "_IONBF"))
-#ifdef _IONBF
- return _IONBF;
-#else
- goto not_there;
-#endif
- break;
}
errno = EINVAL;
return 0;
#endif
-
-MODULE = FileHandle PACKAGE = FileHandle PREFIX = f
-
-SV *
-fgetpos(handle)
- InputStream handle
- CODE:
- {
- Fpos_t pos;
- fgetpos(handle, &pos);
- ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t)));
- }
-
-SysRet
-fsetpos(handle, pos)
- InputStream handle
- SV * pos
- CODE:
- RETVAL = fsetpos(handle, (Fpos_t*)SvPVX(pos));
- OUTPUT:
- RETVAL
-
-int
-ungetc(handle, c)
- InputStream handle
- int c
- CODE:
- RETVAL = ungetc(c, handle);
- OUTPUT:
- RETVAL
-
-OutputStream
-new_tmpfile(packname = "FileHandle")
- char * packname
- CODE:
- RETVAL = tmpfile();
- OUTPUT:
- RETVAL
-
-int
-ferror(handle)
- InputStream handle
-
-SysRet
-fflush(handle)
- OutputStream handle
-
-void
-setbuf(handle, buf)
- OutputStream handle
- char * buf = SvPOK(ST(1)) ? sv_grow(ST(1), BUFSIZ) : 0;
-
-SysRet
-setvbuf(handle, buf, type, size)
- OutputStream handle
- char * buf = SvPOK(ST(1)) ? sv_grow(ST(1), SvIV(ST(3))) : 0;
- int type
- int size
-
MODULE = POSIX PACKAGE = POSIX
double
RETVAL
char *
-setlocale(category, locale)
+setlocale(category, locale = 0)
int category
char * locale
+ CODE:
+ RETVAL = setlocale(category, locale);
+ if (RETVAL) {
+#ifdef LC_CTYPE
+ if (category == LC_CTYPE
+#ifdef LC_ALL
+ || category == LC_ALL
+#endif
+ )
+ {
+ char *newctype;
+#ifdef LC_ALL
+ if (category == LC_ALL)
+ newctype = setlocale(LC_CTYPE, NULL);
+ else
+#endif
+ newctype = RETVAL;
+ perl_new_ctype(newctype);
+ }
+#endif /* LC_CTYPE */
+#ifdef LC_COLLATE
+ if (category == LC_COLLATE
+#ifdef LC_ALL
+ || category == LC_ALL
+#endif
+ )
+ {
+ char *newcoll;
+#ifdef LC_ALL
+ if (category == LC_ALL)
+ newcoll = setlocale(LC_COLLATE, NULL);
+ else
+#endif
+ newcoll = RETVAL;
+ perl_new_collate(newcoll);
+ }
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+ if (category == LC_NUMERIC
+#ifdef LC_ALL
+ || category == LC_ALL
+#endif
+ )
+ {
+ char *newnum;
+#ifdef LC_ALL
+ if (category == LC_ALL)
+ newnum = setlocale(LC_NUMERIC, NULL);
+ else
+#endif
+ newnum = RETVAL;
+ perl_new_numeric(newnum);
+ }
+#endif /* LC_NUMERIC */
+ }
+ OUTPUT:
+ RETVAL
+
double
acos(x)
if (action && oldaction)
RETVAL = sigaction(sig, & act, & oact);
else if (action)
- RETVAL = sigaction(sig, & act, (struct sigaction*)0);
+ RETVAL = sigaction(sig, & act, (struct sigaction *)0);
else if (oldaction)
- RETVAL = sigaction(sig, (struct sigaction*)0, & oact);
+ RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
else
RETVAL = -1;
SysRet
read(fd, buffer, nbytes)
- int fd
- char * buffer = sv_grow(ST(1),SvIV(ST(2))+1);
- size_t nbytes
+ PREINIT:
+ SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
+ INPUT:
+ int fd
+ size_t nbytes
+ char * buffer = sv_grow( sv_buffer, nbytes+1 );
CLEANUP:
- if (RETVAL >= 0) {
- SvCUR(ST(1)) = RETVAL;
- SvPOK_only(ST(1));
- *SvEND(ST(1)) = '\0';
- if (tainting)
- sv_magic(ST(1), 0, 't', 0, 0);
- }
-
-SysRet
-setgid(gid)
- Gid_t gid
+ if (RETVAL >= 0) {
+ SvCUR(sv_buffer) = RETVAL;
+ SvPOK_only(sv_buffer);
+ *SvEND(sv_buffer) = '\0';
+ SvTAINTED_on(sv_buffer);
+ }
SysRet
setpgid(pid, pgid)
pid_t
setsid()
-SysRet
-setuid(uid)
- Uid_t uid
-
pid_t
tcgetpgrp(fd)
int fd
char * s1
char * s2
+void
+strtod(str)
+ char * str
+ PREINIT:
+ double num;
+ char *unparsed;
+ PPCODE:
+ NUMERIC_LOCAL();
+ num = strtod(str, &unparsed);
+ PUSHs(sv_2mortal(newSVnv(num)));
+ if (GIMME == G_ARRAY) {
+ EXTEND(sp, 1);
+ if (unparsed)
+ PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+ else
+ PUSHs(&sv_undef);
+ }
+
+void
+strtol(str, base = 0)
+ char * str
+ int base
+ PREINIT:
+ long num;
+ char *unparsed;
+ PPCODE:
+ num = strtol(str, &unparsed, base);
+ if (num >= IV_MIN && num <= IV_MAX)
+ PUSHs(sv_2mortal(newSViv((IV)num)));
+ else
+ PUSHs(sv_2mortal(newSVnv((double)num)));
+ if (GIMME == G_ARRAY) {
+ EXTEND(sp, 1);
+ if (unparsed)
+ PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+ else
+ PUSHs(&sv_undef);
+ }
+
+void
+strtoul(str, base = 0)
+ char * str
+ int base
+ PREINIT:
+ unsigned long num;
+ char *unparsed;
+ PPCODE:
+ num = strtoul(str, &unparsed, base);
+ if (num <= IV_MAX)
+ PUSHs(sv_2mortal(newSViv((IV)num)));
+ else
+ PUSHs(sv_2mortal(newSVnv((double)num)));
+ if (GIMME == G_ARRAY) {
+ EXTEND(sp, 1);
+ if (unparsed)
+ PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+ else
+ PUSHs(&sv_undef);
+ }
+
SV *
strxfrm(src)
SV * src
CODE:
{
struct tm mytm;
+ init_tm(&mytm); /* XXX workaround - see init_tm() above */
mytm.tm_sec = sec;
mytm.tm_min = min;
mytm.tm_hour = hour;
ctime(time)
Time_t &time
+void
+times()
+ PPCODE:
+ struct tms tms;
+ clock_t realtime;
+ realtime = times( &tms );
+ EXTEND(sp,5);
+ PUSHs( sv_2mortal( newSVnv( realtime ) ) );
+ PUSHs( sv_2mortal( newSVnv( tms.tms_utime ) ) );
+ PUSHs( sv_2mortal( newSVnv( tms.tms_stime ) ) );
+ PUSHs( sv_2mortal( newSVnv( tms.tms_cutime ) ) );
+ PUSHs( sv_2mortal( newSVnv( tms.tms_cstime ) ) );
+
double
difftime(time1, time2)
Time_t time1
CODE:
{
struct tm mytm;
+ init_tm(&mytm); /* XXX workaround - see init_tm() above */
mytm.tm_sec = sec;
mytm.tm_min = min;
mytm.tm_hour = hour;
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;