Oops in change #19809.
[p5sagit/p5-mst-13.2.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             RETVAL=sigprocmask(SIG_BLOCK, &sset, &osset);
1254             if(RETVAL == -1)
1255                XSRETURN_UNDEF;
1256             ENTER;
1257             /* Restore signal mask no matter how we exit this block. */
1258             osset_sv = newSVpv((char *)(&osset), sizeof(sigset_t));
1259             SAVEFREESV( osset_sv );
1260             SAVEDESTRUCTOR_X(restore_sigmask, osset_sv);
1261
1262             RETVAL=-1; /* In case both oldaction and action are 0. */
1263
1264             /* Remember old disposition if desired. */
1265             if (oldaction) {
1266                 svp = hv_fetch(oldaction, "HANDLER", 7, TRUE);
1267                 if(!svp)
1268                     croak("Can't supply an oldaction without a HANDLER");
1269                 if(SvTRUE(*sigsvp)) { /* TBD: what if "0"? */
1270                         sv_setsv(*svp, *sigsvp);
1271                 }
1272                 else {
1273                         sv_setpv(*svp, "DEFAULT");
1274                 }
1275                 RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
1276                 if(RETVAL == -1)
1277                    XSRETURN_UNDEF;
1278                 /* Get back the mask. */
1279                 svp = hv_fetch(oldaction, "MASK", 4, TRUE);
1280                 if (sv_isa(*svp, "POSIX::SigSet")) {
1281                     IV tmp = SvIV((SV*)SvRV(*svp));
1282                     sigset = INT2PTR(sigset_t*, tmp);
1283                 }
1284                 else {
1285                     New(0, sigset, 1, sigset_t);
1286                     sv_setptrobj(*svp, sigset, "POSIX::SigSet");
1287                 }
1288                 *sigset = oact.sa_mask;
1289
1290                 /* Get back the flags. */
1291                 svp = hv_fetch(oldaction, "FLAGS", 5, TRUE);
1292                 sv_setiv(*svp, oact.sa_flags);
1293             }
1294
1295             if (action) {
1296                 /* Vector new handler through %SIG.  (We always use sighandler
1297                    for the C signal handler, which reads %SIG to dispatch.) */
1298                 svp = hv_fetch(action, "HANDLER", 7, FALSE);
1299                 if (!svp)
1300                     croak("Can't supply an action without a HANDLER");
1301                 sv_setsv(*sigsvp, *svp);
1302                 mg_set(*sigsvp);        /* handles DEFAULT and IGNORE */
1303                 if(SvPOK(*svp)) {
1304                         char *s=SvPVX(*svp);
1305                         if(strEQ(s,"IGNORE")) {
1306                                 act.sa_handler = SIG_IGN;
1307                         }
1308                         else if(strEQ(s,"DEFAULT")) {
1309                                 act.sa_handler = SIG_DFL;
1310                         }
1311                         else {
1312                                 act.sa_handler = PL_sighandlerp;
1313                         }
1314                 }
1315                 else {
1316                         act.sa_handler = PL_sighandlerp;
1317                 }
1318
1319                 /* Set up any desired mask. */
1320                 svp = hv_fetch(action, "MASK", 4, FALSE);
1321                 if (svp && sv_isa(*svp, "POSIX::SigSet")) {
1322                     IV tmp = SvIV((SV*)SvRV(*svp));
1323                     sigset = INT2PTR(sigset_t*, tmp);
1324                     act.sa_mask = *sigset;
1325                 }
1326                 else
1327                     sigemptyset(& act.sa_mask);
1328
1329                 /* Set up any desired flags. */
1330                 svp = hv_fetch(action, "FLAGS", 5, FALSE);
1331                 act.sa_flags = svp ? SvIV(*svp) : 0;
1332
1333                 /* Don't worry about cleaning up *sigsvp if this fails,
1334                  * because that means we tried to disposition a
1335                  * nonblockable signal, in which case *sigsvp is
1336                  * essentially meaningless anyway.
1337                  */
1338                 RETVAL = sigaction(sig, & act, (struct sigaction *)0);
1339                if(RETVAL == -1)
1340                    XSRETURN_UNDEF;
1341             }
1342
1343             LEAVE;
1344         }
1345 #endif
1346     OUTPUT:
1347         RETVAL
1348
1349 SysRet
1350 sigpending(sigset)
1351         POSIX::SigSet           sigset
1352
1353 SysRet
1354 sigprocmask(how, sigset, oldsigset = 0)
1355         int                     how
1356         POSIX::SigSet           sigset
1357         POSIX::SigSet           oldsigset = NO_INIT
1358 INIT:
1359         if ( items < 3 ) {
1360             oldsigset = 0;
1361         }
1362         else if (sv_derived_from(ST(2), "POSIX::SigSet")) {
1363             IV tmp = SvIV((SV*)SvRV(ST(2)));
1364             oldsigset = INT2PTR(POSIX__SigSet,tmp);
1365         }
1366         else {
1367             New(0, oldsigset, 1, sigset_t);
1368             sigemptyset(oldsigset);
1369             sv_setref_pv(ST(2), "POSIX::SigSet", (void*)oldsigset);
1370         }
1371
1372 SysRet
1373 sigsuspend(signal_mask)
1374         POSIX::SigSet           signal_mask
1375
1376 void
1377 _exit(status)
1378         int             status
1379
1380 SysRet
1381 close(fd)
1382         int             fd
1383
1384 SysRet
1385 dup(fd)
1386         int             fd
1387
1388 SysRet
1389 dup2(fd1, fd2)
1390         int             fd1
1391         int             fd2
1392
1393 SV *
1394 lseek(fd, offset, whence)
1395         int             fd
1396         Off_t           offset
1397         int             whence
1398     CODE:
1399         Off_t pos = PerlLIO_lseek(fd, offset, whence);
1400         RETVAL = sizeof(Off_t) > sizeof(IV)
1401                  ? newSVnv((NV)pos) : newSViv((IV)pos);
1402     OUTPUT:
1403         RETVAL
1404
1405 void
1406 nice(incr)
1407         int             incr
1408     PPCODE:
1409         errno = 0;
1410         if ((incr = nice(incr)) != -1 || errno == 0) {
1411             if (incr == 0)
1412                 XPUSHs(sv_2mortal(newSVpvn("0 but true", 10)));
1413             else
1414                 XPUSHs(sv_2mortal(newSViv(incr)));
1415         }
1416
1417 void
1418 pipe()
1419     PPCODE:
1420         int fds[2];
1421         if (pipe(fds) != -1) {
1422             EXTEND(SP,2);
1423             PUSHs(sv_2mortal(newSViv(fds[0])));
1424             PUSHs(sv_2mortal(newSViv(fds[1])));
1425         }
1426
1427 SysRet
1428 read(fd, buffer, nbytes)
1429     PREINIT:
1430         SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
1431     INPUT:
1432         int             fd
1433         size_t          nbytes
1434         char *          buffer = sv_grow( sv_buffer, nbytes+1 );
1435     CLEANUP:
1436         if (RETVAL >= 0) {
1437             SvCUR(sv_buffer) = RETVAL;
1438             SvPOK_only(sv_buffer);
1439             *SvEND(sv_buffer) = '\0';
1440             SvTAINTED_on(sv_buffer);
1441         }
1442
1443 SysRet
1444 setpgid(pid, pgid)
1445         pid_t           pid
1446         pid_t           pgid
1447
1448 pid_t
1449 setsid()
1450
1451 pid_t
1452 tcgetpgrp(fd)
1453         int             fd
1454
1455 SysRet
1456 tcsetpgrp(fd, pgrp_id)
1457         int             fd
1458         pid_t           pgrp_id
1459
1460 void
1461 uname()
1462     PPCODE:
1463 #ifdef HAS_UNAME
1464         struct utsname buf;
1465         if (uname(&buf) >= 0) {
1466             EXTEND(SP, 5);
1467             PUSHs(sv_2mortal(newSVpv(buf.sysname, 0)));
1468             PUSHs(sv_2mortal(newSVpv(buf.nodename, 0)));
1469             PUSHs(sv_2mortal(newSVpv(buf.release, 0)));
1470             PUSHs(sv_2mortal(newSVpv(buf.version, 0)));
1471             PUSHs(sv_2mortal(newSVpv(buf.machine, 0)));
1472         }
1473 #else
1474         uname((char *) 0); /* A stub to call not_here(). */
1475 #endif
1476
1477 SysRet
1478 write(fd, buffer, nbytes)
1479         int             fd
1480         char *          buffer
1481         size_t          nbytes
1482
1483 SV *
1484 tmpnam()
1485     PREINIT:
1486         STRLEN i;
1487         int len;
1488     CODE:
1489         RETVAL = newSVpvn("", 0);
1490         SvGROW(RETVAL, L_tmpnam);
1491         len = strlen(tmpnam(SvPV(RETVAL, i)));
1492         SvCUR_set(RETVAL, len);
1493     OUTPUT:
1494         RETVAL
1495
1496 void
1497 abort()
1498
1499 int
1500 mblen(s, n)
1501         char *          s
1502         size_t          n
1503
1504 size_t
1505 mbstowcs(s, pwcs, n)
1506         wchar_t *       s
1507         char *          pwcs
1508         size_t          n
1509
1510 int
1511 mbtowc(pwc, s, n)
1512         wchar_t *       pwc
1513         char *          s
1514         size_t          n
1515
1516 int
1517 wcstombs(s, pwcs, n)
1518         char *          s
1519         wchar_t *       pwcs
1520         size_t          n
1521
1522 int
1523 wctomb(s, wchar)
1524         char *          s
1525         wchar_t         wchar
1526
1527 int
1528 strcoll(s1, s2)
1529         char *          s1
1530         char *          s2
1531
1532 void
1533 strtod(str)
1534         char *          str
1535     PREINIT:
1536         double num;
1537         char *unparsed;
1538     PPCODE:
1539         SET_NUMERIC_LOCAL();
1540         num = strtod(str, &unparsed);
1541         PUSHs(sv_2mortal(newSVnv(num)));
1542         if (GIMME == G_ARRAY) {
1543             EXTEND(SP, 1);
1544             if (unparsed)
1545                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1546             else
1547                 PUSHs(&PL_sv_undef);
1548         }
1549
1550 void
1551 strtol(str, base = 0)
1552         char *          str
1553         int             base
1554     PREINIT:
1555         long num;
1556         char *unparsed;
1557     PPCODE:
1558         num = strtol(str, &unparsed, base);
1559 #if IVSIZE <= LONGSIZE
1560         if (num < IV_MIN || num > IV_MAX)
1561             PUSHs(sv_2mortal(newSVnv((double)num)));
1562         else
1563 #endif
1564             PUSHs(sv_2mortal(newSViv((IV)num)));
1565         if (GIMME == G_ARRAY) {
1566             EXTEND(SP, 1);
1567             if (unparsed)
1568                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1569             else
1570                 PUSHs(&PL_sv_undef);
1571         }
1572
1573 void
1574 strtoul(str, base = 0)
1575         char *          str
1576         int             base
1577     PREINIT:
1578         unsigned long num;
1579         char *unparsed;
1580     PPCODE:
1581         num = strtoul(str, &unparsed, base);
1582 #if IVSIZE <= LONGSIZE
1583         if (num > IV_MAX)
1584             PUSHs(sv_2mortal(newSVnv((double)num)));
1585         else
1586 #endif
1587             PUSHs(sv_2mortal(newSViv((IV)num)));
1588         if (GIMME == G_ARRAY) {
1589             EXTEND(SP, 1);
1590             if (unparsed)
1591                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1592             else
1593                 PUSHs(&PL_sv_undef);
1594         }
1595
1596 void
1597 strxfrm(src)
1598         SV *            src
1599     CODE:
1600         {
1601           STRLEN srclen;
1602           STRLEN dstlen;
1603           char *p = SvPV(src,srclen);
1604           srclen++;
1605           ST(0) = sv_2mortal(NEWSV(800,srclen*4+1));
1606           dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)srclen);
1607           if (dstlen > srclen) {
1608               dstlen++;
1609               SvGROW(ST(0), dstlen);
1610               strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
1611               dstlen--;
1612           }
1613           SvCUR(ST(0)) = dstlen;
1614             SvPOK_only(ST(0));
1615         }
1616
1617 SysRet
1618 mkfifo(filename, mode)
1619         char *          filename
1620         Mode_t          mode
1621     CODE:
1622         TAINT_PROPER("mkfifo");
1623         RETVAL = mkfifo(filename, mode);
1624     OUTPUT:
1625         RETVAL
1626
1627 SysRet
1628 tcdrain(fd)
1629         int             fd
1630
1631
1632 SysRet
1633 tcflow(fd, action)
1634         int             fd
1635         int             action
1636
1637
1638 SysRet
1639 tcflush(fd, queue_selector)
1640         int             fd
1641         int             queue_selector
1642
1643 SysRet
1644 tcsendbreak(fd, duration)
1645         int             fd
1646         int             duration
1647
1648 char *
1649 asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
1650         int             sec
1651         int             min
1652         int             hour
1653         int             mday
1654         int             mon
1655         int             year
1656         int             wday
1657         int             yday
1658         int             isdst
1659     CODE:
1660         {
1661             struct tm mytm;
1662             init_tm(&mytm);     /* XXX workaround - see init_tm() above */
1663             mytm.tm_sec = sec;
1664             mytm.tm_min = min;
1665             mytm.tm_hour = hour;
1666             mytm.tm_mday = mday;
1667             mytm.tm_mon = mon;
1668             mytm.tm_year = year;
1669             mytm.tm_wday = wday;
1670             mytm.tm_yday = yday;
1671             mytm.tm_isdst = isdst;
1672             RETVAL = asctime(&mytm);
1673         }
1674     OUTPUT:
1675         RETVAL
1676
1677 long
1678 clock()
1679
1680 char *
1681 ctime(time)
1682         Time_t          &time
1683
1684 void
1685 times()
1686         PPCODE:
1687         struct tms tms;
1688         clock_t realtime;
1689         realtime = times( &tms );
1690         EXTEND(SP,5);
1691         PUSHs( sv_2mortal( newSViv( (IV) realtime ) ) );
1692         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_utime ) ) );
1693         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_stime ) ) );
1694         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cutime ) ) );
1695         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cstime ) ) );
1696
1697 double
1698 difftime(time1, time2)
1699         Time_t          time1
1700         Time_t          time2
1701
1702 SysRetLong
1703 mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
1704         int             sec
1705         int             min
1706         int             hour
1707         int             mday
1708         int             mon
1709         int             year
1710         int             wday
1711         int             yday
1712         int             isdst
1713     CODE:
1714         {
1715             struct tm mytm;
1716             init_tm(&mytm);     /* XXX workaround - see init_tm() above */
1717             mytm.tm_sec = sec;
1718             mytm.tm_min = min;
1719             mytm.tm_hour = hour;
1720             mytm.tm_mday = mday;
1721             mytm.tm_mon = mon;
1722             mytm.tm_year = year;
1723             mytm.tm_wday = wday;
1724             mytm.tm_yday = yday;
1725             mytm.tm_isdst = isdst;
1726             RETVAL = mktime(&mytm);
1727         }
1728     OUTPUT:
1729         RETVAL
1730
1731 #XXX: if $xsubpp::WantOptimize is always the default
1732 #     sv_setpv(TARG, ...) could be used rather than
1733 #     ST(0) = sv_2mortal(newSVpv(...))
1734 void
1735 strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
1736         char *          fmt
1737         int             sec
1738         int             min
1739         int             hour
1740         int             mday
1741         int             mon
1742         int             year
1743         int             wday
1744         int             yday
1745         int             isdst
1746     CODE:
1747         {
1748             char *buf = my_strftime(fmt, sec, min, hour, mday, mon, year, wday, yday, isdst);
1749             if (buf) {
1750                 ST(0) = sv_2mortal(newSVpv(buf, 0));
1751                 Safefree(buf);
1752             }
1753         }
1754
1755 void
1756 tzset()
1757
1758 void
1759 tzname()
1760     PPCODE:
1761         EXTEND(SP,2);
1762         PUSHs(sv_2mortal(newSVpvn(tzname[0],strlen(tzname[0]))));
1763         PUSHs(sv_2mortal(newSVpvn(tzname[1],strlen(tzname[1]))));
1764
1765 SysRet
1766 access(filename, mode)
1767         char *          filename
1768         Mode_t          mode
1769
1770 char *
1771 ctermid(s = 0)
1772         char *          s = 0;
1773
1774 char *
1775 cuserid(s = 0)
1776         char *          s = 0;
1777
1778 SysRetLong
1779 fpathconf(fd, name)
1780         int             fd
1781         int             name
1782
1783 SysRetLong
1784 pathconf(filename, name)
1785         char *          filename
1786         int             name
1787
1788 SysRet
1789 pause()
1790
1791 SysRet
1792 setgid(gid)
1793         Gid_t           gid
1794
1795 SysRet
1796 setuid(uid)
1797         Uid_t           uid
1798
1799 SysRetLong
1800 sysconf(name)
1801         int             name
1802
1803 char *
1804 ttyname(fd)
1805         int             fd
1806
1807 void
1808 getcwd()
1809     PPCODE:
1810       {
1811         dXSTARG;
1812         getcwd_sv(TARG);
1813         XSprePUSH; PUSHTARG;
1814       }
1815