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));
586 SETERRNO(EBADF,SS$_IVCHAN);
589 retval = io_close(io);
593 IoLINES_LEFT(io) = IoPAGE_LEN(io);
606 if (IoTYPE(io) == '|') {
607 status = PerlProc_pclose(IoIFP(io));
608 STATUS_NATIVE_SET(status);
609 retval = (STATUS_POSIX == 0);
611 else if (IoTYPE(io) == '-')
614 if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */
615 retval = (PerlIO_close(IoOFP(io)) != EOF);
616 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
619 retval = (PerlIO_close(IoIFP(io)) != EOF);
621 IoOFP(io) = IoIFP(io) = Nullfp;
624 SETERRNO(EBADF,SS$_IVCHAN);
644 if (PerlIO_has_cntptr(IoIFP(io))) { /* (the code works without this) */
645 if (PerlIO_get_cnt(IoIFP(io)) > 0) /* cheat a little, since */
646 return FALSE; /* this is the most usual case */
649 ch = PerlIO_getc(IoIFP(io));
651 (void)PerlIO_ungetc(IoIFP(io),ch);
654 if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
655 if (PerlIO_get_cnt(IoIFP(io)) < -1)
656 PerlIO_set_cnt(IoIFP(io),-1);
658 if (op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
659 if (!nextargv(argvgv)) /* get another fp handy */
663 return TRUE; /* normal fp, definitely end of file */
674 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
675 #ifdef ULTRIX_STDIO_BOTCH
677 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
679 return PerlIO_tell(fp);
682 warn("tell() on unopened file");
683 SETERRNO(EBADF,RMS$_IFI);
688 do_seek(GV *gv, long int pos, int whence)
693 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
694 #ifdef ULTRIX_STDIO_BOTCH
696 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
698 return PerlIO_seek(fp, pos, whence) >= 0;
701 warn("seek() on unopened file");
702 SETERRNO(EBADF,RMS$_IFI);
707 do_sysseek(GV *gv, long int pos, int whence)
712 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
713 return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
715 warn("sysseek() on unopened file");
716 SETERRNO(EBADF,RMS$_IFI);
720 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
721 /* code courtesy of William Kucharski */
724 I32 my_chsize(fd, length)
725 I32 fd; /* file descriptor */
726 Off_t length; /* length to set file to */
731 if (PerlLIO_fstat(fd, &filebuf) < 0)
734 if (filebuf.st_size < length) {
736 /* extend file length */
738 if ((PerlLIO_lseek(fd, (length - 1), 0)) < 0)
741 /* write a "0" byte */
743 if ((PerlLIO_write(fd, "", 1)) != 1)
747 /* truncate length */
752 fl.l_type = F_WRLCK; /* write lock on file space */
755 * This relies on the UNDOCUMENTED F_FREESP argument to
756 * fcntl(2), which truncates the file so that it ends at the
757 * position indicated by fl.l_start.
759 * Will minor miracles never cease?
762 if (fcntl(fd, F_FREESP, &fl) < 0)
769 #endif /* F_FREESP */
772 do_print(register SV *sv, PerlIO *fp)
777 /* assuming fp is checked earlier */
783 if (SvIOK(sv) && SvIVX(sv) != 0) {
784 PerlIO_printf(fp, ofmt, (double)SvIVX(sv));
785 return !PerlIO_error(fp);
787 if ( (SvNOK(sv) && SvNVX(sv) != 0.0)
788 || (looks_like_number(sv) && sv_2nv(sv) != 0.0) ) {
789 PerlIO_printf(fp, ofmt, SvNVX(sv));
790 return !PerlIO_error(fp);
793 switch (SvTYPE(sv)) {
802 PerlIO_printf(fp, "%ld", (long)SvIVX(sv));
803 return !PerlIO_error(fp);
807 tmps = SvPV(sv, len);
810 if (len && (PerlIO_write(fp,tmps,len) == 0 || PerlIO_error(fp)))
812 return !PerlIO_error(fp);
822 if (op->op_flags & OPf_REF) {
824 tmpgv = cGVOP->op_gv;
827 if (io && IoIFP(io)) {
829 sv_setpv(statname,"");
831 return (laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &statcache));
837 warn("Stat on unopened file <%s>",
840 sv_setpv(statname,"");
841 return (laststatval = -1);
848 if (SvTYPE(sv) == SVt_PVGV) {
852 else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
853 tmpgv = (GV*)SvRV(sv);
859 sv_setpv(statname, s);
861 laststatval = PerlLIO_stat(s, &statcache);
862 if (laststatval < 0 && dowarn && strchr(s, '\n'))
863 warn(warn_nl, "stat");
873 if (op->op_flags & OPf_REF) {
875 if (cGVOP->op_gv == defgv) {
876 if (laststype != OP_LSTAT)
877 croak("The stat preceding -l _ wasn't an lstat");
880 croak("You can't use -l on a filehandle");
883 laststype = OP_LSTAT;
887 sv_setpv(statname,SvPV(sv, na));
889 laststatval = PerlLIO_lstat(SvPV(sv, na),&statcache);
891 laststatval = PerlLIO_stat(SvPV(sv, na),&statcache);
893 if (laststatval < 0 && dowarn && strchr(SvPV(sv, na), '\n'))
894 warn(warn_nl, "lstat");
899 do_aexec(SV *really, register SV **mark, register SV **sp)
906 New(401,Argv, sp - mark + 1, char*);
908 while (++mark <= sp) {
910 *a++ = SvPVx(*mark, na);
915 if (*Argv[0] != '/') /* will execvp use PATH? */
916 TAINT_ENV(); /* testing IFS here is overkill, probably */
917 if (really && *(tmps = SvPV(really, na)))
918 PerlProc_execvp(tmps,Argv);
920 PerlProc_execvp(Argv[0],Argv);
922 warn("Can't exec \"%s\": %s", Argv[0], Strerror(errno));
933 Argv = Null(char **);
941 #if !defined(OS2) && !defined(WIN32) && !defined(DJGPP)
950 while (*cmd && isSPACE(*cmd))
953 /* save an extra exec if possible */
956 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
974 PerlProc_execl(cshname,"csh", flags,ncmd,(char*)0);
982 /* see if there are shell metacharacters in it */
984 if (*cmd == '.' && isSPACE(cmd[1]))
987 if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
990 for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */
994 for (s = cmd; *s; s++) {
995 if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
996 if (*s == '\n' && !s[1]) {
1001 PerlProc_execl(sh_path, "sh", "-c", cmd, (char*)0);
1006 New(402,Argv, (s - cmd) / 2 + 2, char*);
1007 Cmd = savepvn(cmd, s-cmd);
1009 for (s = Cmd; *s;) {
1010 while (*s && isSPACE(*s)) s++;
1013 while (*s && !isSPACE(*s)) s++;
1019 PerlProc_execvp(Argv[0],Argv);
1020 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1025 warn("Can't exec \"%s\": %s", Argv[0], Strerror(errno));
1031 #endif /* OS2 || WIN32 */
1034 apply(I32 type, register SV **mark, register SV **sp)
1039 register I32 tot = 0;
1042 SV **oldmark = mark;
1044 #define APPLY_TAINT_PROPER() \
1045 if (!(tainting && tainted)) {} else { goto taint_proper; }
1047 /* This is a first heuristic; it doesn't catch tainting magic. */
1049 while (++mark <= sp) {
1050 if (SvTAINTED(*mark)) {
1060 APPLY_TAINT_PROPER();
1063 APPLY_TAINT_PROPER();
1065 while (++mark <= sp) {
1066 char *name = SvPVx(*mark, na);
1067 APPLY_TAINT_PROPER();
1068 if (PerlLIO_chmod(name, val))
1076 APPLY_TAINT_PROPER();
1077 if (sp - mark > 2) {
1078 val = SvIVx(*++mark);
1079 val2 = SvIVx(*++mark);
1080 APPLY_TAINT_PROPER();
1082 while (++mark <= sp) {
1083 char *name = SvPVx(*mark, na);
1084 APPLY_TAINT_PROPER();
1085 if (chown(name, val, val2))
1094 APPLY_TAINT_PROPER();
1097 s = SvPVx(*++mark, na);
1099 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
1101 if (!(val = whichsig(s)))
1102 croak("Unrecognized signal name \"%s\"",s);
1106 APPLY_TAINT_PROPER();
1109 /* kill() doesn't do process groups (job trees?) under VMS */
1110 if (val < 0) val = -val;
1111 if (val == SIGKILL) {
1112 # include <starlet.h>
1113 /* Use native sys$delprc() to insure that target process is
1114 * deleted; supervisor-mode images don't pay attention to
1115 * CRTL's emulation of Unix-style signals and kill()
1117 while (++mark <= sp) {
1118 I32 proc = SvIVx(*mark);
1119 register unsigned long int __vmssts;
1120 APPLY_TAINT_PROPER();
1121 if (!((__vmssts = sys$delprc(&proc,0)) & 1)) {
1125 case SS$_NOSUCHNODE:
1126 SETERRNO(ESRCH,__vmssts);
1129 SETERRNO(EPERM,__vmssts);
1132 SETERRNO(EVMSERR,__vmssts);
1141 while (++mark <= sp) {
1142 I32 proc = SvIVx(*mark);
1143 APPLY_TAINT_PROPER();
1145 if (PerlProc_killpg(proc,val)) /* BSD */
1147 if (PerlProc_kill(-proc,val)) /* SYSV */
1153 while (++mark <= sp) {
1154 I32 proc = SvIVx(*mark);
1155 APPLY_TAINT_PROPER();
1156 if (PerlProc_kill(proc, val))
1164 APPLY_TAINT_PROPER();
1166 while (++mark <= sp) {
1167 s = SvPVx(*mark, na);
1168 APPLY_TAINT_PROPER();
1169 if (euid || unsafe) {
1173 else { /* don't let root wipe out directories without -U */
1175 if (PerlLIO_lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
1177 if (PerlLIO_stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
1190 APPLY_TAINT_PROPER();
1191 if (sp - mark > 2) {
1192 #if defined(I_UTIME) || defined(VMS)
1193 struct utimbuf utbuf;
1201 Zero(&utbuf, sizeof utbuf, char);
1203 utbuf.actime = (Time_t)SvNVx(*++mark); /* time accessed */
1204 utbuf.modtime = (Time_t)SvNVx(*++mark); /* time modified */
1206 utbuf.actime = SvIVx(*++mark); /* time accessed */
1207 utbuf.modtime = SvIVx(*++mark); /* time modified */
1209 APPLY_TAINT_PROPER();
1211 while (++mark <= sp) {
1212 char *name = SvPVx(*mark, na);
1213 APPLY_TAINT_PROPER();
1214 if (PerlLIO_utime(name, &utbuf))
1227 return 0; /* this should never happen */
1229 #undef APPLY_TAINT_PROPER
1232 /* Do the permissions allow some operation? Assumes statcache already set. */
1233 #ifndef VMS /* VMS' cando is in vms.c */
1235 cando(I32 bit, I32 effective, register struct stat *statbufp)
1238 /* [Comments and code from Len Reed]
1239 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
1240 * to write-protected files. The execute permission bit is set
1241 * by the Miscrosoft C library stat() function for the following:
1246 * All files and directories are readable.
1247 * Directories and special files, e.g. "CON", cannot be
1249 * [Comment by Tom Dinger -- a directory can have the write-protect
1250 * bit set in the file system, but DOS permits changes to
1251 * the directory anyway. In addition, all bets are off
1252 * here for networked software, such as Novell and
1256 /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
1257 * too so it will actually look into the files for magic numbers
1259 return (bit & statbufp->st_mode) ? TRUE : FALSE;
1261 #else /* ! DOSISH */
1262 if ((effective ? euid : uid) == 0) { /* root is special */
1263 if (bit == S_IXUSR) {
1264 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
1268 return TRUE; /* root reads and writes anything */
1271 if (statbufp->st_uid == (effective ? euid : uid) ) {
1272 if (statbufp->st_mode & bit)
1273 return TRUE; /* ok as "user" */
1275 else if (ingroup((I32)statbufp->st_gid,effective)) {
1276 if (statbufp->st_mode & bit >> 3)
1277 return TRUE; /* ok as "group" */
1279 else if (statbufp->st_mode & bit >> 6)
1280 return TRUE; /* ok as "other" */
1282 #endif /* ! DOSISH */
1287 ingroup(I32 testgid, I32 effective)
1289 if (testgid == (effective ? egid : gid))
1291 #ifdef HAS_GETGROUPS
1296 Groups_t gary[NGROUPS];
1299 anum = getgroups(NGROUPS,gary);
1301 if (gary[anum] == testgid)
1308 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
1311 do_ipcget(I32 optype, SV **mark, SV **sp)
1317 key = (key_t)SvNVx(*++mark);
1318 n = (optype == OP_MSGGET) ? 0 : SvIVx(*++mark);
1319 flags = SvIVx(*++mark);
1325 return msgget(key, flags);
1329 return semget(key, n, flags);
1333 return shmget(key, n, flags);
1335 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
1337 croak("%s not implemented", op_desc[optype]);
1340 return -1; /* should never happen */
1343 #if defined(__sun) && defined(__svr4__) /* XXX Need metaconfig test */
1344 /* Solaris manpage says that it uses (like linux)
1345 int semctl (int semid, int semnum, int cmd, union semun arg)
1346 but the system include files do not define union semun !!!!
1350 struct semid_ds *buf;
1356 do_ipcctl(I32 optype, SV **mark, SV **sp)
1361 I32 id, n, cmd, infosize, getinfo;
1363 #if defined(__linux__) || (defined(__sun) && defined(__svr4__))
1364 /* XXX Need metaconfig test */
1365 union semun unsemds;
1368 id = SvIVx(*++mark);
1369 n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
1370 cmd = SvIVx(*++mark);
1373 getinfo = (cmd == IPC_STAT);
1379 if (cmd == IPC_STAT || cmd == IPC_SET)
1380 infosize = sizeof(struct msqid_ds);
1385 if (cmd == IPC_STAT || cmd == IPC_SET)
1386 infosize = sizeof(struct shmid_ds);
1391 if (cmd == IPC_STAT || cmd == IPC_SET)
1392 infosize = sizeof(struct semid_ds);
1393 else if (cmd == GETALL || cmd == SETALL)
1395 struct semid_ds semds;
1396 #if defined(__linux__) || (defined(__sun) && defined(__svr4__))
1397 /* XXX Need metaconfig test */
1398 /* linux and Solaris2 uses :
1399 int semctl (int semid, int semnum, int cmd, union semun arg)
1402 struct semid_ds *buf;
1408 if (semctl(id, 0, IPC_STAT, semun) == -1)
1410 if (semctl(id, 0, IPC_STAT, &semds) == -1)
1413 getinfo = (cmd == GETALL);
1414 infosize = semds.sem_nsems * sizeof(short);
1415 /* "short" is technically wrong but much more portable
1416 than guessing about u_?short(_t)? */
1420 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
1422 croak("%s not implemented", op_desc[optype]);
1431 SvPV_force(astr, len);
1432 a = SvGROW(astr, infosize+1);
1436 a = SvPV(astr, len);
1437 if (len != infosize)
1438 croak("Bad arg length for %s, is %lu, should be %ld",
1439 op_desc[optype], (unsigned long)len, (long)infosize);
1445 a = (char *)i; /* ouch */
1452 ret = msgctl(id, cmd, (struct msqid_ds *)a);
1457 #if defined(__linux__) || (defined(__sun) && defined(__svr4__))
1458 /* XXX Need metaconfig test */
1459 unsemds.buf = (struct semid_ds *)a;
1460 ret = semctl(id, n, cmd, unsemds);
1462 ret = semctl(id, n, cmd, (struct semid_ds *)a);
1468 ret = shmctl(id, cmd, (struct shmid_ds *)a);
1472 if (getinfo && ret >= 0) {
1473 SvCUR_set(astr, infosize);
1474 *SvEND(astr) = '\0';
1481 do_msgsnd(SV **mark, SV **sp)
1487 I32 id, msize, flags;
1490 id = SvIVx(*++mark);
1492 flags = SvIVx(*++mark);
1493 mbuf = SvPV(mstr, len);
1494 if ((msize = len - sizeof(long)) < 0)
1495 croak("Arg too short for msgsnd");
1497 return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
1499 croak("msgsnd not implemented");
1504 do_msgrcv(SV **mark, SV **sp)
1511 I32 id, msize, flags, ret;
1514 id = SvIVx(*++mark);
1516 msize = SvIVx(*++mark);
1517 mtype = (long)SvIVx(*++mark);
1518 flags = SvIVx(*++mark);
1519 if (SvTHINKFIRST(mstr)) {
1520 if (SvREADONLY(mstr))
1521 croak("Can't msgrcv to readonly var");
1525 SvPV_force(mstr, len);
1526 mbuf = SvGROW(mstr, sizeof(long)+msize+1);
1529 ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
1531 SvCUR_set(mstr, sizeof(long)+ret);
1532 *SvEND(mstr) = '\0';
1536 croak("msgrcv not implemented");
1541 do_semop(SV **mark, SV **sp)
1550 id = SvIVx(*++mark);
1552 opbuf = SvPV(opstr, opsize);
1553 if (opsize < sizeof(struct sembuf)
1554 || (opsize % sizeof(struct sembuf)) != 0) {
1555 SETERRNO(EINVAL,LIB$_INVARG);
1559 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
1561 croak("semop not implemented");
1566 do_shmio(I32 optype, SV **mark, SV **sp)
1572 I32 id, mpos, msize;
1574 struct shmid_ds shmds;
1576 id = SvIVx(*++mark);
1578 mpos = SvIVx(*++mark);
1579 msize = SvIVx(*++mark);
1581 if (shmctl(id, IPC_STAT, &shmds) == -1)
1583 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
1584 SETERRNO(EFAULT,SS$_ACCVIO); /* can't do as caller requested */
1587 shm = (char *)shmat(id, (char*)NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
1588 if (shm == (char *)-1) /* I hate System V IPC, I really do */
1590 if (optype == OP_SHMREAD) {
1591 SvPV_force(mstr, len);
1592 mbuf = SvGROW(mstr, msize+1);
1594 Copy(shm + mpos, mbuf, msize, char);
1595 SvCUR_set(mstr, msize);
1596 *SvEND(mstr) = '\0';
1602 mbuf = SvPV(mstr, len);
1603 if ((n = len) > msize)
1605 Copy(mbuf, shm + mpos, n, char);
1607 memzero(shm + mpos + n, msize - n);
1611 croak("shm I/O not implemented");
1615 #endif /* SYSV IPC */