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