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