Fix based on:
[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 SysRetLong
1378 lseek(fd, offset, whence)
1379         int             fd
1380         Off_t           offset
1381         int             whence
1382
1383 SysRet
1384 nice(incr)
1385         int             incr
1386
1387 void
1388 pipe()
1389     PPCODE:
1390         int fds[2];
1391         if (pipe(fds) != -1) {
1392             EXTEND(SP,2);
1393             PUSHs(sv_2mortal(newSViv(fds[0])));
1394             PUSHs(sv_2mortal(newSViv(fds[1])));
1395         }
1396
1397 SysRet
1398 read(fd, buffer, nbytes)
1399     PREINIT:
1400         SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
1401     INPUT:
1402         int             fd
1403         size_t          nbytes
1404         char *          buffer = sv_grow( sv_buffer, nbytes+1 );
1405     CLEANUP:
1406         if (RETVAL >= 0) {
1407             SvCUR(sv_buffer) = RETVAL;
1408             SvPOK_only(sv_buffer);
1409             *SvEND(sv_buffer) = '\0';
1410             SvTAINTED_on(sv_buffer);
1411         }
1412
1413 SysRet
1414 setpgid(pid, pgid)
1415         pid_t           pid
1416         pid_t           pgid
1417
1418 pid_t
1419 setsid()
1420
1421 pid_t
1422 tcgetpgrp(fd)
1423         int             fd
1424
1425 SysRet
1426 tcsetpgrp(fd, pgrp_id)
1427         int             fd
1428         pid_t           pgrp_id
1429
1430 void
1431 uname()
1432     PPCODE:
1433 #ifdef HAS_UNAME
1434         struct utsname buf;
1435         if (uname(&buf) >= 0) {
1436             EXTEND(SP, 5);
1437             PUSHs(sv_2mortal(newSVpv(buf.sysname, 0)));
1438             PUSHs(sv_2mortal(newSVpv(buf.nodename, 0)));
1439             PUSHs(sv_2mortal(newSVpv(buf.release, 0)));
1440             PUSHs(sv_2mortal(newSVpv(buf.version, 0)));
1441             PUSHs(sv_2mortal(newSVpv(buf.machine, 0)));
1442         }
1443 #else
1444         uname((char *) 0); /* A stub to call not_here(). */
1445 #endif
1446
1447 SysRet
1448 write(fd, buffer, nbytes)
1449         int             fd
1450         char *          buffer
1451         size_t          nbytes
1452
1453 SV *
1454 tmpnam()
1455     PREINIT:
1456         STRLEN i;
1457         int len;
1458     CODE:
1459         RETVAL = newSVpvn("", 0);
1460         SvGROW(RETVAL, L_tmpnam);
1461         len = strlen(tmpnam(SvPV(RETVAL, i)));
1462         SvCUR_set(RETVAL, len);
1463     OUTPUT:
1464         RETVAL
1465
1466 void
1467 abort()
1468
1469 int
1470 mblen(s, n)
1471         char *          s
1472         size_t          n
1473
1474 size_t
1475 mbstowcs(s, pwcs, n)
1476         wchar_t *       s
1477         char *          pwcs
1478         size_t          n
1479
1480 int
1481 mbtowc(pwc, s, n)
1482         wchar_t *       pwc
1483         char *          s
1484         size_t          n
1485
1486 int
1487 wcstombs(s, pwcs, n)
1488         char *          s
1489         wchar_t *       pwcs
1490         size_t          n
1491
1492 int
1493 wctomb(s, wchar)
1494         char *          s
1495         wchar_t         wchar
1496
1497 int
1498 strcoll(s1, s2)
1499         char *          s1
1500         char *          s2
1501
1502 void
1503 strtod(str)
1504         char *          str
1505     PREINIT:
1506         double num;
1507         char *unparsed;
1508     PPCODE:
1509         SET_NUMERIC_LOCAL();
1510         num = strtod(str, &unparsed);
1511         PUSHs(sv_2mortal(newSVnv(num)));
1512         if (GIMME == G_ARRAY) {
1513             EXTEND(SP, 1);
1514             if (unparsed)
1515                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1516             else
1517                 PUSHs(&PL_sv_undef);
1518         }
1519
1520 void
1521 strtol(str, base = 0)
1522         char *          str
1523         int             base
1524     PREINIT:
1525         long num;
1526         char *unparsed;
1527     PPCODE:
1528         num = strtol(str, &unparsed, base);
1529 #if IVSIZE <= LONGSIZE
1530         if (num < IV_MIN || num > IV_MAX)
1531             PUSHs(sv_2mortal(newSVnv((double)num)));
1532         else
1533 #endif
1534             PUSHs(sv_2mortal(newSViv((IV)num)));
1535         if (GIMME == G_ARRAY) {
1536             EXTEND(SP, 1);
1537             if (unparsed)
1538                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1539             else
1540                 PUSHs(&PL_sv_undef);
1541         }
1542
1543 void
1544 strtoul(str, base = 0)
1545         char *          str
1546         int             base
1547     PREINIT:
1548         unsigned long num;
1549         char *unparsed;
1550     PPCODE:
1551         num = strtoul(str, &unparsed, base);
1552         if (num <= IV_MAX)
1553             PUSHs(sv_2mortal(newSViv((IV)num)));
1554         else
1555             PUSHs(sv_2mortal(newSVnv((double)num)));
1556         if (GIMME == G_ARRAY) {
1557             EXTEND(SP, 1);
1558             if (unparsed)
1559                 PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
1560             else
1561                 PUSHs(&PL_sv_undef);
1562         }
1563
1564 void
1565 strxfrm(src)
1566         SV *            src
1567     CODE:
1568         {
1569           STRLEN srclen;
1570           STRLEN dstlen;
1571           char *p = SvPV(src,srclen);
1572           srclen++;
1573           ST(0) = sv_2mortal(NEWSV(800,srclen*4+1));
1574           dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)srclen);
1575           if (dstlen > srclen) {
1576               dstlen++;
1577               SvGROW(ST(0), dstlen);
1578               strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
1579               dstlen--;
1580           }
1581           SvCUR(ST(0)) = dstlen;
1582             SvPOK_only(ST(0));
1583         }
1584
1585 SysRet
1586 mkfifo(filename, mode)
1587         char *          filename
1588         Mode_t          mode
1589     CODE:
1590         TAINT_PROPER("mkfifo");
1591         RETVAL = mkfifo(filename, mode);
1592     OUTPUT:
1593         RETVAL
1594
1595 SysRet
1596 tcdrain(fd)
1597         int             fd
1598
1599
1600 SysRet
1601 tcflow(fd, action)
1602         int             fd
1603         int             action
1604
1605
1606 SysRet
1607 tcflush(fd, queue_selector)
1608         int             fd
1609         int             queue_selector
1610
1611 SysRet
1612 tcsendbreak(fd, duration)
1613         int             fd
1614         int             duration
1615
1616 char *
1617 asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
1618         int             sec
1619         int             min
1620         int             hour
1621         int             mday
1622         int             mon
1623         int             year
1624         int             wday
1625         int             yday
1626         int             isdst
1627     CODE:
1628         {
1629             struct tm mytm;
1630             init_tm(&mytm);     /* XXX workaround - see init_tm() above */
1631             mytm.tm_sec = sec;
1632             mytm.tm_min = min;
1633             mytm.tm_hour = hour;
1634             mytm.tm_mday = mday;
1635             mytm.tm_mon = mon;
1636             mytm.tm_year = year;
1637             mytm.tm_wday = wday;
1638             mytm.tm_yday = yday;
1639             mytm.tm_isdst = isdst;
1640             RETVAL = asctime(&mytm);
1641         }
1642     OUTPUT:
1643         RETVAL
1644
1645 long
1646 clock()
1647
1648 char *
1649 ctime(time)
1650         Time_t          &time
1651
1652 void
1653 times()
1654         PPCODE:
1655         struct tms tms;
1656         clock_t realtime;
1657         realtime = times( &tms );
1658         EXTEND(SP,5);
1659         PUSHs( sv_2mortal( newSViv( (IV) realtime ) ) );
1660         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_utime ) ) );
1661         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_stime ) ) );
1662         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cutime ) ) );
1663         PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cstime ) ) );
1664
1665 double
1666 difftime(time1, time2)
1667         Time_t          time1
1668         Time_t          time2
1669
1670 SysRetLong
1671 mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
1672         int             sec
1673         int             min
1674         int             hour
1675         int             mday
1676         int             mon
1677         int             year
1678         int             wday
1679         int             yday
1680         int             isdst
1681     CODE:
1682         {
1683             struct tm mytm;
1684             init_tm(&mytm);     /* XXX workaround - see init_tm() above */
1685             mytm.tm_sec = sec;
1686             mytm.tm_min = min;
1687             mytm.tm_hour = hour;
1688             mytm.tm_mday = mday;
1689             mytm.tm_mon = mon;
1690             mytm.tm_year = year;
1691             mytm.tm_wday = wday;
1692             mytm.tm_yday = yday;
1693             mytm.tm_isdst = isdst;
1694             RETVAL = mktime(&mytm);
1695         }
1696     OUTPUT:
1697         RETVAL
1698
1699 #XXX: if $xsubpp::WantOptimize is always the default
1700 #     sv_setpv(TARG, ...) could be used rather than
1701 #     ST(0) = sv_2mortal(newSVpv(...))
1702 void
1703 strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
1704         char *          fmt
1705         int             sec
1706         int             min
1707         int             hour
1708         int             mday
1709         int             mon
1710         int             year
1711         int             wday
1712         int             yday
1713         int             isdst
1714     CODE:
1715         {
1716             char *buf = my_strftime(fmt, sec, min, hour, mday, mon, year, wday, yday, isdst);
1717             if (buf) {
1718                 ST(0) = sv_2mortal(newSVpv(buf, 0));
1719                 Safefree(buf);
1720             }
1721         }
1722
1723 void
1724 tzset()
1725
1726 void
1727 tzname()
1728     PPCODE:
1729         EXTEND(SP,2);
1730         PUSHs(sv_2mortal(newSVpvn(tzname[0],strlen(tzname[0]))));
1731         PUSHs(sv_2mortal(newSVpvn(tzname[1],strlen(tzname[1]))));
1732
1733 SysRet
1734 access(filename, mode)
1735         char *          filename
1736         Mode_t          mode
1737
1738 char *
1739 ctermid(s = 0)
1740         char *          s = 0;
1741
1742 char *
1743 cuserid(s = 0)
1744         char *          s = 0;
1745
1746 SysRetLong
1747 fpathconf(fd, name)
1748         int             fd
1749         int             name
1750
1751 SysRetLong
1752 pathconf(filename, name)
1753         char *          filename
1754         int             name
1755
1756 SysRet
1757 pause()
1758
1759 SysRet
1760 setgid(gid)
1761         Gid_t           gid
1762
1763 SysRet
1764 setuid(uid)
1765         Uid_t           uid
1766
1767 SysRetLong
1768 sysconf(name)
1769         int             name
1770
1771 char *
1772 ttyname(fd)
1773         int             fd
1774
1775 void
1776 getcwd()
1777     PPCODE:
1778       {
1779         dXSTARG;
1780         getcwd_sv(TARG);
1781         XSprePUSH; PUSHTARG;
1782       }
1783