This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
attributes-two.patch also contains a lot of const-ing, hence the
[perl5.git] / ext / POSIX / POSIX.xs
1 #define PERL_EXT_POSIX
2
3 #ifdef NETWARE
4         #define _POSIX_
5         /*
6          * Ideally this should be somewhere down in the includes
7          * but putting it in other places is giving compiler errors.
8          * Also here I am unable to check for HAS_UNAME since it wouldn't have
9          * yet come into the file at this stage - sgp 18th Oct 2000
10          */
11         #include <sys/utsname.h>
12 #endif  /* NETWARE */
13
14 #define PERL_NO_GET_CONTEXT
15
16 #include "EXTERN.h"
17 #define PERLIO_NOT_STDIO 1
18 #include "perl.h"
19 #include "XSUB.h"
20 #if defined(PERL_IMPLICIT_SYS)
21 #  undef signal
22 #  undef open
23 #  undef setmode
24 #  define open PerlLIO_open3
25 #endif
26 #include <ctype.h>
27 #ifdef I_DIRENT    /* XXX maybe better to just rely on perl.h? */
28 #include <dirent.h>
29 #endif
30 #include <errno.h>
31 #ifdef I_FLOAT
32 #include <float.h>
33 #endif
34 #ifdef I_LIMITS
35 #include <limits.h>
36 #endif
37 #include <locale.h>
38 #include <math.h>
39 #ifdef I_PWD
40 #include <pwd.h>
41 #endif
42 #include <setjmp.h>
43 #include <signal.h>
44 #include <stdarg.h>
45
46 #ifdef I_STDDEF
47 #include <stddef.h>
48 #endif
49
50 #ifdef I_UNISTD
51 #include <unistd.h>
52 #endif
53
54 /* XXX This comment is just to make I_TERMIO and I_SGTTY visible to 
55    metaconfig for future extension writers.  We don't use them in POSIX.
56    (This is really sneaky :-)  --AD
57 */
58 #if defined(I_TERMIOS)
59 #include <termios.h>
60 #endif
61 #ifdef I_STDLIB
62 #include <stdlib.h>
63 #endif
64 #ifndef __ultrix__
65 #include <string.h>
66 #endif
67 #include <sys/stat.h>
68 #include <sys/types.h>
69 #include <time.h>
70 #ifdef I_UNISTD
71 #include <unistd.h>
72 #endif
73 #ifdef MACOS_TRADITIONAL
74 #undef fdopen
75 #endif
76 #include <fcntl.h>
77
78 #ifdef HAS_TZNAME
79 #  if !defined(WIN32) && !defined(__CYGWIN__) && !defined(NETWARE) && !defined(__UWIN__)
80 extern char *tzname[];
81 #  endif
82 #else
83 #if !defined(WIN32) && !defined(__UWIN__) || (defined(__MINGW32__) && !defined(tzname))
84 char *tzname[] = { "" , "" };
85 #endif
86 #endif
87
88 #ifndef PERL_UNUSED_DECL
89 #  ifdef HASATTRIBUTE
90 #    if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER)
91 #      define PERL_UNUSED_DECL
92 #    else
93 #      define PERL_UNUSED_DECL __attribute__((unused))
94 #    endif
95 #  else
96 #    define PERL_UNUSED_DECL
97 #  endif
98 #endif
99
100 #ifndef dNOOP
101 #define dNOOP extern int Perl___notused PERL_UNUSED_DECL
102 #endif
103
104 #ifndef dVAR
105 #define dVAR dNOOP
106 #endif
107
108 #if defined(__VMS) && !defined(__POSIX_SOURCE)
109 #  include <libdef.h>       /* LIB$_INVARG constant */
110 #  include <lib$routines.h> /* prototype for lib$ediv() */
111 #  include <starlet.h>      /* prototype for sys$gettim() */
112 #  if DECC_VERSION < 50000000
113 #    define pid_t int       /* old versions of DECC miss this in types.h */
114 #  endif
115
116 #  undef mkfifo
117 #  define mkfifo(a,b) (not_here("mkfifo"),-1)
118 #  define tzset() not_here("tzset")
119
120 #if ((__VMS_VER >= 70000000) && (__DECC_VER >= 50200000)) || (__CRTL_VER >= 70000000)
121 #    define HAS_TZNAME  /* shows up in VMS 7.0 or Dec C 5.6 */
122 #    include <utsname.h>
123 #  endif /* __VMS_VER >= 70000000 or Dec C 5.6 */
124
125    /* The POSIX notion of ttyname() is better served by getname() under VMS */
126    static char ttnambuf[64];
127 #  define ttyname(fd) (isatty(fd) > 0 ? getname(fd,ttnambuf,0) : NULL)
128
129    /* The non-POSIX CRTL times() has void return type, so we just get the
130       current time directly */
131    clock_t vms_times(struct tms *bufptr) {
132         dTHX;
133         clock_t retval;
134         /* Get wall time and convert to 10 ms intervals to
135          * produce the return value that the POSIX standard expects */
136 #  if defined(__DECC) && defined (__ALPHA)
137 #    include <ints.h>
138         uint64 vmstime;
139         _ckvmssts(sys$gettim(&vmstime));
140         vmstime /= 100000;
141         retval = vmstime & 0x7fffffff;
142 #  else
143         /* (Older hw or ccs don't have an atomic 64-bit type, so we
144          * juggle 32-bit ints (and a float) to produce a time_t result
145          * with minimal loss of information.) */
146         long int vmstime[2],remainder,divisor = 100000;
147         _ckvmssts(sys$gettim((unsigned long int *)vmstime));
148         vmstime[1] &= 0x7fff;  /* prevent overflow in EDIV */
149         _ckvmssts(lib$ediv(&divisor,vmstime,(long int *)&retval,&remainder));
150 #  endif
151         /* Fill in the struct tms using the CRTL routine . . .*/
152         times((tbuffer_t *)bufptr);
153         return (clock_t) retval;
154    }
155 #  define times(t) vms_times(t)
156 #else
157 #if defined (__CYGWIN__)
158 #    define tzname _tzname
159 #endif
160 #if defined (WIN32) || defined (NETWARE)
161 #  undef mkfifo
162 #  define mkfifo(a,b) not_here("mkfifo")
163 #  define ttyname(a) (char*)not_here("ttyname")
164 #  define sigset_t long
165 #  define pid_t long
166 #  ifdef __BORLANDC__
167 #    define tzname _tzname
168 #  endif
169 #  ifdef _MSC_VER
170 #    define mode_t short
171 #  endif
172 #  ifdef __MINGW32__
173 #    define mode_t short
174 #    ifndef tzset
175 #      define tzset()           not_here("tzset")
176 #    endif
177 #    ifndef _POSIX_OPEN_MAX
178 #      define _POSIX_OPEN_MAX   FOPEN_MAX       /* XXX bogus ? */
179 #    endif
180 #  endif
181 #  define sigaction(a,b,c)      not_here("sigaction")
182 #  define sigpending(a)         not_here("sigpending")
183 #  define sigprocmask(a,b,c)    not_here("sigprocmask")
184 #  define sigsuspend(a)         not_here("sigsuspend")
185 #  define sigemptyset(a)        not_here("sigemptyset")
186 #  define sigaddset(a,b)        not_here("sigaddset")
187 #  define sigdelset(a,b)        not_here("sigdelset")
188 #  define sigfillset(a)         not_here("sigfillset")
189 #  define sigismember(a,b)      not_here("sigismember")
190 #ifndef NETWARE
191 #  undef setuid
192 #  undef setgid
193 #  define setuid(a)             not_here("setuid")
194 #  define setgid(a)             not_here("setgid")
195 #endif  /* NETWARE */
196 #else
197
198 #  ifndef HAS_MKFIFO
199 #    if defined(OS2) || defined(MACOS_TRADITIONAL)
200 #      define mkfifo(a,b) not_here("mkfifo")
201 #    else       /* !( defined OS2 ) */ 
202 #      ifndef mkfifo
203 #        define mkfifo(path, mode) (mknod((path), (mode) | S_IFIFO, 0))
204 #      endif
205 #    endif
206 #  endif /* !HAS_MKFIFO */
207
208 #  ifdef MACOS_TRADITIONAL
209 #    define ttyname(a) (char*)not_here("ttyname")
210 #    define tzset() not_here("tzset")
211 #  else
212 #    include <grp.h>
213 #    include <sys/times.h>
214 #    ifdef HAS_UNAME
215 #      include <sys/utsname.h>
216 #    endif
217 #    include <sys/wait.h>
218 #  endif
219 #  ifdef I_UTIME
220 #    include <utime.h>
221 #  endif
222 #endif /* WIN32 || NETWARE */
223 #endif /* __VMS */
224
225 typedef int SysRet;
226 typedef long SysRetLong;
227 typedef sigset_t* POSIX__SigSet;
228 typedef HV* POSIX__SigAction;
229 #ifdef I_TERMIOS
230 typedef struct termios* POSIX__Termios;
231 #else /* Define termios types to int, and call not_here for the functions.*/
232 #define POSIX__Termios int
233 #define speed_t int
234 #define tcflag_t int
235 #define cc_t int
236 #define cfgetispeed(x) not_here("cfgetispeed")
237 #define cfgetospeed(x) not_here("cfgetospeed")
238 #define tcdrain(x) not_here("tcdrain")
239 #define tcflush(x,y) not_here("tcflush")
240 #define tcsendbreak(x,y) not_here("tcsendbreak")
241 #define cfsetispeed(x,y) not_here("cfsetispeed")
242 #define cfsetospeed(x,y) not_here("cfsetospeed")
243 #define ctermid(x) (char *) not_here("ctermid")
244 #define tcflow(x,y) not_here("tcflow")
245 #define tcgetattr(x,y) not_here("tcgetattr")
246 #define tcsetattr(x,y,z) not_here("tcsetattr")
247 #endif
248
249 /* Possibly needed prototypes */
250 char *cuserid (char *);
251 #ifndef WIN32
252 double strtod (const char *, char **);
253 long strtol (const char *, char **, int);
254 unsigned long strtoul (const char *, char **, int);
255 #endif
256
257 #ifndef HAS_CUSERID
258 #define cuserid(a) (char *) not_here("cuserid")
259 #endif
260 #ifndef HAS_DIFFTIME
261 #ifndef difftime
262 #define difftime(a,b) not_here("difftime")
263 #endif
264 #endif
265 #ifndef HAS_FPATHCONF
266 #define fpathconf(f,n)  (SysRetLong) not_here("fpathconf")
267 #endif
268 #ifndef HAS_MKTIME
269 #define mktime(a) not_here("mktime")
270 #endif
271 #ifndef HAS_NICE
272 #define nice(a) not_here("nice")
273 #endif
274 #ifndef HAS_PATHCONF
275 #define pathconf(f,n)   (SysRetLong) not_here("pathconf")
276 #endif
277 #ifndef HAS_SYSCONF
278 #define sysconf(n)      (SysRetLong) not_here("sysconf")
279 #endif
280 #ifndef HAS_READLINK
281 #define readlink(a,b,c) not_here("readlink")
282 #endif
283 #ifndef HAS_SETPGID
284 #define setpgid(a,b) not_here("setpgid")
285 #endif
286 #ifndef HAS_SETSID
287 #define setsid() not_here("setsid")
288 #endif
289 #ifndef HAS_STRCOLL
290 #define strcoll(s1,s2) not_here("strcoll")
291 #endif
292 #ifndef HAS_STRTOD
293 #define strtod(s1,s2) not_here("strtod")
294 #endif
295 #ifndef HAS_STRTOL
296 #define strtol(s1,s2,b) not_here("strtol")
297 #endif
298 #ifndef HAS_STRTOUL
299 #define strtoul(s1,s2,b) not_here("strtoul")
300 #endif
301 #ifndef HAS_STRXFRM
302 #define strxfrm(s1,s2,n) not_here("strxfrm")
303 #endif
304 #ifndef HAS_TCGETPGRP
305 #define tcgetpgrp(a) not_here("tcgetpgrp")
306 #endif
307 #ifndef HAS_TCSETPGRP
308 #define tcsetpgrp(a,b) not_here("tcsetpgrp")
309 #endif
310 #ifndef HAS_TIMES
311 #ifndef NETWARE
312 #define times(a) not_here("times")
313 #endif  /* NETWARE */
314 #endif
315 #ifndef HAS_UNAME
316 #define uname(a) not_here("uname")
317 #endif
318 #ifndef HAS_WAITPID
319 #define waitpid(a,b,c) not_here("waitpid")
320 #endif
321
322 #ifndef HAS_MBLEN
323 #ifndef mblen
324 #define mblen(a,b) not_here("mblen")
325 #endif
326 #endif
327 #ifndef HAS_MBSTOWCS
328 #define mbstowcs(s, pwcs, n) not_here("mbstowcs")
329 #endif
330 #ifndef HAS_MBTOWC
331 #define mbtowc(pwc, s, n) not_here("mbtowc")
332 #endif
333 #ifndef HAS_WCSTOMBS
334 #define wcstombs(s, pwcs, n) not_here("wcstombs")
335 #endif
336 #ifndef HAS_WCTOMB
337 #define wctomb(s, wchar) not_here("wcstombs")
338 #endif
339 #if !defined(HAS_MBLEN) && !defined(HAS_MBSTOWCS) && !defined(HAS_MBTOWC) && !defined(HAS_WCSTOMBS) && !defined(HAS_WCTOMB)
340 /* If we don't have these functions, then we wouldn't have gotten a typedef
341    for wchar_t, the wide character type.  Defining wchar_t allows the
342    functions referencing it to compile.  Its actual type is then meaningless,
343    since without the above functions, all sections using it end up calling
344    not_here() and croak.  --Kaveh Ghazi (ghazi@noc.rutgers.edu) 9/18/94. */
345 #ifndef wchar_t
346 #define wchar_t char
347 #endif
348 #endif
349
350 #ifndef HAS_LOCALECONV
351 #define localeconv() not_here("localeconv")
352 #endif
353
354 #ifdef HAS_LONG_DOUBLE
355 #  if LONG_DOUBLESIZE > NVSIZE
356 #    undef HAS_LONG_DOUBLE  /* XXX until we figure out how to use them */
357 #  endif
358 #endif
359
360 #ifndef HAS_LONG_DOUBLE
361 #ifdef LDBL_MAX
362 #undef LDBL_MAX
363 #endif
364 #ifdef LDBL_MIN
365 #undef LDBL_MIN
366 #endif
367 #ifdef LDBL_EPSILON
368 #undef LDBL_EPSILON
369 #endif
370 #endif
371
372 /* Background: in most systems the low byte of the wait status
373  * is the signal (the lowest 7 bits) and the coredump flag is
374  * the eight bit, and the second lowest byte is the exit status.
375  * BeOS bucks the trend and has the bytes in different order.
376  * See beos/beos.c for how the reality is bent even in BeOS
377  * to follow the traditional.  However, to make the POSIX
378  * wait W*() macros to work in BeOS, we need to unbend the
379  * reality back in place. --jhi */
380 #ifdef __BEOS__
381 #    define WMUNGE(x) (((x) & 0xFF00) >> 8 | ((x) & 0x00FF) << 8)
382 #else
383 #    define WMUNGE(x) (x)
384 #endif
385
386 static int
387 not_here(char *s)
388 {
389     croak("POSIX::%s not implemented on this architecture", s);
390     return -1;
391 }
392
393 #include "const-c.inc"
394
395 /* These were implemented in the old "constant" subroutine. They are actually
396    macros that take an integer argument and return an integer result.  */
397 static int
398 int_macro_int (const char *name, STRLEN len, IV *arg_result) {
399   /* Initially switch on the length of the name.  */
400   /* This code has been edited from a "constant" function generated by:
401
402 use ExtUtils::Constant qw (constant_types C_constant XS_constant);
403
404 my $types = {map {($_, 1)} qw(IV)};
405 my @names = (qw(S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISREG WEXITSTATUS WIFEXITED
406                WIFSIGNALED WIFSTOPPED WSTOPSIG WTERMSIG));
407
408 print constant_types(); # macro defs
409 foreach (C_constant ("POSIX", 'int_macro_int', 'IV', $types, undef, 5, @names) ) {
410     print $_, "\n"; # C constant subs
411 }
412 print "#### XS Section:\n";
413 print XS_constant ("POSIX", $types);
414 __END__
415    */
416
417   switch (len) {
418   case 7:
419     /* Names all of length 7.  */
420     /* S_ISBLK S_ISCHR S_ISDIR S_ISREG */
421     /* Offset 5 gives the best switch position.  */
422     switch (name[5]) {
423     case 'E':
424       if (memEQ(name, "S_ISREG", 7)) {
425       /*                    ^       */
426 #ifdef S_ISREG
427         *arg_result = S_ISREG(*arg_result);
428         return PERL_constant_ISIV;
429 #else
430         return PERL_constant_NOTDEF;
431 #endif
432       }
433       break;
434     case 'H':
435       if (memEQ(name, "S_ISCHR", 7)) {
436       /*                    ^       */
437 #ifdef S_ISCHR
438         *arg_result = S_ISCHR(*arg_result);
439         return PERL_constant_ISIV;
440 #else
441         return PERL_constant_NOTDEF;
442 #endif
443       }
444       break;
445     case 'I':
446       if (memEQ(name, "S_ISDIR", 7)) {
447       /*                    ^       */
448 #ifdef S_ISDIR
449         *arg_result = S_ISDIR(*arg_result);
450         return PERL_constant_ISIV;
451 #else
452         return PERL_constant_NOTDEF;
453 #endif
454       }
455       break;
456     case 'L':
457       if (memEQ(name, "S_ISBLK", 7)) {
458       /*                    ^       */
459 #ifdef S_ISBLK
460         *arg_result = S_ISBLK(*arg_result);
461         return PERL_constant_ISIV;
462 #else
463         return PERL_constant_NOTDEF;
464 #endif
465       }
466       break;
467     }
468     break;
469   case 8:
470     /* Names all of length 8.  */
471     /* S_ISFIFO WSTOPSIG WTERMSIG */
472     /* Offset 3 gives the best switch position.  */
473     switch (name[3]) {
474     case 'O':
475       if (memEQ(name, "WSTOPSIG", 8)) {
476       /*                  ^          */
477 #ifdef WSTOPSIG
478         int i = *arg_result;
479         *arg_result = WSTOPSIG(WMUNGE(i));
480         return PERL_constant_ISIV;
481 #else
482         return PERL_constant_NOTDEF;
483 #endif
484       }
485       break;
486     case 'R':
487       if (memEQ(name, "WTERMSIG", 8)) {
488       /*                  ^          */
489 #ifdef WTERMSIG
490         int i = *arg_result;
491         *arg_result = WTERMSIG(WMUNGE(i));
492         return PERL_constant_ISIV;
493 #else
494         return PERL_constant_NOTDEF;
495 #endif
496       }
497       break;
498     case 'S':
499       if (memEQ(name, "S_ISFIFO", 8)) {
500       /*                  ^          */
501 #ifdef S_ISFIFO
502         *arg_result = S_ISFIFO(*arg_result);
503         return PERL_constant_ISIV;
504 #else
505         return PERL_constant_NOTDEF;
506 #endif
507       }
508       break;
509     }
510     break;
511   case 9:
512     if (memEQ(name, "WIFEXITED", 9)) {
513 #ifdef WIFEXITED
514       int i = *arg_result;
515       *arg_result = WIFEXITED(WMUNGE(i));
516       return PERL_constant_ISIV;
517 #else
518       return PERL_constant_NOTDEF;
519 #endif
520     }
521     break;
522   case 10:
523     if (memEQ(name, "WIFSTOPPED", 10)) {
524 #ifdef WIFSTOPPED
525       int i = *arg_result;
526       *arg_result = WIFSTOPPED(WMUNGE(i));
527       return PERL_constant_ISIV;
528 #else
529       return PERL_constant_NOTDEF;
530 #endif
531     }
532     break;
533   case 11:
534     /* Names all of length 11.  */
535     /* WEXITSTATUS WIFSIGNALED */
536     /* Offset 1 gives the best switch position.  */
537     switch (name[1]) {
538     case 'E':
539       if (memEQ(name, "WEXITSTATUS", 11)) {
540       /*                ^                */
541 #ifdef WEXITSTATUS
542         int i = *arg_result;
543         *arg_result = WEXITSTATUS(WMUNGE(i));
544         return PERL_constant_ISIV;
545 #else
546         return PERL_constant_NOTDEF;
547 #endif
548       }
549       break;
550     case 'I':
551       if (memEQ(name, "WIFSIGNALED", 11)) {
552       /*                ^                */
553 #ifdef WIFSIGNALED
554         int i = *arg_result;
555         *arg_result = WIFSIGNALED(WMUNGE(i));
556         return PERL_constant_ISIV;
557 #else
558         return PERL_constant_NOTDEF;
559 #endif
560       }
561       break;
562     }
563     break;
564   }
565   return PERL_constant_NOTFOUND;
566 }
567
568 static void
569 restore_sigmask(pTHX_ SV *osset_sv)
570 {
571      /* Fortunately, restoring the signal mask can't fail, because
572       * there's nothing we can do about it if it does -- we're not
573       * supposed to return -1 from sigaction unless the disposition
574       * was unaffected.
575       */
576      sigset_t *ossetp = (sigset_t *) SvPV_nolen( osset_sv );
577      (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
578 }
579
580 MODULE = SigSet         PACKAGE = POSIX::SigSet         PREFIX = sig
581
582 POSIX::SigSet
583 new(packname = "POSIX::SigSet", ...)
584     char *              packname
585     CODE:
586         {
587             int i;
588             New(0, RETVAL, 1, sigset_t);
589             sigemptyset(RETVAL);
590             for (i = 1; i < items; i++)
591                 sigaddset(RETVAL, SvIV(ST(i)));
592         }
593     OUTPUT:
594         RETVAL
595
596 void
597 DESTROY(sigset)
598         POSIX::SigSet   sigset
599     CODE:
600         Safefree(sigset);
601
602 SysRet
603 sigaddset(sigset, sig)
604         POSIX::SigSet   sigset
605         int             sig
606
607 SysRet
608 sigdelset(sigset, sig)
609         POSIX::SigSet   sigset
610         int             sig
611
612 SysRet
613 sigemptyset(sigset)
614         POSIX::SigSet   sigset
615
616 SysRet
617 sigfillset(sigset)
618         POSIX::SigSet   sigset
619
620 int
621 sigismember(sigset, sig)
622         POSIX::SigSet   sigset
623         int             sig
624
625
626 MODULE = Termios        PACKAGE = POSIX::Termios        PREFIX = cf
627
628 POSIX::Termios
629 new(packname = "POSIX::Termios", ...)
630     char *              packname
631     CODE:
632         {
633 #ifdef I_TERMIOS
634             New(0, RETVAL, 1, struct termios);
635 #else
636             not_here("termios");
637         RETVAL = 0;
638 #endif
639         }
640     OUTPUT:
641         RETVAL
642
643 void
644 DESTROY(termios_ref)
645         POSIX::Termios  termios_ref
646     CODE:
647 #ifdef I_TERMIOS
648         Safefree(termios_ref);
649 #else
650             not_here("termios");
651 #endif
652
653 SysRet
654 getattr(termios_ref, fd = 0)
655         POSIX::Termios  termios_ref
656         int             fd
657     CODE:
658         RETVAL = tcgetattr(fd, termios_ref);
659     OUTPUT:
660         RETVAL
661
662 SysRet
663 setattr(termios_ref, fd = 0, optional_actions = 0)
664         POSIX::Termios  termios_ref
665         int             fd
666         int             optional_actions
667     CODE:
668         RETVAL = tcsetattr(fd, optional_actions, termios_ref);
669     OUTPUT:
670         RETVAL
671
672 speed_t
673 cfgetispeed(termios_ref)
674         POSIX::Termios  termios_ref
675
676 speed_t
677 cfgetospeed(termios_ref)
678         POSIX::Termios  termios_ref
679
680 tcflag_t
681 getiflag(termios_ref)
682         POSIX::Termios  termios_ref
683     CODE:
684 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
685         RETVAL = termios_ref->c_iflag;
686 #else
687      not_here("getiflag");
688      RETVAL = 0;
689 #endif
690     OUTPUT:
691         RETVAL
692
693 tcflag_t
694 getoflag(termios_ref)
695         POSIX::Termios  termios_ref
696     CODE:
697 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
698         RETVAL = termios_ref->c_oflag;
699 #else
700      not_here("getoflag");
701      RETVAL = 0;
702 #endif
703     OUTPUT:
704         RETVAL
705
706 tcflag_t
707 getcflag(termios_ref)
708         POSIX::Termios  termios_ref
709     CODE:
710 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
711         RETVAL = termios_ref->c_cflag;
712 #else
713      not_here("getcflag");
714      RETVAL = 0;
715 #endif
716     OUTPUT:
717         RETVAL
718
719 tcflag_t
720 getlflag(termios_ref)
721         POSIX::Termios  termios_ref
722     CODE:
723 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
724         RETVAL = termios_ref->c_lflag;
725 #else
726      not_here("getlflag");
727      RETVAL = 0;
728 #endif
729     OUTPUT:
730         RETVAL
731
732 cc_t
733 getcc(termios_ref, ccix)
734         POSIX::Termios  termios_ref
735         int             ccix
736     CODE:
737 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
738         if (ccix >= NCCS)
739             croak("Bad getcc subscript");
740         RETVAL = termios_ref->c_cc[ccix];
741 #else
742      not_here("getcc");
743      RETVAL = 0;
744 #endif
745     OUTPUT:
746         RETVAL
747
748 SysRet
749 cfsetispeed(termios_ref, speed)
750         POSIX::Termios  termios_ref
751         speed_t         speed
752
753 SysRet
754 cfsetospeed(termios_ref, speed)
755         POSIX::Termios  termios_ref
756         speed_t         speed
757
758 void
759 setiflag(termios_ref, iflag)
760         POSIX::Termios  termios_ref
761         tcflag_t        iflag
762     CODE:
763 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
764         termios_ref->c_iflag = iflag;
765 #else
766             not_here("setiflag");
767 #endif
768
769 void
770 setoflag(termios_ref, oflag)
771         POSIX::Termios  termios_ref
772         tcflag_t        oflag
773     CODE:
774 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
775         termios_ref->c_oflag = oflag;
776 #else
777             not_here("setoflag");
778 #endif
779
780 void
781 setcflag(termios_ref, cflag)
782         POSIX::Termios  termios_ref
783         tcflag_t        cflag
784     CODE:
785 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
786         termios_ref->c_cflag = cflag;
787 #else
788             not_here("setcflag");
789 #endif
790
791 void
792 setlflag(termios_ref, lflag)
793         POSIX::Termios  termios_ref
794         tcflag_t        lflag
795     CODE:
796 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
797         termios_ref->c_lflag = lflag;
798 #else
799             not_here("setlflag");
800 #endif
801
802 void
803 setcc(termios_ref, ccix, cc)
804         POSIX::Termios  termios_ref
805         int             ccix
806         cc_t            cc
807     CODE:
808 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
809         if (ccix >= NCCS)
810             croak("Bad setcc subscript");
811         termios_ref->c_cc[ccix] = cc;
812 #else
813             not_here("setcc");
814 #endif
815
816
817 MODULE = POSIX          PACKAGE = POSIX
818
819 INCLUDE: const-xs.inc
820
821 void
822 int_macro_int(sv, iv)
823     PREINIT:
824         dXSTARG;
825         STRLEN          len;
826         int             type;
827     INPUT:
828         SV *            sv;
829         const char *    s = SvPV(sv, len);
830         IV              iv;
831     PPCODE:
832         /* Change this to int_macro_int(s, len, &iv, &nv);
833            if you need to return both NVs and IVs */
834         type = int_macro_int(s, len, &iv);
835       /* Return 1 or 2 items. First is error message, or undef if no error.
836            Second, if present, is found value */
837         switch (type) {
838         case PERL_constant_NOTFOUND:
839           sv = sv_2mortal(newSVpvf("%s is not a valid POSIX macro", s));
840           EXTEND(SP, 1);
841           PUSHs(&PL_sv_undef);
842           PUSHs(sv);
843           break;
844         case PERL_constant_NOTDEF:
845           sv = sv_2mortal(newSVpvf(
846             "Your vendor has not defined POSIX macro %s, used", s));
847           EXTEND(SP, 1);
848           PUSHs(&PL_sv_undef);
849           PUSHs(sv);
850           break;
851         case PERL_constant_ISIV:
852           PUSHi(iv);
853           break;
854         default:
855           sv = sv_2mortal(newSVpvf(
856             "Unexpected return type %d while processing POSIX macro %s, used",
857                type, s));
858           EXTEND(SP, 1);
859           PUSHs(&PL_sv_undef);
860           PUSHs(sv);
861         }
862
863 int
864 isalnum(charstring)
865         SV *    charstring
866     PREINIT:
867         STRLEN  len;
868     CODE:
869         unsigned char *s = (unsigned char *) SvPV(charstring, len);
870         unsigned char *e = s + len;
871         for (RETVAL = 1; RETVAL && s < e; s++)
872             if (!isalnum(*s))
873                 RETVAL = 0;
874     OUTPUT:
875         RETVAL
876
877 int
878 isalpha(charstring)
879         SV *    charstring
880     PREINIT:
881         STRLEN  len;
882     CODE:
883         unsigned char *s = (unsigned char *) SvPV(charstring, len);
884         unsigned char *e = s + len;
885         for (RETVAL = 1; RETVAL && s < e; s++)
886             if (!isalpha(*s))
887                 RETVAL = 0;
888     OUTPUT:
889         RETVAL
890
891 int
892 iscntrl(charstring)
893         SV *    charstring
894     PREINIT:
895         STRLEN  len;
896     CODE:
897         unsigned char *s = (unsigned char *) SvPV(charstring, len);
898         unsigned char *e = s + len;
899         for (RETVAL = 1; RETVAL && s < e; s++)
900             if (!iscntrl(*s))
901                 RETVAL = 0;
902     OUTPUT:
903         RETVAL
904
905 int
906 isdigit(charstring)
907         SV *    charstring
908     PREINIT:
909         STRLEN  len;
910     CODE:
911         unsigned char *s = (unsigned char *) SvPV(charstring, len);
912         unsigned char *e = s + len;
913         for (RETVAL = 1; RETVAL && s < e; s++)
914             if (!isdigit(*s))
915                 RETVAL = 0;
916     OUTPUT:
917         RETVAL
918
919 int
920 isgraph(charstring)
921         SV *    charstring
922     PREINIT:
923         STRLEN  len;
924     CODE:
925         unsigned char *s = (unsigned char *) SvPV(charstring, len);
926         unsigned char *e = s + len;
927         for (RETVAL = 1; RETVAL && s < e; s++)
928             if (!isgraph(*s))
929                 RETVAL = 0;
930     OUTPUT:
931         RETVAL
932
933 int
934 islower(charstring)
935         SV *    charstring
936     PREINIT:
937         STRLEN  len;
938     CODE:
939         unsigned char *s = (unsigned char *) SvPV(charstring, len);
940         unsigned char *e = s + len;
941         for (RETVAL = 1; RETVAL && s < e; s++)
942             if (!islower(*s))
943                 RETVAL = 0;
944     OUTPUT:
945         RETVAL
946
947 int
948 isprint(charstring)
949         SV *    charstring
950     PREINIT:
951         STRLEN  len;
952     CODE:
953         unsigned char *s = (unsigned char *) SvPV(charstring, len);
954         unsigned char *e = s + len;
955         for (RETVAL = 1; RETVAL && s < e; s++)
956             if (!isprint(*s))
957                 RETVAL = 0;
958     OUTPUT:
959         RETVAL
960
961 int
962 ispunct(charstring)
963         SV *    charstring
964     PREINIT:
965         STRLEN  len;
966     CODE:
967         unsigned char *s = (unsigned char *) SvPV(charstring, len);
968         unsigned char *e = s + len;
969         for (RETVAL = 1; RETVAL && s < e; s++)
970             if (!ispunct(*s))
971                 RETVAL = 0;
972     OUTPUT:
973         RETVAL
974
975 int
976 isspace(charstring)
977         SV *    charstring
978     PREINIT:
979         STRLEN  len;
980     CODE:
981         unsigned char *s = (unsigned char *) SvPV(charstring, len);
982         unsigned char *e = s + len;
983         for (RETVAL = 1; RETVAL && s < e; s++)
984             if (!isspace(*s))
985                 RETVAL = 0;
986     OUTPUT:
987         RETVAL
988
989 int
990 isupper(charstring)
991         SV *    charstring
992     PREINIT:
993         STRLEN  len;
994     CODE:
995         unsigned char *s = (unsigned char *) SvPV(charstring, len);
996         unsigned char *e = s + len;
997         for (RETVAL = 1; RETVAL && s < e; s++)
998             if (!isupper(*s))
999                 RETVAL = 0;
1000     OUTPUT:
1001         RETVAL
1002
1003 int
1004 isxdigit(charstring)
1005         SV *    charstring
1006     PREINIT:
1007         STRLEN  len;
1008     CODE:
1009         unsigned char *s = (unsigned char *) SvPV(charstring, len);
1010         unsigned char *e = s + len;
1011         for (RETVAL = 1; RETVAL && s < e; s++)
1012             if (!isxdigit(*s))
1013                 RETVAL = 0;
1014     OUTPUT:
1015         RETVAL
1016
1017 SysRet
1018 open(filename, flags = O_RDONLY, mode = 0666)
1019         char *          filename
1020         int             flags
1021         Mode_t          mode
1022     CODE:
1023         if (flags & (O_APPEND|O_CREAT|O_TRUNC|O_RDWR|O_WRONLY|O_EXCL))
1024             TAINT_PROPER("open");
1025         RETVAL = open(filename, flags, mode);
1026     OUTPUT:
1027         RETVAL
1028
1029
1030 HV *
1031 localeconv()
1032     CODE:
1033 #ifdef HAS_LOCALECONV
1034         struct lconv *lcbuf;
1035         RETVAL = newHV();
1036         sv_2mortal((SV*)RETVAL);
1037         if ((lcbuf = localeconv())) {
1038             /* the strings */
1039             if (lcbuf->decimal_point && *lcbuf->decimal_point)
1040                 hv_store(RETVAL, "decimal_point", 13,
1041                     newSVpv(lcbuf->decimal_point, 0), 0);
1042             if (lcbuf->thousands_sep && *lcbuf->thousands_sep)
1043                 hv_store(RETVAL, "thousands_sep", 13,
1044                     newSVpv(lcbuf->thousands_sep, 0), 0);
1045 #ifndef NO_LOCALECONV_GROUPING
1046             if (lcbuf->grouping && *lcbuf->grouping)
1047                 hv_store(RETVAL, "grouping", 8,
1048                     newSVpv(lcbuf->grouping, 0), 0);
1049 #endif
1050             if (lcbuf->int_curr_symbol && *lcbuf->int_curr_symbol)
1051                 hv_store(RETVAL, "int_curr_symbol", 15,
1052                     newSVpv(lcbuf->int_curr_symbol, 0), 0);
1053             if (lcbuf->currency_symbol && *lcbuf->currency_symbol)
1054                 hv_store(RETVAL, "currency_symbol", 15,
1055                     newSVpv(lcbuf->currency_symbol, 0), 0);
1056             if (lcbuf->mon_decimal_point && *lcbuf->mon_decimal_point)
1057                 hv_store(RETVAL, "mon_decimal_point", 17,
1058                     newSVpv(lcbuf->mon_decimal_point, 0), 0);
1059 #ifndef NO_LOCALECONV_MON_THOUSANDS_SEP
1060             if (lcbuf->mon_thousands_sep && *lcbuf->mon_thousands_sep)
1061                 hv_store(RETVAL, "mon_thousands_sep", 17,
1062                     newSVpv(lcbuf->mon_thousands_sep, 0), 0);
1063 #endif                    
1064 #ifndef NO_LOCALECONV_MON_GROUPING
1065             if (lcbuf->mon_grouping && *lcbuf->mon_grouping)
1066                 hv_store(RETVAL, "mon_grouping", 12,
1067                     newSVpv(lcbuf->mon_grouping, 0), 0);
1068 #endif
1069             if (lcbuf->positive_sign && *lcbuf->positive_sign)
1070                 hv_store(RETVAL, "positive_sign", 13,
1071                     newSVpv(lcbuf->positive_sign, 0), 0);
1072             if (lcbuf->negative_sign && *lcbuf->negative_sign)
1073                 hv_store(RETVAL, "negative_sign", 13,
1074                     newSVpv(lcbuf->negative_sign, 0), 0);
1075             /* the integers */
1076             if (lcbuf->int_frac_digits != CHAR_MAX)
1077                 hv_store(RETVAL, "int_frac_digits", 15,
1078                     newSViv(lcbuf->int_frac_digits), 0);
1079             if (lcbuf->frac_digits != CHAR_MAX)
1080                 hv_store(RETVAL, "frac_digits", 11,
1081                     newSViv(lcbuf->frac_digits), 0);
1082             if (lcbuf->p_cs_precedes != CHAR_MAX)
1083                 hv_store(RETVAL, "p_cs_precedes", 13,
1084                     newSViv(lcbuf->p_cs_precedes), 0);
1085             if (lcbuf->p_sep_by_space != CHAR_MAX)
1086                 hv_store(RETVAL, "p_sep_by_space", 14,
1087                     newSViv(lcbuf->p_sep_by_space), 0);
1088             if (lcbuf->n_cs_precedes != CHAR_MAX)
1089                 hv_store(RETVAL, "n_cs_precedes", 13,
1090                     newSViv(lcbuf->n_cs_precedes), 0);
1091             if (lcbuf->n_sep_by_space != CHAR_MAX)
1092                 hv_store(RETVAL, "n_sep_by_space", 14,
1093                     newSViv(lcbuf->n_sep_by_space), 0);
1094             if (lcbuf->p_sign_posn != CHAR_MAX)
1095                 hv_store(RETVAL, "p_sign_posn", 11,
1096                     newSViv(lcbuf->p_sign_posn), 0);
1097             if (lcbuf->n_sign_posn != CHAR_MAX)
1098                 hv_store(RETVAL, "n_sign_posn", 11,
1099                     newSViv(lcbuf->n_sign_posn), 0);
1100         }
1101 #else
1102         localeconv(); /* A stub to call not_here(). */
1103 #endif
1104     OUTPUT:
1105         RETVAL
1106
1107 char *
1108 setlocale(category, locale = 0)
1109         int             category
1110         char *          locale
1111     CODE:
1112         RETVAL = setlocale(category, locale);
1113         if (RETVAL) {
1114 #ifdef USE_LOCALE_CTYPE
1115             if (category == LC_CTYPE
1116 #ifdef LC_ALL
1117                 || category == LC_ALL
1118 #endif
1119                 )
1120             {
1121                 char *newctype;
1122 #ifdef LC_ALL
1123                 if (category == LC_ALL)
1124                     newctype = setlocale(LC_CTYPE, NULL);
1125                 else
1126 #endif
1127                     newctype = RETVAL;
1128                 new_ctype(newctype);
1129             }
1130 #endif /* USE_LOCALE_CTYPE */
1131 #ifdef USE_LOCALE_COLLATE
1132             if (category == LC_COLLATE
1133 #ifdef LC_ALL
1134                 || category == LC_ALL
1135 #endif
1136                 )
1137             {
1138                 char *newcoll;
1139 #ifdef LC_ALL
1140                 if (category == LC_ALL)
1141                     newcoll = setlocale(LC_COLLATE, NULL);
1142                 else
1143 #endif
1144                     newcoll = RETVAL;
1145                 new_collate(newcoll);
1146             }
1147 #endif /* USE_LOCALE_COLLATE */
1148 #ifdef USE_LOCALE_NUMERIC
1149             if (category == LC_NUMERIC
1150 #ifdef LC_ALL
1151                 || category == LC_ALL
1152 #endif
1153                 )
1154             {
1155                 char *newnum;
1156 #ifdef LC_ALL
1157                 if (category == LC_ALL)
1158                     newnum = setlocale(LC_NUMERIC, NULL);
1159                 else
1160 #endif
1161                     newnum = RETVAL;
1162                 new_numeric(newnum);
1163             }
1164 #endif /* USE_LOCALE_NUMERIC */
1165         }
1166     OUTPUT:
1167         RETVAL
1168
1169
1170 NV
1171 acos(x)
1172         NV              x
1173
1174 NV
1175 asin(x)
1176         NV              x
1177
1178 NV
1179 atan(x)
1180         NV              x
1181
1182 NV
1183 ceil(x)
1184         NV              x
1185
1186 NV
1187 cosh(x)
1188         NV              x
1189
1190 NV
1191 floor(x)
1192         NV              x
1193
1194 NV
1195 fmod(x,y)
1196         NV              x
1197         NV              y
1198
1199 void
1200 frexp(x)
1201         NV              x
1202     PPCODE:
1203         int expvar;
1204         /* (We already know stack is long enough.) */
1205         PUSHs(sv_2mortal(newSVnv(frexp(x,&expvar))));
1206         PUSHs(sv_2mortal(newSViv(expvar)));
1207
1208 NV
1209 ldexp(x,exp)
1210         NV              x
1211         int             exp
1212
1213 NV
1214 log10(x)
1215         NV              x
1216
1217 void
1218 modf(x)
1219         NV              x
1220     PPCODE:
1221         NV intvar;
1222         /* (We already know stack is long enough.) */
1223         PUSHs(sv_2mortal(newSVnv(Perl_modf(x,&intvar))));
1224         PUSHs(sv_2mortal(newSVnv(intvar)));
1225
1226 NV
1227 sinh(x)
1228         NV              x
1229
1230 NV
1231 tan(x)
1232         NV              x
1233
1234 NV
1235 tanh(x)
1236         NV              x
1237
1238 SysRet
1239 sigaction(sig, optaction, oldaction = 0)
1240         int                     sig
1241         SV *                    optaction
1242         POSIX::SigAction        oldaction
1243     CODE:
1244 #if defined(WIN32) || defined(NETWARE)
1245         RETVAL = not_here("sigaction");
1246 #else
1247 # This code is really grody because we're trying to make the signal
1248 # interface look beautiful, which is hard.
1249
1250         {
1251             POSIX__SigAction action;
1252             GV *siggv = gv_fetchpv("SIG", TRUE, SVt_PVHV);
1253             struct sigaction act;
1254             struct sigaction oact;
1255             sigset_t sset;
1256             SV *osset_sv;
1257             sigset_t osset;
1258             POSIX__SigSet sigset;
1259             SV** svp;
1260             SV** sigsvp;
1261             if (sig == 0 && SvPOK(ST(0))) {
1262                 char *s = SvPVX(ST(0));
1263                 int i = whichsig(s);
1264
1265                 if (i < 0 && memEQ(s, "SIG", 3))
1266                     i = whichsig(s + 3);
1267                 if (i < 0) {
1268                     if (ckWARN(WARN_SIGNAL))
1269                         Perl_warner(aTHX_ packWARN(WARN_SIGNAL),
1270                                     "No such signal: SIG%s", s);
1271                     XSRETURN_UNDEF;
1272                 }
1273                 else
1274                     sig = i;
1275             }
1276             sigsvp = hv_fetch(GvHVn(siggv),
1277                               PL_sig_name[sig],
1278                               strlen(PL_sig_name[sig]),
1279                               TRUE);
1280
1281             /* Check optaction and set action */
1282             if(SvTRUE(optaction)) {
1283                 if(sv_isa(optaction, "POSIX::SigAction"))
1284                         action = (HV*)SvRV(optaction);
1285                 else
1286                         croak("action is not of type POSIX::SigAction");
1287             }
1288             else {
1289                 action=0;
1290             }
1291
1292             /* sigaction() is supposed to look atomic. In particular, any
1293              * signal handler invoked during a sigaction() call should
1294              * see either the old or the new disposition, and not something
1295              * in between. We use sigprocmask() to make it so.
1296              */
1297             sigfillset(&sset);
1298             RETVAL=sigprocmask(SIG_BLOCK, &sset, &osset);
1299             if(RETVAL == -1)
1300                XSRETURN_UNDEF;
1301             ENTER;
1302             /* Restore signal mask no matter how we exit this block. */
1303             osset_sv = newSVpv((char *)(&osset), sizeof(sigset_t));
1304             SAVEFREESV( osset_sv );
1305             SAVEDESTRUCTOR_X(restore_sigmask, osset_sv);
1306
1307             RETVAL=-1; /* In case both oldaction and action are 0. */
1308
1309             /* Remember old disposition if desired. */
1310             if (oldaction) {
1311                 svp = hv_fetch(oldaction, "HANDLER", 7, TRUE);
1312                 if(!svp)
1313                     croak("Can't supply an oldaction without a HANDLER");
1314                 if(SvTRUE(*sigsvp)) { /* TBD: what if "0"? */
1315                         sv_setsv(*svp, *sigsvp);
1316                 }
1317                 else {
1318                         sv_setpv(*svp, "DEFAULT");
1319                 }
1320                 RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
1321                 if(RETVAL == -1)
1322                    XSRETURN_UNDEF;
1323                 /* Get back the mask. */
1324                 svp = hv_fetch(oldaction, "MASK", 4, TRUE);
1325                 if (sv_isa(*svp, "POSIX::SigSet")) {
1326                     IV tmp = SvIV((SV*)SvRV(*svp));
1327                     sigset = INT2PTR(sigset_t*, tmp);
1328                 }
1329                 else {
1330                     New(0, sigset, 1, sigset_t);
1331                     sv_setptrobj(*svp, sigset, "POSIX::SigSet");
1332                 }
1333                 *sigset = oact.sa_mask;
1334
1335                 /* Get back the flags. */
1336                 svp = hv_fetch(oldaction, "FLAGS", 5, TRUE);
1337                 sv_setiv(*svp, oact.sa_flags);
1338
1339                 /* Get back whether the old handler used safe signals. */
1340                 svp = hv_fetch(oldaction, "SAFE", 4, TRUE);
1341                 sv_setiv(*svp, oact.sa_handler == PL_csighandlerp);
1342             }
1343
1344             if (action) {
1345                 /* Safe signals use "csighandler", which vectors through the
1346                    PL_sighandlerp pointer when it's safe to do so.
1347                    (BTW, "csighandler" is very different from "sighandler".) */
1348                 svp = hv_fetch(action, "SAFE", 4, FALSE);
1349                 act.sa_handler = (*svp && SvTRUE(*svp))
1350                                  ? PL_csighandlerp : PL_sighandlerp;
1351
1352                 /* Vector new Perl handler through %SIG.
1353                    (The core signal handlers read %SIG to dispatch.) */
1354                 svp = hv_fetch(action, "HANDLER", 7, FALSE);
1355                 if (!svp)
1356                     croak("Can't supply an action without a HANDLER");
1357                 sv_setsv(*sigsvp, *svp);
1358
1359                 /* This call actually calls sigaction() with almost the
1360                    right settings, including appropriate interpretation
1361                    of DEFAULT and IGNORE.  However, why are we doing
1362                    this when we're about to do it again just below?  XXX */
1363                 mg_set(*sigsvp);
1364
1365                 /* And here again we duplicate -- DEFAULT/IGNORE checking. */
1366                 if(SvPOK(*svp)) {
1367                         char *s=SvPVX(*svp);
1368                         if(strEQ(s,"IGNORE")) {
1369                                 act.sa_handler = SIG_IGN;
1370                         }
1371                         else if(strEQ(s,"DEFAULT")) {
1372                                 act.sa_handler = SIG_DFL;
1373                         }
1374                 }
1375
1376                 /* Set up any desired mask. */
1377                 svp = hv_fetch(action, "MASK", 4, FALSE);
1378                 if (svp && sv_isa(*svp, "POSIX::SigSet")) {
1379                     IV tmp = SvIV((SV*)SvRV(*svp));
1380                     sigset = INT2PTR(sigset_t*, tmp);
1381                     act.sa_mask = *sigset;
1382                 }
1383                 else
1384                     sigemptyset(& act.sa_mask);
1385
1386                 /* Set up any desired flags. */
1387                 svp = hv_fetch(action, "FLAGS", 5, FALSE);
1388                 act.sa_flags = svp ? SvIV(*svp) : 0;
1389
1390                 /* Don't worry about cleaning up *sigsvp if this fails,
1391                  * because that means we tried to disposition a
1392                  * nonblockable signal, in which case *sigsvp is
1393                  * essentially meaningless anyway.
1394                  */
1395                 RETVAL = sigaction(sig, & act, (struct sigaction *)0);
1396                if(RETVAL == -1)
1397                    XSRETURN_UNDEF;
1398             }
1399
1400             LEAVE;
1401         }
1402 #endif
1403     OUTPUT:
1404         RETVAL
1405
1406 SysRet
1407 sigpending(sigset)
1408         POSIX::SigSet           sigset
1409
1410 SysRet
1411 sigprocmask(how, sigset, oldsigset = 0)
1412         int                     how
1413         POSIX::SigSet           sigset = NO_INIT
1414         POSIX::SigSet           oldsigset = NO_INIT
1415 INIT:
1416         if (! SvOK(ST(1))) {
1417             sigset = NULL;
1418         } else if (sv_isa(ST(1), "POSIX::SigSet")) {
1419             IV tmp = SvIV((SV*)SvRV(ST(1)));
1420             sigset = INT2PTR(POSIX__SigSet,tmp);
1421         } else {
1422             croak("sigset is not of type POSIX::SigSet");
1423         }
1424
1425         if (items < 3 || ! SvOK(ST(2))) {
1426             oldsigset = NULL;
1427         } else if (sv_isa(ST(2), "POSIX::SigSet")) {
1428             IV tmp = SvIV((SV*)SvRV(ST(2)));
1429             oldsigset = INT2PTR(POSIX__SigSet,tmp);
1430         } else {
1431             croak("oldsigset is not of type POSIX::SigSet");
1432         }
1433
1434 SysRet
1435 sigsuspend(signal_mask)
1436         POSIX::SigSet           signal_mask
1437
1438 void
1439 _exit(status)
1440         int             status
1441
1442 SysRet
1443 close(fd)
1444         int             fd
1445
1446 SysRet
1447 dup(fd)
1448         int             fd
1449
1450 SysRet
1451 dup2(fd1, fd2)
1452         int             fd1
1453         int             fd2
1454
1455 SV *
1456 lseek(fd, offset, whence)
1457         int             fd
1458         Off_t           offset
1459         int             whence
1460     CODE:
1461         Off_t pos = PerlLIO_lseek(fd, offset, whence);
1462         RETVAL = sizeof(Off_t) > sizeof(IV)
1463                  ? newSVnv((NV)pos) : newSViv((IV)pos);
1464     OUTPUT:
1465         RETVAL
1466
1467 void
1468 nice(incr)
1469         int             incr
1470     PPCODE:
1471         errno = 0;
1472         if ((incr = nice(incr)) != -1 || errno == 0) {
1473             if (incr == 0)
1474                 XPUSHs(sv_2mortal(newSVpvn("0 but true", 10)));
1475             else
1476                 XPUSHs(sv_2mortal(newSViv(incr)));
1477         }
1478
1479 void
1480 pipe()
1481     PPCODE:
1482         int fds[2];
1483         if (pipe(fds) != -1) {
1484             EXTEND(SP,2);
1485             PUSHs(sv_2mortal(newSViv(fds[0])));
1486             PUSHs(sv_2mortal(newSViv(fds[1])));
1487         }
1488
1489 SysRet
1490 read(fd, buffer, nbytes)
1491     PREINIT:
1492         SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
1493     INPUT:
1494         int             fd
1495         size_t          nbytes
1496         char *          buffer = sv_grow( sv_buffer, nbytes+1 );
1497     CLEANUP:
1498         if (RETVAL >= 0) {
1499             SvCUR_set(sv_buffer, RETVAL);
1500             SvPOK_only(sv_buffer);
1501             *SvEND(sv_buffer) = '\0';
1502             SvTAINTED_on(sv_buffer);
1503         }
1504
1505 SysRet
1506 setpgid(pid, pgid)
1507         pid_t           pid
1508         pid_t           pgid
1509
1510 pid_t
1511 setsid()
1512
1513 pid_t
1514 tcgetpgrp(fd)
1515         int             fd
1516
1517 SysRet
1518 tcsetpgrp(fd, pgrp_id)
1519         int             fd
1520         pid_t           pgrp_id
1521
1522 void
1523 uname()
1524     PPCODE:
1525 #ifdef HAS_UNAME
1526         struct utsname buf;
1527         if (uname(&buf) >= 0) {
1528             EXTEND(SP, 5);
1529             PUSHs(sv_2mortal(newSVpv(buf.sysname, 0)));
1530             PUSHs(sv_2mortal(newSVpv(buf.nodename, 0)));
1531             PUSHs(sv_2mortal(newSVpv(buf.release, 0)));
1532             PUSHs(sv_2mortal(newSVpv(buf.version, 0)));
1533             PUSHs(sv_2mortal(newSVpv(buf.machine, 0)));
1534         }
1535 #else
1536         uname((char *) 0); /* A stub to call not_here(). */
1537 #endif
1538
1539 SysRet
1540 write(fd, buffer, nbytes)
1541         int             fd
1542         char *          buffer
1543         size_t          nbytes
1544
1545 SV *
1546 tmpnam()
1547     PREINIT:
1548         STRLEN i;
1549         int len;
1550     CODE:
1551         RETVAL = newSVpvn("", 0);
1552         SvGROW(RETVAL, L_tmpnam);
1553         len = strlen(tmpnam(SvPV(RETVAL, i)));
1554         SvCUR_set(RETVAL, len);
1555     OUTPUT:
1556         RETVAL
1557
1558 void
1559 abort()
1560
1561 int
1562 mblen(s, n)
1563         char *          s
1564         size_t          n
1565
1566 size_t
1567 mbstowcs(s, pwcs, n)
1568         wchar_t *       s
1569         char *          pwcs
1570         size_t          n
1571
1572 int
1573 mbtowc(pwc, s, n)
1574         wchar_t *       pwc
1575         char *          s
1576         size_t          n
1577
1578 int
1579 wcstombs(s, pwcs, n)
1580         char *          s
1581         wchar_t *       pwcs
1582         size_t          n
1583
1584 int
1585 wctomb(s, wchar)
1586         char *          s
1587         wchar_t         wchar
1588
1589 int
1590 strcoll(s1, s2)
1591         char *          s1
1592         char *          s2
1593
1594 void
1595 strtod(str)
1596         char *          str
1597     PREINIT:
1598         double num;
1599         char *unparsed;
1600     PPCODE:
1601         SET_NUMERIC_LOCAL();
1602         num = strtod(str, &unparsed);
1603         PUSHs(sv_2mortal(newSVnv(num)));
1604         if (GIMME == G_ARRAY) {
1605             EXTEND(SP, 1);
1606             if (unparsed)
1607                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1608             else
1609                 PUSHs(&PL_sv_undef);
1610         }
1611
1612 void
1613 strtol(str, base = 0)
1614         char *          str
1615         int             base
1616     PREINIT:
1617         long num;
1618         char *unparsed;
1619     PPCODE:
1620         num = strtol(str, &unparsed, base);
1621 #if IVSIZE <= LONGSIZE
1622         if (num < IV_MIN || num > IV_MAX)
1623             PUSHs(sv_2mortal(newSVnv((double)num)));
1624         else
1625 #endif
1626             PUSHs(sv_2mortal(newSViv((IV)num)));
1627         if (GIMME == G_ARRAY) {
1628             EXTEND(SP, 1);
1629             if (unparsed)
1630                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1631             else
1632                 PUSHs(&PL_sv_undef);
1633         }
1634
1635 void
1636 strtoul(str, base = 0)
1637         char *          str
1638         int             base
1639     PREINIT:
1640         unsigned long num;
1641         char *unparsed;
1642     PPCODE:
1643         num = strtoul(str, &unparsed, base);
1644 #if IVSIZE <= LONGSIZE
1645         if (num > IV_MAX)
1646             PUSHs(sv_2mortal(newSVnv((double)num)));
1647         else
1648 #endif
1649             PUSHs(sv_2mortal(newSViv((IV)num)));
1650         if (GIMME == G_ARRAY) {
1651             EXTEND(SP, 1);
1652             if (unparsed)
1653                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1654             else
1655                 PUSHs(&PL_sv_undef);
1656         }
1657
1658 void
1659 strxfrm(src)
1660         SV *            src
1661     CODE:
1662         {
1663           STRLEN srclen;
1664           STRLEN dstlen;
1665           char *p = SvPV(src,srclen);
1666           srclen++;
1667           ST(0) = sv_2mortal(NEWSV(800,srclen*4+1));
1668           dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)srclen);
1669           if (dstlen > srclen) {
1670               dstlen++;
1671               SvGROW(ST(0), dstlen);
1672               strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
1673               dstlen--;
1674           }
1675           SvCUR_set(ST(0), dstlen);
1676             SvPOK_only(ST(0));
1677         }
1678
1679 SysRet
1680 mkfifo(filename, mode)
1681         char *          filename
1682         Mode_t          mode
1683     CODE:
1684         TAINT_PROPER("mkfifo");
1685         RETVAL = mkfifo(filename, mode);
1686     OUTPUT:
1687         RETVAL
1688
1689 SysRet
1690 tcdrain(fd)
1691         int             fd
1692
1693
1694 SysRet
1695 tcflow(fd, action)
1696         int             fd
1697         int             action
1698
1699
1700 SysRet
1701 tcflush(fd, queue_selector)
1702         int             fd
1703         int             queue_selector
1704
1705 SysRet
1706 tcsendbreak(fd, duration)
1707         int             fd
1708         int             duration
1709
1710 char *
1711 asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
1712         int             sec
1713         int             min
1714         int             hour
1715         int             mday
1716         int             mon
1717         int             year
1718         int             wday
1719         int             yday
1720         int             isdst
1721     CODE:
1722         {
1723             struct tm mytm;
1724             init_tm(&mytm);     /* XXX workaround - see init_tm() above */
1725             mytm.tm_sec = sec;
1726             mytm.tm_min = min;
1727             mytm.tm_hour = hour;
1728             mytm.tm_mday = mday;
1729             mytm.tm_mon = mon;
1730             mytm.tm_year = year;
1731             mytm.tm_wday = wday;
1732             mytm.tm_yday = yday;
1733             mytm.tm_isdst = isdst;
1734             RETVAL = asctime(&mytm);
1735         }
1736     OUTPUT:
1737         RETVAL
1738
1739 long
1740 clock()
1741
1742 char *
1743 ctime(time)
1744         Time_t          &time
1745
1746 void
1747 times()
1748         PPCODE:
1749         struct tms tms;
1750         clock_t realtime;
1751         realtime = times( &tms );
1752         EXTEND(SP,5);
1753         PUSHs( sv_2mortal( newSViv( (IV) realtime ) ) );
1754         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_utime ) ) );
1755         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_stime ) ) );
1756         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cutime ) ) );
1757         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cstime ) ) );
1758
1759 double
1760 difftime(time1, time2)
1761         Time_t          time1
1762         Time_t          time2
1763
1764 SysRetLong
1765 mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
1766         int             sec
1767         int             min
1768         int             hour
1769         int             mday
1770         int             mon
1771         int             year
1772         int             wday
1773         int             yday
1774         int             isdst
1775     CODE:
1776         {
1777             struct tm mytm;
1778             init_tm(&mytm);     /* XXX workaround - see init_tm() above */
1779             mytm.tm_sec = sec;
1780             mytm.tm_min = min;
1781             mytm.tm_hour = hour;
1782             mytm.tm_mday = mday;
1783             mytm.tm_mon = mon;
1784             mytm.tm_year = year;
1785             mytm.tm_wday = wday;
1786             mytm.tm_yday = yday;
1787             mytm.tm_isdst = isdst;
1788             RETVAL = mktime(&mytm);
1789         }
1790     OUTPUT:
1791         RETVAL
1792
1793 #XXX: if $xsubpp::WantOptimize is always the default
1794 #     sv_setpv(TARG, ...) could be used rather than
1795 #     ST(0) = sv_2mortal(newSVpv(...))
1796 void
1797 strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
1798         char *          fmt
1799         int             sec
1800         int             min
1801         int             hour
1802         int             mday
1803         int             mon
1804         int             year
1805         int             wday
1806         int             yday
1807         int             isdst
1808     CODE:
1809         {
1810             char *buf = my_strftime(fmt, sec, min, hour, mday, mon, year, wday, yday, isdst);
1811             if (buf) {
1812                 ST(0) = sv_2mortal(newSVpv(buf, 0));
1813                 Safefree(buf);
1814             }
1815         }
1816
1817 void
1818 tzset()
1819
1820 void
1821 tzname()
1822     PPCODE:
1823         EXTEND(SP,2);
1824         PUSHs(sv_2mortal(newSVpvn(tzname[0],strlen(tzname[0]))));
1825         PUSHs(sv_2mortal(newSVpvn(tzname[1],strlen(tzname[1]))));
1826
1827 SysRet
1828 access(filename, mode)
1829         char *          filename
1830         Mode_t          mode
1831
1832 char *
1833 ctermid(s = 0)
1834         char *          s = 0;
1835     CODE:
1836 #ifdef HAS_CTERMID_R
1837         s = safemalloc((size_t) L_ctermid);
1838 #endif
1839         RETVAL = ctermid(s);
1840     OUTPUT:
1841         RETVAL
1842     CLEANUP:
1843 #ifdef HAS_CTERMID_R
1844         Safefree(s);
1845 #endif
1846
1847 char *
1848 cuserid(s = 0)
1849         char *          s = 0;
1850
1851 SysRetLong
1852 fpathconf(fd, name)
1853         int             fd
1854         int             name
1855
1856 SysRetLong
1857 pathconf(filename, name)
1858         char *          filename
1859         int             name
1860
1861 SysRet
1862 pause()
1863
1864 SysRet
1865 setgid(gid)
1866         Gid_t           gid
1867     CLEANUP:
1868 #ifndef WIN32
1869         if (RETVAL >= 0) {
1870             PL_gid  = getgid();
1871             PL_egid = getegid();
1872         }
1873 #endif
1874
1875 SysRet
1876 setuid(uid)
1877         Uid_t           uid
1878     CLEANUP:
1879 #ifndef WIN32
1880         if (RETVAL >= 0) {
1881             PL_uid  = getuid();
1882             PL_euid = geteuid();
1883         }
1884 #endif
1885
1886 SysRetLong
1887 sysconf(name)
1888         int             name
1889
1890 char *
1891 ttyname(fd)
1892         int             fd
1893
1894 void
1895 getcwd()
1896     PPCODE:
1897       {
1898         dXSTARG;
1899         getcwd_sv(TARG);
1900         XSprePUSH; PUSHTARG;
1901       }
1902
1903 SysRet
1904 lchown(uid, gid, path)
1905        Uid_t           uid
1906        Gid_t           gid
1907        char *          path
1908     CODE:
1909 #ifdef HAS_LCHOWN
1910        /* yes, the order of arguments is different,
1911         * but consistent with CORE::chown() */
1912        RETVAL = lchown(path, uid, gid);
1913 #else
1914        RETVAL = not_here("lchown");
1915 #endif
1916     OUTPUT:
1917        RETVAL