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