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