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