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