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