Win32 passes all but t/lib/peek.t with perlio and home-grown crlf.
[p5sagit/p5-mst-13.2.git] / doio.c
CommitLineData
a0d0e21e 1/* doio.c
a687059c 2 *
3818b22b 3 * Copyright (c) 1991-2000, 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"
864dbfa3 18#define PERL_IN_DOIO_C
a687059c 19#include "perl.h"
20
fe14fcc3 21#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
aec308ec 22#ifndef HAS_SEM
c2ab57d4 23#include <sys/ipc.h>
aec308ec 24#endif
fe14fcc3 25#ifdef HAS_MSG
c2ab57d4 26#include <sys/msg.h>
e5d73d77 27#endif
fe14fcc3 28#ifdef HAS_SHM
c2ab57d4 29#include <sys/shm.h>
a0d0e21e 30# ifndef HAS_SHMAT_PROTOTYPE
20ce7b12 31 extern Shmat_t shmat (int, char *, int);
a0d0e21e 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
85aff577 44#ifdef O_EXCL
45# define OPEN_EXCL O_EXCL
46#else
47# define OPEN_EXCL 0
48#endif
a687059c 49
76121258 50#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
51#include <signal.h>
52#endif
53
fab3f3a7 54#ifdef SOCKS_64BIT_BUG
55typedef struct __s64_iobuffer {
56 struct __s64_iobuffer *next, *last; /* Queue pointer */
57 PerlIO *fp; /* assigned file pointer */
58 int cnt; /* Buffer counter */
59 int size; /* Buffer size */
60 int *buffer; /* the buffer */
61} S64_IOB;
62
fab3f3a7 63#endif
64
a687059c 65bool
6170680b 66Perl_do_open(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
67 int rawmode, int rawperm, PerlIO *supplied_fp)
68{
69 return do_open9(gv, name, len, as_raw, rawmode, rawperm,
70 supplied_fp, Nullsv, 0);
71}
72
73bool
74Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
75 int rawmode, int rawperm, PerlIO *supplied_fp, SV *svs,
76 I32 num_svs)
a687059c 77{
a0d0e21e 78 register IO *io = GvIOn(gv);
760ac839 79 PerlIO *saveifp = Nullfp;
80 PerlIO *saveofp = Nullfp;
9f37169a 81 char savetype = IoTYPE_CLOSED;
c07a80fd 82 int writing = 0;
760ac839 83 PerlIO *fp;
c07a80fd 84 int fd;
85 int result;
3500f679 86 bool was_fdopen = FALSE;
16fe6d59 87 bool in_raw = 0, in_crlf = 0, out_raw = 0, out_crlf = 0;
b931b1d9 88 char *type = NULL;
89 char *deftype = NULL;
90 char mode[4]; /* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */
a687059c 91
b931b1d9 92 Zero(mode,sizeof(mode),char);
3280af22 93 PL_forkprocess = 1; /* assume true if no fork */
c07a80fd 94
b931b1d9 95 /* Collect default raw/crlf info from the op */
16fe6d59 96 if (PL_op && PL_op->op_type == OP_OPEN) {
97 /* set up disciplines */
98 U8 flags = PL_op->op_private;
99 in_raw = (flags & OPpOPEN_IN_RAW);
100 in_crlf = (flags & OPpOPEN_IN_CRLF);
101 out_raw = (flags & OPpOPEN_OUT_RAW);
102 out_crlf = (flags & OPpOPEN_OUT_CRLF);
103 }
104
b931b1d9 105 /* If currently open - close before we re-open */
a0d0e21e 106 if (IoIFP(io)) {
760ac839 107 fd = PerlIO_fileno(IoIFP(io));
50952442 108 if (IoTYPE(io) == IoTYPE_STD)
c2ab57d4 109 result = 0;
3280af22 110 else if (fd <= PL_maxsysfd) {
8990e307 111 saveifp = IoIFP(io);
112 saveofp = IoOFP(io);
113 savetype = IoTYPE(io);
6e21c824 114 result = 0;
115 }
50952442 116 else if (IoTYPE(io) == IoTYPE_PIPE)
3028581b 117 result = PerlProc_pclose(IoIFP(io));
8990e307 118 else if (IoIFP(io) != IoOFP(io)) {
119 if (IoOFP(io)) {
760ac839 120 result = PerlIO_close(IoOFP(io));
6170680b 121 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
c2ab57d4 122 }
123 else
760ac839 124 result = PerlIO_close(IoIFP(io));
a687059c 125 }
a687059c 126 else
760ac839 127 result = PerlIO_close(IoIFP(io));
3280af22 128 if (result == EOF && fd > PL_maxsysfd)
bf49b057 129 PerlIO_printf(Perl_error_log,
6170680b 130 "Warning: unable to close filehandle %s properly.\n",
131 GvENAME(gv));
8990e307 132 IoOFP(io) = IoIFP(io) = Nullfp;
a687059c 133 }
c07a80fd 134
135 if (as_raw) {
b931b1d9 136 /* sysopen style args, i.e. integer mode and permissions */
137
09458382 138#if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
5ff3f7a4 139 rawmode |= O_LARGEFILE;
140#endif
141
9d116dd7 142#ifndef O_ACCMODE
143#define O_ACCMODE 3 /* Assume traditional implementation */
144#endif
5ff3f7a4 145
9d116dd7 146 switch (result = rawmode & O_ACCMODE) {
147 case O_RDONLY:
50952442 148 IoTYPE(io) = IoTYPE_RDONLY;
9d116dd7 149 break;
150 case O_WRONLY:
50952442 151 IoTYPE(io) = IoTYPE_WRONLY;
9d116dd7 152 break;
153 case O_RDWR:
154 default:
50952442 155 IoTYPE(io) = IoTYPE_RDWR;
9d116dd7 156 break;
157 }
158
c07a80fd 159 writing = (result > 0);
3028581b 160 fd = PerlLIO_open3(name, rawmode, rawperm);
9d116dd7 161
c07a80fd 162 if (fd == -1)
163 fp = NULL;
164 else {
16fe6d59 165 STRLEN ix = 0;
b931b1d9 166 if (result == O_RDONLY) {
167 mode[ix++] = 'r';
168 }
360e5741 169#ifdef O_APPEND
16fe6d59 170 else if (rawmode & O_APPEND) {
b931b1d9 171 mode[ix++] = 'a';
16fe6d59 172 if (result != O_WRONLY)
b931b1d9 173 mode[ix++] = '+';
16fe6d59 174 }
360e5741 175#endif
16fe6d59 176 else {
177 if (result == O_WRONLY)
b931b1d9 178 mode[ix++] = 'w';
16fe6d59 179 else {
b931b1d9 180 mode[ix++] = 'r';
181 mode[ix++] = '+';
16fe6d59 182 }
183 }
184 if (rawmode & O_BINARY)
b931b1d9 185 mode[ix++] = 'b';
186 mode[ix] = '\0';
187 fp = PerlIO_fdopen(fd, mode);
c07a80fd 188 if (!fp)
3028581b 189 PerlLIO_close(fd);
c07a80fd 190 }
a687059c 191 }
c07a80fd 192 else {
b931b1d9 193 /* Regular (non-sys) open */
faecd977 194 char *oname = name;
faecd977 195 STRLEN olen = len;
b931b1d9 196 char *tend;
197 int dodup = 0;
c07a80fd 198
faecd977 199 type = savepvn(name, len);
b931b1d9 200 tend = type+len;
faecd977 201 SAVEFREEPV(type);
b931b1d9 202 /* Loose trailing white space */
203 while (tend > type && isSPACE(tend[-1]))
204 *tend-- = '\0';
6170680b 205 if (num_svs) {
b931b1d9 206 /* New style explict name, type is just mode and discipline/layer info */
faecd977 207 STRLEN l;
208 name = SvPV(svs, l) ;
209 len = (I32)l;
210 name = savepvn(name, len);
211 SAVEFREEPV(name);
b931b1d9 212 /*SUPPRESS 530*/
213 for (; isSPACE(*type); type++) ;
6170680b 214 }
faecd977 215 else {
faecd977 216 name = type;
b931b1d9 217 len = tend-type;
faecd977 218 }
6170680b 219 IoTYPE(io) = *type;
b931b1d9 220 if (*type == IoTYPE_RDWR && (!num_svs || tend > type+1 && tend[-1] != IoTYPE_PIPE)) { /* scary */
6170680b 221 mode[1] = *type++;
c07a80fd 222 writing = 1;
a687059c 223 }
c07a80fd 224
9f37169a 225 if (*type == IoTYPE_PIPE) {
b931b1d9 226 if (num_svs) {
227 if (type[1] != IoTYPE_STD) {
228 unknown_desr:
229 Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
230 }
231 type++;
6170680b 232 }
c07a80fd 233 /*SUPPRESS 530*/
b931b1d9 234 for (type++; isSPACE(*type); type++) ;
faecd977 235 if (!num_svs) {
6170680b 236 name = type;
b931b1d9 237 len = tend-type;
faecd977 238 }
06eaf0bc 239 if (*name == '\0') { /* command is missing 19990114 */
240 dTHR;
241 if (ckWARN(WARN_PIPE))
cea2e8a9 242 Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
06eaf0bc 243 errno = EPIPE;
244 goto say_false;
245 }
6170680b 246 if (strNE(name,"-") || num_svs)
c07a80fd 247 TAINT_ENV();
248 TAINT_PROPER("piped open");
b931b1d9 249 if (!num_svs && name[len-1] == '|') {
d008e5eb 250 dTHR;
faecd977 251 name[--len] = '\0' ;
599cee73 252 if (ckWARN(WARN_PIPE))
9a7dcd9c 253 Perl_warner(aTHX_ WARN_PIPE, "Can't open bidirectional pipe");
7b8d334a 254 }
a1d180c4 255 mode[0] = 'w';
c07a80fd 256 writing = 1;
a1d180c4 257 if (out_raw)
258 strcat(mode, "b");
259 else if (out_crlf)
260 strcat(mode, "t");
261 fp = PerlProc_popen(name,mode);
c07a80fd 262 }
9f37169a 263 else if (*type == IoTYPE_WRONLY) {
c07a80fd 264 TAINT_PROPER("open");
6170680b 265 type++;
9f37169a 266 if (*type == IoTYPE_WRONLY) {
267 /* Two IoTYPE_WRONLYs in a row make for an IoTYPE_APPEND. */
50952442 268 mode[0] = IoTYPE(io) = IoTYPE_APPEND;
6170680b 269 type++;
a0d0e21e 270 }
c07a80fd 271 else
272 mode[0] = 'w';
273 writing = 1;
274
16fe6d59 275 if (out_raw)
276 strcat(mode, "b");
277 else if (out_crlf)
278 strcat(mode, "t");
279
6170680b 280 if (*type == '&') {
281 name = type;
c07a80fd 282 duplicity:
b931b1d9 283 if (num_svs)
284 goto unknown_desr;
c07a80fd 285 dodup = 1;
286 name++;
287 if (*name == '=') {
288 dodup = 0;
a0d0e21e 289 name++;
c07a80fd 290 }
291 if (!*name && supplied_fp)
292 fp = supplied_fp;
a0d0e21e 293 else {
c07a80fd 294 /*SUPPRESS 530*/
295 for (; isSPACE(*name); name++) ;
296 if (isDIGIT(*name))
297 fd = atoi(name);
298 else {
299 IO* thatio;
300 gv = gv_fetchpv(name,FALSE,SVt_PVIO);
301 thatio = GvIO(gv);
302 if (!thatio) {
6e21c824 303#ifdef EINVAL
c07a80fd 304 SETERRNO(EINVAL,SS$_IVCHAN);
6e21c824 305#endif
c07a80fd 306 goto say_false;
307 }
308 if (IoIFP(thatio)) {
54195c32 309 PerlIO *fp = IoIFP(thatio);
7211d486 310 /* Flush stdio buffer before dup. --mjd
311 * Unfortunately SEEK_CURing 0 seems to
312 * be optimized away on most platforms;
313 * only Solaris and Linux seem to flush
314 * on that. --jhi */
2c534a3f 315#ifdef USE_SFIO
316 /* sfio fails to clear error on next
317 sfwrite, contrary to documentation.
318 -- Nick Clark */
319 if (PerlIO_seek(fp, 0, SEEK_CUR) == -1)
320 PerlIO_clearerr(fp);
321#endif
7211d486 322 /* On the other hand, do all platforms
323 * take gracefully to flushing a read-only
324 * filehandle? Perhaps we should do
325 * fsetpos(src)+fgetpos(dst)? --nik */
326 PerlIO_flush(fp);
54195c32 327 fd = PerlIO_fileno(fp);
0759c907 328 /* When dup()ing STDIN, STDOUT or STDERR
329 * explicitly set appropriate access mode */
330 if (IoIFP(thatio) == PerlIO_stdout()
331 || IoIFP(thatio) == PerlIO_stderr())
332 IoTYPE(io) = IoTYPE_WRONLY;
333 else if (IoIFP(thatio) == PerlIO_stdin())
334 IoTYPE(io) = IoTYPE_RDONLY;
335 /* When dup()ing a socket, say result is
336 * one as well */
337 else if (IoTYPE(thatio) == IoTYPE_SOCKET)
50952442 338 IoTYPE(io) = IoTYPE_SOCKET;
c07a80fd 339 }
340 else
341 fd = -1;
a0d0e21e 342 }
fec02dd3 343 if (dodup)
3028581b 344 fd = PerlLIO_dup(fd);
3500f679 345 else
346 was_fdopen = TRUE;
760ac839 347 if (!(fp = PerlIO_fdopen(fd,mode))) {
c07a80fd 348 if (dodup)
3028581b 349 PerlLIO_close(fd);
faecd977 350 }
c07a80fd 351 }
bf38876a 352 }
c07a80fd 353 else {
354 /*SUPPRESS 530*/
6170680b 355 for (; isSPACE(*type); type++) ;
b931b1d9 356 if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
357 /*SUPPRESS 530*/
358 type++;
760ac839 359 fp = PerlIO_stdout();
50952442 360 IoTYPE(io) = IoTYPE_STD;
c07a80fd 361 }
362 else {
6170680b 363 fp = PerlIO_open((num_svs ? name : type), mode);
c07a80fd 364 }
bf38876a 365 }
366 }
9f37169a 367 else if (*type == IoTYPE_RDONLY) {
c07a80fd 368 /*SUPPRESS 530*/
6170680b 369 for (type++; isSPACE(*type); type++) ;
bf38876a 370 mode[0] = 'r';
16fe6d59 371 if (in_raw)
372 strcat(mode, "b");
373 else if (in_crlf)
374 strcat(mode, "t");
375
6170680b 376 if (*type == '&') {
377 name = type;
bf38876a 378 goto duplicity;
6170680b 379 }
b931b1d9 380 if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
381 /*SUPPRESS 530*/
382 type++;
760ac839 383 fp = PerlIO_stdin();
50952442 384 IoTYPE(io) = IoTYPE_STD;
a687059c 385 }
bf38876a 386 else
6170680b 387 fp = PerlIO_open((num_svs ? name : type), mode);
a687059c 388 }
b931b1d9 389 else if ((num_svs && type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
390 (!num_svs && tend > type+1 && tend[-1] == IoTYPE_PIPE)) {
6170680b 391 if (num_svs) {
b931b1d9 392 type += 2; /* skip over '-|' */
6170680b 393 }
394 else {
b931b1d9 395 *--tend = '\0';
396 while (tend > type && isSPACE(tend[-1]))
397 *--tend = '\0';
6170680b 398 /*SUPPRESS 530*/
399 for (; isSPACE(*type); type++) ;
400 name = type;
b931b1d9 401 len = tend-type;
6170680b 402 }
06eaf0bc 403 if (*name == '\0') { /* command is missing 19990114 */
404 dTHR;
405 if (ckWARN(WARN_PIPE))
cea2e8a9 406 Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
06eaf0bc 407 errno = EPIPE;
408 goto say_false;
409 }
6170680b 410 if (strNE(name,"-") || num_svs)
79072805 411 TAINT_ENV();
412 TAINT_PROPER("piped open");
a1d180c4 413 mode[0] = 'r';
414 if (in_raw)
415 strcat(mode, "b");
416 else if (in_crlf)
417 strcat(mode, "t");
418 fp = PerlProc_popen(name,mode);
50952442 419 IoTYPE(io) = IoTYPE_PIPE;
a687059c 420 }
421 else {
6170680b 422 if (num_svs)
423 goto unknown_desr;
424 name = type;
50952442 425 IoTYPE(io) = IoTYPE_RDONLY;
99b89507 426 /*SUPPRESS 530*/
427 for (; isSPACE(*name); name++) ;
88b61e10 428 mode[0] = 'r';
429 if (in_raw)
430 strcat(mode, "b");
431 else if (in_crlf)
432 strcat(mode, "t");
a687059c 433 if (strEQ(name,"-")) {
760ac839 434 fp = PerlIO_stdin();
50952442 435 IoTYPE(io) = IoTYPE_STD;
a687059c 436 }
16fe6d59 437 else {
16fe6d59 438 fp = PerlIO_open(name,mode);
439 }
a687059c 440 }
441 }
bee1dbe2 442 if (!fp) {
d008e5eb 443 dTHR;
50952442 444 if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n'))
cea2e8a9 445 Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
6e21c824 446 goto say_false;
bee1dbe2 447 }
88b61e10 448 if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD) {
96827780 449 dTHR;
3280af22 450 if (PerlLIO_fstat(PerlIO_fileno(fp),&PL_statbuf) < 0) {
760ac839 451 (void)PerlIO_close(fp);
6e21c824 452 goto say_false;
a687059c 453 }
3280af22 454 if (S_ISSOCK(PL_statbuf.st_mode))
50952442 455 IoTYPE(io) = IoTYPE_SOCKET; /* in case a socket was passed in to us */
99b89507 456#ifdef HAS_SOCKET
457 else if (
c623bd54 458#ifdef S_IFMT
3280af22 459 !(PL_statbuf.st_mode & S_IFMT)
99b89507 460#else
b28d0864 461 !PL_statbuf.st_mode
99b89507 462#endif
0759c907 463 && IoTYPE(io) != IoTYPE_WRONLY /* Dups of STD* filehandles already have */
464 && IoTYPE(io) != IoTYPE_RDONLY /* type so they aren't marked as sockets */
465 ) { /* on OS's that return 0 on fstat()ed pipe */
96827780 466 char tmpbuf[256];
467 Sock_size_t buflen = sizeof tmpbuf;
3028581b 468 if (PerlSock_getsockname(PerlIO_fileno(fp), (struct sockaddr *)tmpbuf,
d574b85e 469 &buflen) >= 0
470 || errno != ENOTSOCK)
50952442 471 IoTYPE(io) = IoTYPE_SOCKET; /* some OS's return 0 on fstat()ed socket */
99b89507 472 /* but some return 0 for streams too, sigh */
473 }
bf38876a 474#endif
a687059c 475 }
6e21c824 476 if (saveifp) { /* must use old fp? */
760ac839 477 fd = PerlIO_fileno(saveifp);
6e21c824 478 if (saveofp) {
760ac839 479 PerlIO_flush(saveofp); /* emulate PerlIO_close() */
6e21c824 480 if (saveofp != saveifp) { /* was a socket? */
760ac839 481 PerlIO_close(saveofp);
99b89507 482 if (fd > 2)
483 Safefree(saveofp);
6e21c824 484 }
485 }
760ac839 486 if (fd != PerlIO_fileno(fp)) {
d8a83dd3 487 Pid_t pid;
79072805 488 SV *sv;
bee1dbe2 489
3028581b 490 PerlLIO_dup2(PerlIO_fileno(fp), fd);
4755096e 491 LOCK_FDPID_MUTEX;
3280af22 492 sv = *av_fetch(PL_fdpid,PerlIO_fileno(fp),TRUE);
a0d0e21e 493 (void)SvUPGRADE(sv, SVt_IV);
463ee0b2 494 pid = SvIVX(sv);
495 SvIVX(sv) = 0;
3280af22 496 sv = *av_fetch(PL_fdpid,fd,TRUE);
4755096e 497 UNLOCK_FDPID_MUTEX;
a0d0e21e 498 (void)SvUPGRADE(sv, SVt_IV);
463ee0b2 499 SvIVX(sv) = pid;
3500f679 500 if (!was_fdopen)
501 PerlIO_close(fp);
bee1dbe2 502
6e21c824 503 }
504 fp = saveifp;
760ac839 505 PerlIO_clearerr(fp);
6e21c824 506 }
a0d0e21e 507#if defined(HAS_FCNTL) && defined(F_SETFD)
a8710ca1 508 {
509 int save_errno = errno;
510 fd = PerlIO_fileno(fp);
511 fcntl(fd,F_SETFD,fd > PL_maxsysfd); /* can change errno */
512 errno = save_errno;
513 }
1462b684 514#endif
8990e307 515 IoIFP(io) = fp;
b931b1d9 516 if (!num_svs) {
517 /* Need to supply default type info from open.pm */
ac27b0f5 518 SV *layers = PL_curcop->cop_io;
b931b1d9 519 type = NULL;
ac27b0f5 520 if (layers) {
521 STRLEN len;
522 type = SvPV(layers,len);
523 if (type && mode[0] != 'r') {
524 /* Skip to write part */
525 char *s = strchr(type,0);
526 if (s && (s-type) < len) {
527 type = s+1;
528 }
529 }
530 }
63dbdb06 531 else if (O_BINARY != O_TEXT && IoTYPE(io) != IoTYPE_STD) {
ac27b0f5 532 type = ":crlf";
533 }
b931b1d9 534 }
535 if (type) {
536 while (isSPACE(*type)) type++;
537 if (*type) {
ac27b0f5 538 if (PerlIO_apply_layers(aTHX_ IoIFP(io),mode,type) != 0) {
539 goto say_false;
540 }
b931b1d9 541 }
542 }
543
684bef36 544 IoFLAGS(io) &= ~IOf_NOLINE;
bf38876a 545 if (writing) {
96827780 546 dTHR;
50952442 547 if (IoTYPE(io) == IoTYPE_SOCKET
548 || (IoTYPE(io) == IoTYPE_WRONLY && S_ISCHR(PL_statbuf.st_mode)) )
16fe6d59 549 {
b931b1d9 550 mode[0] = 'w';
16fe6d59 551 if (!(IoOFP(io) = PerlIO_fdopen(PerlIO_fileno(fp),mode))) {
760ac839 552 PerlIO_close(fp);
8990e307 553 IoIFP(io) = Nullfp;
6e21c824 554 goto say_false;
fe14fcc3 555 }
ac27b0f5 556 if (type && *type) {
557 if (PerlIO_apply_layers(aTHX_ IoOFP(io),mode,type) != 0) {
558 PerlIO_close(IoOFP(io));
559 PerlIO_close(fp);
560 IoIFP(io) = Nullfp;
561 IoOFP(io) = Nullfp;
562 goto say_false;
563 }
564 }
1462b684 565 }
566 else
8990e307 567 IoOFP(io) = fp;
bf38876a 568 }
a687059c 569 return TRUE;
6e21c824 570
571say_false:
8990e307 572 IoIFP(io) = saveifp;
573 IoOFP(io) = saveofp;
574 IoTYPE(io) = savetype;
6e21c824 575 return FALSE;
a687059c 576}
577
760ac839 578PerlIO *
864dbfa3 579Perl_nextargv(pTHX_ register GV *gv)
a687059c 580{
79072805 581 register SV *sv;
99b89507 582#ifndef FLEXFILENAMES
c623bd54 583 int filedev;
584 int fileino;
99b89507 585#endif
761237fe 586 Uid_t fileuid;
587 Gid_t filegid;
18708f5a 588 IO *io = GvIOp(gv);
fe14fcc3 589
3280af22 590 if (!PL_argvoutgv)
591 PL_argvoutgv = gv_fetchpv("ARGVOUT",TRUE,SVt_PVIO);
18708f5a 592 if (io && (IoFLAGS(io) & IOf_ARGV) && (IoFLAGS(io) & IOf_START)) {
593 IoFLAGS(io) &= ~IOf_START;
7a1c5554 594 if (PL_inplace) {
595 if (!PL_argvout_stack)
596 PL_argvout_stack = newAV();
18708f5a 597 av_push(PL_argvout_stack, SvREFCNT_inc(PL_defoutgv));
7a1c5554 598 }
18708f5a 599 }
3280af22 600 if (PL_filemode & (S_ISUID|S_ISGID)) {
601 PerlIO_flush(IoIFP(GvIOn(PL_argvoutgv))); /* chmod must follow last write */
fe14fcc3 602#ifdef HAS_FCHMOD
3280af22 603 (void)fchmod(PL_lastfd,PL_filemode);
fe14fcc3 604#else
b28d0864 605 (void)PerlLIO_chmod(PL_oldname,PL_filemode);
fe14fcc3 606#endif
607 }
3280af22 608 PL_filemode = 0;
79072805 609 while (av_len(GvAV(gv)) >= 0) {
11343788 610 dTHR;
85aff577 611 STRLEN oldlen;
79072805 612 sv = av_shift(GvAV(gv));
8990e307 613 SAVEFREESV(sv);
79072805 614 sv_setsv(GvSV(gv),sv);
615 SvSETMAGIC(GvSV(gv));
3280af22 616 PL_oldname = SvPVx(GvSV(gv), oldlen);
9d116dd7 617 if (do_open(gv,PL_oldname,oldlen,PL_inplace!=0,O_RDONLY,0,Nullfp)) {
3280af22 618 if (PL_inplace) {
79072805 619 TAINT_PROPER("inplace open");
3280af22 620 if (oldlen == 1 && *PL_oldname == '-') {
4633a7c4 621 setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
a0d0e21e 622 return IoIFP(GvIOp(gv));
c623bd54 623 }
99b89507 624#ifndef FLEXFILENAMES
b28d0864 625 filedev = PL_statbuf.st_dev;
626 fileino = PL_statbuf.st_ino;
99b89507 627#endif
3280af22 628 PL_filemode = PL_statbuf.st_mode;
629 fileuid = PL_statbuf.st_uid;
630 filegid = PL_statbuf.st_gid;
631 if (!S_ISREG(PL_filemode)) {
0453d815 632 if (ckWARN_d(WARN_INPLACE))
633 Perl_warner(aTHX_ WARN_INPLACE,
634 "Can't do inplace edit: %s is not a regular file",
635 PL_oldname );
79072805 636 do_close(gv,FALSE);
c623bd54 637 continue;
638 }
3280af22 639 if (*PL_inplace) {
640 char *star = strchr(PL_inplace, '*');
2d259d92 641 if (star) {
3280af22 642 char *begin = PL_inplace;
2d259d92 643 sv_setpvn(sv, "", 0);
644 do {
645 sv_catpvn(sv, begin, star - begin);
3280af22 646 sv_catpvn(sv, PL_oldname, oldlen);
2d259d92 647 begin = ++star;
648 } while ((star = strchr(begin, '*')));
3d66d7bb 649 if (*begin)
650 sv_catpv(sv,begin);
2d259d92 651 }
652 else {
3280af22 653 sv_catpv(sv,PL_inplace);
2d259d92 654 }
c623bd54 655#ifndef FLEXFILENAMES
b28d0864 656 if (PerlLIO_stat(SvPVX(sv),&PL_statbuf) >= 0
657 && PL_statbuf.st_dev == filedev
658 && PL_statbuf.st_ino == fileino
39e571d4 659#ifdef DJGPP
660 || (_djstat_fail_bits & _STFAIL_TRUENAME)!=0
661#endif
f248d071 662 )
663 {
664 if (ckWARN_d(WARN_INPLACE))
665 Perl_warner(aTHX_ WARN_INPLACE,
666 "Can't do inplace edit: %s would not be unique",
667 SvPVX(sv));
79072805 668 do_close(gv,FALSE);
c623bd54 669 continue;
670 }
671#endif
fe14fcc3 672#ifdef HAS_RENAME
d308986b 673#if !defined(DOSISH) && !defined(__CYGWIN__)
3280af22 674 if (PerlLIO_rename(PL_oldname,SvPVX(sv)) < 0) {
0453d815 675 if (ckWARN_d(WARN_INPLACE))
a1d180c4 676 Perl_warner(aTHX_ WARN_INPLACE,
0453d815 677 "Can't rename %s to %s: %s, skipping file",
678 PL_oldname, SvPVX(sv), Strerror(errno) );
79072805 679 do_close(gv,FALSE);
c623bd54 680 continue;
681 }
a687059c 682#else
79072805 683 do_close(gv,FALSE);
3028581b 684 (void)PerlLIO_unlink(SvPVX(sv));
b28d0864 685 (void)PerlLIO_rename(PL_oldname,SvPVX(sv));
9d116dd7 686 do_open(gv,SvPVX(sv),SvCUR(sv),PL_inplace!=0,O_RDONLY,0,Nullfp);
55497cff 687#endif /* DOSISH */
ff8e2863 688#else
463ee0b2 689 (void)UNLINK(SvPVX(sv));
b28d0864 690 if (link(PL_oldname,SvPVX(sv)) < 0) {
0453d815 691 if (ckWARN_d(WARN_INPLACE))
692 Perl_warner(aTHX_ WARN_INPLACE,
693 "Can't rename %s to %s: %s, skipping file",
694 PL_oldname, SvPVX(sv), Strerror(errno) );
79072805 695 do_close(gv,FALSE);
c623bd54 696 continue;
697 }
b28d0864 698 (void)UNLINK(PL_oldname);
a687059c 699#endif
700 }
701 else {
a8c18271 702#if !defined(DOSISH) && !defined(AMIGAOS)
edc7bc49 703# ifndef VMS /* Don't delete; use automatic file versioning */
3280af22 704 if (UNLINK(PL_oldname) < 0) {
0453d815 705 if (ckWARN_d(WARN_INPLACE))
706 Perl_warner(aTHX_ WARN_INPLACE,
707 "Can't remove %s: %s, skipping file",
708 PL_oldname, Strerror(errno) );
79072805 709 do_close(gv,FALSE);
fe14fcc3 710 continue;
711 }
edc7bc49 712# endif
ff8e2863 713#else
cea2e8a9 714 Perl_croak(aTHX_ "Can't do inplace edit without backup");
ff8e2863 715#endif
a687059c 716 }
717
3280af22 718 sv_setpvn(sv,">",!PL_inplace);
719 sv_catpvn(sv,PL_oldname,oldlen);
748a9306 720 SETERRNO(0,0); /* in case sprintf set errno */
4119ab01 721#ifdef VMS
722 if (!do_open(PL_argvoutgv,SvPVX(sv),SvCUR(sv),PL_inplace!=0,
18708f5a 723 O_WRONLY|O_CREAT|O_TRUNC,0,Nullfp))
4119ab01 724#else
3280af22 725 if (!do_open(PL_argvoutgv,SvPVX(sv),SvCUR(sv),PL_inplace!=0,
18708f5a 726 O_WRONLY|O_CREAT|OPEN_EXCL,0666,Nullfp))
4119ab01 727#endif
18708f5a 728 {
0453d815 729 if (ckWARN_d(WARN_INPLACE))
730 Perl_warner(aTHX_ WARN_INPLACE, "Can't do inplace edit on %s: %s",
731 PL_oldname, Strerror(errno) );
79072805 732 do_close(gv,FALSE);
fe14fcc3 733 continue;
734 }
3280af22 735 setdefout(PL_argvoutgv);
736 PL_lastfd = PerlIO_fileno(IoIFP(GvIOp(PL_argvoutgv)));
737 (void)PerlLIO_fstat(PL_lastfd,&PL_statbuf);
fe14fcc3 738#ifdef HAS_FCHMOD
3280af22 739 (void)fchmod(PL_lastfd,PL_filemode);
a687059c 740#else
3e3baf6d 741# if !(defined(WIN32) && defined(__BORLANDC__))
742 /* Borland runtime creates a readonly file! */
b28d0864 743 (void)PerlLIO_chmod(PL_oldname,PL_filemode);
3e3baf6d 744# endif
a687059c 745#endif
3280af22 746 if (fileuid != PL_statbuf.st_uid || filegid != PL_statbuf.st_gid) {
fe14fcc3 747#ifdef HAS_FCHOWN
3280af22 748 (void)fchown(PL_lastfd,fileuid,filegid);
a687059c 749#else
fe14fcc3 750#ifdef HAS_CHOWN
b28d0864 751 (void)PerlLIO_chown(PL_oldname,fileuid,filegid);
a687059c 752#endif
b1248f16 753#endif
fe14fcc3 754 }
a687059c 755 }
a0d0e21e 756 return IoIFP(GvIOp(gv));
a687059c 757 }
4d61ec05 758 else {
759 dTHR;
760 if (ckWARN_d(WARN_INPLACE)) {
6af84f9f 761 int eno = errno;
762 if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0
763 && !S_ISREG(PL_statbuf.st_mode))
764 {
4d61ec05 765 Perl_warner(aTHX_ WARN_INPLACE,
766 "Can't do inplace edit: %s is not a regular file",
9a7dcd9c 767 PL_oldname);
6af84f9f 768 }
4d61ec05 769 else
9a7dcd9c 770 Perl_warner(aTHX_ WARN_INPLACE, "Can't open %s: %s",
6af84f9f 771 PL_oldname, Strerror(eno));
4d61ec05 772 }
773 }
a687059c 774 }
18708f5a 775 if (io && (IoFLAGS(io) & IOf_ARGV))
776 IoFLAGS(io) |= IOf_START;
3280af22 777 if (PL_inplace) {
778 (void)do_close(PL_argvoutgv,FALSE);
7a1c5554 779 if (io && (IoFLAGS(io) & IOf_ARGV)
780 && PL_argvout_stack && AvFILLp(PL_argvout_stack) >= 0)
781 {
18708f5a 782 GV *oldout = (GV*)av_pop(PL_argvout_stack);
783 setdefout(oldout);
784 SvREFCNT_dec(oldout);
785 return Nullfp;
786 }
4633a7c4 787 setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
a687059c 788 }
789 return Nullfp;
790}
791
fe14fcc3 792#ifdef HAS_PIPE
afd9f252 793void
864dbfa3 794Perl_do_pipe(pTHX_ SV *sv, GV *rgv, GV *wgv)
afd9f252 795{
79072805 796 register IO *rstio;
797 register IO *wstio;
afd9f252 798 int fd[2];
799
79072805 800 if (!rgv)
afd9f252 801 goto badexit;
79072805 802 if (!wgv)
afd9f252 803 goto badexit;
804
a0d0e21e 805 rstio = GvIOn(rgv);
806 wstio = GvIOn(wgv);
afd9f252 807
a0d0e21e 808 if (IoIFP(rstio))
79072805 809 do_close(rgv,FALSE);
a0d0e21e 810 if (IoIFP(wstio))
79072805 811 do_close(wgv,FALSE);
afd9f252 812
3028581b 813 if (PerlProc_pipe(fd) < 0)
afd9f252 814 goto badexit;
760ac839 815 IoIFP(rstio) = PerlIO_fdopen(fd[0], "r");
816 IoOFP(wstio) = PerlIO_fdopen(fd[1], "w");
8990e307 817 IoIFP(wstio) = IoOFP(wstio);
50952442 818 IoTYPE(rstio) = IoTYPE_RDONLY;
819 IoTYPE(wstio) = IoTYPE_WRONLY;
8990e307 820 if (!IoIFP(rstio) || !IoOFP(wstio)) {
760ac839 821 if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio));
3028581b 822 else PerlLIO_close(fd[0]);
760ac839 823 if (IoOFP(wstio)) PerlIO_close(IoOFP(wstio));
3028581b 824 else PerlLIO_close(fd[1]);
fe14fcc3 825 goto badexit;
826 }
afd9f252 827
3280af22 828 sv_setsv(sv,&PL_sv_yes);
afd9f252 829 return;
830
831badexit:
3280af22 832 sv_setsv(sv,&PL_sv_undef);
afd9f252 833 return;
834}
b1248f16 835#endif
afd9f252 836
517844ec 837/* explicit renamed to avoid C++ conflict -- kja */
a687059c 838bool
864dbfa3 839Perl_do_close(pTHX_ GV *gv, bool not_implicit)
a687059c 840{
1193dd27 841 bool retval;
842 IO *io;
a687059c 843
79072805 844 if (!gv)
3280af22 845 gv = PL_argvgv;
a0d0e21e 846 if (!gv || SvTYPE(gv) != SVt_PVGV) {
1d2dff63 847 if (not_implicit)
848 SETERRNO(EBADF,SS$_IVCHAN);
c2ab57d4 849 return FALSE;
99b89507 850 }
79072805 851 io = GvIO(gv);
852 if (!io) { /* never opened */
1d2dff63 853 if (not_implicit) {
d008e5eb 854 dTHR;
2dd78f96 855 if (ckWARN(WARN_UNOPENED)) /* no check for closed here */
856 report_evil_fh(gv, io, PL_op->op_type);
1d2dff63 857 SETERRNO(EBADF,SS$_IVCHAN);
858 }
a687059c 859 return FALSE;
860 }
f2b5be74 861 retval = io_close(io, not_implicit);
517844ec 862 if (not_implicit) {
1193dd27 863 IoLINES(io) = 0;
864 IoPAGE(io) = 0;
865 IoLINES_LEFT(io) = IoPAGE_LEN(io);
866 }
50952442 867 IoTYPE(io) = IoTYPE_CLOSED;
1193dd27 868 return retval;
869}
870
871bool
f2b5be74 872Perl_io_close(pTHX_ IO *io, bool not_implicit)
1193dd27 873{
874 bool retval = FALSE;
875 int status;
876
8990e307 877 if (IoIFP(io)) {
50952442 878 if (IoTYPE(io) == IoTYPE_PIPE) {
3028581b 879 status = PerlProc_pclose(IoIFP(io));
f2b5be74 880 if (not_implicit) {
881 STATUS_NATIVE_SET(status);
882 retval = (STATUS_POSIX == 0);
883 }
884 else {
885 retval = (status != -1);
886 }
a687059c 887 }
50952442 888 else if (IoTYPE(io) == IoTYPE_STD)
a687059c 889 retval = TRUE;
890 else {
8990e307 891 if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */
760ac839 892 retval = (PerlIO_close(IoOFP(io)) != EOF);
893 PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
c2ab57d4 894 }
895 else
760ac839 896 retval = (PerlIO_close(IoIFP(io)) != EOF);
a687059c 897 }
8990e307 898 IoOFP(io) = IoIFP(io) = Nullfp;
79072805 899 }
f2b5be74 900 else if (not_implicit) {
20408e3c 901 SETERRNO(EBADF,SS$_IVCHAN);
902 }
1193dd27 903
a687059c 904 return retval;
905}
906
907bool
864dbfa3 908Perl_do_eof(pTHX_ GV *gv)
a687059c 909{
11343788 910 dTHR;
79072805 911 register IO *io;
a687059c 912 int ch;
913
79072805 914 io = GvIO(gv);
a687059c 915
79072805 916 if (!io)
a687059c 917 return TRUE;
af8c498a 918 else if (ckWARN(WARN_IO)
50952442 919 && (IoTYPE(io) == IoTYPE_WRONLY || IoIFP(io) == PerlIO_stdout()
af8c498a 920 || IoIFP(io) == PerlIO_stderr()))
921 {
2dd78f96 922 /* integrate to report_evil_fh()? */
a1d180c4 923 char *name = NULL;
2dd78f96 924 if (isGV(gv)) {
925 SV* sv = sv_newmortal();
926 gv_efullname4(sv, gv, Nullch, FALSE);
927 name = SvPV_nolen(sv);
928 }
929 if (name && *name)
930 Perl_warner(aTHX_ WARN_IO,
931 "Filehandle %s opened only for output", name);
932 else
933 Perl_warner(aTHX_ WARN_IO,
934 "Filehandle opened only for output");
af8c498a 935 }
a687059c 936
8990e307 937 while (IoIFP(io)) {
a687059c 938
760ac839 939 if (PerlIO_has_cntptr(IoIFP(io))) { /* (the code works without this) */
a20bf0c3 940 if (PerlIO_get_cnt(IoIFP(io)) > 0) /* cheat a little, since */
760ac839 941 return FALSE; /* this is the most usual case */
942 }
a687059c 943
760ac839 944 ch = PerlIO_getc(IoIFP(io));
a687059c 945 if (ch != EOF) {
760ac839 946 (void)PerlIO_ungetc(IoIFP(io),ch);
a687059c 947 return FALSE;
948 }
fab3f3a7 949
760ac839 950 if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
a20bf0c3 951 if (PerlIO_get_cnt(IoIFP(io)) < -1)
952 PerlIO_set_cnt(IoIFP(io),-1);
760ac839 953 }
533c011a 954 if (PL_op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
3280af22 955 if (!nextargv(PL_argvgv)) /* get another fp handy */
a687059c 956 return TRUE;
957 }
958 else
959 return TRUE; /* normal fp, definitely end of file */
960 }
961 return TRUE;
962}
963
5ff3f7a4 964Off_t
864dbfa3 965Perl_do_tell(pTHX_ GV *gv)
a687059c 966{
79072805 967 register IO *io;
96e4d5b1 968 register PerlIO *fp;
a687059c 969
96e4d5b1 970 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
bee1dbe2 971#ifdef ULTRIX_STDIO_BOTCH
96e4d5b1 972 if (PerlIO_eof(fp))
973 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
bee1dbe2 974#endif
8903cb82 975 return PerlIO_tell(fp);
96e4d5b1 976 }
d008e5eb 977 {
978 dTHR;
2dd78f96 979 if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
980 report_evil_fh(gv, io, PL_op->op_type);
d008e5eb 981 }
748a9306 982 SETERRNO(EBADF,RMS$_IFI);
5ff3f7a4 983 return (Off_t)-1;
a687059c 984}
985
986bool
864dbfa3 987Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
a687059c 988{
79072805 989 register IO *io;
137443ea 990 register PerlIO *fp;
a687059c 991
137443ea 992 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
bee1dbe2 993#ifdef ULTRIX_STDIO_BOTCH
137443ea 994 if (PerlIO_eof(fp))
995 (void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
bee1dbe2 996#endif
8903cb82 997 return PerlIO_seek(fp, pos, whence) >= 0;
137443ea 998 }
d008e5eb 999 {
1000 dTHR;
2dd78f96 1001 if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
1002 report_evil_fh(gv, io, PL_op->op_type);
d008e5eb 1003 }
748a9306 1004 SETERRNO(EBADF,RMS$_IFI);
a687059c 1005 return FALSE;
1006}
1007
97cc44eb 1008Off_t
864dbfa3 1009Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence)
8903cb82 1010{
1011 register IO *io;
1012 register PerlIO *fp;
1013
1014 if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
3028581b 1015 return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
d008e5eb 1016 {
1017 dTHR;
2dd78f96 1018 if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
1019 report_evil_fh(gv, io, PL_op->op_type);
d008e5eb 1020 }
8903cb82 1021 SETERRNO(EBADF,RMS$_IFI);
d9b3e12d 1022 return (Off_t)-1;
8903cb82 1023}
1024
6ff81951 1025int
16fe6d59 1026Perl_mode_from_discipline(pTHX_ SV *discp)
1027{
1028 int mode = O_BINARY;
1029 if (discp) {
1030 STRLEN len;
1031 char *s = SvPV(discp,len);
1032 while (*s) {
1033 if (*s == ':') {
1034 switch (s[1]) {
1035 case 'r':
1036 if (len > 3 && strnEQ(s+1, "raw", 3)
1037 && (!s[4] || s[4] == ':' || isSPACE(s[4])))
1038 {
1039 mode = O_BINARY;
1040 s += 4;
1041 len -= 4;
1042 break;
1043 }
1044 /* FALL THROUGH */
1045 case 'c':
1046 if (len > 4 && strnEQ(s+1, "crlf", 4)
1047 && (!s[5] || s[5] == ':' || isSPACE(s[5])))
1048 {
1049 mode = O_TEXT;
1050 s += 5;
1051 len -= 5;
1052 break;
1053 }
1054 /* FALL THROUGH */
1055 default:
1056 goto fail_discipline;
1057 }
1058 }
1059 else if (isSPACE(*s)) {
1060 ++s;
1061 --len;
1062 }
1063 else {
1064 char *end;
1065fail_discipline:
1066 end = strchr(s+1, ':');
1067 if (!end)
1068 end = s+len;
60382766 1069#ifndef PERLIO_LAYERS
16fe6d59 1070 Perl_croak(aTHX_ "Unknown discipline '%.*s'", end-s, s);
60382766 1071#else
1072 s = end;
1073#endif
16fe6d59 1074 }
1075 }
1076 }
1077 return mode;
1078}
1079
1080int
1081Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int mode)
6ff81951 1082{
60382766 1083 /* The old body of this is now in non-LAYER part of perlio.c
1084 * This is a stub for any XS code which might have been calling it.
1085 */
1086 char *name = (O_BINARY != O_TEXT && !(mode & O_BINARY)) ? ":crlf" : ":raw";
1087 return PerlIO_binmode(aTHX_ fp, iotype, mode, name);
6ff81951 1088}
1089
a0d0e21e 1090#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
c2ab57d4 1091 /* code courtesy of William Kucharski */
fe14fcc3 1092#define HAS_CHSIZE
6eb13c3b 1093
517844ec 1094I32 my_chsize(fd, length)
79072805 1095I32 fd; /* file descriptor */
85e6fe83 1096Off_t length; /* length to set file to */
6eb13c3b 1097{
6eb13c3b 1098 struct flock fl;
1099 struct stat filebuf;
1100
3028581b 1101 if (PerlLIO_fstat(fd, &filebuf) < 0)
6eb13c3b 1102 return -1;
1103
1104 if (filebuf.st_size < length) {
1105
1106 /* extend file length */
1107
3028581b 1108 if ((PerlLIO_lseek(fd, (length - 1), 0)) < 0)
6eb13c3b 1109 return -1;
1110
1111 /* write a "0" byte */
1112
3028581b 1113 if ((PerlLIO_write(fd, "", 1)) != 1)
6eb13c3b 1114 return -1;
1115 }
1116 else {
1117 /* truncate length */
1118
1119 fl.l_whence = 0;
1120 fl.l_len = 0;
1121 fl.l_start = length;
a0d0e21e 1122 fl.l_type = F_WRLCK; /* write lock on file space */
6eb13c3b 1123
1124 /*
a0d0e21e 1125 * This relies on the UNDOCUMENTED F_FREESP argument to
6eb13c3b 1126 * fcntl(2), which truncates the file so that it ends at the
1127 * position indicated by fl.l_start.
1128 *
1129 * Will minor miracles never cease?
1130 */
1131
a0d0e21e 1132 if (fcntl(fd, F_FREESP, &fl) < 0)
6eb13c3b 1133 return -1;
1134
1135 }
1136
1137 return 0;
1138}
a0d0e21e 1139#endif /* F_FREESP */
ff8e2863 1140
a687059c 1141bool
864dbfa3 1142Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
a687059c 1143{
1144 register char *tmps;
463ee0b2 1145 STRLEN len;
a687059c 1146
79072805 1147 /* assuming fp is checked earlier */
1148 if (!sv)
1149 return TRUE;
3280af22 1150 if (PL_ofmt) {
8990e307 1151 if (SvGMAGICAL(sv))
79072805 1152 mg_get(sv);
463ee0b2 1153 if (SvIOK(sv) && SvIVX(sv) != 0) {
65202027 1154 PerlIO_printf(fp, PL_ofmt, (NV)SvIVX(sv));
760ac839 1155 return !PerlIO_error(fp);
79072805 1156 }
463ee0b2 1157 if ( (SvNOK(sv) && SvNVX(sv) != 0.0)
79072805 1158 || (looks_like_number(sv) && sv_2nv(sv) != 0.0) ) {
3280af22 1159 PerlIO_printf(fp, PL_ofmt, SvNVX(sv));
760ac839 1160 return !PerlIO_error(fp);
79072805 1161 }
a687059c 1162 }
79072805 1163 switch (SvTYPE(sv)) {
1164 case SVt_NULL:
d008e5eb 1165 {
1166 dTHR;
1167 if (ckWARN(WARN_UNINITIALIZED))
b89fed5f 1168 report_uninit();
d008e5eb 1169 }
ff8e2863 1170 return TRUE;
79072805 1171 case SVt_IV:
a0d0e21e 1172 if (SvIOK(sv)) {
1173 if (SvGMAGICAL(sv))
1174 mg_get(sv);
cf2093f6 1175 if (SvIsUV(sv))
57def98f 1176 PerlIO_printf(fp, "%"UVuf, (UV)SvUVX(sv));
cf2093f6 1177 else
57def98f 1178 PerlIO_printf(fp, "%"IVdf, (IV)SvIVX(sv));
760ac839 1179 return !PerlIO_error(fp);
a0d0e21e 1180 }
1181 /* FALL THROUGH */
79072805 1182 default:
fba9e08b 1183#if 0
4b3603a4 1184 /* XXX Fix this when the I/O disciplines arrive. XXX */
1185 if (DO_UTF8(sv))
1186 sv_utf8_downgrade(sv, FALSE);
fba9e08b 1187#endif
463ee0b2 1188 tmps = SvPV(sv, len);
79072805 1189 break;
ff8e2863 1190 }
94e4c244 1191 /* To detect whether the process is about to overstep its
1192 * filesize limit we would need getrlimit(). We could then
1193 * also transparently raise the limit with setrlimit() --
1194 * but only until the system hard limit/the filesystem limit,
c5dd3cdd 1195 * at which we would get EPERM. Note that when using buffered
1196 * io the write failure can be delayed until the flush/close. --jhi */
a21ac455 1197 if (len && (PerlIO_write(fp,tmps,len) == 0))
a687059c 1198 return FALSE;
760ac839 1199 return !PerlIO_error(fp);
a687059c 1200}
1201
79072805 1202I32
cea2e8a9 1203Perl_my_stat(pTHX)
a687059c 1204{
4e35701f 1205 djSP;
79072805 1206 IO *io;
2dd78f96 1207 GV* gv;
79072805 1208
533c011a 1209 if (PL_op->op_flags & OPf_REF) {
924508f0 1210 EXTEND(SP,1);
2dd78f96 1211 gv = cGVOP_gv;
748a9306 1212 do_fstat:
2dd78f96 1213 io = GvIO(gv);
8990e307 1214 if (io && IoIFP(io)) {
2dd78f96 1215 PL_statgv = gv;
3280af22 1216 sv_setpv(PL_statname,"");
1217 PL_laststype = OP_STAT;
1218 return (PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache));
a687059c 1219 }
1220 else {
2dd78f96 1221 if (gv == PL_defgv)
3280af22 1222 return PL_laststatval;
2dd78f96 1223 if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
1224 report_evil_fh(gv, io, PL_op->op_type);
3280af22 1225 PL_statgv = Nullgv;
1226 sv_setpv(PL_statname,"");
1227 return (PL_laststatval = -1);
a687059c 1228 }
1229 }
1230 else {
748a9306 1231 SV* sv = POPs;
4b74e3fb 1232 char *s;
2d8e6c8d 1233 STRLEN n_a;
79072805 1234 PUTBACK;
748a9306 1235 if (SvTYPE(sv) == SVt_PVGV) {
2dd78f96 1236 gv = (GV*)sv;
748a9306 1237 goto do_fstat;
1238 }
1239 else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
2dd78f96 1240 gv = (GV*)SvRV(sv);
748a9306 1241 goto do_fstat;
1242 }
1243
2d8e6c8d 1244 s = SvPV(sv, n_a);
3280af22 1245 PL_statgv = Nullgv;
1246 sv_setpv(PL_statname, s);
1247 PL_laststype = OP_STAT;
1248 PL_laststatval = PerlLIO_stat(s, &PL_statcache);
599cee73 1249 if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(s, '\n'))
cea2e8a9 1250 Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "stat");
3280af22 1251 return PL_laststatval;
a687059c 1252 }
1253}
1254
79072805 1255I32
cea2e8a9 1256Perl_my_lstat(pTHX)
c623bd54 1257{
4e35701f 1258 djSP;
79072805 1259 SV *sv;
2d8e6c8d 1260 STRLEN n_a;
533c011a 1261 if (PL_op->op_flags & OPf_REF) {
924508f0 1262 EXTEND(SP,1);
638eceb6 1263 if (cGVOP_gv == PL_defgv) {
3280af22 1264 if (PL_laststype != OP_LSTAT)
cea2e8a9 1265 Perl_croak(aTHX_ "The stat preceding -l _ wasn't an lstat");
3280af22 1266 return PL_laststatval;
fe14fcc3 1267 }
cea2e8a9 1268 Perl_croak(aTHX_ "You can't use -l on a filehandle");
fe14fcc3 1269 }
c623bd54 1270
3280af22 1271 PL_laststype = OP_LSTAT;
1272 PL_statgv = Nullgv;
79072805 1273 sv = POPs;
1274 PUTBACK;
2d8e6c8d 1275 sv_setpv(PL_statname,SvPV(sv, n_a));
2d8e6c8d 1276 PL_laststatval = PerlLIO_lstat(SvPV(sv, n_a),&PL_statcache);
2d8e6c8d 1277 if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(SvPV(sv, n_a), '\n'))
cea2e8a9 1278 Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "lstat");
3280af22 1279 return PL_laststatval;
c623bd54 1280}
1281
a687059c 1282bool
864dbfa3 1283Perl_do_aexec(pTHX_ SV *really, register SV **mark, register SV **sp)
a687059c 1284{
d5a9bfb0 1285 return do_aexec5(really, mark, sp, 0, 0);
1286}
1287
1288bool
2aa1486d 1289Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
1290 int fd, int do_report)
d5a9bfb0 1291{
cd39f2b6 1292#ifdef MACOS_TRADITIONAL
1293 Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
1294#else
a687059c 1295 register char **a;
a687059c 1296 char *tmps;
2d8e6c8d 1297 STRLEN n_a;
a687059c 1298
79072805 1299 if (sp > mark) {
11343788 1300 dTHR;
3280af22 1301 New(401,PL_Argv, sp - mark + 1, char*);
1302 a = PL_Argv;
79072805 1303 while (++mark <= sp) {
1304 if (*mark)
2d8e6c8d 1305 *a++ = SvPVx(*mark, n_a);
a687059c 1306 else
1307 *a++ = "";
1308 }
1309 *a = Nullch;
3280af22 1310 if (*PL_Argv[0] != '/') /* will execvp use PATH? */
79072805 1311 TAINT_ENV(); /* testing IFS here is overkill, probably */
2d8e6c8d 1312 if (really && *(tmps = SvPV(really, n_a)))
3280af22 1313 PerlProc_execvp(tmps,PL_Argv);
a687059c 1314 else
3280af22 1315 PerlProc_execvp(PL_Argv[0],PL_Argv);
599cee73 1316 if (ckWARN(WARN_EXEC))
a1d180c4 1317 Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
599cee73 1318 PL_Argv[0], Strerror(errno));
d5a9bfb0 1319 if (do_report) {
1320 int e = errno;
1321
1322 PerlLIO_write(fd, (void*)&e, sizeof(int));
1323 PerlLIO_close(fd);
1324 }
a687059c 1325 }
bee1dbe2 1326 do_execfree();
cd39f2b6 1327#endif
a687059c 1328 return FALSE;
1329}
1330
fe14fcc3 1331void
864dbfa3 1332Perl_do_execfree(pTHX)
ff8e2863 1333{
3280af22 1334 if (PL_Argv) {
1335 Safefree(PL_Argv);
1336 PL_Argv = Null(char **);
ff8e2863 1337 }
3280af22 1338 if (PL_Cmd) {
1339 Safefree(PL_Cmd);
1340 PL_Cmd = Nullch;
ff8e2863 1341 }
1342}
1343
cd39f2b6 1344#if !defined(OS2) && !defined(WIN32) && !defined(DJGPP) && !defined(EPOC) && !defined(MACOS_TRADITIONAL)
760ac839 1345
a687059c 1346bool
864dbfa3 1347Perl_do_exec(pTHX_ char *cmd)
a687059c 1348{
e446cec8 1349 return do_exec3(cmd,0,0);
1350}
1351
1352bool
864dbfa3 1353Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
e446cec8 1354{
a687059c 1355 register char **a;
1356 register char *s;
a687059c 1357 char flags[10];
1358
748a9306 1359 while (*cmd && isSPACE(*cmd))
1360 cmd++;
1361
a687059c 1362 /* save an extra exec if possible */
1363
bf38876a 1364#ifdef CSH
3280af22 1365 if (strnEQ(cmd,PL_cshname,PL_cshlen) && strnEQ(cmd+PL_cshlen," -c",3)) {
a687059c 1366 strcpy(flags,"-c");
3280af22 1367 s = cmd+PL_cshlen+3;
a687059c 1368 if (*s == 'f') {
1369 s++;
1370 strcat(flags,"f");
1371 }
1372 if (*s == ' ')
1373 s++;
1374 if (*s++ == '\'') {
1375 char *ncmd = s;
1376
1377 while (*s)
1378 s++;
1379 if (s[-1] == '\n')
1380 *--s = '\0';
1381 if (s[-1] == '\'') {
1382 *--s = '\0';
3280af22 1383 PerlProc_execl(PL_cshname,"csh", flags,ncmd,(char*)0);
a687059c 1384 *s = '\'';
1385 return FALSE;
1386 }
1387 }
1388 }
bf38876a 1389#endif /* CSH */
a687059c 1390
1391 /* see if there are shell metacharacters in it */
1392
748a9306 1393 if (*cmd == '.' && isSPACE(cmd[1]))
1394 goto doshell;
1395
1396 if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
1397 goto doshell;
1398
c170e444 1399 for (s = cmd; *s && isALNUM(*s); s++) ; /* catch VAR=val gizmo */
63f2c1e1 1400 if (*s == '=')
1401 goto doshell;
748a9306 1402
a687059c 1403 for (s = cmd; *s; s++) {
93a17b20 1404 if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
a687059c 1405 if (*s == '\n' && !s[1]) {
1406 *s = '\0';
1407 break;
1408 }
603a98b0 1409 /* handle the 2>&1 construct at the end */
1410 if (*s == '>' && s[1] == '&' && s[2] == '1'
1411 && s > cmd + 1 && s[-1] == '2' && isSPACE(s[-2])
1412 && (!s[3] || isSPACE(s[3])))
1413 {
1414 char *t = s + 3;
1415
1416 while (*t && isSPACE(*t))
1417 ++t;
1418 if (!*t && (dup2(1,2) != -1)) {
1419 s[-2] = '\0';
1420 break;
1421 }
1422 }
a687059c 1423 doshell:
3280af22 1424 PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char*)0);
a687059c 1425 return FALSE;
1426 }
1427 }
748a9306 1428
3280af22 1429 New(402,PL_Argv, (s - cmd) / 2 + 2, char*);
1430 PL_Cmd = savepvn(cmd, s-cmd);
1431 a = PL_Argv;
1432 for (s = PL_Cmd; *s;) {
99b89507 1433 while (*s && isSPACE(*s)) s++;
a687059c 1434 if (*s)
1435 *(a++) = s;
99b89507 1436 while (*s && !isSPACE(*s)) s++;
a687059c 1437 if (*s)
1438 *s++ = '\0';
1439 }
1440 *a = Nullch;
3280af22 1441 if (PL_Argv[0]) {
1442 PerlProc_execvp(PL_Argv[0],PL_Argv);
b1248f16 1443 if (errno == ENOEXEC) { /* for system V NIH syndrome */
ff8e2863 1444 do_execfree();
a687059c 1445 goto doshell;
b1248f16 1446 }
d008e5eb 1447 {
1448 dTHR;
e446cec8 1449 int e = errno;
1450
d008e5eb 1451 if (ckWARN(WARN_EXEC))
a1d180c4 1452 Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
d008e5eb 1453 PL_Argv[0], Strerror(errno));
e446cec8 1454 if (do_report) {
1455 PerlLIO_write(fd, (void*)&e, sizeof(int));
1456 PerlLIO_close(fd);
1457 }
d008e5eb 1458 }
a687059c 1459 }
ff8e2863 1460 do_execfree();
a687059c 1461 return FALSE;
1462}
1463
6890e559 1464#endif /* OS2 || WIN32 */
760ac839 1465
79072805 1466I32
864dbfa3 1467Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
a687059c 1468{
11343788 1469 dTHR;
79072805 1470 register I32 val;
1471 register I32 val2;
1472 register I32 tot = 0;
20408e3c 1473 char *what;
a687059c 1474 char *s;
79072805 1475 SV **oldmark = mark;
2d8e6c8d 1476 STRLEN n_a;
a687059c 1477
20408e3c 1478#define APPLY_TAINT_PROPER() \
3280af22 1479 STMT_START { \
17406bd6 1480 if (PL_tainted) { TAINT_PROPER(what); } \
873ef191 1481 } STMT_END
20408e3c 1482
1483 /* This is a first heuristic; it doesn't catch tainting magic. */
3280af22 1484 if (PL_tainting) {
463ee0b2 1485 while (++mark <= sp) {
bbce6d69 1486 if (SvTAINTED(*mark)) {
1487 TAINT;
1488 break;
1489 }
463ee0b2 1490 }
1491 mark = oldmark;
1492 }
a687059c 1493 switch (type) {
79072805 1494 case OP_CHMOD:
20408e3c 1495 what = "chmod";
1496 APPLY_TAINT_PROPER();
79072805 1497 if (++mark <= sp) {
463ee0b2 1498 val = SvIVx(*mark);
20408e3c 1499 APPLY_TAINT_PROPER();
1500 tot = sp - mark;
79072805 1501 while (++mark <= sp) {
2d8e6c8d 1502 char *name = SvPVx(*mark, n_a);
20408e3c 1503 APPLY_TAINT_PROPER();
1504 if (PerlLIO_chmod(name, val))
a687059c 1505 tot--;
1506 }
1507 }
1508 break;
fe14fcc3 1509#ifdef HAS_CHOWN
79072805 1510 case OP_CHOWN:
20408e3c 1511 what = "chown";
1512 APPLY_TAINT_PROPER();
79072805 1513 if (sp - mark > 2) {
463ee0b2 1514 val = SvIVx(*++mark);
1515 val2 = SvIVx(*++mark);
20408e3c 1516 APPLY_TAINT_PROPER();
a0d0e21e 1517 tot = sp - mark;
79072805 1518 while (++mark <= sp) {
2d8e6c8d 1519 char *name = SvPVx(*mark, n_a);
20408e3c 1520 APPLY_TAINT_PROPER();
36660982 1521 if (PerlLIO_chown(name, val, val2))
a687059c 1522 tot--;
1523 }
1524 }
1525 break;
b1248f16 1526#endif
a1d180c4 1527/*
dd64f1c3 1528XXX Should we make lchown() directly available from perl?
1529For now, we'll let Configure test for HAS_LCHOWN, but do
1530nothing in the core.
1531 --AD 5/1998
1532*/
fe14fcc3 1533#ifdef HAS_KILL
79072805 1534 case OP_KILL:
20408e3c 1535 what = "kill";
1536 APPLY_TAINT_PROPER();
55497cff 1537 if (mark == sp)
1538 break;
2d8e6c8d 1539 s = SvPVx(*++mark, n_a);
79072805 1540 if (isUPPER(*s)) {
1541 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
1542 s += 3;
1543 if (!(val = whichsig(s)))
cea2e8a9 1544 Perl_croak(aTHX_ "Unrecognized signal name \"%s\"",s);
79072805 1545 }
1546 else
463ee0b2 1547 val = SvIVx(*mark);
20408e3c 1548 APPLY_TAINT_PROPER();
1549 tot = sp - mark;
3595fcef 1550#ifdef VMS
1551 /* kill() doesn't do process groups (job trees?) under VMS */
1552 if (val < 0) val = -val;
1553 if (val == SIGKILL) {
1554# include <starlet.h>
1555 /* Use native sys$delprc() to insure that target process is
1556 * deleted; supervisor-mode images don't pay attention to
1557 * CRTL's emulation of Unix-style signals and kill()
1558 */
1559 while (++mark <= sp) {
1560 I32 proc = SvIVx(*mark);
1561 register unsigned long int __vmssts;
20408e3c 1562 APPLY_TAINT_PROPER();
3595fcef 1563 if (!((__vmssts = sys$delprc(&proc,0)) & 1)) {
1564 tot--;
1565 switch (__vmssts) {
1566 case SS$_NONEXPR:
1567 case SS$_NOSUCHNODE:
1568 SETERRNO(ESRCH,__vmssts);
1569 break;
1570 case SS$_NOPRIV:
1571 SETERRNO(EPERM,__vmssts);
1572 break;
1573 default:
1574 SETERRNO(EVMSERR,__vmssts);
1575 }
1576 }
1577 }
1578 break;
1579 }
1580#endif
79072805 1581 if (val < 0) {
1582 val = -val;
1583 while (++mark <= sp) {
463ee0b2 1584 I32 proc = SvIVx(*mark);
20408e3c 1585 APPLY_TAINT_PROPER();
fe14fcc3 1586#ifdef HAS_KILLPG
3028581b 1587 if (PerlProc_killpg(proc,val)) /* BSD */
a687059c 1588#else
3028581b 1589 if (PerlProc_kill(-proc,val)) /* SYSV */
a687059c 1590#endif
79072805 1591 tot--;
a687059c 1592 }
79072805 1593 }
1594 else {
1595 while (++mark <= sp) {
20408e3c 1596 I32 proc = SvIVx(*mark);
1597 APPLY_TAINT_PROPER();
1598 if (PerlProc_kill(proc, val))
79072805 1599 tot--;
a687059c 1600 }
1601 }
1602 break;
b1248f16 1603#endif
79072805 1604 case OP_UNLINK:
20408e3c 1605 what = "unlink";
1606 APPLY_TAINT_PROPER();
79072805 1607 tot = sp - mark;
1608 while (++mark <= sp) {
2d8e6c8d 1609 s = SvPVx(*mark, n_a);
20408e3c 1610 APPLY_TAINT_PROPER();
3280af22 1611 if (PL_euid || PL_unsafe) {
a687059c 1612 if (UNLINK(s))
1613 tot--;
1614 }
1615 else { /* don't let root wipe out directories without -U */
3280af22 1616 if (PerlLIO_lstat(s,&PL_statbuf) < 0 || S_ISDIR(PL_statbuf.st_mode))
a687059c 1617 tot--;
1618 else {
1619 if (UNLINK(s))
1620 tot--;
1621 }
1622 }
1623 }
1624 break;
a0d0e21e 1625#ifdef HAS_UTIME
79072805 1626 case OP_UTIME:
20408e3c 1627 what = "utime";
1628 APPLY_TAINT_PROPER();
79072805 1629 if (sp - mark > 2) {
748a9306 1630#if defined(I_UTIME) || defined(VMS)
663a0e37 1631 struct utimbuf utbuf;
1632#else
a687059c 1633 struct {
dd2821f6 1634 Time_t actime;
1635 Time_t modtime;
a687059c 1636 } utbuf;
663a0e37 1637#endif
a687059c 1638
afd9f252 1639 Zero(&utbuf, sizeof utbuf, char);
517844ec 1640#ifdef BIG_TIME
dd2821f6 1641 utbuf.actime = (Time_t)SvNVx(*++mark); /* time accessed */
1642 utbuf.modtime = (Time_t)SvNVx(*++mark); /* time modified */
517844ec 1643#else
dd2821f6 1644 utbuf.actime = (Time_t)SvIVx(*++mark); /* time accessed */
1645 utbuf.modtime = (Time_t)SvIVx(*++mark); /* time modified */
517844ec 1646#endif
20408e3c 1647 APPLY_TAINT_PROPER();
79072805 1648 tot = sp - mark;
1649 while (++mark <= sp) {
2d8e6c8d 1650 char *name = SvPVx(*mark, n_a);
20408e3c 1651 APPLY_TAINT_PROPER();
1652 if (PerlLIO_utime(name, &utbuf))
a687059c 1653 tot--;
1654 }
a687059c 1655 }
1656 else
79072805 1657 tot = 0;
a687059c 1658 break;
a0d0e21e 1659#endif
a687059c 1660 }
1661 return tot;
20408e3c 1662
20408e3c 1663#undef APPLY_TAINT_PROPER
a687059c 1664}
1665
1666/* Do the permissions allow some operation? Assumes statcache already set. */
a0d0e21e 1667#ifndef VMS /* VMS' cando is in vms.c */
7f4774ae 1668bool
1669Perl_cando(pTHX_ Mode_t mode, Uid_t effective, register Stat_t *statbufp)
1670/* Note: we use `effective' both for uids and gids.
1671 * Here we are betting on Uid_t being equal or wider than Gid_t. */
a687059c 1672{
bee1dbe2 1673#ifdef DOSISH
fe14fcc3 1674 /* [Comments and code from Len Reed]
1675 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
1676 * to write-protected files. The execute permission bit is set
1677 * by the Miscrosoft C library stat() function for the following:
1678 * .exe files
1679 * .com files
1680 * .bat files
1681 * directories
1682 * All files and directories are readable.
1683 * Directories and special files, e.g. "CON", cannot be
1684 * write-protected.
1685 * [Comment by Tom Dinger -- a directory can have the write-protect
1686 * bit set in the file system, but DOS permits changes to
1687 * the directory anyway. In addition, all bets are off
1688 * here for networked software, such as Novell and
1689 * Sun's PC-NFS.]
1690 */
1691
bee1dbe2 1692 /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
1693 * too so it will actually look into the files for magic numbers
1694 */
7f4774ae 1695 return (mode & statbufp->st_mode) ? TRUE : FALSE;
fe14fcc3 1696
55497cff 1697#else /* ! DOSISH */
3280af22 1698 if ((effective ? PL_euid : PL_uid) == 0) { /* root is special */
7f4774ae 1699 if (mode == S_IXUSR) {
c623bd54 1700 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
a687059c 1701 return TRUE;
1702 }
1703 else
1704 return TRUE; /* root reads and writes anything */
1705 return FALSE;
1706 }
3280af22 1707 if (statbufp->st_uid == (effective ? PL_euid : PL_uid) ) {
7f4774ae 1708 if (statbufp->st_mode & mode)
a687059c 1709 return TRUE; /* ok as "user" */
1710 }
d8eceb89 1711 else if (ingroup(statbufp->st_gid,effective)) {
7f4774ae 1712 if (statbufp->st_mode & mode >> 3)
a687059c 1713 return TRUE; /* ok as "group" */
1714 }
7f4774ae 1715 else if (statbufp->st_mode & mode >> 6)
a687059c 1716 return TRUE; /* ok as "other" */
1717 return FALSE;
55497cff 1718#endif /* ! DOSISH */
a687059c 1719}
a0d0e21e 1720#endif /* ! VMS */
a687059c 1721
d8eceb89 1722bool
1723Perl_ingroup(pTHX_ Gid_t testgid, Uid_t effective)
a687059c 1724{
cd39f2b6 1725#ifdef MACOS_TRADITIONAL
1726 /* This is simply not correct for AppleShare, but fix it yerself. */
1727 return TRUE;
1728#else
3280af22 1729 if (testgid == (effective ? PL_egid : PL_gid))
a687059c 1730 return TRUE;
fe14fcc3 1731#ifdef HAS_GETGROUPS
a687059c 1732#ifndef NGROUPS
1733#define NGROUPS 32
1734#endif
1735 {
a0d0e21e 1736 Groups_t gary[NGROUPS];
79072805 1737 I32 anum;
a687059c 1738
1739 anum = getgroups(NGROUPS,gary);
1740 while (--anum >= 0)
1741 if (gary[anum] == testgid)
1742 return TRUE;
1743 }
1744#endif
1745 return FALSE;
cd39f2b6 1746#endif
a687059c 1747}
c2ab57d4 1748
fe14fcc3 1749#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
c2ab57d4 1750
79072805 1751I32
864dbfa3 1752Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
c2ab57d4 1753{
11343788 1754 dTHR;
c2ab57d4 1755 key_t key;
79072805 1756 I32 n, flags;
c2ab57d4 1757
463ee0b2 1758 key = (key_t)SvNVx(*++mark);
1759 n = (optype == OP_MSGGET) ? 0 : SvIVx(*++mark);
1760 flags = SvIVx(*++mark);
748a9306 1761 SETERRNO(0,0);
c2ab57d4 1762 switch (optype)
1763 {
fe14fcc3 1764#ifdef HAS_MSG
79072805 1765 case OP_MSGGET:
c2ab57d4 1766 return msgget(key, flags);
e5d73d77 1767#endif
fe14fcc3 1768#ifdef HAS_SEM
79072805 1769 case OP_SEMGET:
c2ab57d4 1770 return semget(key, n, flags);
e5d73d77 1771#endif
fe14fcc3 1772#ifdef HAS_SHM
79072805 1773 case OP_SHMGET:
c2ab57d4 1774 return shmget(key, n, flags);
e5d73d77 1775#endif
fe14fcc3 1776#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
e5d73d77 1777 default:
cea2e8a9 1778 Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
e5d73d77 1779#endif
c2ab57d4 1780 }
1781 return -1; /* should never happen */
1782}
1783
79072805 1784I32
864dbfa3 1785Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp)
c2ab57d4 1786{
11343788 1787 dTHR;
79072805 1788 SV *astr;
c2ab57d4 1789 char *a;
a0d0e21e 1790 I32 id, n, cmd, infosize, getinfo;
1791 I32 ret = -1;
c2ab57d4 1792
463ee0b2 1793 id = SvIVx(*++mark);
1794 n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
1795 cmd = SvIVx(*++mark);
79072805 1796 astr = *++mark;
c2ab57d4 1797 infosize = 0;
1798 getinfo = (cmd == IPC_STAT);
1799
1800 switch (optype)
1801 {
fe14fcc3 1802#ifdef HAS_MSG
79072805 1803 case OP_MSGCTL:
c2ab57d4 1804 if (cmd == IPC_STAT || cmd == IPC_SET)
1805 infosize = sizeof(struct msqid_ds);
1806 break;
e5d73d77 1807#endif
fe14fcc3 1808#ifdef HAS_SHM
79072805 1809 case OP_SHMCTL:
c2ab57d4 1810 if (cmd == IPC_STAT || cmd == IPC_SET)
1811 infosize = sizeof(struct shmid_ds);
1812 break;
e5d73d77 1813#endif
fe14fcc3 1814#ifdef HAS_SEM
79072805 1815 case OP_SEMCTL:
39398f3f 1816#ifdef Semctl
c2ab57d4 1817 if (cmd == IPC_STAT || cmd == IPC_SET)
1818 infosize = sizeof(struct semid_ds);
1819 else if (cmd == GETALL || cmd == SETALL)
1820 {
8e591e46 1821 struct semid_ds semds;
bd89102f 1822 union semun semun;
e6f0bdd6 1823#ifdef EXTRA_F_IN_SEMUN_BUF
1824 semun.buff = &semds;
1825#else
84902520 1826 semun.buf = &semds;
e6f0bdd6 1827#endif
c2ab57d4 1828 getinfo = (cmd == GETALL);
9b89d93d 1829 if (Semctl(id, 0, IPC_STAT, semun) == -1)
1830 return -1;
6e21c824 1831 infosize = semds.sem_nsems * sizeof(short);
1832 /* "short" is technically wrong but much more portable
1833 than guessing about u_?short(_t)? */
c2ab57d4 1834 }
39398f3f 1835#else
cea2e8a9 1836 Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
39398f3f 1837#endif
c2ab57d4 1838 break;
e5d73d77 1839#endif
fe14fcc3 1840#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
e5d73d77 1841 default:
cea2e8a9 1842 Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
e5d73d77 1843#endif
c2ab57d4 1844 }
1845
1846 if (infosize)
1847 {
a0d0e21e 1848 STRLEN len;
c2ab57d4 1849 if (getinfo)
1850 {
a0d0e21e 1851 SvPV_force(astr, len);
1852 a = SvGROW(astr, infosize+1);
c2ab57d4 1853 }
1854 else
1855 {
463ee0b2 1856 a = SvPV(astr, len);
1857 if (len != infosize)
cea2e8a9 1858 Perl_croak(aTHX_ "Bad arg length for %s, is %lu, should be %ld",
4ec43091 1859 PL_op_desc[optype],
1860 (unsigned long)len,
1861 (long)infosize);
c2ab57d4 1862 }
1863 }
1864 else
1865 {
c030ccd9 1866 IV i = SvIV(astr);
56431972 1867 a = INT2PTR(char *,i); /* ouch */
c2ab57d4 1868 }
748a9306 1869 SETERRNO(0,0);
c2ab57d4 1870 switch (optype)
1871 {
fe14fcc3 1872#ifdef HAS_MSG
79072805 1873 case OP_MSGCTL:
bee1dbe2 1874 ret = msgctl(id, cmd, (struct msqid_ds *)a);
c2ab57d4 1875 break;
e5d73d77 1876#endif
fe14fcc3 1877#ifdef HAS_SEM
bd89102f 1878 case OP_SEMCTL: {
39398f3f 1879#ifdef Semctl
bd89102f 1880 union semun unsemds;
1881
e6f0bdd6 1882#ifdef EXTRA_F_IN_SEMUN_BUF
1883 unsemds.buff = (struct semid_ds *)a;
1884#else
bd89102f 1885 unsemds.buf = (struct semid_ds *)a;
e6f0bdd6 1886#endif
bd89102f 1887 ret = Semctl(id, n, cmd, unsemds);
39398f3f 1888#else
cea2e8a9 1889 Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
39398f3f 1890#endif
bd89102f 1891 }
c2ab57d4 1892 break;
e5d73d77 1893#endif
fe14fcc3 1894#ifdef HAS_SHM
79072805 1895 case OP_SHMCTL:
bee1dbe2 1896 ret = shmctl(id, cmd, (struct shmid_ds *)a);
c2ab57d4 1897 break;
e5d73d77 1898#endif
c2ab57d4 1899 }
1900 if (getinfo && ret >= 0) {
79072805 1901 SvCUR_set(astr, infosize);
1902 *SvEND(astr) = '\0';
a0d0e21e 1903 SvSETMAGIC(astr);
c2ab57d4 1904 }
1905 return ret;
1906}
1907
79072805 1908I32
864dbfa3 1909Perl_do_msgsnd(pTHX_ SV **mark, SV **sp)
c2ab57d4 1910{
fe14fcc3 1911#ifdef HAS_MSG
11343788 1912 dTHR;
79072805 1913 SV *mstr;
c2ab57d4 1914 char *mbuf;
79072805 1915 I32 id, msize, flags;
463ee0b2 1916 STRLEN len;
c2ab57d4 1917
463ee0b2 1918 id = SvIVx(*++mark);
79072805 1919 mstr = *++mark;
463ee0b2 1920 flags = SvIVx(*++mark);
1921 mbuf = SvPV(mstr, len);
1922 if ((msize = len - sizeof(long)) < 0)
cea2e8a9 1923 Perl_croak(aTHX_ "Arg too short for msgsnd");
748a9306 1924 SETERRNO(0,0);
bee1dbe2 1925 return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
e5d73d77 1926#else
cea2e8a9 1927 Perl_croak(aTHX_ "msgsnd not implemented");
e5d73d77 1928#endif
c2ab57d4 1929}
1930
79072805 1931I32
864dbfa3 1932Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
c2ab57d4 1933{
fe14fcc3 1934#ifdef HAS_MSG
11343788 1935 dTHR;
79072805 1936 SV *mstr;
c2ab57d4 1937 char *mbuf;
1938 long mtype;
79072805 1939 I32 id, msize, flags, ret;
463ee0b2 1940 STRLEN len;
79072805 1941
463ee0b2 1942 id = SvIVx(*++mark);
79072805 1943 mstr = *++mark;
c2e66d9e 1944 /* suppress warning when reading into undef var --jhi */
1945 if (! SvOK(mstr))
1946 sv_setpvn(mstr, "", 0);
463ee0b2 1947 msize = SvIVx(*++mark);
1948 mtype = (long)SvIVx(*++mark);
1949 flags = SvIVx(*++mark);
a0d0e21e 1950 SvPV_force(mstr, len);
1951 mbuf = SvGROW(mstr, sizeof(long)+msize+1);
a1d180c4 1952
748a9306 1953 SETERRNO(0,0);
bee1dbe2 1954 ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
c2ab57d4 1955 if (ret >= 0) {
79072805 1956 SvCUR_set(mstr, sizeof(long)+ret);
1957 *SvEND(mstr) = '\0';
41d6edb2 1958#ifndef INCOMPLETE_TAINTS
1959 /* who knows who has been playing with this message? */
1960 SvTAINTED_on(mstr);
1961#endif
c2ab57d4 1962 }
1963 return ret;
e5d73d77 1964#else
cea2e8a9 1965 Perl_croak(aTHX_ "msgrcv not implemented");
e5d73d77 1966#endif
c2ab57d4 1967}
1968
79072805 1969I32
864dbfa3 1970Perl_do_semop(pTHX_ SV **mark, SV **sp)
c2ab57d4 1971{
fe14fcc3 1972#ifdef HAS_SEM
11343788 1973 dTHR;
79072805 1974 SV *opstr;
c2ab57d4 1975 char *opbuf;
463ee0b2 1976 I32 id;
1977 STRLEN opsize;
c2ab57d4 1978
463ee0b2 1979 id = SvIVx(*++mark);
79072805 1980 opstr = *++mark;
463ee0b2 1981 opbuf = SvPV(opstr, opsize);
c2ab57d4 1982 if (opsize < sizeof(struct sembuf)
1983 || (opsize % sizeof(struct sembuf)) != 0) {
748a9306 1984 SETERRNO(EINVAL,LIB$_INVARG);
c2ab57d4 1985 return -1;
1986 }
748a9306 1987 SETERRNO(0,0);
6e21c824 1988 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
e5d73d77 1989#else
cea2e8a9 1990 Perl_croak(aTHX_ "semop not implemented");
e5d73d77 1991#endif
c2ab57d4 1992}
1993
79072805 1994I32
864dbfa3 1995Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
c2ab57d4 1996{
fe14fcc3 1997#ifdef HAS_SHM
11343788 1998 dTHR;
79072805 1999 SV *mstr;
c2ab57d4 2000 char *mbuf, *shm;
79072805 2001 I32 id, mpos, msize;
463ee0b2 2002 STRLEN len;
c2ab57d4 2003 struct shmid_ds shmds;
c2ab57d4 2004
463ee0b2 2005 id = SvIVx(*++mark);
79072805 2006 mstr = *++mark;
463ee0b2 2007 mpos = SvIVx(*++mark);
2008 msize = SvIVx(*++mark);
748a9306 2009 SETERRNO(0,0);
c2ab57d4 2010 if (shmctl(id, IPC_STAT, &shmds) == -1)
2011 return -1;
2012 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
748a9306 2013 SETERRNO(EFAULT,SS$_ACCVIO); /* can't do as caller requested */
c2ab57d4 2014 return -1;
2015 }
8ac85365 2016 shm = (char *)shmat(id, (char*)NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
c2ab57d4 2017 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2018 return -1;
79072805 2019 if (optype == OP_SHMREAD) {
9f538c04 2020 /* suppress warning when reading into undef var (tchrist 3/Mar/00) */
2021 if (! SvOK(mstr))
2022 sv_setpvn(mstr, "", 0);
a0d0e21e 2023 SvPV_force(mstr, len);
2024 mbuf = SvGROW(mstr, msize+1);
2025
bee1dbe2 2026 Copy(shm + mpos, mbuf, msize, char);
79072805 2027 SvCUR_set(mstr, msize);
2028 *SvEND(mstr) = '\0';
a0d0e21e 2029 SvSETMAGIC(mstr);
d929ce6f 2030#ifndef INCOMPLETE_TAINTS
2031 /* who knows who has been playing with this shared memory? */
2032 SvTAINTED_on(mstr);
2033#endif
c2ab57d4 2034 }
2035 else {
79072805 2036 I32 n;
c2ab57d4 2037
a0d0e21e 2038 mbuf = SvPV(mstr, len);
463ee0b2 2039 if ((n = len) > msize)
c2ab57d4 2040 n = msize;
bee1dbe2 2041 Copy(mbuf, shm + mpos, n, char);
c2ab57d4 2042 if (n < msize)
bee1dbe2 2043 memzero(shm + mpos + n, msize - n);
c2ab57d4 2044 }
2045 return shmdt(shm);
e5d73d77 2046#else
cea2e8a9 2047 Perl_croak(aTHX_ "shm I/O not implemented");
e5d73d77 2048#endif
c2ab57d4 2049}
2050
fe14fcc3 2051#endif /* SYSV IPC */
4e35701f 2052
0e32cd81 2053#ifdef SOCKS_64BIT_BUG
2054
fab3f3a7 2055/**
2056 ** getc and ungetc wrappers for the 64 bit problems with SOCKS 5 support
2057 ** Workaround to the problem, that SOCKS maps a socket 'getc' to revc
2058 ** without checking the ungetc buffer.
2059 **/
0e32cd81 2060
fab3f3a7 2061static S64_IOB *s64_buffer = (S64_IOB *) NULL;
2062
9d44748a 2063/* initialize the buffer area */
2064/* required after a fork(2) call in order to remove side effects */
2065void Perl_do_s64_init_buffer() {
2066 s64_buffer = (S64_IOB *) NULL;
2067}
2068
fab3f3a7 2069/* get a buffered stream pointer */
0e32cd81 2070static S64_IOB *S_s64_get_buffer( PerlIO *fp) {
fab3f3a7 2071 S64_IOB *ptr = s64_buffer;
0e32cd81 2072 while( ptr && ptr->fp != fp)
fab3f3a7 2073 ptr = ptr->next;
2074 return( ptr);
2075}
2076
2077/* create a buffered stream pointer */
9d44748a 2078static S64_IOB *S_s64_create_buffer( PerlIO *f) {
fab3f3a7 2079 S64_IOB *ptr = malloc( sizeof( S64_IOB));
2080 if( ptr) {
2081 ptr->fp = f;
2082 ptr->cnt = ptr->size = 0;
2083 ptr->buffer = (int *) NULL;
2084 ptr->next = s64_buffer;
2085 ptr->last = (S64_IOB *) NULL;
2086 if( s64_buffer) s64_buffer->last = ptr;
2087 s64_buffer = ptr;
2088 }
2089 return( ptr);
2090}
2091
2092/* delete a buffered stream pointer */
2093void Perl_do_s64_delete_buffer( PerlIO *f) {
2094 S64_IOB *ptr = _s64_get_buffer(f);
2095 if( ptr) {
2096 /* fix the stream pointer according to the bytes buffered */
2097 /* required, if this is called in a seek-context */
2098 if( ptr->cnt) fseek(f,-ptr->cnt,SEEK_CUR);
2099 if( ptr->buffer) free( ptr->buffer);
2100 if( ptr->last)
2101 ptr->last->next = ptr->next;
2102 else
2103 s64_buffer = ptr->next;
2104 free( ptr);
2105 }
2106}
2107
2108/* internal buffer management */
2109#define _S64_BUFFER_SIZE 32
9d44748a 2110static int S_s64_malloc( S64_IOB *ptr) {
fab3f3a7 2111 if( ptr) {
2112 if( !ptr->buffer) {
2113 ptr->buffer = (int *) calloc( _S64_BUFFER_SIZE, sizeof( int));
2114 ptr->size = ptr->cnt = 0;
2115 } else {
2116 ptr->buffer = (int *) realloc( ptr->buffer, ptr->size + _S64_BUFFER_SIZE);
2117 }
2118
2119 if( !ptr->buffer)
2120 return( 0);
2121
2122 ptr->size += _S64_BUFFER_SIZE;
60382766 2123
fab3f3a7 2124 return( 1);
2125 }
2126
2127 return( 0);
2128}
2129
2130/* SOCKS 64 bit getc replacement */
2131int Perl_do_s64_getc( PerlIO *f) {
2132 S64_IOB *ptr = _s64_get_buffer(f);
2133 if( ptr) {
60382766 2134 if( ptr->cnt)
fab3f3a7 2135 return( ptr->buffer[--ptr->cnt]);
2136 }
2137 return( getc(f));
2138}
2139
2140/* SOCKS 64 bit ungetc replacement */
2141int Perl_do_s64_ungetc( int ch, PerlIO *f) {
2142 S64_IOB *ptr = _s64_get_buffer(f);
2143
2144 if( !ptr) ptr=_s64_create_buffer(f);
2145 if( !ptr) return( EOF);
60382766 2146 if( !ptr->buffer || (ptr->buffer && ptr->cnt >= ptr->size))
fab3f3a7 2147 if( !_s64_malloc( ptr)) return( EOF);
2148 ptr->buffer[ptr->cnt++] = ch;
2149
2150 return( ch);
2151}
2152
2153/* SOCKS 64 bit fread replacement */
2154SSize_t Perl_do_s64_fread(void *buf, SSize_t count, PerlIO* f) {
2155 SSize_t len = 0;
2156 char *bufptr = (char *) buf;
2157 S64_IOB *ptr = _s64_get_buffer(f);
2158 if( ptr) {
2159 while( ptr->cnt && count) {
2160 *bufptr++ = ptr->buffer[--ptr->cnt];
2161 count--, len++;
2162 }
2163 }
2164 if( count)
2165 len += (SSize_t)fread(bufptr,1,count,f);
2166
2167 return( len);
2168}
2169
2170/* SOCKS 64 bit fseek replacement */
2171int Perl_do_s64_seek(PerlIO* f, Off_t offset, int whence) {
2172 S64_IOB *ptr = _s64_get_buffer(f);
2173
2174 /* Simply clear the buffer and seek if the position is absolute */
2175 if( SEEK_SET == whence || SEEK_END == whence) {
2176 if( ptr) ptr->cnt = 0;
2177
2178 /* In case of relative positioning clear the buffer and calculate */
2179 /* a fixed offset */
2180 } else if( SEEK_CUR == whence) {
2181 if( ptr) {
2182 offset -= (Off_t)ptr->cnt;
2183 ptr->cnt = 0;
2184 }
2185 }
2186
2187 /* leave out buffer untouched otherwise, because fseek will fail */
2188 /* seek now */
2189 return( fseeko( f, offset, whence));
2190}
2191
2192/* SOCKS 64 bit ftell replacement */
2193Off_t Perl_do_s64_tell(PerlIO* f) {
2194 Off_t offset = 0;
2195 S64_IOB *ptr = _s64_get_buffer(f);
2196 if( ptr)
2197 offset = ptr->cnt;
2198 return( ftello(f) - offset);
2199}
2200
2201#endif