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