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