This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[win32] Various win32 fixes
[perl5.git] / doio.c
CommitLineData
a0d0e21e 1/* doio.c
a687059c 2 *
9607fc9c 3 * Copyright (c) 1991-1997, Larry Wall
a687059c 4 *
6e21c824
LW
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.
a687059c 7 *
a0d0e21e
LW
8 */
9
10/*
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."
a687059c
LW
15 */
16
17#include "EXTERN.h"
18#include "perl.h"
19
fe14fcc3 20#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
c2ab57d4 21#include <sys/ipc.h>
fe14fcc3 22#ifdef HAS_MSG
c2ab57d4 23#include <sys/msg.h>
e5d73d77 24#endif
fe14fcc3 25#ifdef HAS_SEM
c2ab57d4 26#include <sys/sem.h>
e5d73d77 27#endif
fe14fcc3 28#ifdef HAS_SHM
c2ab57d4 29#include <sys/shm.h>
a0d0e21e
LW
30# ifndef HAS_SHMAT_PROTOTYPE
31 extern Shmat_t shmat _((int, char *, int));
32# endif
c2ab57d4 33#endif
e5d73d77 34#endif
c2ab57d4 35
663a0e37 36#ifdef I_UTIME
3e3baf6d 37# ifdef _MSC_VER
3fe9a6f1 38# include <sys/utime.h>
39# else
40# include <utime.h>
41# endif
663a0e37 42#endif
ff8e2863
LW
43#ifdef I_FCNTL
44#include <fcntl.h>
45#endif
fe14fcc3
LW
46#ifdef I_SYS_FILE
47#include <sys/file.h>
48#endif
a687059c 49
76121258 50#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
51#include <signal.h>
52#endif
53
54/* XXX If this causes problems, set i_unistd=undef in the hint file. */
55#ifdef I_UNISTD
56# include <unistd.h>
57#endif
58
232e078e
AD
59#if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
60# include <sys/socket.h>
61# include <netdb.h>
62# ifndef ENOTSOCK
63# ifdef I_NET_ERRNO
64# include <net/errno.h>
65# endif
66# endif
67#endif
68
d574b85e
CS
69/* Put this after #includes because <unistd.h> defines _XOPEN_*. */
70#ifndef Sock_size_t
137443ea 71# if _XOPEN_VERSION >= 5 || defined(_XOPEN_SOURCE_EXTENDED) || defined(__GLIBC__)
d574b85e
CS
72# define Sock_size_t Size_t
73# else
74# define Sock_size_t int
75# endif
76#endif
77
a687059c 78bool
8ac85365 79do_open(GV *gv, register char *name, I32 len, int as_raw, int rawmode, int rawperm, FILE *supplied_fp)
a687059c 80{
a0d0e21e 81 register IO *io = GvIOn(gv);
760ac839
LW
82 PerlIO *saveifp = Nullfp;
83 PerlIO *saveofp = Nullfp;
6e21c824 84 char savetype = ' ';
c07a80fd 85 int writing = 0;
760ac839 86 PerlIO *fp;
c07a80fd 87 int fd;
88 int result;
a687059c 89
a687059c 90 forkprocess = 1; /* assume true if no fork */
c07a80fd 91
a0d0e21e 92 if (IoIFP(io)) {
760ac839 93 fd = PerlIO_fileno(IoIFP(io));
8990e307 94 if (IoTYPE(io) == '-')
c2ab57d4 95 result = 0;
6e21c824 96 else if (fd <= maxsysfd) {
8990e307
LW
97 saveifp = IoIFP(io);
98 saveofp = IoOFP(io);
99 savetype = IoTYPE(io);
6e21c824
LW
100 result = 0;
101 }
8990e307
LW
102 else if (IoTYPE(io) == '|')
103 result = my_pclose(IoIFP(io));
104 else if (IoIFP(io) != IoOFP(io)) {
105 if (IoOFP(io)) {
760ac839
LW
106 result = PerlIO_close(IoOFP(io));
107 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
c2ab57d4
LW
108 }
109 else
760ac839 110 result = PerlIO_close(IoIFP(io));
a687059c 111 }
a687059c 112 else
760ac839 113 result = PerlIO_close(IoIFP(io));
6e21c824 114 if (result == EOF && fd > maxsysfd)
760ac839 115 PerlIO_printf(PerlIO_stderr(), "Warning: unable to close filehandle %s properly.\n",
79072805 116 GvENAME(gv));
8990e307 117 IoOFP(io) = IoIFP(io) = Nullfp;
a687059c 118 }
c07a80fd 119
120 if (as_raw) {
121 result = rawmode & 3;
122 IoTYPE(io) = "<>++"[result];
123 writing = (result > 0);
124 fd = open(name, rawmode, rawperm);
125 if (fd == -1)
126 fp = NULL;
127 else {
360e5741
CS
128 char *fpmode;
129 if (result == 0)
130 fpmode = "r";
131#ifdef O_APPEND
132 else if (rawmode & O_APPEND)
133 fpmode = (result == 1) ? "a" : "a+";
134#endif
135 else
136 fpmode = (result == 1) ? "w" : "r+";
137 fp = PerlIO_fdopen(fd, fpmode);
c07a80fd 138 if (!fp)
139 close(fd);
140 }
a687059c 141 }
c07a80fd 142 else {
143 char *myname;
144 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
145 int dodup;
146
147 myname = savepvn(name, len);
148 SAVEFREEPV(myname);
149 name = myname;
150 while (len && isSPACE(name[len-1]))
151 name[--len] = '\0';
152
153 mode[0] = mode[1] = mode[2] = '\0';
154 IoTYPE(io) = *name;
155 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
156 mode[1] = *name++;
157 --len;
158 writing = 1;
a687059c 159 }
c07a80fd 160
161 if (*name == '|') {
162 /*SUPPRESS 530*/
163 for (name++; isSPACE(*name); name++) ;
164 if (strNE(name,"-"))
165 TAINT_ENV();
166 TAINT_PROPER("piped open");
167 if (dowarn && name[strlen(name)-1] == '|')
168 warn("Can't do bidirectional pipe");
169 fp = my_popen(name,"w");
170 writing = 1;
171 }
172 else if (*name == '>') {
173 TAINT_PROPER("open");
bf38876a 174 name++;
c07a80fd 175 if (*name == '>') {
176 mode[0] = IoTYPE(io) = 'a';
bf38876a 177 name++;
a0d0e21e 178 }
c07a80fd 179 else
180 mode[0] = 'w';
181 writing = 1;
182
183 if (*name == '&') {
184 duplicity:
185 dodup = 1;
186 name++;
187 if (*name == '=') {
188 dodup = 0;
a0d0e21e 189 name++;
c07a80fd 190 }
191 if (!*name && supplied_fp)
192 fp = supplied_fp;
a0d0e21e 193 else {
c07a80fd 194 /*SUPPRESS 530*/
195 for (; isSPACE(*name); name++) ;
196 if (isDIGIT(*name))
197 fd = atoi(name);
198 else {
199 IO* thatio;
200 gv = gv_fetchpv(name,FALSE,SVt_PVIO);
201 thatio = GvIO(gv);
202 if (!thatio) {
6e21c824 203#ifdef EINVAL
c07a80fd 204 SETERRNO(EINVAL,SS$_IVCHAN);
6e21c824 205#endif
c07a80fd 206 goto say_false;
207 }
208 if (IoIFP(thatio)) {
760ac839 209 fd = PerlIO_fileno(IoIFP(thatio));
c07a80fd 210 if (IoTYPE(thatio) == 's')
211 IoTYPE(io) = 's';
212 }
213 else
214 fd = -1;
a0d0e21e 215 }
fec02dd3 216 if (dodup)
c07a80fd 217 fd = dup(fd);
760ac839 218 if (!(fp = PerlIO_fdopen(fd,mode))) {
c07a80fd 219 if (dodup)
220 close(fd);
517844ec 221 }
c07a80fd 222 }
bf38876a 223 }
c07a80fd 224 else {
225 /*SUPPRESS 530*/
226 for (; isSPACE(*name); name++) ;
227 if (strEQ(name,"-")) {
760ac839 228 fp = PerlIO_stdout();
c07a80fd 229 IoTYPE(io) = '-';
230 }
231 else {
760ac839 232 fp = PerlIO_open(name,mode);
c07a80fd 233 }
bf38876a
LW
234 }
235 }
c07a80fd 236 else if (*name == '<') {
237 /*SUPPRESS 530*/
238 for (name++; isSPACE(*name); name++) ;
bf38876a 239 mode[0] = 'r';
bf38876a
LW
240 if (*name == '&')
241 goto duplicity;
a687059c 242 if (strEQ(name,"-")) {
760ac839 243 fp = PerlIO_stdin();
8990e307 244 IoTYPE(io) = '-';
a687059c 245 }
bf38876a 246 else
760ac839 247 fp = PerlIO_open(name,mode);
a687059c
LW
248 }
249 else if (name[len-1] == '|') {
a687059c 250 name[--len] = '\0';
99b89507 251 while (len && isSPACE(name[len-1]))
a687059c 252 name[--len] = '\0';
99b89507
LW
253 /*SUPPRESS 530*/
254 for (; isSPACE(*name); name++) ;
79072805
LW
255 if (strNE(name,"-"))
256 TAINT_ENV();
257 TAINT_PROPER("piped open");
258 fp = my_popen(name,"r");
8990e307 259 IoTYPE(io) = '|';
a687059c
LW
260 }
261 else {
8990e307 262 IoTYPE(io) = '<';
99b89507
LW
263 /*SUPPRESS 530*/
264 for (; isSPACE(*name); name++) ;
a687059c 265 if (strEQ(name,"-")) {
760ac839 266 fp = PerlIO_stdin();
8990e307 267 IoTYPE(io) = '-';
a687059c
LW
268 }
269 else
760ac839 270 fp = PerlIO_open(name,"r");
a687059c
LW
271 }
272 }
bee1dbe2 273 if (!fp) {
8990e307 274 if (dowarn && IoTYPE(io) == '<' && strchr(name, '\n'))
bee1dbe2 275 warn(warn_nl, "open");
6e21c824 276 goto say_false;
bee1dbe2 277 }
8990e307
LW
278 if (IoTYPE(io) &&
279 IoTYPE(io) != '|' && IoTYPE(io) != '-') {
96827780 280 dTHR;
760ac839
LW
281 if (Fstat(PerlIO_fileno(fp),&statbuf) < 0) {
282 (void)PerlIO_close(fp);
6e21c824 283 goto say_false;
a687059c 284 }
1462b684 285 if (S_ISSOCK(statbuf.st_mode))
8990e307 286 IoTYPE(io) = 's'; /* in case a socket was passed in to us */
99b89507
LW
287#ifdef HAS_SOCKET
288 else if (
c623bd54 289#ifdef S_IFMT
99b89507
LW
290 !(statbuf.st_mode & S_IFMT)
291#else
292 !statbuf.st_mode
293#endif
294 ) {
96827780
MB
295 char tmpbuf[256];
296 Sock_size_t buflen = sizeof tmpbuf;
297 if (getsockname(PerlIO_fileno(fp), (struct sockaddr *)tmpbuf,
d574b85e
CS
298 &buflen) >= 0
299 || errno != ENOTSOCK)
8990e307 300 IoTYPE(io) = 's'; /* some OS's return 0 on fstat()ed socket */
99b89507
LW
301 /* but some return 0 for streams too, sigh */
302 }
bf38876a 303#endif
a687059c 304 }
6e21c824 305 if (saveifp) { /* must use old fp? */
760ac839 306 fd = PerlIO_fileno(saveifp);
6e21c824 307 if (saveofp) {
760ac839 308 PerlIO_flush(saveofp); /* emulate PerlIO_close() */
6e21c824 309 if (saveofp != saveifp) { /* was a socket? */
760ac839 310 PerlIO_close(saveofp);
99b89507
LW
311 if (fd > 2)
312 Safefree(saveofp);
6e21c824
LW
313 }
314 }
760ac839 315 if (fd != PerlIO_fileno(fp)) {
bee1dbe2 316 int pid;
79072805 317 SV *sv;
bee1dbe2 318
760ac839
LW
319 dup2(PerlIO_fileno(fp), fd);
320 sv = *av_fetch(fdpid,PerlIO_fileno(fp),TRUE);
a0d0e21e 321 (void)SvUPGRADE(sv, SVt_IV);
463ee0b2
LW
322 pid = SvIVX(sv);
323 SvIVX(sv) = 0;
79072805 324 sv = *av_fetch(fdpid,fd,TRUE);
a0d0e21e 325 (void)SvUPGRADE(sv, SVt_IV);
463ee0b2 326 SvIVX(sv) = pid;
760ac839 327 PerlIO_close(fp);
bee1dbe2 328
6e21c824
LW
329 }
330 fp = saveifp;
760ac839 331 PerlIO_clearerr(fp);
6e21c824 332 }
a0d0e21e 333#if defined(HAS_FCNTL) && defined(F_SETFD)
760ac839 334 fd = PerlIO_fileno(fp);
a0d0e21e 335 fcntl(fd,F_SETFD,fd > maxsysfd);
1462b684 336#endif
8990e307 337 IoIFP(io) = fp;
bf38876a 338 if (writing) {
96827780 339 dTHR;
8990e307
LW
340 if (IoTYPE(io) == 's'
341 || (IoTYPE(io) == '>' && S_ISCHR(statbuf.st_mode)) ) {
760ac839
LW
342 if (!(IoOFP(io) = PerlIO_fdopen(PerlIO_fileno(fp),"w"))) {
343 PerlIO_close(fp);
8990e307 344 IoIFP(io) = Nullfp;
6e21c824 345 goto say_false;
fe14fcc3 346 }
1462b684
LW
347 }
348 else
8990e307 349 IoOFP(io) = fp;
bf38876a 350 }
a687059c 351 return TRUE;
6e21c824
LW
352
353say_false:
8990e307
LW
354 IoIFP(io) = saveifp;
355 IoOFP(io) = saveofp;
356 IoTYPE(io) = savetype;
6e21c824 357 return FALSE;
a687059c
LW
358}
359
760ac839 360PerlIO *
8ac85365 361nextargv(register GV *gv)
a687059c 362{
79072805 363 register SV *sv;
99b89507 364#ifndef FLEXFILENAMES
c623bd54
LW
365 int filedev;
366 int fileino;
99b89507 367#endif
c623bd54
LW
368 int fileuid;
369 int filegid;
fe14fcc3 370
79072805 371 if (!argvoutgv)
85e6fe83 372 argvoutgv = gv_fetchpv("ARGVOUT",TRUE,SVt_PVIO);
fe14fcc3 373 if (filemode & (S_ISUID|S_ISGID)) {
760ac839 374 PerlIO_flush(IoIFP(GvIOn(argvoutgv))); /* chmod must follow last write */
fe14fcc3
LW
375#ifdef HAS_FCHMOD
376 (void)fchmod(lastfd,filemode);
377#else
378 (void)chmod(oldname,filemode);
379#endif
380 }
381 filemode = 0;
79072805 382 while (av_len(GvAV(gv)) >= 0) {
11343788 383 dTHR;
463ee0b2 384 STRLEN len;
79072805 385 sv = av_shift(GvAV(gv));
8990e307 386 SAVEFREESV(sv);
79072805
LW
387 sv_setsv(GvSV(gv),sv);
388 SvSETMAGIC(GvSV(gv));
463ee0b2 389 oldname = SvPVx(GvSV(gv), len);
c07a80fd 390 if (do_open(gv,oldname,len,FALSE,0,0,Nullfp)) {
a687059c 391 if (inplace) {
79072805 392 TAINT_PROPER("inplace open");
c623bd54 393 if (strEQ(oldname,"-")) {
4633a7c4 394 setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
a0d0e21e 395 return IoIFP(GvIOp(gv));
c623bd54 396 }
99b89507 397#ifndef FLEXFILENAMES
c623bd54
LW
398 filedev = statbuf.st_dev;
399 fileino = statbuf.st_ino;
99b89507 400#endif
a687059c
LW
401 filemode = statbuf.st_mode;
402 fileuid = statbuf.st_uid;
403 filegid = statbuf.st_gid;
c623bd54
LW
404 if (!S_ISREG(filemode)) {
405 warn("Can't do inplace edit: %s is not a regular file",
406 oldname );
79072805 407 do_close(gv,FALSE);
c623bd54
LW
408 continue;
409 }
a687059c 410 if (*inplace) {
ff8e2863 411#ifdef SUFFIX
79072805 412 add_suffix(sv,inplace);
ff8e2863 413#else
79072805 414 sv_catpv(sv,inplace);
ff8e2863 415#endif
c623bd54 416#ifndef FLEXFILENAMES
a0d0e21e 417 if (Stat(SvPVX(sv),&statbuf) >= 0
c623bd54 418 && statbuf.st_dev == filedev
39e571d4
LM
419 && statbuf.st_ino == fileino
420#ifdef DJGPP
421 || (_djstat_fail_bits & _STFAIL_TRUENAME)!=0
422#endif
423 ) {
424 warn("Can't do inplace edit: %s would not be uniq",
463ee0b2 425 SvPVX(sv) );
79072805 426 do_close(gv,FALSE);
c623bd54
LW
427 continue;
428 }
429#endif
fe14fcc3 430#ifdef HAS_RENAME
bee1dbe2 431#ifndef DOSISH
463ee0b2 432 if (rename(oldname,SvPVX(sv)) < 0) {
c623bd54 433 warn("Can't rename %s to %s: %s, skipping file",
2304df62 434 oldname, SvPVX(sv), Strerror(errno) );
79072805 435 do_close(gv,FALSE);
c623bd54
LW
436 continue;
437 }
a687059c 438#else
79072805 439 do_close(gv,FALSE);
463ee0b2
LW
440 (void)unlink(SvPVX(sv));
441 (void)rename(oldname,SvPVX(sv));
1193dd27 442 do_open(gv,SvPVX(sv),SvCUR(sv),FALSE,0,0,Nullfp);
55497cff 443#endif /* DOSISH */
ff8e2863 444#else
463ee0b2
LW
445 (void)UNLINK(SvPVX(sv));
446 if (link(oldname,SvPVX(sv)) < 0) {
c623bd54 447 warn("Can't rename %s to %s: %s, skipping file",
2304df62 448 oldname, SvPVX(sv), Strerror(errno) );
79072805 449 do_close(gv,FALSE);
c623bd54
LW
450 continue;
451 }
a687059c
LW
452 (void)UNLINK(oldname);
453#endif
454 }
455 else {
a8c18271 456#if !defined(DOSISH) && !defined(AMIGAOS)
edc7bc49 457# ifndef VMS /* Don't delete; use automatic file versioning */
fe14fcc3
LW
458 if (UNLINK(oldname) < 0) {
459 warn("Can't rename %s to %s: %s, skipping file",
2304df62 460 oldname, SvPVX(sv), Strerror(errno) );
79072805 461 do_close(gv,FALSE);
fe14fcc3
LW
462 continue;
463 }
edc7bc49 464# endif
ff8e2863 465#else
463ee0b2 466 croak("Can't do inplace edit without backup");
ff8e2863 467#endif
a687059c
LW
468 }
469
79072805
LW
470 sv_setpvn(sv,">",1);
471 sv_catpv(sv,oldname);
748a9306 472 SETERRNO(0,0); /* in case sprintf set errno */
c07a80fd 473 if (!do_open(argvoutgv,SvPVX(sv),SvCUR(sv),FALSE,0,0,Nullfp)) {
c623bd54 474 warn("Can't do inplace edit on %s: %s",
2304df62 475 oldname, Strerror(errno) );
79072805 476 do_close(gv,FALSE);
fe14fcc3
LW
477 continue;
478 }
4633a7c4 479 setdefout(argvoutgv);
760ac839 480 lastfd = PerlIO_fileno(IoIFP(GvIOp(argvoutgv)));
a0d0e21e 481 (void)Fstat(lastfd,&statbuf);
fe14fcc3
LW
482#ifdef HAS_FCHMOD
483 (void)fchmod(lastfd,filemode);
a687059c 484#else
3e3baf6d
TB
485# if !(defined(WIN32) && defined(__BORLANDC__))
486 /* Borland runtime creates a readonly file! */
a687059c 487 (void)chmod(oldname,filemode);
3e3baf6d 488# endif
a687059c 489#endif
fe14fcc3
LW
490 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
491#ifdef HAS_FCHOWN
492 (void)fchown(lastfd,fileuid,filegid);
a687059c 493#else
fe14fcc3
LW
494#ifdef HAS_CHOWN
495 (void)chown(oldname,fileuid,filegid);
a687059c 496#endif
b1248f16 497#endif
fe14fcc3 498 }
a687059c 499 }
a0d0e21e 500 return IoIFP(GvIOp(gv));
a687059c
LW
501 }
502 else
760ac839 503 PerlIO_printf(PerlIO_stderr(), "Can't open %s: %s\n",SvPV(sv, na), Strerror(errno));
a687059c
LW
504 }
505 if (inplace) {
79072805 506 (void)do_close(argvoutgv,FALSE);
4633a7c4 507 setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
a687059c
LW
508 }
509 return Nullfp;
510}
511
fe14fcc3 512#ifdef HAS_PIPE
afd9f252 513void
8ac85365 514do_pipe(SV *sv, GV *rgv, GV *wgv)
afd9f252 515{
79072805
LW
516 register IO *rstio;
517 register IO *wstio;
afd9f252
LW
518 int fd[2];
519
79072805 520 if (!rgv)
afd9f252 521 goto badexit;
79072805 522 if (!wgv)
afd9f252
LW
523 goto badexit;
524
a0d0e21e
LW
525 rstio = GvIOn(rgv);
526 wstio = GvIOn(wgv);
afd9f252 527
a0d0e21e 528 if (IoIFP(rstio))
79072805 529 do_close(rgv,FALSE);
a0d0e21e 530 if (IoIFP(wstio))
79072805 531 do_close(wgv,FALSE);
afd9f252
LW
532
533 if (pipe(fd) < 0)
534 goto badexit;
760ac839
LW
535 IoIFP(rstio) = PerlIO_fdopen(fd[0], "r");
536 IoOFP(wstio) = PerlIO_fdopen(fd[1], "w");
8990e307
LW
537 IoIFP(wstio) = IoOFP(wstio);
538 IoTYPE(rstio) = '<';
539 IoTYPE(wstio) = '>';
540 if (!IoIFP(rstio) || !IoOFP(wstio)) {
760ac839 541 if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio));
fe14fcc3 542 else close(fd[0]);
760ac839 543 if (IoOFP(wstio)) PerlIO_close(IoOFP(wstio));
fe14fcc3
LW
544 else close(fd[1]);
545 goto badexit;
546 }
afd9f252 547
79072805 548 sv_setsv(sv,&sv_yes);
afd9f252
LW
549 return;
550
551badexit:
79072805 552 sv_setsv(sv,&sv_undef);
afd9f252
LW
553 return;
554}
b1248f16 555#endif
afd9f252 556
517844ec 557/* explicit renamed to avoid C++ conflict -- kja */
a687059c 558bool
a0d0e21e 559#ifndef CAN_PROTOTYPE
517844ec 560do_close(gv,not_implicit)
79072805 561GV *gv;
517844ec 562bool not_implicit;
8990e307 563#else
517844ec 564do_close(GV *gv, bool not_implicit)
a0d0e21e 565#endif /* CAN_PROTOTYPE */
a687059c 566{
1193dd27
IZ
567 bool retval;
568 IO *io;
a687059c 569
79072805
LW
570 if (!gv)
571 gv = argvgv;
a0d0e21e 572 if (!gv || SvTYPE(gv) != SVt_PVGV) {
748a9306 573 SETERRNO(EBADF,SS$_IVCHAN);
c2ab57d4 574 return FALSE;
99b89507 575 }
79072805
LW
576 io = GvIO(gv);
577 if (!io) { /* never opened */
517844ec 578 if (dowarn && not_implicit)
79072805 579 warn("Close on unopened file <%s>",GvENAME(gv));
a687059c
LW
580 return FALSE;
581 }
1193dd27 582 retval = io_close(io);
517844ec 583 if (not_implicit) {
1193dd27
IZ
584 IoLINES(io) = 0;
585 IoPAGE(io) = 0;
586 IoLINES_LEFT(io) = IoPAGE_LEN(io);
587 }
588 IoTYPE(io) = ' ';
589 return retval;
590}
591
592bool
8ac85365 593io_close(IO *io)
1193dd27
IZ
594{
595 bool retval = FALSE;
596 int status;
597
8990e307
LW
598 if (IoIFP(io)) {
599 if (IoTYPE(io) == '|') {
600 status = my_pclose(IoIFP(io));
f86702cc 601 STATUS_NATIVE_SET(status);
1e422769 602 retval = (STATUS_POSIX == 0);
a687059c 603 }
8990e307 604 else if (IoTYPE(io) == '-')
a687059c
LW
605 retval = TRUE;
606 else {
8990e307 607 if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */
760ac839
LW
608 retval = (PerlIO_close(IoOFP(io)) != EOF);
609 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
c2ab57d4
LW
610 }
611 else
760ac839 612 retval = (PerlIO_close(IoIFP(io)) != EOF);
a687059c 613 }
8990e307 614 IoOFP(io) = IoIFP(io) = Nullfp;
79072805 615 }
1193dd27 616
a687059c
LW
617 return retval;
618}
619
620bool
8ac85365 621do_eof(GV *gv)
a687059c 622{
11343788 623 dTHR;
79072805 624 register IO *io;
a687059c
LW
625 int ch;
626
79072805 627 io = GvIO(gv);
a687059c 628
79072805 629 if (!io)
a687059c
LW
630 return TRUE;
631
8990e307 632 while (IoIFP(io)) {
a687059c 633
760ac839
LW
634 if (PerlIO_has_cntptr(IoIFP(io))) { /* (the code works without this) */
635 if (PerlIO_get_cnt(IoIFP(io)) > 0) /* cheat a little, since */
636 return FALSE; /* this is the most usual case */
637 }
a687059c 638
760ac839 639 ch = PerlIO_getc(IoIFP(io));
a687059c 640 if (ch != EOF) {
760ac839 641 (void)PerlIO_ungetc(IoIFP(io),ch);
a687059c
LW
642 return FALSE;
643 }
760ac839
LW
644 if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
645 if (PerlIO_get_cnt(IoIFP(io)) < -1)
646 PerlIO_set_cnt(IoIFP(io),-1);
647 }
8990e307 648 if (op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
79072805 649 if (!nextargv(argvgv)) /* get another fp handy */
a687059c
LW
650 return TRUE;
651 }
652 else
653 return TRUE; /* normal fp, definitely end of file */
654 }
655 return TRUE;
656}
657
658long
8ac85365 659do_tell(GV *gv)
a687059c 660{
79072805 661 register IO *io;
96e4d5b1 662 register PerlIO *fp;
a687059c 663
96e4d5b1 664 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
bee1dbe2 665#ifdef ULTRIX_STDIO_BOTCH
96e4d5b1 666 if (PerlIO_eof(fp))
667 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
bee1dbe2 668#endif
8903cb82 669 return PerlIO_tell(fp);
96e4d5b1 670 }
a687059c 671 if (dowarn)
8903cb82 672 warn("tell() on unopened file");
748a9306 673 SETERRNO(EBADF,RMS$_IFI);
a687059c
LW
674 return -1L;
675}
676
677bool
8ac85365 678do_seek(GV *gv, long int pos, int whence)
a687059c 679{
79072805 680 register IO *io;
137443ea 681 register PerlIO *fp;
a687059c 682
137443ea 683 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
bee1dbe2 684#ifdef ULTRIX_STDIO_BOTCH
137443ea 685 if (PerlIO_eof(fp))
686 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
bee1dbe2 687#endif
8903cb82 688 return PerlIO_seek(fp, pos, whence) >= 0;
137443ea 689 }
a687059c 690 if (dowarn)
8903cb82 691 warn("seek() on unopened file");
748a9306 692 SETERRNO(EBADF,RMS$_IFI);
a687059c
LW
693 return FALSE;
694}
695
8903cb82 696long
8ac85365 697do_sysseek(GV *gv, long int pos, int whence)
8903cb82 698{
699 register IO *io;
700 register PerlIO *fp;
701
702 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
703 return lseek(PerlIO_fileno(fp), pos, whence);
704 if (dowarn)
705 warn("sysseek() on unopened file");
706 SETERRNO(EBADF,RMS$_IFI);
707 return -1L;
708}
709
a0d0e21e 710#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
c2ab57d4 711 /* code courtesy of William Kucharski */
fe14fcc3 712#define HAS_CHSIZE
6eb13c3b 713
517844ec 714I32 my_chsize(fd, length)
79072805 715I32 fd; /* file descriptor */
85e6fe83 716Off_t length; /* length to set file to */
6eb13c3b 717{
6eb13c3b
LW
718 struct flock fl;
719 struct stat filebuf;
720
a0d0e21e 721 if (Fstat(fd, &filebuf) < 0)
6eb13c3b
LW
722 return -1;
723
724 if (filebuf.st_size < length) {
725
726 /* extend file length */
727
728 if ((lseek(fd, (length - 1), 0)) < 0)
729 return -1;
730
731 /* write a "0" byte */
732
733 if ((write(fd, "", 1)) != 1)
734 return -1;
735 }
736 else {
737 /* truncate length */
738
739 fl.l_whence = 0;
740 fl.l_len = 0;
741 fl.l_start = length;
a0d0e21e 742 fl.l_type = F_WRLCK; /* write lock on file space */
6eb13c3b
LW
743
744 /*
a0d0e21e 745 * This relies on the UNDOCUMENTED F_FREESP argument to
6eb13c3b
LW
746 * fcntl(2), which truncates the file so that it ends at the
747 * position indicated by fl.l_start.
748 *
749 * Will minor miracles never cease?
750 */
751
a0d0e21e 752 if (fcntl(fd, F_FREESP, &fl) < 0)
6eb13c3b
LW
753 return -1;
754
755 }
756
757 return 0;
758}
a0d0e21e 759#endif /* F_FREESP */
ff8e2863 760
a687059c 761bool
8ac85365 762do_print(register SV *sv, FILE *fp)
a687059c
LW
763{
764 register char *tmps;
463ee0b2 765 STRLEN len;
a687059c 766
79072805
LW
767 /* assuming fp is checked earlier */
768 if (!sv)
769 return TRUE;
770 if (ofmt) {
8990e307 771 if (SvGMAGICAL(sv))
79072805 772 mg_get(sv);
463ee0b2 773 if (SvIOK(sv) && SvIVX(sv) != 0) {
760ac839
LW
774 PerlIO_printf(fp, ofmt, (double)SvIVX(sv));
775 return !PerlIO_error(fp);
79072805 776 }
463ee0b2 777 if ( (SvNOK(sv) && SvNVX(sv) != 0.0)
79072805 778 || (looks_like_number(sv) && sv_2nv(sv) != 0.0) ) {
760ac839
LW
779 PerlIO_printf(fp, ofmt, SvNVX(sv));
780 return !PerlIO_error(fp);
79072805 781 }
a687059c 782 }
79072805
LW
783 switch (SvTYPE(sv)) {
784 case SVt_NULL:
8990e307
LW
785 if (dowarn)
786 warn(warn_uninit);
ff8e2863 787 return TRUE;
79072805 788 case SVt_IV:
a0d0e21e
LW
789 if (SvIOK(sv)) {
790 if (SvGMAGICAL(sv))
791 mg_get(sv);
760ac839
LW
792 PerlIO_printf(fp, "%ld", (long)SvIVX(sv));
793 return !PerlIO_error(fp);
a0d0e21e
LW
794 }
795 /* FALL THROUGH */
79072805 796 default:
463ee0b2 797 tmps = SvPV(sv, len);
79072805 798 break;
ff8e2863 799 }
760ac839 800 if (len && (PerlIO_write(fp,tmps,len) == 0 || PerlIO_error(fp)))
a687059c 801 return FALSE;
760ac839 802 return !PerlIO_error(fp);
a687059c
LW
803}
804
79072805 805I32
8ac85365 806my_stat(ARGSproto)
a687059c 807{
4e35701f 808 djSP;
79072805 809 IO *io;
748a9306 810 GV* tmpgv;
79072805 811
a0d0e21e 812 if (op->op_flags & OPf_REF) {
79072805 813 EXTEND(sp,1);
748a9306
LW
814 tmpgv = cGVOP->op_gv;
815 do_fstat:
816 io = GvIO(tmpgv);
8990e307 817 if (io && IoIFP(io)) {
748a9306 818 statgv = tmpgv;
79072805
LW
819 sv_setpv(statname,"");
820 laststype = OP_STAT;
760ac839 821 return (laststatval = Fstat(PerlIO_fileno(IoIFP(io)), &statcache));
a687059c
LW
822 }
823 else {
748a9306 824 if (tmpgv == defgv)
57ebbfd0 825 return laststatval;
a687059c
LW
826 if (dowarn)
827 warn("Stat on unopened file <%s>",
748a9306 828 GvENAME(tmpgv));
79072805
LW
829 statgv = Nullgv;
830 sv_setpv(statname,"");
57ebbfd0 831 return (laststatval = -1);
a687059c
LW
832 }
833 }
834 else {
748a9306 835 SV* sv = POPs;
79072805 836 PUTBACK;
748a9306
LW
837 if (SvTYPE(sv) == SVt_PVGV) {
838 tmpgv = (GV*)sv;
839 goto do_fstat;
840 }
841 else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
842 tmpgv = (GV*)SvRV(sv);
843 goto do_fstat;
844 }
845
79072805 846 statgv = Nullgv;
463ee0b2 847 sv_setpv(statname,SvPV(sv, na));
79072805 848 laststype = OP_STAT;
a0d0e21e 849 laststatval = Stat(SvPV(sv, na),&statcache);
463ee0b2 850 if (laststatval < 0 && dowarn && strchr(SvPV(sv, na), '\n'))
bee1dbe2
LW
851 warn(warn_nl, "stat");
852 return laststatval;
a687059c
LW
853 }
854}
855
79072805 856I32
8ac85365 857my_lstat(ARGSproto)
c623bd54 858{
4e35701f 859 djSP;
79072805 860 SV *sv;
a0d0e21e 861 if (op->op_flags & OPf_REF) {
79072805
LW
862 EXTEND(sp,1);
863 if (cGVOP->op_gv == defgv) {
864 if (laststype != OP_LSTAT)
463ee0b2 865 croak("The stat preceding -l _ wasn't an lstat");
fe14fcc3
LW
866 return laststatval;
867 }
463ee0b2 868 croak("You can't use -l on a filehandle");
fe14fcc3 869 }
c623bd54 870
79072805
LW
871 laststype = OP_LSTAT;
872 statgv = Nullgv;
873 sv = POPs;
874 PUTBACK;
463ee0b2 875 sv_setpv(statname,SvPV(sv, na));
fe14fcc3 876#ifdef HAS_LSTAT
463ee0b2 877 laststatval = lstat(SvPV(sv, na),&statcache);
c623bd54 878#else
a0d0e21e 879 laststatval = Stat(SvPV(sv, na),&statcache);
c623bd54 880#endif
463ee0b2 881 if (laststatval < 0 && dowarn && strchr(SvPV(sv, na), '\n'))
bee1dbe2
LW
882 warn(warn_nl, "lstat");
883 return laststatval;
c623bd54
LW
884}
885
a687059c 886bool
8ac85365 887do_aexec(SV *really, register SV **mark, register SV **sp)
a687059c 888{
a687059c 889 register char **a;
a687059c
LW
890 char *tmps;
891
79072805 892 if (sp > mark) {
11343788 893 dTHR;
79072805 894 New(401,Argv, sp - mark + 1, char*);
bee1dbe2 895 a = Argv;
79072805
LW
896 while (++mark <= sp) {
897 if (*mark)
463ee0b2 898 *a++ = SvPVx(*mark, na);
a687059c
LW
899 else
900 *a++ = "";
901 }
902 *a = Nullch;
bee1dbe2 903 if (*Argv[0] != '/') /* will execvp use PATH? */
79072805 904 TAINT_ENV(); /* testing IFS here is overkill, probably */
463ee0b2 905 if (really && *(tmps = SvPV(really, na)))
bee1dbe2 906 execvp(tmps,Argv);
a687059c 907 else
bee1dbe2 908 execvp(Argv[0],Argv);
a0d0e21e
LW
909 if (dowarn)
910 warn("Can't exec \"%s\": %s", Argv[0], Strerror(errno));
a687059c 911 }
bee1dbe2 912 do_execfree();
a687059c
LW
913 return FALSE;
914}
915
fe14fcc3 916void
8ac85365 917do_execfree(void)
ff8e2863
LW
918{
919 if (Argv) {
920 Safefree(Argv);
921 Argv = Null(char **);
922 }
923 if (Cmd) {
924 Safefree(Cmd);
925 Cmd = Nullch;
926 }
927}
928
39e571d4 929#if !defined(OS2) && !defined(WIN32) && !defined(DJGPP)
760ac839 930
a687059c 931bool
8ac85365 932do_exec(char *cmd)
a687059c
LW
933{
934 register char **a;
935 register char *s;
a687059c
LW
936 char flags[10];
937
748a9306
LW
938 while (*cmd && isSPACE(*cmd))
939 cmd++;
940
a687059c
LW
941 /* save an extra exec if possible */
942
bf38876a
LW
943#ifdef CSH
944 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
a687059c 945 strcpy(flags,"-c");
bf38876a 946 s = cmd+cshlen+3;
a687059c
LW
947 if (*s == 'f') {
948 s++;
949 strcat(flags,"f");
950 }
951 if (*s == ' ')
952 s++;
953 if (*s++ == '\'') {
954 char *ncmd = s;
955
956 while (*s)
957 s++;
958 if (s[-1] == '\n')
959 *--s = '\0';
960 if (s[-1] == '\'') {
961 *--s = '\0';
bf38876a 962 execl(cshname,"csh", flags,ncmd,(char*)0);
a687059c
LW
963 *s = '\'';
964 return FALSE;
965 }
966 }
967 }
bf38876a 968#endif /* CSH */
a687059c
LW
969
970 /* see if there are shell metacharacters in it */
971
748a9306
LW
972 if (*cmd == '.' && isSPACE(cmd[1]))
973 goto doshell;
974
975 if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
976 goto doshell;
977
99b89507 978 for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */
63f2c1e1
LW
979 if (*s == '=')
980 goto doshell;
748a9306 981
a687059c 982 for (s = cmd; *s; s++) {
93a17b20 983 if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
a687059c
LW
984 if (*s == '\n' && !s[1]) {
985 *s = '\0';
986 break;
987 }
988 doshell:
ff68c719 989 execl(sh_path, "sh", "-c", cmd, (char*)0);
a687059c
LW
990 return FALSE;
991 }
992 }
748a9306 993
ff8e2863 994 New(402,Argv, (s - cmd) / 2 + 2, char*);
a0d0e21e 995 Cmd = savepvn(cmd, s-cmd);
ff8e2863
LW
996 a = Argv;
997 for (s = Cmd; *s;) {
99b89507 998 while (*s && isSPACE(*s)) s++;
a687059c
LW
999 if (*s)
1000 *(a++) = s;
99b89507 1001 while (*s && !isSPACE(*s)) s++;
a687059c
LW
1002 if (*s)
1003 *s++ = '\0';
1004 }
1005 *a = Nullch;
ff8e2863
LW
1006 if (Argv[0]) {
1007 execvp(Argv[0],Argv);
b1248f16 1008 if (errno == ENOEXEC) { /* for system V NIH syndrome */
ff8e2863 1009 do_execfree();
a687059c 1010 goto doshell;
b1248f16 1011 }
a0d0e21e
LW
1012 if (dowarn)
1013 warn("Can't exec \"%s\": %s", Argv[0], Strerror(errno));
a687059c 1014 }
ff8e2863 1015 do_execfree();
a687059c
LW
1016 return FALSE;
1017}
1018
6890e559 1019#endif /* OS2 || WIN32 */
760ac839 1020
79072805 1021I32
8ac85365 1022apply(I32 type, register SV **mark, register SV **sp)
a687059c 1023{
11343788 1024 dTHR;
79072805
LW
1025 register I32 val;
1026 register I32 val2;
1027 register I32 tot = 0;
a687059c 1028 char *s;
79072805 1029 SV **oldmark = mark;
a687059c 1030
463ee0b2
LW
1031 if (tainting) {
1032 while (++mark <= sp) {
bbce6d69 1033 if (SvTAINTED(*mark)) {
1034 TAINT;
1035 break;
1036 }
463ee0b2
LW
1037 }
1038 mark = oldmark;
1039 }
a687059c 1040 switch (type) {
79072805
LW
1041 case OP_CHMOD:
1042 TAINT_PROPER("chmod");
1043 if (++mark <= sp) {
1044 tot = sp - mark;
463ee0b2 1045 val = SvIVx(*mark);
79072805 1046 while (++mark <= sp) {
463ee0b2 1047 if (chmod(SvPVx(*mark, na),val))
a687059c
LW
1048 tot--;
1049 }
1050 }
1051 break;
fe14fcc3 1052#ifdef HAS_CHOWN
79072805
LW
1053 case OP_CHOWN:
1054 TAINT_PROPER("chown");
1055 if (sp - mark > 2) {
463ee0b2
LW
1056 val = SvIVx(*++mark);
1057 val2 = SvIVx(*++mark);
a0d0e21e 1058 tot = sp - mark;
79072805 1059 while (++mark <= sp) {
463ee0b2 1060 if (chown(SvPVx(*mark, na),val,val2))
a687059c
LW
1061 tot--;
1062 }
1063 }
1064 break;
b1248f16 1065#endif
fe14fcc3 1066#ifdef HAS_KILL
79072805
LW
1067 case OP_KILL:
1068 TAINT_PROPER("kill");
55497cff 1069 if (mark == sp)
1070 break;
463ee0b2 1071 s = SvPVx(*++mark, na);
79072805
LW
1072 tot = sp - mark;
1073 if (isUPPER(*s)) {
1074 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
1075 s += 3;
1076 if (!(val = whichsig(s)))
463ee0b2 1077 croak("Unrecognized signal name \"%s\"",s);
79072805
LW
1078 }
1079 else
463ee0b2 1080 val = SvIVx(*mark);
3595fcef 1081#ifdef VMS
1082 /* kill() doesn't do process groups (job trees?) under VMS */
1083 if (val < 0) val = -val;
1084 if (val == SIGKILL) {
1085# include <starlet.h>
1086 /* Use native sys$delprc() to insure that target process is
1087 * deleted; supervisor-mode images don't pay attention to
1088 * CRTL's emulation of Unix-style signals and kill()
1089 */
1090 while (++mark <= sp) {
1091 I32 proc = SvIVx(*mark);
1092 register unsigned long int __vmssts;
1093 if (!((__vmssts = sys$delprc(&proc,0)) & 1)) {
1094 tot--;
1095 switch (__vmssts) {
1096 case SS$_NONEXPR:
1097 case SS$_NOSUCHNODE:
1098 SETERRNO(ESRCH,__vmssts);
1099 break;
1100 case SS$_NOPRIV:
1101 SETERRNO(EPERM,__vmssts);
1102 break;
1103 default:
1104 SETERRNO(EVMSERR,__vmssts);
1105 }
1106 }
1107 }
1108 break;
1109 }
1110#endif
79072805
LW
1111 if (val < 0) {
1112 val = -val;
1113 while (++mark <= sp) {
463ee0b2 1114 I32 proc = SvIVx(*mark);
fe14fcc3 1115#ifdef HAS_KILLPG
79072805 1116 if (killpg(proc,val)) /* BSD */
a687059c 1117#else
79072805 1118 if (kill(-proc,val)) /* SYSV */
a687059c 1119#endif
79072805 1120 tot--;
a687059c 1121 }
79072805
LW
1122 }
1123 else {
1124 while (++mark <= sp) {
463ee0b2 1125 if (kill(SvIVx(*mark),val))
79072805 1126 tot--;
a687059c
LW
1127 }
1128 }
1129 break;
b1248f16 1130#endif
79072805
LW
1131 case OP_UNLINK:
1132 TAINT_PROPER("unlink");
1133 tot = sp - mark;
1134 while (++mark <= sp) {
463ee0b2 1135 s = SvPVx(*mark, na);
a687059c
LW
1136 if (euid || unsafe) {
1137 if (UNLINK(s))
1138 tot--;
1139 }
1140 else { /* don't let root wipe out directories without -U */
fe14fcc3 1141#ifdef HAS_LSTAT
c623bd54 1142 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
a687059c 1143#else
a0d0e21e 1144 if (Stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
a687059c 1145#endif
a687059c
LW
1146 tot--;
1147 else {
1148 if (UNLINK(s))
1149 tot--;
1150 }
1151 }
1152 }
1153 break;
a0d0e21e 1154#ifdef HAS_UTIME
79072805
LW
1155 case OP_UTIME:
1156 TAINT_PROPER("utime");
1157 if (sp - mark > 2) {
748a9306 1158#if defined(I_UTIME) || defined(VMS)
663a0e37
LW
1159 struct utimbuf utbuf;
1160#else
a687059c 1161 struct {
663a0e37
LW
1162 long actime;
1163 long modtime;
a687059c 1164 } utbuf;
663a0e37 1165#endif
a687059c 1166
afd9f252 1167 Zero(&utbuf, sizeof utbuf, char);
517844ec 1168#ifdef BIG_TIME
1169 utbuf.actime = (Time_t)SvNVx(*++mark); /* time accessed */
1170 utbuf.modtime = (Time_t)SvNVx(*++mark); /* time modified */
1171#else
463ee0b2
LW
1172 utbuf.actime = SvIVx(*++mark); /* time accessed */
1173 utbuf.modtime = SvIVx(*++mark); /* time modified */
517844ec 1174#endif
79072805
LW
1175 tot = sp - mark;
1176 while (++mark <= sp) {
463ee0b2 1177 if (utime(SvPVx(*mark, na),&utbuf))
a687059c
LW
1178 tot--;
1179 }
a687059c
LW
1180 }
1181 else
79072805 1182 tot = 0;
a687059c 1183 break;
a0d0e21e 1184#endif
a687059c
LW
1185 }
1186 return tot;
1187}
1188
1189/* Do the permissions allow some operation? Assumes statcache already set. */
a0d0e21e 1190#ifndef VMS /* VMS' cando is in vms.c */
79072805 1191I32
8ac85365 1192cando(I32 bit, I32 effective, register struct stat *statbufp)
a687059c 1193{
bee1dbe2 1194#ifdef DOSISH
fe14fcc3
LW
1195 /* [Comments and code from Len Reed]
1196 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
1197 * to write-protected files. The execute permission bit is set
1198 * by the Miscrosoft C library stat() function for the following:
1199 * .exe files
1200 * .com files
1201 * .bat files
1202 * directories
1203 * All files and directories are readable.
1204 * Directories and special files, e.g. "CON", cannot be
1205 * write-protected.
1206 * [Comment by Tom Dinger -- a directory can have the write-protect
1207 * bit set in the file system, but DOS permits changes to
1208 * the directory anyway. In addition, all bets are off
1209 * here for networked software, such as Novell and
1210 * Sun's PC-NFS.]
1211 */
1212
bee1dbe2
LW
1213 /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
1214 * too so it will actually look into the files for magic numbers
1215 */
fe14fcc3
LW
1216 return (bit & statbufp->st_mode) ? TRUE : FALSE;
1217
55497cff 1218#else /* ! DOSISH */
a687059c 1219 if ((effective ? euid : uid) == 0) { /* root is special */
c623bd54
LW
1220 if (bit == S_IXUSR) {
1221 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
a687059c
LW
1222 return TRUE;
1223 }
1224 else
1225 return TRUE; /* root reads and writes anything */
1226 return FALSE;
1227 }
1228 if (statbufp->st_uid == (effective ? euid : uid) ) {
1229 if (statbufp->st_mode & bit)
1230 return TRUE; /* ok as "user" */
1231 }
79072805 1232 else if (ingroup((I32)statbufp->st_gid,effective)) {
a687059c
LW
1233 if (statbufp->st_mode & bit >> 3)
1234 return TRUE; /* ok as "group" */
1235 }
1236 else if (statbufp->st_mode & bit >> 6)
1237 return TRUE; /* ok as "other" */
1238 return FALSE;
55497cff 1239#endif /* ! DOSISH */
a687059c 1240}
a0d0e21e 1241#endif /* ! VMS */
a687059c 1242
79072805 1243I32
8ac85365 1244ingroup(I32 testgid, I32 effective)
a687059c
LW
1245{
1246 if (testgid == (effective ? egid : gid))
1247 return TRUE;
fe14fcc3 1248#ifdef HAS_GETGROUPS
a687059c
LW
1249#ifndef NGROUPS
1250#define NGROUPS 32
1251#endif
1252 {
a0d0e21e 1253 Groups_t gary[NGROUPS];
79072805 1254 I32 anum;
a687059c
LW
1255
1256 anum = getgroups(NGROUPS,gary);
1257 while (--anum >= 0)
1258 if (gary[anum] == testgid)
1259 return TRUE;
1260 }
1261#endif
1262 return FALSE;
1263}
c2ab57d4 1264
fe14fcc3 1265#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
c2ab57d4 1266
79072805 1267I32
8ac85365 1268do_ipcget(I32 optype, SV **mark, SV **sp)
c2ab57d4 1269{
11343788 1270 dTHR;
c2ab57d4 1271 key_t key;
79072805 1272 I32 n, flags;
c2ab57d4 1273
463ee0b2
LW
1274 key = (key_t)SvNVx(*++mark);
1275 n = (optype == OP_MSGGET) ? 0 : SvIVx(*++mark);
1276 flags = SvIVx(*++mark);
748a9306 1277 SETERRNO(0,0);
c2ab57d4
LW
1278 switch (optype)
1279 {
fe14fcc3 1280#ifdef HAS_MSG
79072805 1281 case OP_MSGGET:
c2ab57d4 1282 return msgget(key, flags);
e5d73d77 1283#endif
fe14fcc3 1284#ifdef HAS_SEM
79072805 1285 case OP_SEMGET:
c2ab57d4 1286 return semget(key, n, flags);
e5d73d77 1287#endif
fe14fcc3 1288#ifdef HAS_SHM
79072805 1289 case OP_SHMGET:
c2ab57d4 1290 return shmget(key, n, flags);
e5d73d77 1291#endif
fe14fcc3 1292#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
e5d73d77 1293 default:
c07a80fd 1294 croak("%s not implemented", op_desc[optype]);
e5d73d77 1295#endif
c2ab57d4
LW
1296 }
1297 return -1; /* should never happen */
1298}
1299
79072805 1300I32
8ac85365 1301do_ipcctl(I32 optype, SV **mark, SV **sp)
c2ab57d4 1302{
11343788 1303 dTHR;
79072805 1304 SV *astr;
c2ab57d4 1305 char *a;
a0d0e21e
LW
1306 I32 id, n, cmd, infosize, getinfo;
1307 I32 ret = -1;
3e3baf6d
TB
1308#ifdef __linux__ /* XXX Need metaconfig test */
1309 union semun unsemds;
1310#endif
c2ab57d4 1311
463ee0b2
LW
1312 id = SvIVx(*++mark);
1313 n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
1314 cmd = SvIVx(*++mark);
79072805 1315 astr = *++mark;
c2ab57d4
LW
1316 infosize = 0;
1317 getinfo = (cmd == IPC_STAT);
1318
1319 switch (optype)
1320 {
fe14fcc3 1321#ifdef HAS_MSG
79072805 1322 case OP_MSGCTL:
c2ab57d4
LW
1323 if (cmd == IPC_STAT || cmd == IPC_SET)
1324 infosize = sizeof(struct msqid_ds);
1325 break;
e5d73d77 1326#endif
fe14fcc3 1327#ifdef HAS_SHM
79072805 1328 case OP_SHMCTL:
c2ab57d4
LW
1329 if (cmd == IPC_STAT || cmd == IPC_SET)
1330 infosize = sizeof(struct shmid_ds);
1331 break;
e5d73d77 1332#endif
fe14fcc3 1333#ifdef HAS_SEM
79072805 1334 case OP_SEMCTL:
c2ab57d4
LW
1335 if (cmd == IPC_STAT || cmd == IPC_SET)
1336 infosize = sizeof(struct semid_ds);
1337 else if (cmd == GETALL || cmd == SETALL)
1338 {
8e591e46 1339 struct semid_ds semds;
3e3baf6d 1340#ifdef __linux__ /* XXX Need metaconfig test */
84902520
TB
1341/* linux (and Solaris2?) uses :
1342 int semctl (int semid, int semnum, int cmd, union semun arg)
3e3baf6d
TB
1343 union semun {
1344 int val;
1345 struct semid_ds *buf;
1346 ushort *array;
1347 };
1348*/
84902520
TB
1349 union semun semun;
1350 semun.buf = &semds;
1351 if (semctl(id, 0, IPC_STAT, semun) == -1)
3e3baf6d 1352#else
c2ab57d4 1353 if (semctl(id, 0, IPC_STAT, &semds) == -1)
3e3baf6d 1354#endif
c2ab57d4
LW
1355 return -1;
1356 getinfo = (cmd == GETALL);
6e21c824
LW
1357 infosize = semds.sem_nsems * sizeof(short);
1358 /* "short" is technically wrong but much more portable
1359 than guessing about u_?short(_t)? */
c2ab57d4
LW
1360 }
1361 break;
e5d73d77 1362#endif
fe14fcc3 1363#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
e5d73d77 1364 default:
c07a80fd 1365 croak("%s not implemented", op_desc[optype]);
e5d73d77 1366#endif
c2ab57d4
LW
1367 }
1368
1369 if (infosize)
1370 {
a0d0e21e 1371 STRLEN len;
c2ab57d4
LW
1372 if (getinfo)
1373 {
a0d0e21e
LW
1374 SvPV_force(astr, len);
1375 a = SvGROW(astr, infosize+1);
c2ab57d4
LW
1376 }
1377 else
1378 {
463ee0b2
LW
1379 a = SvPV(astr, len);
1380 if (len != infosize)
9607fc9c 1381 croak("Bad arg length for %s, is %lu, should be %ld",
1382 op_desc[optype], (unsigned long)len, (long)infosize);
c2ab57d4
LW
1383 }
1384 }
1385 else
1386 {
c030ccd9 1387 IV i = SvIV(astr);
c2ab57d4
LW
1388 a = (char *)i; /* ouch */
1389 }
748a9306 1390 SETERRNO(0,0);
c2ab57d4
LW
1391 switch (optype)
1392 {
fe14fcc3 1393#ifdef HAS_MSG
79072805 1394 case OP_MSGCTL:
bee1dbe2 1395 ret = msgctl(id, cmd, (struct msqid_ds *)a);
c2ab57d4 1396 break;
e5d73d77 1397#endif
fe14fcc3 1398#ifdef HAS_SEM
79072805 1399 case OP_SEMCTL:
3e3baf6d
TB
1400#ifdef __linux__ /* XXX Need metaconfig test */
1401 unsemds.buf = (struct semid_ds *)a;
1402 ret = semctl(id, n, cmd, unsemds);
1403#else
79072805 1404 ret = semctl(id, n, cmd, (struct semid_ds *)a);
3e3baf6d 1405#endif
c2ab57d4 1406 break;
e5d73d77 1407#endif
fe14fcc3 1408#ifdef HAS_SHM
79072805 1409 case OP_SHMCTL:
bee1dbe2 1410 ret = shmctl(id, cmd, (struct shmid_ds *)a);
c2ab57d4 1411 break;
e5d73d77 1412#endif
c2ab57d4
LW
1413 }
1414 if (getinfo && ret >= 0) {
79072805
LW
1415 SvCUR_set(astr, infosize);
1416 *SvEND(astr) = '\0';
a0d0e21e 1417 SvSETMAGIC(astr);
c2ab57d4
LW
1418 }
1419 return ret;
1420}
1421
79072805 1422I32
8ac85365 1423do_msgsnd(SV **mark, SV **sp)
c2ab57d4 1424{
fe14fcc3 1425#ifdef HAS_MSG
11343788 1426 dTHR;
79072805 1427 SV *mstr;
c2ab57d4 1428 char *mbuf;
79072805 1429 I32 id, msize, flags;
463ee0b2 1430 STRLEN len;
c2ab57d4 1431
463ee0b2 1432 id = SvIVx(*++mark);
79072805 1433 mstr = *++mark;
463ee0b2
LW
1434 flags = SvIVx(*++mark);
1435 mbuf = SvPV(mstr, len);
1436 if ((msize = len - sizeof(long)) < 0)
1437 croak("Arg too short for msgsnd");
748a9306 1438 SETERRNO(0,0);
bee1dbe2 1439 return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
e5d73d77 1440#else
463ee0b2 1441 croak("msgsnd not implemented");
e5d73d77 1442#endif
c2ab57d4
LW
1443}
1444
79072805 1445I32
8ac85365 1446do_msgrcv(SV **mark, SV **sp)
c2ab57d4 1447{
fe14fcc3 1448#ifdef HAS_MSG
11343788 1449 dTHR;
79072805 1450 SV *mstr;
c2ab57d4
LW
1451 char *mbuf;
1452 long mtype;
79072805 1453 I32 id, msize, flags, ret;
463ee0b2 1454 STRLEN len;
79072805 1455
463ee0b2 1456 id = SvIVx(*++mark);
79072805 1457 mstr = *++mark;
463ee0b2
LW
1458 msize = SvIVx(*++mark);
1459 mtype = (long)SvIVx(*++mark);
1460 flags = SvIVx(*++mark);
ed6116ce
LW
1461 if (SvTHINKFIRST(mstr)) {
1462 if (SvREADONLY(mstr))
1463 croak("Can't msgrcv to readonly var");
1464 if (SvROK(mstr))
1465 sv_unref(mstr);
1466 }
a0d0e21e
LW
1467 SvPV_force(mstr, len);
1468 mbuf = SvGROW(mstr, sizeof(long)+msize+1);
1469
748a9306 1470 SETERRNO(0,0);
bee1dbe2 1471 ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
c2ab57d4 1472 if (ret >= 0) {
79072805
LW
1473 SvCUR_set(mstr, sizeof(long)+ret);
1474 *SvEND(mstr) = '\0';
c2ab57d4
LW
1475 }
1476 return ret;
e5d73d77 1477#else
463ee0b2 1478 croak("msgrcv not implemented");
e5d73d77 1479#endif
c2ab57d4
LW
1480}
1481
79072805 1482I32
8ac85365 1483do_semop(SV **mark, SV **sp)
c2ab57d4 1484{
fe14fcc3 1485#ifdef HAS_SEM
11343788 1486 dTHR;
79072805 1487 SV *opstr;
c2ab57d4 1488 char *opbuf;
463ee0b2
LW
1489 I32 id;
1490 STRLEN opsize;
c2ab57d4 1491
463ee0b2 1492 id = SvIVx(*++mark);
79072805 1493 opstr = *++mark;
463ee0b2 1494 opbuf = SvPV(opstr, opsize);
c2ab57d4
LW
1495 if (opsize < sizeof(struct sembuf)
1496 || (opsize % sizeof(struct sembuf)) != 0) {
748a9306 1497 SETERRNO(EINVAL,LIB$_INVARG);
c2ab57d4
LW
1498 return -1;
1499 }
748a9306 1500 SETERRNO(0,0);
6e21c824 1501 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
e5d73d77 1502#else
463ee0b2 1503 croak("semop not implemented");
e5d73d77 1504#endif
c2ab57d4
LW
1505}
1506
79072805 1507I32
8ac85365 1508do_shmio(I32 optype, SV **mark, SV **sp)
c2ab57d4 1509{
fe14fcc3 1510#ifdef HAS_SHM
11343788 1511 dTHR;
79072805 1512 SV *mstr;
c2ab57d4 1513 char *mbuf, *shm;
79072805 1514 I32 id, mpos, msize;
463ee0b2 1515 STRLEN len;
c2ab57d4 1516 struct shmid_ds shmds;
c2ab57d4 1517
463ee0b2 1518 id = SvIVx(*++mark);
79072805 1519 mstr = *++mark;
463ee0b2
LW
1520 mpos = SvIVx(*++mark);
1521 msize = SvIVx(*++mark);
748a9306 1522 SETERRNO(0,0);
c2ab57d4
LW
1523 if (shmctl(id, IPC_STAT, &shmds) == -1)
1524 return -1;
1525 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
748a9306 1526 SETERRNO(EFAULT,SS$_ACCVIO); /* can't do as caller requested */
c2ab57d4
LW
1527 return -1;
1528 }
8ac85365 1529 shm = (char *)shmat(id, (char*)NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
c2ab57d4
LW
1530 if (shm == (char *)-1) /* I hate System V IPC, I really do */
1531 return -1;
79072805 1532 if (optype == OP_SHMREAD) {
a0d0e21e
LW
1533 SvPV_force(mstr, len);
1534 mbuf = SvGROW(mstr, msize+1);
1535
bee1dbe2 1536 Copy(shm + mpos, mbuf, msize, char);
79072805
LW
1537 SvCUR_set(mstr, msize);
1538 *SvEND(mstr) = '\0';
a0d0e21e 1539 SvSETMAGIC(mstr);
c2ab57d4
LW
1540 }
1541 else {
79072805 1542 I32 n;
c2ab57d4 1543
a0d0e21e 1544 mbuf = SvPV(mstr, len);
463ee0b2 1545 if ((n = len) > msize)
c2ab57d4 1546 n = msize;
bee1dbe2 1547 Copy(mbuf, shm + mpos, n, char);
c2ab57d4 1548 if (n < msize)
bee1dbe2 1549 memzero(shm + mpos + n, msize - n);
c2ab57d4
LW
1550 }
1551 return shmdt(shm);
e5d73d77 1552#else
463ee0b2 1553 croak("shm I/O not implemented");
e5d73d77 1554#endif
c2ab57d4
LW
1555}
1556
fe14fcc3 1557#endif /* SYSV IPC */
4e35701f 1558