3 * Copyright (c) 1991-1997, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
11 * "Far below them they saw the white waters pour into a foaming bowl, and
12 * then swirl darkly about a deep oval basin in the rocks, until they found
13 * their way out again through a narrow gate, and flowed away, fuming and
14 * chattering, into calmer and more level reaches."
20 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
30 # ifndef HAS_SHMAT_PROTOTYPE
31 extern Shmat_t shmat _((int, char *, int));
37 # if defined(_MSC_VER) || defined(__MINGW32__)
38 # include <sys/utime.h>
51 # define OPEN_EXCL O_EXCL
56 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
60 /* XXX If this causes problems, set i_unistd=undef in the hint file. */
65 #if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
66 # include <sys/socket.h>
70 # include <net/errno.h>
75 /* Put this after #includes because <unistd.h> defines _XOPEN_*. */
77 # if _XOPEN_VERSION >= 5 || defined(_XOPEN_SOURCE_EXTENDED) || defined(__GLIBC__)
78 # define Sock_size_t Size_t
80 # define Sock_size_t int
85 do_open(GV *gv, register char *name, I32 len, int as_raw, int rawmode, int rawperm, PerlIO *supplied_fp)
87 register IO *io = GvIOn(gv);
88 PerlIO *saveifp = Nullfp;
89 PerlIO *saveofp = Nullfp;
95 bool was_fdopen = FALSE;
97 forkprocess = 1; /* assume true if no fork */
100 fd = PerlIO_fileno(IoIFP(io));
101 if (IoTYPE(io) == '-')
103 else if (fd <= maxsysfd) {
106 savetype = IoTYPE(io);
109 else if (IoTYPE(io) == '|')
110 result = PerlProc_pclose(IoIFP(io));
111 else if (IoIFP(io) != IoOFP(io)) {
113 result = PerlIO_close(IoOFP(io));
114 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
117 result = PerlIO_close(IoIFP(io));
120 result = PerlIO_close(IoIFP(io));
121 if (result == EOF && fd > maxsysfd)
122 PerlIO_printf(PerlIO_stderr(), "Warning: unable to close filehandle %s properly.\n",
124 IoOFP(io) = IoIFP(io) = Nullfp;
128 result = rawmode & 3;
129 IoTYPE(io) = "<>++"[result];
130 writing = (result > 0);
131 fd = PerlLIO_open3(name, rawmode, rawperm);
139 else if (rawmode & O_APPEND)
140 fpmode = (result == 1) ? "a" : "a+";
143 fpmode = (result == 1) ? "w" : "r+";
144 fp = PerlIO_fdopen(fd, fpmode);
151 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
154 myname = savepvn(name, len);
157 while (len && isSPACE(name[len-1]))
160 mode[0] = mode[1] = mode[2] = '\0';
162 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
170 for (name++; isSPACE(*name); name++) ;
173 TAINT_PROPER("piped open");
174 if (dowarn && name[strlen(name)-1] == '|')
175 warn("Can't do bidirectional pipe");
176 fp = PerlProc_popen(name,"w");
179 else if (*name == '>') {
180 TAINT_PROPER("open");
183 mode[0] = IoTYPE(io) = 'a';
198 if (!*name && supplied_fp)
202 for (; isSPACE(*name); name++) ;
207 gv = gv_fetchpv(name,FALSE,SVt_PVIO);
211 SETERRNO(EINVAL,SS$_IVCHAN);
216 fd = PerlIO_fileno(IoIFP(thatio));
217 if (IoTYPE(thatio) == 's')
224 fd = PerlLIO_dup(fd);
227 if (!(fp = PerlIO_fdopen(fd,mode))) {
235 for (; isSPACE(*name); name++) ;
236 if (strEQ(name,"-")) {
237 fp = PerlIO_stdout();
241 fp = PerlIO_open(name,mode);
245 else if (*name == '<') {
247 for (name++; isSPACE(*name); name++) ;
251 if (strEQ(name,"-")) {
256 fp = PerlIO_open(name,mode);
258 else if (name[len-1] == '|') {
260 while (len && isSPACE(name[len-1]))
263 for (; isSPACE(*name); name++) ;
266 TAINT_PROPER("piped open");
267 fp = PerlProc_popen(name,"r");
273 for (; isSPACE(*name); name++) ;
274 if (strEQ(name,"-")) {
279 fp = PerlIO_open(name,"r");
283 if (dowarn && IoTYPE(io) == '<' && strchr(name, '\n'))
284 warn(warn_nl, "open");
288 IoTYPE(io) != '|' && IoTYPE(io) != '-') {
290 if (PerlLIO_fstat(PerlIO_fileno(fp),&statbuf) < 0) {
291 (void)PerlIO_close(fp);
294 if (S_ISSOCK(statbuf.st_mode))
295 IoTYPE(io) = 's'; /* in case a socket was passed in to us */
299 !(statbuf.st_mode & S_IFMT)
305 Sock_size_t buflen = sizeof tmpbuf;
306 if (PerlSock_getsockname(PerlIO_fileno(fp), (struct sockaddr *)tmpbuf,
308 || errno != ENOTSOCK)
309 IoTYPE(io) = 's'; /* some OS's return 0 on fstat()ed socket */
310 /* but some return 0 for streams too, sigh */
314 if (saveifp) { /* must use old fp? */
315 fd = PerlIO_fileno(saveifp);
317 PerlIO_flush(saveofp); /* emulate PerlIO_close() */
318 if (saveofp != saveifp) { /* was a socket? */
319 PerlIO_close(saveofp);
324 if (fd != PerlIO_fileno(fp)) {
328 PerlLIO_dup2(PerlIO_fileno(fp), fd);
329 sv = *av_fetch(fdpid,PerlIO_fileno(fp),TRUE);
330 (void)SvUPGRADE(sv, SVt_IV);
333 sv = *av_fetch(fdpid,fd,TRUE);
334 (void)SvUPGRADE(sv, SVt_IV);
343 #if defined(HAS_FCNTL) && defined(F_SETFD)
344 fd = PerlIO_fileno(fp);
345 fcntl(fd,F_SETFD,fd > maxsysfd);
350 if (IoTYPE(io) == 's'
351 || (IoTYPE(io) == '>' && S_ISCHR(statbuf.st_mode)) ) {
352 if (!(IoOFP(io) = PerlIO_fdopen(PerlIO_fileno(fp),"w"))) {
366 IoTYPE(io) = savetype;
371 nextargv(register GV *gv)
374 #ifndef FLEXFILENAMES
382 argvoutgv = gv_fetchpv("ARGVOUT",TRUE,SVt_PVIO);
383 if (filemode & (S_ISUID|S_ISGID)) {
384 PerlIO_flush(IoIFP(GvIOn(argvoutgv))); /* chmod must follow last write */
386 (void)fchmod(lastfd,filemode);
388 (void)PerlLIO_chmod(oldname,filemode);
392 while (av_len(GvAV(gv)) >= 0) {
395 sv = av_shift(GvAV(gv));
397 sv_setsv(GvSV(gv),sv);
398 SvSETMAGIC(GvSV(gv));
399 oldname = SvPVx(GvSV(gv), oldlen);
400 if (do_open(gv,oldname,oldlen,inplace!=0,0,0,Nullfp)) {
402 TAINT_PROPER("inplace open");
403 if (oldlen == 1 && *oldname == '-') {
404 setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
405 return IoIFP(GvIOp(gv));
407 #ifndef FLEXFILENAMES
408 filedev = statbuf.st_dev;
409 fileino = statbuf.st_ino;
411 filemode = statbuf.st_mode;
412 fileuid = statbuf.st_uid;
413 filegid = statbuf.st_gid;
414 if (!S_ISREG(filemode)) {
415 warn("Can't do inplace edit: %s is not a regular file",
422 add_suffix(sv,inplace);
424 sv_catpv(sv,inplace);
426 #ifndef FLEXFILENAMES
427 if (PerlLIO_stat(SvPVX(sv),&statbuf) >= 0
428 && statbuf.st_dev == filedev
429 && statbuf.st_ino == fileino
431 || (_djstat_fail_bits & _STFAIL_TRUENAME)!=0
434 warn("Can't do inplace edit: %s would not be uniq",
442 if (PerlLIO_rename(oldname,SvPVX(sv)) < 0) {
443 warn("Can't rename %s to %s: %s, skipping file",
444 oldname, SvPVX(sv), Strerror(errno) );
450 (void)PerlLIO_unlink(SvPVX(sv));
451 (void)PerlLIO_rename(oldname,SvPVX(sv));
452 do_open(gv,SvPVX(sv),SvCUR(sv),inplace!=0,0,0,Nullfp);
455 (void)UNLINK(SvPVX(sv));
456 if (link(oldname,SvPVX(sv)) < 0) {
457 warn("Can't rename %s to %s: %s, skipping file",
458 oldname, SvPVX(sv), Strerror(errno) );
462 (void)UNLINK(oldname);
466 #if !defined(DOSISH) && !defined(AMIGAOS)
467 # ifndef VMS /* Don't delete; use automatic file versioning */
468 if (UNLINK(oldname) < 0) {
469 warn("Can't remove %s: %s, skipping file",
470 oldname, Strerror(errno) );
476 croak("Can't do inplace edit without backup");
480 sv_setpvn(sv,">",!inplace);
481 sv_catpvn(sv,oldname,oldlen);
482 SETERRNO(0,0); /* in case sprintf set errno */
483 if (!do_open(argvoutgv,SvPVX(sv),SvCUR(sv),inplace!=0,
484 O_WRONLY|O_CREAT|OPEN_EXCL,0666,Nullfp)) {
485 warn("Can't do inplace edit on %s: %s",
486 oldname, Strerror(errno) );
490 setdefout(argvoutgv);
491 lastfd = PerlIO_fileno(IoIFP(GvIOp(argvoutgv)));
492 (void)PerlLIO_fstat(lastfd,&statbuf);
494 (void)fchmod(lastfd,filemode);
496 # if !(defined(WIN32) && defined(__BORLANDC__))
497 /* Borland runtime creates a readonly file! */
498 (void)PerlLIO_chmod(oldname,filemode);
501 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
503 (void)fchown(lastfd,fileuid,filegid);
506 (void)chown(oldname,fileuid,filegid);
511 return IoIFP(GvIOp(gv));
514 PerlIO_printf(PerlIO_stderr(), "Can't open %s: %s\n",
515 SvPV(sv, na), Strerror(errno));
518 (void)do_close(argvoutgv,FALSE);
519 setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
526 do_pipe(SV *sv, GV *rgv, GV *wgv)
545 if (PerlProc_pipe(fd) < 0)
547 IoIFP(rstio) = PerlIO_fdopen(fd[0], "r");
548 IoOFP(wstio) = PerlIO_fdopen(fd[1], "w");
549 IoIFP(wstio) = IoOFP(wstio);
552 if (!IoIFP(rstio) || !IoOFP(wstio)) {
553 if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio));
554 else PerlLIO_close(fd[0]);
555 if (IoOFP(wstio)) PerlIO_close(IoOFP(wstio));
556 else PerlLIO_close(fd[1]);
560 sv_setsv(sv,&sv_yes);
564 sv_setsv(sv,&sv_undef);
569 /* explicit renamed to avoid C++ conflict -- kja */
571 do_close(GV *gv, bool not_implicit)
578 if (!gv || SvTYPE(gv) != SVt_PVGV) {
579 SETERRNO(EBADF,SS$_IVCHAN);
583 if (!io) { /* never opened */
584 if (dowarn && not_implicit)
585 warn("Close on unopened file <%s>",GvENAME(gv));
588 retval = io_close(io);
592 IoLINES_LEFT(io) = IoPAGE_LEN(io);
605 if (IoTYPE(io) == '|') {
606 status = PerlProc_pclose(IoIFP(io));
607 STATUS_NATIVE_SET(status);
608 retval = (STATUS_POSIX == 0);
610 else if (IoTYPE(io) == '-')
613 if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */
614 retval = (PerlIO_close(IoOFP(io)) != EOF);
615 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
618 retval = (PerlIO_close(IoIFP(io)) != EOF);
620 IoOFP(io) = IoIFP(io) = Nullfp;
640 if (PerlIO_has_cntptr(IoIFP(io))) { /* (the code works without this) */
641 if (PerlIO_get_cnt(IoIFP(io)) > 0) /* cheat a little, since */
642 return FALSE; /* this is the most usual case */
645 ch = PerlIO_getc(IoIFP(io));
647 (void)PerlIO_ungetc(IoIFP(io),ch);
650 if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
651 if (PerlIO_get_cnt(IoIFP(io)) < -1)
652 PerlIO_set_cnt(IoIFP(io),-1);
654 if (op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
655 if (!nextargv(argvgv)) /* get another fp handy */
659 return TRUE; /* normal fp, definitely end of file */
670 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
671 #ifdef ULTRIX_STDIO_BOTCH
673 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
675 return PerlIO_tell(fp);
678 warn("tell() on unopened file");
679 SETERRNO(EBADF,RMS$_IFI);
684 do_seek(GV *gv, long int pos, int whence)
689 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
690 #ifdef ULTRIX_STDIO_BOTCH
692 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
694 return PerlIO_seek(fp, pos, whence) >= 0;
697 warn("seek() on unopened file");
698 SETERRNO(EBADF,RMS$_IFI);
703 do_sysseek(GV *gv, long int pos, int whence)
708 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
709 return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
711 warn("sysseek() on unopened file");
712 SETERRNO(EBADF,RMS$_IFI);
716 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
717 /* code courtesy of William Kucharski */
720 I32 my_chsize(fd, length)
721 I32 fd; /* file descriptor */
722 Off_t length; /* length to set file to */
727 if (PerlLIO_fstat(fd, &filebuf) < 0)
730 if (filebuf.st_size < length) {
732 /* extend file length */
734 if ((PerlLIO_lseek(fd, (length - 1), 0)) < 0)
737 /* write a "0" byte */
739 if ((PerlLIO_write(fd, "", 1)) != 1)
743 /* truncate length */
748 fl.l_type = F_WRLCK; /* write lock on file space */
751 * This relies on the UNDOCUMENTED F_FREESP argument to
752 * fcntl(2), which truncates the file so that it ends at the
753 * position indicated by fl.l_start.
755 * Will minor miracles never cease?
758 if (fcntl(fd, F_FREESP, &fl) < 0)
765 #endif /* F_FREESP */
768 do_print(register SV *sv, PerlIO *fp)
773 /* assuming fp is checked earlier */
779 if (SvIOK(sv) && SvIVX(sv) != 0) {
780 PerlIO_printf(fp, ofmt, (double)SvIVX(sv));
781 return !PerlIO_error(fp);
783 if ( (SvNOK(sv) && SvNVX(sv) != 0.0)
784 || (looks_like_number(sv) && sv_2nv(sv) != 0.0) ) {
785 PerlIO_printf(fp, ofmt, SvNVX(sv));
786 return !PerlIO_error(fp);
789 switch (SvTYPE(sv)) {
798 PerlIO_printf(fp, "%ld", (long)SvIVX(sv));
799 return !PerlIO_error(fp);
803 tmps = SvPV(sv, len);
806 if (len && (PerlIO_write(fp,tmps,len) == 0 || PerlIO_error(fp)))
808 return !PerlIO_error(fp);
818 if (op->op_flags & OPf_REF) {
820 tmpgv = cGVOP->op_gv;
823 if (io && IoIFP(io)) {
825 sv_setpv(statname,"");
827 return (laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &statcache));
833 warn("Stat on unopened file <%s>",
836 sv_setpv(statname,"");
837 return (laststatval = -1);
844 if (SvTYPE(sv) == SVt_PVGV) {
848 else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
849 tmpgv = (GV*)SvRV(sv);
855 sv_setpv(statname, s);
857 laststatval = PerlLIO_stat(s, &statcache);
858 if (laststatval < 0 && dowarn && strchr(s, '\n'))
859 warn(warn_nl, "stat");
869 if (op->op_flags & OPf_REF) {
871 if (cGVOP->op_gv == defgv) {
872 if (laststype != OP_LSTAT)
873 croak("The stat preceding -l _ wasn't an lstat");
876 croak("You can't use -l on a filehandle");
879 laststype = OP_LSTAT;
883 sv_setpv(statname,SvPV(sv, na));
885 laststatval = PerlLIO_lstat(SvPV(sv, na),&statcache);
887 laststatval = PerlLIO_stat(SvPV(sv, na),&statcache);
889 if (laststatval < 0 && dowarn && strchr(SvPV(sv, na), '\n'))
890 warn(warn_nl, "lstat");
895 do_aexec(SV *really, register SV **mark, register SV **sp)
902 New(401,Argv, sp - mark + 1, char*);
904 while (++mark <= sp) {
906 *a++ = SvPVx(*mark, na);
911 if (*Argv[0] != '/') /* will execvp use PATH? */
912 TAINT_ENV(); /* testing IFS here is overkill, probably */
913 if (really && *(tmps = SvPV(really, na)))
914 PerlProc_execvp(tmps,Argv);
916 PerlProc_execvp(Argv[0],Argv);
918 warn("Can't exec \"%s\": %s", Argv[0], Strerror(errno));
929 Argv = Null(char **);
937 #if !defined(OS2) && !defined(WIN32) && !defined(DJGPP)
946 while (*cmd && isSPACE(*cmd))
949 /* save an extra exec if possible */
952 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
970 PerlProc_execl(cshname,"csh", flags,ncmd,(char*)0);
978 /* see if there are shell metacharacters in it */
980 if (*cmd == '.' && isSPACE(cmd[1]))
983 if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
986 for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */
990 for (s = cmd; *s; s++) {
991 if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
992 if (*s == '\n' && !s[1]) {
997 PerlProc_execl(sh_path, "sh", "-c", cmd, (char*)0);
1002 New(402,Argv, (s - cmd) / 2 + 2, char*);
1003 Cmd = savepvn(cmd, s-cmd);
1005 for (s = Cmd; *s;) {
1006 while (*s && isSPACE(*s)) s++;
1009 while (*s && !isSPACE(*s)) s++;
1015 PerlProc_execvp(Argv[0],Argv);
1016 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1021 warn("Can't exec \"%s\": %s", Argv[0], Strerror(errno));
1027 #endif /* OS2 || WIN32 */
1030 apply(I32 type, register SV **mark, register SV **sp)
1035 register I32 tot = 0;
1037 SV **oldmark = mark;
1040 while (++mark <= sp) {
1041 if (SvTAINTED(*mark)) {
1050 TAINT_PROPER("chmod");
1054 while (++mark <= sp) {
1055 if (PerlLIO_chmod(SvPVx(*mark, na),val))
1062 TAINT_PROPER("chown");
1063 if (sp - mark > 2) {
1064 val = SvIVx(*++mark);
1065 val2 = SvIVx(*++mark);
1067 while (++mark <= sp) {
1068 if (chown(SvPVx(*mark, na),val,val2))
1076 TAINT_PROPER("kill");
1079 s = SvPVx(*++mark, na);
1082 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
1084 if (!(val = whichsig(s)))
1085 croak("Unrecognized signal name \"%s\"",s);
1090 /* kill() doesn't do process groups (job trees?) under VMS */
1091 if (val < 0) val = -val;
1092 if (val == SIGKILL) {
1093 # include <starlet.h>
1094 /* Use native sys$delprc() to insure that target process is
1095 * deleted; supervisor-mode images don't pay attention to
1096 * CRTL's emulation of Unix-style signals and kill()
1098 while (++mark <= sp) {
1099 I32 proc = SvIVx(*mark);
1100 register unsigned long int __vmssts;
1101 if (!((__vmssts = sys$delprc(&proc,0)) & 1)) {
1105 case SS$_NOSUCHNODE:
1106 SETERRNO(ESRCH,__vmssts);
1109 SETERRNO(EPERM,__vmssts);
1112 SETERRNO(EVMSERR,__vmssts);
1121 while (++mark <= sp) {
1122 I32 proc = SvIVx(*mark);
1124 if (PerlProc_killpg(proc,val)) /* BSD */
1126 if (PerlProc_kill(-proc,val)) /* SYSV */
1132 while (++mark <= sp) {
1133 if (PerlProc_kill(SvIVx(*mark),val))
1140 TAINT_PROPER("unlink");
1142 while (++mark <= sp) {
1143 s = SvPVx(*mark, na);
1144 if (euid || unsafe) {
1148 else { /* don't let root wipe out directories without -U */
1150 if (PerlLIO_lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
1152 if (PerlLIO_stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
1164 TAINT_PROPER("utime");
1165 if (sp - mark > 2) {
1166 #if defined(I_UTIME) || defined(VMS)
1167 struct utimbuf utbuf;
1175 Zero(&utbuf, sizeof utbuf, char);
1177 utbuf.actime = (Time_t)SvNVx(*++mark); /* time accessed */
1178 utbuf.modtime = (Time_t)SvNVx(*++mark); /* time modified */
1180 utbuf.actime = SvIVx(*++mark); /* time accessed */
1181 utbuf.modtime = SvIVx(*++mark); /* time modified */
1184 while (++mark <= sp) {
1185 if (PerlLIO_utime(SvPVx(*mark, na),&utbuf))
1197 /* Do the permissions allow some operation? Assumes statcache already set. */
1198 #ifndef VMS /* VMS' cando is in vms.c */
1200 cando(I32 bit, I32 effective, register struct stat *statbufp)
1203 /* [Comments and code from Len Reed]
1204 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
1205 * to write-protected files. The execute permission bit is set
1206 * by the Miscrosoft C library stat() function for the following:
1211 * All files and directories are readable.
1212 * Directories and special files, e.g. "CON", cannot be
1214 * [Comment by Tom Dinger -- a directory can have the write-protect
1215 * bit set in the file system, but DOS permits changes to
1216 * the directory anyway. In addition, all bets are off
1217 * here for networked software, such as Novell and
1221 /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
1222 * too so it will actually look into the files for magic numbers
1224 return (bit & statbufp->st_mode) ? TRUE : FALSE;
1226 #else /* ! DOSISH */
1227 if ((effective ? euid : uid) == 0) { /* root is special */
1228 if (bit == S_IXUSR) {
1229 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
1233 return TRUE; /* root reads and writes anything */
1236 if (statbufp->st_uid == (effective ? euid : uid) ) {
1237 if (statbufp->st_mode & bit)
1238 return TRUE; /* ok as "user" */
1240 else if (ingroup((I32)statbufp->st_gid,effective)) {
1241 if (statbufp->st_mode & bit >> 3)
1242 return TRUE; /* ok as "group" */
1244 else if (statbufp->st_mode & bit >> 6)
1245 return TRUE; /* ok as "other" */
1247 #endif /* ! DOSISH */
1252 ingroup(I32 testgid, I32 effective)
1254 if (testgid == (effective ? egid : gid))
1256 #ifdef HAS_GETGROUPS
1261 Groups_t gary[NGROUPS];
1264 anum = getgroups(NGROUPS,gary);
1266 if (gary[anum] == testgid)
1273 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
1276 do_ipcget(I32 optype, SV **mark, SV **sp)
1282 key = (key_t)SvNVx(*++mark);
1283 n = (optype == OP_MSGGET) ? 0 : SvIVx(*++mark);
1284 flags = SvIVx(*++mark);
1290 return msgget(key, flags);
1294 return semget(key, n, flags);
1298 return shmget(key, n, flags);
1300 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
1302 croak("%s not implemented", op_desc[optype]);
1305 return -1; /* should never happen */
1308 #if defined(__sun__) && defined(__svr4__) /* XXX Need metaconfig test */
1309 /* Solaris manpage says that it uses (like linux)
1310 int semctl (int semid, int semnum, int cmd, union semun arg)
1311 but the system include files do not define union semun !!!!
1315 struct semid_ds *buf;
1321 do_ipcctl(I32 optype, SV **mark, SV **sp)
1326 I32 id, n, cmd, infosize, getinfo;
1328 #if defined(__linux__) || (defined(__sun__) && defined(__svr4__))
1329 /* XXX Need metaconfig test */
1330 union semun unsemds;
1333 id = SvIVx(*++mark);
1334 n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
1335 cmd = SvIVx(*++mark);
1338 getinfo = (cmd == IPC_STAT);
1344 if (cmd == IPC_STAT || cmd == IPC_SET)
1345 infosize = sizeof(struct msqid_ds);
1350 if (cmd == IPC_STAT || cmd == IPC_SET)
1351 infosize = sizeof(struct shmid_ds);
1356 if (cmd == IPC_STAT || cmd == IPC_SET)
1357 infosize = sizeof(struct semid_ds);
1358 else if (cmd == GETALL || cmd == SETALL)
1360 struct semid_ds semds;
1361 #if defined(__linux__) || (defined(__sun__) && defined(__svr4__))
1362 /* XXX Need metaconfig test */
1363 /* linux and Solaris2 uses :
1364 int semctl (int semid, int semnum, int cmd, union semun arg)
1367 struct semid_ds *buf;
1373 if (semctl(id, 0, IPC_STAT, semun) == -1)
1375 if (semctl(id, 0, IPC_STAT, &semds) == -1)
1378 getinfo = (cmd == GETALL);
1379 infosize = semds.sem_nsems * sizeof(short);
1380 /* "short" is technically wrong but much more portable
1381 than guessing about u_?short(_t)? */
1385 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
1387 croak("%s not implemented", op_desc[optype]);
1396 SvPV_force(astr, len);
1397 a = SvGROW(astr, infosize+1);
1401 a = SvPV(astr, len);
1402 if (len != infosize)
1403 croak("Bad arg length for %s, is %lu, should be %ld",
1404 op_desc[optype], (unsigned long)len, (long)infosize);
1410 a = (char *)i; /* ouch */
1417 ret = msgctl(id, cmd, (struct msqid_ds *)a);
1422 #if defined(__linux__) || (defined(__sun__) && defined(__svr4__))
1423 /* XXX Need metaconfig test */
1424 unsemds.buf = (struct semid_ds *)a;
1425 ret = semctl(id, n, cmd, unsemds);
1427 ret = semctl(id, n, cmd, (struct semid_ds *)a);
1433 ret = shmctl(id, cmd, (struct shmid_ds *)a);
1437 if (getinfo && ret >= 0) {
1438 SvCUR_set(astr, infosize);
1439 *SvEND(astr) = '\0';
1446 do_msgsnd(SV **mark, SV **sp)
1452 I32 id, msize, flags;
1455 id = SvIVx(*++mark);
1457 flags = SvIVx(*++mark);
1458 mbuf = SvPV(mstr, len);
1459 if ((msize = len - sizeof(long)) < 0)
1460 croak("Arg too short for msgsnd");
1462 return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
1464 croak("msgsnd not implemented");
1469 do_msgrcv(SV **mark, SV **sp)
1476 I32 id, msize, flags, ret;
1479 id = SvIVx(*++mark);
1481 msize = SvIVx(*++mark);
1482 mtype = (long)SvIVx(*++mark);
1483 flags = SvIVx(*++mark);
1484 if (SvTHINKFIRST(mstr)) {
1485 if (SvREADONLY(mstr))
1486 croak("Can't msgrcv to readonly var");
1490 SvPV_force(mstr, len);
1491 mbuf = SvGROW(mstr, sizeof(long)+msize+1);
1494 ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
1496 SvCUR_set(mstr, sizeof(long)+ret);
1497 *SvEND(mstr) = '\0';
1501 croak("msgrcv not implemented");
1506 do_semop(SV **mark, SV **sp)
1515 id = SvIVx(*++mark);
1517 opbuf = SvPV(opstr, opsize);
1518 if (opsize < sizeof(struct sembuf)
1519 || (opsize % sizeof(struct sembuf)) != 0) {
1520 SETERRNO(EINVAL,LIB$_INVARG);
1524 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
1526 croak("semop not implemented");
1531 do_shmio(I32 optype, SV **mark, SV **sp)
1537 I32 id, mpos, msize;
1539 struct shmid_ds shmds;
1541 id = SvIVx(*++mark);
1543 mpos = SvIVx(*++mark);
1544 msize = SvIVx(*++mark);
1546 if (shmctl(id, IPC_STAT, &shmds) == -1)
1548 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
1549 SETERRNO(EFAULT,SS$_ACCVIO); /* can't do as caller requested */
1552 shm = (char *)shmat(id, (char*)NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
1553 if (shm == (char *)-1) /* I hate System V IPC, I really do */
1555 if (optype == OP_SHMREAD) {
1556 SvPV_force(mstr, len);
1557 mbuf = SvGROW(mstr, msize+1);
1559 Copy(shm + mpos, mbuf, msize, char);
1560 SvCUR_set(mstr, msize);
1561 *SvEND(mstr) = '\0';
1567 mbuf = SvPV(mstr, len);
1568 if ((n = len) > msize)
1570 Copy(mbuf, shm + mpos, n, char);
1572 memzero(shm + mpos + n, msize - n);
1576 croak("shm I/O not implemented");
1580 #endif /* SYSV IPC */