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