/* doio.c
*
- * Copyright (c) 1991-2001, Larry Wall
+ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*/
/*
- * "Far below them they saw the white waters pour into a foaming bowl, and
- * then swirl darkly about a deep oval basin in the rocks, until they found
- * their way out again through a narrow gate, and flowed away, fuming and
- * chattering, into calmer and more level reaches."
+ * Far below them they saw the white waters pour into a foaming bowl, and
+ * then swirl darkly about a deep oval basin in the rocks, until they found
+ * their way out again through a narrow gate, and flowed away, fuming and
+ * chattering, into calmer and more level reaches.
+ *
+ * [p.684 of _The Lord of the Rings_, IV/vi: "The Forbidden Pool"]
+ */
+
+/* This file contains functions that do the actual I/O on behalf of ops.
+ * For example, pp_print() calls the do_print() function in this file for
+ * each argument needing printing.
*/
#include "EXTERN.h"
# define OPEN_EXCL 0
#endif
-#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
-#include <signal.h>
-#endif
-
-bool
-Perl_do_open(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
- int rawmode, int rawperm, PerlIO *supplied_fp)
-{
- return do_openn(gv, name, len, as_raw, rawmode, rawperm,
- supplied_fp, (SV **) NULL, 0);
-}
+#define PERL_MODE_MAX 8
+#define PERL_FLAGS_MAX 10
-bool
-Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
- int rawmode, int rawperm, PerlIO *supplied_fp, SV *svs,
- I32 num_svs)
-{
- return do_openn(gv, name, len, as_raw, rawmode, rawperm,
- supplied_fp, &svs, 1);
-}
+#include <signal.h>
bool
-Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
+Perl_do_openn(pTHX_ GV *gv, register const char *oname, I32 len, int as_raw,
int rawmode, int rawperm, PerlIO *supplied_fp, SV **svp,
I32 num_svs)
{
- register IO *io = GvIOn(gv);
- PerlIO *saveifp = Nullfp;
- PerlIO *saveofp = Nullfp;
+ dVAR;
+ register IO * const io = GvIOn(gv);
+ PerlIO *saveifp = NULL;
+ PerlIO *saveofp = NULL;
int savefd = -1;
char savetype = IoTYPE_CLOSED;
int writing = 0;
bool was_fdopen = FALSE;
bool in_raw = 0, in_crlf = 0, out_raw = 0, out_crlf = 0;
char *type = NULL;
- char mode[8]; /* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */
+ char mode[PERL_MODE_MAX]; /* file mode ("r\0", "rb\0", "ab\0" etc.) */
SV *namesv;
+ PERL_ARGS_ASSERT_DO_OPENN;
+
Zero(mode,sizeof(mode),char);
PL_forkprocess = 1; /* assume true if no fork */
/* Collect default raw/crlf info from the op */
if (PL_op && PL_op->op_type == OP_OPEN) {
- /* set up disciplines */
- U8 flags = PL_op->op_private;
+ /* set up IO layers */
+ const U8 flags = PL_op->op_private;
in_raw = (flags & OPpOPEN_IN_RAW);
in_crlf = (flags & OPpOPEN_IN_CRLF);
out_raw = (flags & OPpOPEN_OUT_RAW);
if (result == EOF && fd > PL_maxsysfd) {
/* Why is this not Perl_warn*() call ? */
PerlIO_printf(Perl_error_log,
- "Warning: unable to close filehandle %s properly.\n",
- GvENAME(gv));
+ "Warning: unable to close filehandle %"HEKf" properly.\n",
+ HEKfARG(GvENAME_HEK(gv))
+ );
}
- IoOFP(io) = IoIFP(io) = Nullfp;
+ IoOFP(io) = IoIFP(io) = NULL;
}
if (as_raw) {
/* sysopen style args, i.e. integer mode and permissions */
STRLEN ix = 0;
- if (num_svs != 0) {
- Perl_croak(aTHX_ "panic: sysopen with multiple args");
- }
- if (rawmode & (O_WRONLY|O_RDWR|O_CREAT
+ const int appendtrunc =
+ 0
#ifdef O_APPEND /* Not fully portable. */
- |O_APPEND
+ |O_APPEND
#endif
#ifdef O_TRUNC /* Not fully portable. */
- |O_TRUNC
+ |O_TRUNC
#endif
- ))
- TAINT_PROPER("sysopen");
- mode[ix++] = '#'; /* Marker to openn to use numeric "sysopen" */
+ ;
+ const int modifyingmode = O_WRONLY|O_RDWR|O_CREAT|appendtrunc;
+ int ismodifying;
-#if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
- rawmode |= O_LARGEFILE; /* Transparently largefiley. */
-#endif
+ if (num_svs != 0) {
+ Perl_croak(aTHX_ "panic: sysopen with multiple args, num_svs=%ld",
+ (long) num_svs);
+ }
+ /* It's not always
-#ifndef O_ACCMODE
-#define O_ACCMODE 3 /* Assume traditional implementation */
-#endif
+ O_RDONLY 0
+ O_WRONLY 1
+ O_RDWR 2
- switch (result = rawmode & O_ACCMODE) {
- case O_RDONLY:
- IoTYPE(io) = IoTYPE_RDONLY;
- break;
- case O_WRONLY:
- IoTYPE(io) = IoTYPE_WRONLY;
- break;
- case O_RDWR:
- default:
- IoTYPE(io) = IoTYPE_RDWR;
- break;
- }
- writing = (result > 0);
+ It might be (in OS/390 and Mac OS Classic it is)
- if (result == O_RDONLY) {
- mode[ix++] = 'r';
- }
-#ifdef O_APPEND
- else if (rawmode & O_APPEND) {
- mode[ix++] = 'a';
- if (result != O_WRONLY)
- mode[ix++] = '+';
+ O_WRONLY 1
+ O_RDONLY 2
+ O_RDWR 3
+
+ This means that simple & with O_RDWR would look
+ like O_RDONLY is present. Therefore we have to
+ be more careful.
+ */
+ if ((ismodifying = (rawmode & modifyingmode))) {
+ if ((ismodifying & O_WRONLY) == O_WRONLY ||
+ (ismodifying & O_RDWR) == O_RDWR ||
+ (ismodifying & (O_CREAT|appendtrunc)))
+ TAINT_PROPER("sysopen");
}
+ mode[ix++] = IoTYPE_NUMERIC; /* Marker to openn to use numeric "sysopen" */
+
+#if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
+ rawmode |= O_LARGEFILE; /* Transparently largefiley. */
#endif
- else {
- if (result == O_WRONLY)
- mode[ix++] = 'w';
- else {
- mode[ix++] = 'r';
- mode[ix++] = '+';
- }
- }
- if (rawmode & O_BINARY)
- mode[ix++] = 'b';
- mode[ix] = '\0';
- namesv = sv_2mortal(newSVpvn(name,strlen(name)));
+ IoTYPE(io) = PerlIO_intmode2str(rawmode, &mode[ix], &writing);
+
+ namesv = newSVpvn_flags(oname, len, SVs_TEMP);
num_svs = 1;
svp = &namesv;
- type = Nullch;
+ type = NULL;
fp = PerlIO_openn(aTHX_ type, mode, -1, rawmode, rawperm, NULL, num_svs, svp);
}
else {
/* Regular (non-sys) open */
- char *oname = name;
+ char *name;
STRLEN olen = len;
char *tend;
int dodup = 0;
- type = savepvn(name, len);
+ type = savepvn(oname, len);
tend = type+len;
SAVEFREEPV(type);
- /* Loose trailing white space */
- while (tend > type && isSPACE(tend[-1]))
- *tend-- = '\0';
+
+ /* Lose leading and trailing white space */
+ while (isSPACE(*type))
+ type++;
+ while (tend > type && isSPACE(tend[-1]))
+ *--tend = '\0';
+
if (num_svs) {
- /* New style explict name, type is just mode and discipline/layer info */
- STRLEN l = 0;
- name = SvOK(*svp) ? SvPV(*svp, l) : "";
- len = (I32)l;
- name = savepvn(name, len);
+ /* New style explicit name, type is just mode and layer info */
+#ifdef USE_STDIO
+ if (SvROK(*svp) && !strchr(oname,'&')) {
+ if (ckWARN(WARN_IO))
+ Perl_warner(aTHX_ packWARN(WARN_IO),
+ "Can't open a reference");
+ SETERRNO(EINVAL, LIB_INVARG);
+ goto say_false;
+ }
+#endif /* USE_STDIO */
+ name = (SvOK(*svp) || SvGMAGICAL(*svp)) ?
+ savesvpv (*svp) : savepvs ("");
SAVEFREEPV(name);
- /*SUPPRESS 530*/
- for (; isSPACE(*type); type++) ;
}
else {
name = type;
if ((*type == IoTYPE_RDWR) && /* scary */
(*(type+1) == IoTYPE_RDONLY || *(type+1) == IoTYPE_WRONLY) &&
((!num_svs || (tend > type+1 && tend[-1] != IoTYPE_PIPE)))) {
- TAINT_PROPER("open");
+ TAINT_PROPER("open");
mode[1] = *type++;
writing = 1;
}
if (*type == IoTYPE_PIPE) {
if (num_svs) {
if (type[1] != IoTYPE_STD) {
- unknown_desr:
+ unknown_open_mode:
Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
}
type++;
}
- /*SUPPRESS 530*/
- for (type++; isSPACE(*type); type++) ;
+ do {
+ type++;
+ } while (isSPACE(*type));
if (!num_svs) {
name = type;
len = tend-type;
if (*name == '\0') {
/* command is missing 19990114 */
if (ckWARN(WARN_PIPE))
- Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
+ Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
errno = EPIPE;
goto say_false;
}
- if (strNE(name,"-") || num_svs)
+ if (!(*name == '-' && name[1] == '\0') || num_svs)
TAINT_ENV();
TAINT_PROPER("piped open");
if (!num_svs && name[len-1] == '|') {
name[--len] = '\0' ;
if (ckWARN(WARN_PIPE))
- Perl_warner(aTHX_ WARN_PIPE, "Can't open bidirectional pipe");
+ Perl_warner(aTHX_ packWARN(WARN_PIPE), "Can't open bidirectional pipe");
}
mode[0] = 'w';
writing = 1;
- if (out_raw)
- strcat(mode, "b");
- else if (out_crlf)
- strcat(mode, "t");
+ if (out_raw)
+ mode[1] = 'b';
+ else if (out_crlf)
+ mode[1] = 't';
if (num_svs > 1) {
fp = PerlProc_popen_list(mode, num_svs, svp);
}
else {
fp = PerlProc_popen(name,mode);
}
- }
+ if (num_svs) {
+ if (*type) {
+ if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
+ goto say_false;
+ }
+ }
+ }
+ } /* IoTYPE_PIPE */
else if (*type == IoTYPE_WRONLY) {
TAINT_PROPER("open");
type++;
}
writing = 1;
- if (out_raw)
- strcat(mode, "b");
- else if (out_crlf)
- strcat(mode, "t");
-
+ if (out_raw)
+ mode[1] = 'b';
+ else if (out_crlf)
+ mode[1] = 't';
if (*type == '&') {
duplicity:
- dodup = 1;
+ dodup = PERLIO_DUP_FD;
type++;
if (*type == '=') {
dodup = 0;
fp = supplied_fp;
}
else {
+ PerlIO *that_fp = NULL;
if (num_svs > 1) {
+ /* diag_listed_as: More than one argument to '%s' open */
Perl_croak(aTHX_ "More than one argument to '%c&' open",IoTYPE(io));
}
- if (num_svs && SvIOK(*svp)) {
+ while (isSPACE(*type))
+ type++;
+ if (num_svs && (SvIOK(*svp) || (SvPOK(*svp) && looks_like_number(*svp)))) {
fd = SvUV(*svp);
+ num_svs = 0;
}
else if (isDIGIT(*type)) {
- /*SUPPRESS 530*/
- for (; isSPACE(*type); type++) ;
fd = atoi(type);
}
else {
- IO* thatio;
+ const IO* thatio;
if (num_svs) {
thatio = sv_2io(*svp);
}
else {
- GV *thatgv;
- /*SUPPRESS 530*/
- for (; isSPACE(*type); type++) ;
- thatgv = gv_fetchpv(type,FALSE,SVt_PVIO);
+ GV * const thatgv = gv_fetchpvn_flags(type, tend - type,
+ 0, SVt_PVIO);
thatio = GvIO(thatgv);
}
if (!thatio) {
#ifdef EINVAL
- SETERRNO(EINVAL,SS$_IVCHAN);
+ SETERRNO(EINVAL,SS_IVCHAN);
#endif
goto say_false;
}
- if (IoIFP(thatio)) {
- PerlIO *fp = IoIFP(thatio);
+ if ((that_fp = IoIFP(thatio))) {
/* Flush stdio buffer before dup. --mjd
* Unfortunately SEEK_CURing 0 seems to
* be optimized away on most platforms;
#ifdef USE_SFIO
/* sfio fails to clear error on next
sfwrite, contrary to documentation.
- -- Nick Clark */
- if (PerlIO_seek(fp, 0, SEEK_CUR) == -1)
- PerlIO_clearerr(fp);
+ -- Nicholas Clark */
+ if (PerlIO_seek(that_fp, 0, SEEK_CUR) == -1)
+ PerlIO_clearerr(that_fp);
#endif
/* On the other hand, do all platforms
* take gracefully to flushing a read-only
* filehandle? Perhaps we should do
* fsetpos(src)+fgetpos(dst)? --nik */
- PerlIO_flush(fp);
- fd = PerlIO_fileno(fp);
+ PerlIO_flush(that_fp);
+ fd = PerlIO_fileno(that_fp);
/* When dup()ing STDIN, STDOUT or STDERR
* explicitly set appropriate access mode */
- if (IoIFP(thatio) == PerlIO_stdout()
- || IoIFP(thatio) == PerlIO_stderr())
+ if (that_fp == PerlIO_stdout()
+ || that_fp == PerlIO_stderr())
IoTYPE(io) = IoTYPE_WRONLY;
- else if (IoIFP(thatio) == PerlIO_stdin())
+ else if (that_fp == PerlIO_stdin())
IoTYPE(io) = IoTYPE_RDONLY;
/* When dup()ing a socket, say result is
* one as well */
else
fd = -1;
}
- if (dodup)
- fd = PerlLIO_dup(fd);
- else
- was_fdopen = TRUE;
if (!num_svs)
- type = Nullch;
- if (!(fp = PerlIO_openn(aTHX_ type,mode,fd,0,0,NULL,num_svs,svp))) {
+ type = NULL;
+ if (that_fp) {
+ fp = PerlIO_fdupopen(aTHX_ that_fp, NULL, dodup);
+ }
+ else {
if (dodup)
- PerlLIO_close(fd);
+ fd = PerlLIO_dup(fd);
+ else
+ was_fdopen = TRUE;
+ if (!(fp = PerlIO_openn(aTHX_ type,mode,fd,0,0,NULL,num_svs,svp))) {
+ if (dodup && fd >= 0)
+ PerlLIO_close(fd);
+ }
}
}
} /* & */
else {
- if (num_svs > 1) {
- Perl_croak(aTHX_ "More than one argument to '>' open");
- }
- /*SUPPRESS 530*/
- for (; isSPACE(*type); type++) ;
+ while (isSPACE(*type))
+ type++;
if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
- /*SUPPRESS 530*/
type++;
fp = PerlIO_stdout();
IoTYPE(io) = IoTYPE_STD;
+ if (num_svs > 1) {
+ /* diag_listed_as: More than one argument to '%s' open */
+ Perl_croak(aTHX_ "More than one argument to '>%c' open",IoTYPE_STD);
+ }
}
else {
if (!num_svs) {
- namesv = sv_2mortal(newSVpvn(type,strlen(type)));
+ namesv = newSVpvn_flags(type, tend - type, SVs_TEMP);
num_svs = 1;
svp = &namesv;
- type = Nullch;
+ type = NULL;
}
fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
}
} /* !& */
- }
+ if (!fp && type && *type && *type != ':' && !isIDFIRST(*type))
+ goto unknown_open_mode;
+ } /* IoTYPE_WRONLY */
else if (*type == IoTYPE_RDONLY) {
- if (num_svs > 1) {
- Perl_croak(aTHX_ "More than one argument to '<' open");
- }
- /*SUPPRESS 530*/
- for (type++; isSPACE(*type); type++) ;
+ do {
+ type++;
+ } while (isSPACE(*type));
mode[0] = 'r';
- if (in_raw)
- strcat(mode, "b");
- else if (in_crlf)
- strcat(mode, "t");
-
+ if (in_raw)
+ mode[1] = 'b';
+ else if (in_crlf)
+ mode[1] = 't';
if (*type == '&') {
goto duplicity;
}
if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
- /*SUPPRESS 530*/
type++;
fp = PerlIO_stdin();
IoTYPE(io) = IoTYPE_STD;
+ if (num_svs > 1) {
+ /* diag_listed_as: More than one argument to '%s' open */
+ Perl_croak(aTHX_ "More than one argument to '<%c' open",IoTYPE_STD);
+ }
}
else {
if (!num_svs) {
- namesv = sv_2mortal(newSVpvn(type,strlen(type)));
+ namesv = newSVpvn_flags(type, tend - type, SVs_TEMP);
num_svs = 1;
svp = &namesv;
- type = Nullch;
+ type = NULL;
}
fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
}
- }
- else if ((num_svs && type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
+ if (!fp && type && *type && *type != ':' && !isIDFIRST(*type))
+ goto unknown_open_mode;
+ } /* IoTYPE_RDONLY */
+ else if ((num_svs && /* '-|...' or '...|' */
+ type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
(!num_svs && tend > type+1 && tend[-1] == IoTYPE_PIPE)) {
if (num_svs) {
type += 2; /* skip over '-|' */
*--tend = '\0';
while (tend > type && isSPACE(tend[-1]))
*--tend = '\0';
- /*SUPPRESS 530*/
- for (; isSPACE(*type); type++) ;
+ for (; isSPACE(*type); type++)
+ ;
name = type;
len = tend-type;
}
if (*name == '\0') {
/* command is missing 19990114 */
if (ckWARN(WARN_PIPE))
- Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
+ Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
errno = EPIPE;
goto say_false;
}
- if (strNE(name,"-") || num_svs)
+ if (!(*name == '-' && name[1] == '\0') || num_svs)
TAINT_ENV();
TAINT_PROPER("piped open");
mode[0] = 'r';
- if (in_raw)
- strcat(mode, "b");
- else if (in_crlf)
- strcat(mode, "t");
+
+ if (in_raw)
+ mode[1] = 'b';
+ else if (in_crlf)
+ mode[1] = 't';
+
if (num_svs > 1) {
fp = PerlProc_popen_list(mode,num_svs,svp);
}
fp = PerlProc_popen(name,mode);
}
IoTYPE(io) = IoTYPE_PIPE;
+ if (num_svs) {
+ while (isSPACE(*type))
+ type++;
+ if (*type) {
+ if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) {
+ goto say_false;
+ }
+ }
+ }
}
- else {
+ else { /* layer(Args) */
if (num_svs)
- goto unknown_desr;
+ goto unknown_open_mode;
name = type;
IoTYPE(io) = IoTYPE_RDONLY;
- /*SUPPRESS 530*/
- for (; isSPACE(*name); name++) ;
+ for (; isSPACE(*name); name++)
+ ;
mode[0] = 'r';
- if (in_raw)
- strcat(mode, "b");
- else if (in_crlf)
- strcat(mode, "t");
- if (strEQ(name,"-")) {
+
+ if (in_raw)
+ mode[1] = 'b';
+ else if (in_crlf)
+ mode[1] = 't';
+
+ if (*name == '-' && name[1] == '\0') {
fp = PerlIO_stdin();
IoTYPE(io) = IoTYPE_STD;
}
else {
if (!num_svs) {
- namesv = sv_2mortal(newSVpvn(type,strlen(type)));
+ namesv = newSVpvn_flags(type, tend - type, SVs_TEMP);
num_svs = 1;
svp = &namesv;
- type = Nullch;
+ type = NULL;
}
fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
}
}
}
if (!fp) {
- if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n'))
- Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
+ if (IoTYPE(io) == IoTYPE_RDONLY && ckWARN(WARN_NEWLINE)
+ && strchr(oname, '\n')
+
+ )
+ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
goto say_false;
}
if (ckWARN(WARN_IO)) {
if ((IoTYPE(io) == IoTYPE_RDONLY) &&
(fp == PerlIO_stdout() || fp == PerlIO_stderr())) {
- Perl_warner(aTHX_ WARN_IO,
- "Filehandle STD%s opened only for input",
- (fp == PerlIO_stdout()) ? "OUT" : "ERR");
+ Perl_warner(aTHX_ packWARN(WARN_IO),
+ "Filehandle STD%s reopened as %"HEKf
+ " only for input",
+ ((fp == PerlIO_stdout()) ? "OUT" : "ERR"),
+ HEKfARG(GvENAME_HEK(gv)));
}
else if ((IoTYPE(io) == IoTYPE_WRONLY) && fp == PerlIO_stdin()) {
- Perl_warner(aTHX_ WARN_IO,
- "Filehandle STDIN opened only for output");
+ Perl_warner(aTHX_ packWARN(WARN_IO),
+ "Filehandle STDIN reopened as %"HEKf" only for output",
+ HEKfARG(GvENAME_HEK(gv))
+ );
}
}
- if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD &&
- /* FIXME: This next term is a hack to avoid fileno on PerlIO::Scalar */
- !(num_svs && SvROK(*svp))) {
- if (PerlLIO_fstat(PerlIO_fileno(fp),&PL_statbuf) < 0) {
- (void)PerlIO_close(fp);
+ fd = PerlIO_fileno(fp);
+ /* If there is no fd (e.g. PerlIO::scalar) assume it isn't a
+ * socket - this covers PerlIO::scalar - otherwise unless we "know" the
+ * type probe for socket-ness.
+ */
+ if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD && fd >= 0) {
+ if (PerlLIO_fstat(fd,&PL_statbuf) < 0) {
+ /* If PerlIO claims to have fd we had better be able to fstat() it. */
+ (void) PerlIO_close(fp);
goto say_false;
}
+#ifndef PERL_MICRO
if (S_ISSOCK(PL_statbuf.st_mode))
IoTYPE(io) = IoTYPE_SOCKET; /* in case a socket was passed in to us */
#ifdef HAS_SOCKET
&& IoTYPE(io) != IoTYPE_WRONLY /* Dups of STD* filehandles already have */
&& IoTYPE(io) != IoTYPE_RDONLY /* type so they aren't marked as sockets */
) { /* on OS's that return 0 on fstat()ed pipe */
- char tmpbuf[256];
- Sock_size_t buflen = sizeof tmpbuf;
- if (PerlSock_getsockname(PerlIO_fileno(fp), (struct sockaddr *)tmpbuf,
- &buflen) >= 0
- || errno != ENOTSOCK)
- IoTYPE(io) = IoTYPE_SOCKET; /* some OS's return 0 on fstat()ed socket */
- /* but some return 0 for streams too, sigh */
- }
-#endif
+ char tmpbuf[256];
+ Sock_size_t buflen = sizeof tmpbuf;
+ if (PerlSock_getsockname(fd, (struct sockaddr *)tmpbuf, &buflen) >= 0
+ || errno != ENOTSOCK)
+ IoTYPE(io) = IoTYPE_SOCKET; /* some OS's return 0 on fstat()ed socket */
+ /* but some return 0 for streams too, sigh */
+ }
+#endif /* HAS_SOCKET */
+#endif /* !PERL_MICRO */
}
+
+ /* Eeek - FIXME !!!
+ * If this is a standard handle we discard all the layer stuff
+ * and just dup the fd into whatever was on the handle before !
+ */
+
if (saveifp) { /* must use old fp? */
/* If fd is less that PL_maxsysfd i.e. STDIN..STDERR
then dup the new fileno down
*/
- fd = PerlIO_fileno(fp);
if (saveofp) {
PerlIO_flush(saveofp); /* emulate PerlIO_close() */
if (saveofp != saveifp) { /* was a socket? */
}
}
if (savefd != fd) {
- Pid_t pid;
- SV *sv;
+ /* Still a small can-of-worms here if (say) PerlIO::scalar
+ is assigned to (say) STDOUT - for now let dup2() fail
+ and provide the error
+ */
if (PerlLIO_dup2(fd, savefd) < 0) {
(void)PerlIO_close(fp);
goto say_false;
}
#ifdef VMS
if (savefd != PerlIO_fileno(PerlIO_stdin())) {
- char newname[FILENAME_MAX+1];
- if (PerlIO_getname(fp, newname)) {
- if (fd == PerlIO_fileno(PerlIO_stdout())) Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT", newname);
- if (fd == PerlIO_fileno(PerlIO_stderr())) Perl_vmssetuserlnm(aTHX_ "SYS$ERROR", newname);
- }
+ char newname[FILENAME_MAX+1];
+ if (PerlIO_getname(fp, newname)) {
+ if (fd == PerlIO_fileno(PerlIO_stdout()))
+ Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT", newname);
+ if (fd == PerlIO_fileno(PerlIO_stderr()))
+ Perl_vmssetuserlnm(aTHX_ "SYS$ERROR", newname);
+ }
}
#endif
- LOCK_FDPID_MUTEX;
- sv = *av_fetch(PL_fdpid,fd,TRUE);
- (void)SvUPGRADE(sv, SVt_IV);
- pid = SvIVX(sv);
- SvIVX(sv) = 0;
- sv = *av_fetch(PL_fdpid,savefd,TRUE);
- UNLOCK_FDPID_MUTEX;
- (void)SvUPGRADE(sv, SVt_IV);
- SvIVX(sv) = pid;
- if (!was_fdopen)
+
+#if !defined(WIN32)
+ /* PL_fdpid isn't used on Windows, so avoid this useless work.
+ * XXX Probably the same for a lot of other places. */
+ {
+ Pid_t pid;
+ SV *sv;
+
+ sv = *av_fetch(PL_fdpid,fd,TRUE);
+ SvUPGRADE(sv, SVt_IV);
+ pid = SvIVX(sv);
+ SvIV_set(sv, 0);
+ sv = *av_fetch(PL_fdpid,savefd,TRUE);
+ SvUPGRADE(sv, SVt_IV);
+ SvIV_set(sv, pid);
+ }
+#endif
+
+ if (was_fdopen) {
+ /* need to close fp without closing underlying fd */
+ int ofd = PerlIO_fileno(fp);
+ int dupfd = PerlLIO_dup(ofd);
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+ /* Assume if we have F_SETFD we have F_GETFD */
+ int coe = fcntl(ofd,F_GETFD);
+#endif
+ PerlIO_close(fp);
+ PerlLIO_dup2(dupfd,ofd);
+#if defined(HAS_FCNTL) && defined(F_SETFD)
+ /* The dup trick has lost close-on-exec on ofd */
+ fcntl(ofd,F_SETFD, coe);
+#endif
+ PerlLIO_close(dupfd);
+ }
+ else
PerlIO_close(fp);
}
fp = saveifp;
PerlIO_clearerr(fp);
+ fd = PerlIO_fileno(fp);
}
#if defined(HAS_FCNTL) && defined(F_SETFD)
- {
- int save_errno = errno;
- fd = PerlIO_fileno(fp);
+ if (fd >= 0) {
+ dSAVE_ERRNO;
fcntl(fd,F_SETFD,fd > PL_maxsysfd); /* can change errno */
- errno = save_errno;
+ RESTORE_ERRNO;
}
#endif
IoIFP(io) = fp;
IoFLAGS(io) &= ~IOf_NOLINE;
if (writing) {
if (IoTYPE(io) == IoTYPE_SOCKET
- || (IoTYPE(io) == IoTYPE_WRONLY && S_ISCHR(PL_statbuf.st_mode)) ) {
- mode[0] = 'w';
- if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,mode,PerlIO_fileno(fp),0,0,NULL,num_svs,svp))) {
+ || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(PL_statbuf.st_mode)) ) {
+ char *s = mode;
+ if (*s == IoTYPE_IMPLICIT || *s == IoTYPE_NUMERIC)
+ s++;
+ *s = 'w';
+ if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,s,fd,0,0,NULL,0,svp))) {
PerlIO_close(fp);
- IoIFP(io) = Nullfp;
+ IoIFP(io) = NULL;
goto say_false;
}
}
PerlIO *
Perl_nextargv(pTHX_ register GV *gv)
{
+ dVAR;
register SV *sv;
#ifndef FLEXFILENAMES
int filedev;
#endif
Uid_t fileuid;
Gid_t filegid;
- IO *io = GvIOp(gv);
+ IO * const io = GvIOp(gv);
+
+ PERL_ARGS_ASSERT_NEXTARGV;
if (!PL_argvoutgv)
- PL_argvoutgv = gv_fetchpv("ARGVOUT",TRUE,SVt_PVIO);
+ PL_argvoutgv = gv_fetchpvs("ARGVOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO);
if (io && (IoFLAGS(io) & IOf_ARGV) && (IoFLAGS(io) & IOf_START)) {
IoFLAGS(io) &= ~IOf_START;
if (PL_inplace) {
- if (!PL_argvout_stack)
- PL_argvout_stack = newAV();
- av_push(PL_argvout_stack, SvREFCNT_inc(PL_defoutgv));
+ assert(PL_defoutgv);
+ Perl_av_create_and_push(aTHX_ &PL_argvout_stack,
+ SvREFCNT_inc_simple_NN(PL_defoutgv));
}
}
if (PL_filemode & (S_ISUID|S_ISGID)) {
PerlIO_flush(IoIFP(GvIOn(PL_argvoutgv))); /* chmod must follow last write */
#ifdef HAS_FCHMOD
- (void)fchmod(PL_lastfd,PL_filemode);
+ if (PL_lastfd != -1)
+ (void)fchmod(PL_lastfd,PL_filemode);
#else
(void)PerlLIO_chmod(PL_oldname,PL_filemode);
#endif
}
+ PL_lastfd = -1;
PL_filemode = 0;
+ if (!GvAV(gv))
+ return NULL;
while (av_len(GvAV(gv)) >= 0) {
STRLEN oldlen;
sv = av_shift(GvAV(gv));
SAVEFREESV(sv);
- sv_setsv(GvSV(gv),sv);
+ sv_setsv(GvSVn(gv),sv);
SvSETMAGIC(GvSV(gv));
PL_oldname = SvPVx(GvSV(gv), oldlen);
- if (do_open(gv,PL_oldname,oldlen,PL_inplace!=0,O_RDONLY,0,Nullfp)) {
+ if (do_open(gv,PL_oldname,oldlen,PL_inplace!=0,O_RDONLY,0,NULL)) {
if (PL_inplace) {
TAINT_PROPER("inplace open");
if (oldlen == 1 && *PL_oldname == '-') {
- setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
+ setdefout(gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL,
+ SVt_PVIO));
return IoIFP(GvIOp(gv));
}
#ifndef FLEXFILENAMES
fileuid = PL_statbuf.st_uid;
filegid = PL_statbuf.st_gid;
if (!S_ISREG(PL_filemode)) {
- if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
- "Can't do inplace edit: %s is not a regular file",
- PL_oldname );
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
+ "Can't do inplace edit: %s is not a regular file",
+ PL_oldname );
do_close(gv,FALSE);
continue;
}
- if (*PL_inplace) {
- char *star = strchr(PL_inplace, '*');
+ if (*PL_inplace && strNE(PL_inplace, "*")) {
+ const char *star = strchr(PL_inplace, '*');
if (star) {
- char *begin = PL_inplace;
- sv_setpvn(sv, "", 0);
+ const char *begin = PL_inplace;
+ sv_setpvs(sv, "");
do {
sv_catpvn(sv, begin, star - begin);
sv_catpvn(sv, PL_oldname, oldlen);
sv_catpv(sv,PL_inplace);
}
#ifndef FLEXFILENAMES
- if (PerlLIO_stat(SvPVX(sv),&PL_statbuf) >= 0
- && PL_statbuf.st_dev == filedev
- && PL_statbuf.st_ino == fileino
+ if ((PerlLIO_stat(SvPVX_const(sv),&PL_statbuf) >= 0
+ && PL_statbuf.st_dev == filedev
+ && PL_statbuf.st_ino == fileino)
#ifdef DJGPP
- || (_djstat_fail_bits & _STFAIL_TRUENAME)!=0
+ || ((_djstat_fail_bits & _STFAIL_TRUENAME)!=0)
#endif
)
{
- if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
- "Can't do inplace edit: %s would not be unique",
- SvPVX(sv));
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
+ "Can't do inplace edit: %"SVf" would not be unique",
+ SVfARG(sv));
do_close(gv,FALSE);
continue;
}
#endif
#ifdef HAS_RENAME
-#if !defined(DOSISH) && !defined(__CYGWIN__)
- if (PerlLIO_rename(PL_oldname,SvPVX(sv)) < 0) {
- if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
- "Can't rename %s to %s: %s, skipping file",
- PL_oldname, SvPVX(sv), Strerror(errno) );
+#if !defined(DOSISH) && !defined(__CYGWIN__) && !defined(EPOC)
+ if (PerlLIO_rename(PL_oldname,SvPVX_const(sv)) < 0) {
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
+ "Can't rename %s to %"SVf": %s, skipping file",
+ PL_oldname, SVfARG(sv), Strerror(errno));
do_close(gv,FALSE);
continue;
}
#else
do_close(gv,FALSE);
- (void)PerlLIO_unlink(SvPVX(sv));
- (void)PerlLIO_rename(PL_oldname,SvPVX(sv));
- do_open(gv,SvPVX(sv),SvCUR(sv),PL_inplace!=0,O_RDONLY,0,Nullfp);
+ (void)PerlLIO_unlink(SvPVX_const(sv));
+ (void)PerlLIO_rename(PL_oldname,SvPVX_const(sv));
+ do_open(gv,(char*)SvPVX_const(sv),SvCUR(sv),TRUE,O_RDONLY,0,NULL);
#endif /* DOSISH */
#else
- (void)UNLINK(SvPVX(sv));
- if (link(PL_oldname,SvPVX(sv)) < 0) {
- if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
- "Can't rename %s to %s: %s, skipping file",
- PL_oldname, SvPVX(sv), Strerror(errno) );
+ (void)UNLINK(SvPVX_const(sv));
+ if (link(PL_oldname,SvPVX_const(sv)) < 0) {
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
+ "Can't rename %s to %"SVf": %s, skipping file",
+ PL_oldname, SVfARG(sv), Strerror(errno) );
do_close(gv,FALSE);
continue;
}
#if !defined(DOSISH) && !defined(AMIGAOS)
# ifndef VMS /* Don't delete; use automatic file versioning */
if (UNLINK(PL_oldname) < 0) {
- if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
- "Can't remove %s: %s, skipping file",
- PL_oldname, Strerror(errno) );
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE),
+ "Can't remove %s: %s, skipping file",
+ PL_oldname, Strerror(errno) );
do_close(gv,FALSE);
continue;
}
#endif
}
- sv_setpvn(sv,">",!PL_inplace);
- sv_catpvn(sv,PL_oldname,oldlen);
+ sv_setpvn(sv,PL_oldname,oldlen);
SETERRNO(0,0); /* in case sprintf set errno */
+ if (!Perl_do_openn(aTHX_ PL_argvoutgv, (char*)SvPVX_const(sv),
+ SvCUR(sv), TRUE,
#ifdef VMS
- if (!do_open(PL_argvoutgv,SvPVX(sv),SvCUR(sv),PL_inplace!=0,
- O_WRONLY|O_CREAT|O_TRUNC,0,Nullfp))
+ O_WRONLY|O_CREAT|O_TRUNC,0,
#else
- if (!do_open(PL_argvoutgv,SvPVX(sv),SvCUR(sv),PL_inplace!=0,
- O_WRONLY|O_CREAT|OPEN_EXCL,0666,Nullfp))
+ O_WRONLY|O_CREAT|OPEN_EXCL,0600,
#endif
- {
- if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE, "Can't do inplace edit on %s: %s",
- PL_oldname, Strerror(errno) );
+ NULL, NULL, 0)) {
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit on %s: %s",
+ PL_oldname, Strerror(errno) );
do_close(gv,FALSE);
continue;
}
#ifdef HAS_FCHMOD
(void)fchmod(PL_lastfd,PL_filemode);
#else
-# if !(defined(WIN32) && defined(__BORLANDC__))
- /* Borland runtime creates a readonly file! */
(void)PerlLIO_chmod(PL_oldname,PL_filemode);
-# endif
#endif
if (fileuid != PL_statbuf.st_uid || filegid != PL_statbuf.st_gid) {
#ifdef HAS_FCHOWN
}
else {
if (ckWARN_d(WARN_INPLACE)) {
- int eno = errno;
+ const int eno = errno;
if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0
&& !S_ISREG(PL_statbuf.st_mode))
{
- Perl_warner(aTHX_ WARN_INPLACE,
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE),
"Can't do inplace edit: %s is not a regular file",
PL_oldname);
}
else
- Perl_warner(aTHX_ WARN_INPLACE, "Can't open %s: %s",
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't open %s: %s",
PL_oldname, Strerror(eno));
}
}
if (io && (IoFLAGS(io) & IOf_ARGV)
&& PL_argvout_stack && AvFILLp(PL_argvout_stack) >= 0)
{
- GV *oldout = (GV*)av_pop(PL_argvout_stack);
+ GV * const oldout = MUTABLE_GV(av_pop(PL_argvout_stack));
setdefout(oldout);
SvREFCNT_dec(oldout);
- return Nullfp;
+ return NULL;
}
- setdefout(gv_fetchpv("STDOUT",TRUE,SVt_PVIO));
+ setdefout(gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO));
}
- return Nullfp;
+ return NULL;
}
-#ifdef HAS_PIPE
-void
-Perl_do_pipe(pTHX_ SV *sv, GV *rgv, GV *wgv)
-{
- register IO *rstio;
- register IO *wstio;
- int fd[2];
-
- if (!rgv)
- goto badexit;
- if (!wgv)
- goto badexit;
-
- rstio = GvIOn(rgv);
- wstio = GvIOn(wgv);
-
- if (IoIFP(rstio))
- do_close(rgv,FALSE);
- if (IoIFP(wstio))
- do_close(wgv,FALSE);
-
- if (PerlProc_pipe(fd) < 0)
- goto badexit;
- IoIFP(rstio) = PerlIO_fdopen(fd[0], "r");
- IoOFP(wstio) = PerlIO_fdopen(fd[1], "w");
- IoIFP(wstio) = IoOFP(wstio);
- IoTYPE(rstio) = IoTYPE_RDONLY;
- IoTYPE(wstio) = IoTYPE_WRONLY;
- if (!IoIFP(rstio) || !IoOFP(wstio)) {
- if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio));
- else PerlLIO_close(fd[0]);
- if (IoOFP(wstio)) PerlIO_close(IoOFP(wstio));
- else PerlLIO_close(fd[1]);
- goto badexit;
- }
-
- sv_setsv(sv,&PL_sv_yes);
- return;
-
-badexit:
- sv_setsv(sv,&PL_sv_undef);
- return;
-}
-#endif
-
/* explicit renamed to avoid C++ conflict -- kja */
bool
Perl_do_close(pTHX_ GV *gv, bool not_implicit)
{
+ dVAR;
bool retval;
IO *io;
if (!gv)
gv = PL_argvgv;
- if (!gv || SvTYPE(gv) != SVt_PVGV) {
+ if (!gv || !isGV_with_GP(gv)) {
if (not_implicit)
- SETERRNO(EBADF,SS$_IVCHAN);
+ SETERRNO(EBADF,SS_IVCHAN);
return FALSE;
}
io = GvIO(gv);
if (!io) { /* never opened */
if (not_implicit) {
- if (ckWARN(WARN_UNOPENED)) /* no check for closed here */
- report_evil_fh(gv, io, PL_op->op_type);
- SETERRNO(EBADF,SS$_IVCHAN);
+ report_evil_fh(gv);
+ SETERRNO(EBADF,SS_IVCHAN);
}
return FALSE;
}
bool
Perl_io_close(pTHX_ IO *io, bool not_implicit)
{
+ dVAR;
bool retval = FALSE;
- int status;
+
+ PERL_ARGS_ASSERT_IO_CLOSE;
if (IoIFP(io)) {
if (IoTYPE(io) == IoTYPE_PIPE) {
- status = PerlProc_pclose(IoIFP(io));
+ const int status = PerlProc_pclose(IoIFP(io));
if (not_implicit) {
- STATUS_NATIVE_SET(status);
- retval = (STATUS_POSIX == 0);
+ STATUS_NATIVE_CHILD_SET(status);
+ retval = (STATUS_UNIX == 0);
}
else {
retval = (status != -1);
retval = TRUE;
else {
if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */
- retval = (PerlIO_close(IoOFP(io)) != EOF);
+ const bool prev_err = PerlIO_error(IoOFP(io));
+ retval = (PerlIO_close(IoOFP(io)) != EOF && !prev_err);
PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */
}
- else
- retval = (PerlIO_close(IoIFP(io)) != EOF);
+ else {
+ const bool prev_err = PerlIO_error(IoIFP(io));
+ retval = (PerlIO_close(IoIFP(io)) != EOF && !prev_err);
+ }
}
- IoOFP(io) = IoIFP(io) = Nullfp;
+ IoOFP(io) = IoIFP(io) = NULL;
}
else if (not_implicit) {
- SETERRNO(EBADF,SS$_IVCHAN);
+ SETERRNO(EBADF,SS_IVCHAN);
}
return retval;
bool
Perl_do_eof(pTHX_ GV *gv)
{
- register IO *io;
- int ch;
+ dVAR;
+ register IO * const io = GvIO(gv);
- io = GvIO(gv);
+ PERL_ARGS_ASSERT_DO_EOF;
if (!io)
return TRUE;
- else if (ckWARN(WARN_IO) && (IoTYPE(io) == IoTYPE_WRONLY))
- {
- /* integrate to report_evil_fh()? */
- char *name = NULL;
- if (isGV(gv)) {
- SV* sv = sv_newmortal();
- gv_efullname4(sv, gv, Nullch, FALSE);
- name = SvPV_nolen(sv);
- }
- if (name && *name)
- Perl_warner(aTHX_ WARN_IO,
- "Filehandle %s opened only for output", name);
- else
- Perl_warner(aTHX_ WARN_IO,
- "Filehandle opened only for output");
- }
+ else if (IoTYPE(io) == IoTYPE_WRONLY)
+ report_wrongway_fh(gv, '>');
while (IoIFP(io)) {
-
if (PerlIO_has_cntptr(IoIFP(io))) { /* (the code works without this) */
if (PerlIO_get_cnt(IoIFP(io)) > 0) /* cheat a little, since */
return FALSE; /* this is the most usual case */
}
- ch = PerlIO_getc(IoIFP(io));
- if (ch != EOF) {
- (void)PerlIO_ungetc(IoIFP(io),ch);
- return FALSE;
+ {
+ /* getc and ungetc can stomp on errno */
+ dSAVE_ERRNO;
+ const int ch = PerlIO_getc(IoIFP(io));
+ if (ch != EOF) {
+ (void)PerlIO_ungetc(IoIFP(io),ch);
+ RESTORE_ERRNO;
+ return FALSE;
+ }
+ RESTORE_ERRNO;
}
if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
PerlIO_set_cnt(IoIFP(io),-1);
}
if (PL_op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
- if (!nextargv(PL_argvgv)) /* get another fp handy */
+ if (gv != PL_argvgv || !nextargv(gv)) /* get another fp handy */
return TRUE;
}
else
Off_t
Perl_do_tell(pTHX_ GV *gv)
{
- register IO *io = 0;
+ dVAR;
+ IO *const io = GvIO(gv);
register PerlIO *fp;
- if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
+ PERL_ARGS_ASSERT_DO_TELL;
+
+ if (io && (fp = IoIFP(io))) {
#ifdef ULTRIX_STDIO_BOTCH
if (PerlIO_eof(fp))
(void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
#endif
return PerlIO_tell(fp);
}
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- SETERRNO(EBADF,RMS$_IFI);
+ report_evil_fh(gv);
+ SETERRNO(EBADF,RMS_IFI);
return (Off_t)-1;
}
bool
Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
{
- register IO *io = 0;
+ dVAR;
+ IO *const io = GvIO(gv);
register PerlIO *fp;
- if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
+ if (io && (fp = IoIFP(io))) {
#ifdef ULTRIX_STDIO_BOTCH
if (PerlIO_eof(fp))
(void)PerlIO_seek(fp, 0L, 2); /* ultrix 1.2 workaround */
#endif
return PerlIO_seek(fp, pos, whence) >= 0;
}
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- SETERRNO(EBADF,RMS$_IFI);
+ report_evil_fh(gv);
+ SETERRNO(EBADF,RMS_IFI);
return FALSE;
}
Off_t
Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence)
{
- register IO *io = 0;
+ dVAR;
+ IO *const io = GvIO(gv);
register PerlIO *fp;
- if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
+ PERL_ARGS_ASSERT_DO_SYSSEEK;
+
+ if (io && (fp = IoIFP(io)))
return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- SETERRNO(EBADF,RMS$_IFI);
+ report_evil_fh(gv);
+ SETERRNO(EBADF,RMS_IFI);
return (Off_t)-1;
}
int
-Perl_mode_from_discipline(pTHX_ SV *discp)
+Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len)
{
int mode = O_BINARY;
- if (discp) {
- STRLEN len;
- char *s = SvPV(discp,len);
+ if (s) {
while (*s) {
if (*s == ':') {
switch (s[1]) {
case 'r':
- if (len > 3 && strnEQ(s+1, "raw", 3)
+ if (s[2] == 'a' && s[3] == 'w'
&& (!s[4] || s[4] == ':' || isSPACE(s[4])))
{
mode = O_BINARY;
}
/* FALL THROUGH */
case 'c':
- if (len > 4 && strnEQ(s+1, "crlf", 4)
+ if (s[2] == 'r' && s[3] == 'l' && s[4] == 'f'
&& (!s[5] || s[5] == ':' || isSPACE(s[5])))
{
mode = O_TEXT;
--len;
}
else {
- char *end;
+ const char *end;
fail_discipline:
end = strchr(s+1, ':');
if (!end)
end = s+len;
#ifndef PERLIO_LAYERS
- Perl_croak(aTHX_ "Unknown discipline '%.*s'", end-s, s);
+ Perl_croak(aTHX_ "IO layers (like '%.*s') unavailable", end-s, s);
#else
+ len -= end-s;
s = end;
#endif
}
return mode;
}
-int
-Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int mode)
+#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE)
+I32
+my_chsize(int fd, Off_t length)
{
- /* The old body of this is now in non-LAYER part of perlio.c
- * This is a stub for any XS code which might have been calling it.
- */
- char *name = (O_BINARY != O_TEXT && !(mode & O_BINARY)) ? ":crlf" : ":raw";
- return PerlIO_binmode(aTHX_ fp, iotype, mode, name);
-}
-
-#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
+#ifdef F_FREESP
/* code courtesy of William Kucharski */
#define HAS_CHSIZE
-I32 my_chsize(fd, length)
-I32 fd; /* file descriptor */
-Off_t length; /* length to set file to */
-{
- struct flock fl;
- struct stat filebuf;
+ Stat_t filebuf;
if (PerlLIO_fstat(fd, &filebuf) < 0)
return -1;
}
else {
/* truncate length */
-
+ struct flock fl;
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = length;
return -1;
}
-
return 0;
-}
+#else
+ Perl_croak_nocontext("truncate not implemented");
#endif /* F_FREESP */
+ return -1;
+}
+#endif /* !HAS_TRUNCATE && !HAS_CHSIZE */
bool
Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
{
- register char *tmps;
- STRLEN len;
+ dVAR;
+
+ PERL_ARGS_ASSERT_DO_PRINT;
/* assuming fp is checked earlier */
if (!sv)
return TRUE;
- if (PL_ofmt) {
- if (SvGMAGICAL(sv))
- mg_get(sv);
- if (SvIOK(sv) && SvIVX(sv) != 0) {
- PerlIO_printf(fp, PL_ofmt, (NV)SvIVX(sv));
- return !PerlIO_error(fp);
- }
- if ( (SvNOK(sv) && SvNVX(sv) != 0.0)
- || (looks_like_number(sv) && sv_2nv(sv) != 0.0) ) {
- PerlIO_printf(fp, PL_ofmt, SvNVX(sv));
- return !PerlIO_error(fp);
- }
+ if (SvTYPE(sv) == SVt_IV && SvIOK(sv)) {
+ assert(!SvGMAGICAL(sv));
+ if (SvIsUV(sv))
+ PerlIO_printf(fp, "%"UVuf, (UV)SvUVX(sv));
+ else
+ PerlIO_printf(fp, "%"IVdf, (IV)SvIVX(sv));
+ return !PerlIO_error(fp);
}
- switch (SvTYPE(sv)) {
- case SVt_NULL:
- if (ckWARN(WARN_UNINITIALIZED))
- report_uninit();
- return TRUE;
- case SVt_IV:
- if (SvIOK(sv)) {
- if (SvGMAGICAL(sv))
- mg_get(sv);
- if (SvIsUV(sv))
- PerlIO_printf(fp, "%"UVuf, (UV)SvUVX(sv));
- else
- PerlIO_printf(fp, "%"IVdf, (IV)SvIVX(sv));
- return !PerlIO_error(fp);
- }
- /* FALL THROUGH */
- default:
- if (PerlIO_isutf8(fp)) {
- if (!SvUTF8(sv))
- sv_utf8_upgrade(sv = sv_mortalcopy(sv));
- }
- else if (DO_UTF8(sv)) {
- if (!sv_utf8_downgrade((sv = sv_mortalcopy(sv)), TRUE)) {
- Perl_warner(aTHX_ WARN_UTF8, "Wide character in print");
+ else {
+ STRLEN len;
+ /* Do this first to trigger any overloading. */
+ const char *tmps = SvPV_const(sv, len);
+ U8 *tmpbuf = NULL;
+ bool happy = TRUE;
+
+ if (PerlIO_isutf8(fp)) { /* If the stream is utf8 ... */
+ if (!SvUTF8(sv)) { /* Convert to utf8 if necessary */
+ /* We don't modify the original scalar. */
+ tmpbuf = bytes_to_utf8((const U8*) tmps, &len);
+ tmps = (char *) tmpbuf;
+ }
+ else if (ckWARN4_d(WARN_UTF8, WARN_SURROGATE, WARN_NON_UNICODE, WARN_NONCHAR)) {
+ (void) check_utf8_print((const U8*) tmps, len);
+ }
+ } /* else stream isn't utf8 */
+ else if (DO_UTF8(sv)) { /* But if is utf8 internally, attempt to
+ convert to bytes */
+ STRLEN tmplen = len;
+ bool utf8 = TRUE;
+ U8 * const result = bytes_from_utf8((const U8*) tmps, &tmplen, &utf8);
+ if (!utf8) {
+
+ /* Here, succeeded in downgrading from utf8. Set up to below
+ * output the converted value */
+ tmpbuf = result;
+ tmps = (char *) tmpbuf;
+ len = tmplen;
+ }
+ else { /* Non-utf8 output stream, but string only representable in
+ utf8 */
+ assert((char *)result == tmps);
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_UTF8),
+ "Wide character in %s",
+ PL_op ? OP_DESC(PL_op) : "print"
+ );
+ /* Could also check that isn't one of the things to avoid
+ * in utf8 by using check_utf8_print(), but not doing so,
+ * since the stream isn't a UTF8 stream */
}
}
- tmps = SvPV(sv, len);
- break;
+ /* To detect whether the process is about to overstep its
+ * filesize limit we would need getrlimit(). We could then
+ * also transparently raise the limit with setrlimit() --
+ * but only until the system hard limit/the filesystem limit,
+ * at which we would get EPERM. Note that when using buffered
+ * io the write failure can be delayed until the flush/close. --jhi */
+ if (len && (PerlIO_write(fp,tmps,len) == 0))
+ happy = FALSE;
+ Safefree(tmpbuf);
+ return happy ? !PerlIO_error(fp) : FALSE;
}
- /* To detect whether the process is about to overstep its
- * filesize limit we would need getrlimit(). We could then
- * also transparently raise the limit with setrlimit() --
- * but only until the system hard limit/the filesystem limit,
- * at which we would get EPERM. Note that when using buffered
- * io the write failure can be delayed until the flush/close. --jhi */
- if (len && (PerlIO_write(fp,tmps,len) == 0))
- return FALSE;
- return !PerlIO_error(fp);
}
I32
-Perl_my_stat(pTHX)
+Perl_my_stat_flags(pTHX_ const U32 flags)
{
+ dVAR;
dSP;
IO *io;
GV* gv;
if (PL_op->op_flags & OPf_REF) {
- EXTEND(SP,1);
gv = cGVOP_gv;
do_fstat:
+ if (gv == PL_defgv)
+ return PL_laststatval;
io = GvIO(gv);
- if (io && IoIFP(io)) {
- PL_statgv = gv;
- sv_setpv(PL_statname,"");
- PL_laststype = OP_STAT;
- return (PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache));
- }
- else {
- if (gv == PL_defgv)
- return PL_laststatval;
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- PL_statgv = Nullgv;
- sv_setpv(PL_statname,"");
- return (PL_laststatval = -1);
- }
+ do_fstat_have_io:
+ PL_laststype = OP_STAT;
+ PL_statgv = gv ? gv : (GV *)io;
+ sv_setpvs(PL_statname, "");
+ if(io) {
+ if (IoIFP(io)) {
+ return (PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache));
+ } else if (IoDIRP(io)) {
+ return (PL_laststatval = PerlLIO_fstat(my_dirfd(IoDIRP(io)), &PL_statcache));
+ }
+ }
+ PL_laststatval = -1;
+ report_evil_fh(gv);
+ return -1;
}
+ else if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
+ == OPpFT_STACKED)
+ return PL_laststatval;
else {
- SV* sv = POPs;
- char *s;
- STRLEN n_a;
- PUTBACK;
- if (SvTYPE(sv) == SVt_PVGV) {
- gv = (GV*)sv;
- goto do_fstat;
- }
- else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
- gv = (GV*)SvRV(sv);
+ SV* const sv = TOPs;
+ const char *s;
+ STRLEN len;
+ if ((gv = MAYBE_DEREF_GV_flags(sv,flags))) {
goto do_fstat;
}
+ else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVIO) {
+ io = MUTABLE_IO(SvRV(sv));
+ gv = NULL;
+ goto do_fstat_have_io;
+ }
- s = SvPV(sv, n_a);
- PL_statgv = Nullgv;
- sv_setpv(PL_statname, s);
+ s = SvPV_flags_const(sv, len, flags);
+ PL_statgv = NULL;
+ sv_setpvn(PL_statname, s, len);
+ s = SvPVX_const(PL_statname); /* s now NUL-terminated */
PL_laststype = OP_STAT;
PL_laststatval = PerlLIO_stat(s, &PL_statcache);
if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(s, '\n'))
- Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "stat");
+ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat");
return PL_laststatval;
}
}
+
I32
-Perl_my_lstat(pTHX)
+Perl_my_lstat_flags(pTHX_ const U32 flags)
{
+ dVAR;
+ static const char no_prev_lstat[] = "The stat preceding -l _ wasn't an lstat";
dSP;
- SV *sv;
- STRLEN n_a;
+ const char *file;
if (PL_op->op_flags & OPf_REF) {
- EXTEND(SP,1);
if (cGVOP_gv == PL_defgv) {
if (PL_laststype != OP_LSTAT)
- Perl_croak(aTHX_ "The stat preceding -l _ wasn't an lstat");
+ Perl_croak(aTHX_ no_prev_lstat);
return PL_laststatval;
}
- Perl_croak(aTHX_ "You can't use -l on a filehandle");
+ PL_laststatval = -1;
+ if (ckWARN(WARN_IO)) {
+ Perl_warner(aTHX_ packWARN(WARN_IO),
+ "Use of -l on filehandle %"HEKf,
+ HEKfARG(GvENAME_HEK(cGVOP_gv)));
+ }
+ return -1;
}
+ if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
+ == OPpFT_STACKED) {
+ if (PL_laststype != OP_LSTAT)
+ Perl_croak(aTHX_ no_prev_lstat);
+ return PL_laststatval;
+ }
PL_laststype = OP_LSTAT;
- PL_statgv = Nullgv;
- sv = POPs;
- PUTBACK;
- sv_setpv(PL_statname,SvPV(sv, n_a));
- PL_laststatval = PerlLIO_lstat(SvPV(sv, n_a),&PL_statcache);
- if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(SvPV(sv, n_a), '\n'))
- Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "lstat");
+ PL_statgv = NULL;
+ file = SvPV_flags_const_nolen(TOPs, flags);
+ sv_setpv(PL_statname,file);
+ PL_laststatval = PerlLIO_lstat(file,&PL_statcache);
+ if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(file, '\n'))
+ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "lstat");
return PL_laststatval;
}
-bool
-Perl_do_aexec(pTHX_ SV *really, register SV **mark, register SV **sp)
+static void
+S_exec_failed(pTHX_ const char *cmd, int fd, int do_report)
{
- return do_aexec5(really, mark, sp, 0, 0);
+ const int e = errno;
+ PERL_ARGS_ASSERT_EXEC_FAILED;
+ if (ckWARN(WARN_EXEC))
+ Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
+ cmd, Strerror(e));
+ if (do_report) {
+ PerlLIO_write(fd, (void*)&e, sizeof(int));
+ PerlLIO_close(fd);
+ }
}
bool
Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
int fd, int do_report)
{
-#ifdef MACOS_TRADITIONAL
+ dVAR;
+ PERL_ARGS_ASSERT_DO_AEXEC5;
+#if defined(__SYMBIAN32__) || defined(__LIBCATAMOUNT__)
Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
#else
- register char **a;
- char *tmps = Nullch;
- STRLEN n_a;
-
if (sp > mark) {
- New(401,PL_Argv, sp - mark + 1, char*);
+ const char **a;
+ const char *tmps = NULL;
+ Newx(PL_Argv, sp - mark + 1, const char*);
a = PL_Argv;
+
while (++mark <= sp) {
if (*mark)
- *a++ = SvPVx(*mark, n_a);
+ *a++ = SvPV_nolen_const(*mark);
else
*a++ = "";
}
- *a = Nullch;
+ *a = NULL;
if (really)
- tmps = SvPV(really, n_a);
+ tmps = SvPV_nolen_const(really);
if ((!really && *PL_Argv[0] != '/') ||
(really && *tmps != '/')) /* will execvp use PATH? */
TAINT_ENV(); /* testing IFS here is overkill, probably */
+ PERL_FPU_PRE_EXEC
if (really && *tmps)
PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv));
else
PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
- if (ckWARN(WARN_EXEC))
- Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
- (really ? tmps : PL_Argv[0]), Strerror(errno));
- if (do_report) {
- int e = errno;
-
- PerlLIO_write(fd, (void*)&e, sizeof(int));
- PerlLIO_close(fd);
- }
+ PERL_FPU_POST_EXEC
+ S_exec_failed(aTHX_ (really ? tmps : PL_Argv[0]), fd, do_report);
}
do_execfree();
#endif
void
Perl_do_execfree(pTHX)
{
- if (PL_Argv) {
- Safefree(PL_Argv);
- PL_Argv = Null(char **);
- }
- if (PL_Cmd) {
- Safefree(PL_Cmd);
- PL_Cmd = Nullch;
- }
+ dVAR;
+ Safefree(PL_Argv);
+ PL_Argv = NULL;
+ Safefree(PL_Cmd);
+ PL_Cmd = NULL;
}
-#if !defined(OS2) && !defined(WIN32) && !defined(DJGPP) && !defined(EPOC) && !defined(MACOS_TRADITIONAL)
-
-bool
-Perl_do_exec(pTHX_ char *cmd)
-{
- return do_exec3(cmd,0,0);
-}
+#ifdef PERL_DEFAULT_DO_EXEC3_IMPLEMENTATION
bool
-Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
+Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
{
- register char **a;
+ dVAR;
+ register const char **a;
register char *s;
+ char *buf;
+ char *cmd;
+ /* Make a copy so we can change it */
+ const Size_t cmdlen = strlen(incmd) + 1;
+
+ PERL_ARGS_ASSERT_DO_EXEC3;
+
+ Newx(buf, cmdlen, char);
+ cmd = buf;
+ memcpy(cmd, incmd, cmdlen);
while (*cmd && isSPACE(*cmd))
cmd++;
#ifdef CSH
{
- char flags[10];
+ char flags[PERL_FLAGS_MAX];
if (strnEQ(cmd,PL_cshname,PL_cshlen) &&
strnEQ(cmd+PL_cshlen," -c",3)) {
- strcpy(flags,"-c");
+ my_strlcpy(flags, "-c", PERL_FLAGS_MAX);
s = cmd+PL_cshlen+3;
if (*s == 'f') {
s++;
- strcat(flags,"f");
+ my_strlcat(flags, "f", PERL_FLAGS_MAX - 2);
}
if (*s == ' ')
s++;
if (*s++ == '\'') {
- char *ncmd = s;
+ char * const ncmd = s;
while (*s)
s++;
*--s = '\0';
if (s[-1] == '\'') {
*--s = '\0';
- PerlProc_execl(PL_cshname,"csh", flags, ncmd, (char*)0);
+ PERL_FPU_PRE_EXEC
+ PerlProc_execl(PL_cshname, "csh", flags, ncmd, (char*)NULL);
+ PERL_FPU_POST_EXEC
*s = '\'';
+ S_exec_failed(aTHX_ PL_cshname, fd, do_report);
+ Safefree(buf);
return FALSE;
}
}
if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
goto doshell;
- for (s = cmd; *s && isALNUM(*s); s++) ; /* catch VAR=val gizmo */
+ s = cmd;
+ while (isALNUM(*s))
+ s++; /* catch VAR=val gizmo */
if (*s == '=')
goto doshell;
&& s > cmd + 1 && s[-1] == '2' && isSPACE(s[-2])
&& (!s[3] || isSPACE(s[3])))
{
- char *t = s + 3;
+ const char *t = s + 3;
while (*t && isSPACE(*t))
++t;
- if (!*t && (dup2(1,2) != -1)) {
+ if (!*t && (PerlLIO_dup2(1,2) != -1)) {
s[-2] = '\0';
break;
}
}
doshell:
- PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char*)0);
+ PERL_FPU_PRE_EXEC
+ PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL);
+ PERL_FPU_POST_EXEC
+ S_exec_failed(aTHX_ PL_sh_path, fd, do_report);
+ Safefree(buf);
return FALSE;
}
}
- New(402,PL_Argv, (s - cmd) / 2 + 2, char*);
+ Newx(PL_Argv, (s - cmd) / 2 + 2, const char*);
PL_Cmd = savepvn(cmd, s-cmd);
a = PL_Argv;
for (s = PL_Cmd; *s;) {
- while (*s && isSPACE(*s)) s++;
+ while (isSPACE(*s))
+ s++;
if (*s)
*(a++) = s;
- while (*s && !isSPACE(*s)) s++;
+ while (*s && !isSPACE(*s))
+ s++;
if (*s)
*s++ = '\0';
}
- *a = Nullch;
+ *a = NULL;
if (PL_Argv[0]) {
- PerlProc_execvp(PL_Argv[0],PL_Argv);
+ PERL_FPU_PRE_EXEC
+ PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
+ PERL_FPU_POST_EXEC
if (errno == ENOEXEC) { /* for system V NIH syndrome */
do_execfree();
goto doshell;
}
- {
- int e = errno;
-
- if (ckWARN(WARN_EXEC))
- Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
- PL_Argv[0], Strerror(errno));
- if (do_report) {
- PerlLIO_write(fd, (void*)&e, sizeof(int));
- PerlLIO_close(fd);
- }
- }
+ S_exec_failed(aTHX_ PL_Argv[0], fd, do_report);
}
do_execfree();
+ Safefree(buf);
return FALSE;
}
#endif /* OS2 || WIN32 */
+#ifdef VMS
+#include <starlet.h> /* for sys$delprc */
+#endif
+
I32
Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
{
+ dVAR;
register I32 val;
- register I32 val2;
register I32 tot = 0;
- char *what;
- char *s;
- SV **oldmark = mark;
- STRLEN n_a;
+ const char *const what = PL_op_name[type];
+ const char *s;
+ STRLEN len;
+ SV ** const oldmark = mark;
+
+ PERL_ARGS_ASSERT_APPLY;
+
+ /* Doing this ahead of the switch statement preserves the old behaviour,
+ where attempting to use kill as a taint test test would fail on
+ platforms where kill was not defined. */
+#ifndef HAS_KILL
+ if (type == OP_KILL)
+ Perl_die(aTHX_ PL_no_func, what);
+#endif
+#ifndef HAS_CHOWN
+ if (type == OP_CHOWN)
+ Perl_die(aTHX_ PL_no_func, what);
+#endif
+
#define APPLY_TAINT_PROPER() \
STMT_START { \
}
switch (type) {
case OP_CHMOD:
- what = "chmod";
APPLY_TAINT_PROPER();
if (++mark <= sp) {
- val = SvIVx(*mark);
+ val = SvIV(*mark);
APPLY_TAINT_PROPER();
tot = sp - mark;
while (++mark <= sp) {
- char *name = SvPVx(*mark, n_a);
- APPLY_TAINT_PROPER();
- if (PerlLIO_chmod(name, val))
- tot--;
+ GV* gv;
+ if ((gv = MAYBE_DEREF_GV(*mark))) {
+ if (GvIO(gv) && IoIFP(GvIOp(gv))) {
+#ifdef HAS_FCHMOD
+ APPLY_TAINT_PROPER();
+ if (fchmod(PerlIO_fileno(IoIFP(GvIOn(gv))), val))
+ tot--;
+#else
+ Perl_die(aTHX_ PL_no_func, "fchmod");
+#endif
+ }
+ else {
+ tot--;
+ }
+ }
+ else {
+ const char *name = SvPV_nomg_const_nolen(*mark);
+ APPLY_TAINT_PROPER();
+ if (PerlLIO_chmod(name, val))
+ tot--;
+ }
}
}
break;
#ifdef HAS_CHOWN
case OP_CHOWN:
- what = "chown";
APPLY_TAINT_PROPER();
if (sp - mark > 2) {
+ register I32 val2;
val = SvIVx(*++mark);
val2 = SvIVx(*++mark);
APPLY_TAINT_PROPER();
tot = sp - mark;
while (++mark <= sp) {
- char *name = SvPVx(*mark, n_a);
- APPLY_TAINT_PROPER();
- if (PerlLIO_chown(name, val, val2))
- tot--;
+ GV* gv;
+ if ((gv = MAYBE_DEREF_GV(*mark))) {
+ if (GvIO(gv) && IoIFP(GvIOp(gv))) {
+#ifdef HAS_FCHOWN
+ APPLY_TAINT_PROPER();
+ if (fchown(PerlIO_fileno(IoIFP(GvIOn(gv))), val, val2))
+ tot--;
+#else
+ Perl_die(aTHX_ PL_no_func, "fchown");
+#endif
+ }
+ else {
+ tot--;
+ }
+ }
+ else {
+ const char *name = SvPV_nomg_const_nolen(*mark);
+ APPLY_TAINT_PROPER();
+ if (PerlLIO_chown(name, val, val2))
+ tot--;
+ }
}
}
break;
*/
#ifdef HAS_KILL
case OP_KILL:
- what = "kill";
APPLY_TAINT_PROPER();
if (mark == sp)
break;
- s = SvPVx(*++mark, n_a);
- if (isUPPER(*s)) {
- if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
+ s = SvPVx_const(*++mark, len);
+ if (isALPHA(*s)) {
+ if (*s == 'S' && s[1] == 'I' && s[2] == 'G') {
s += 3;
- if (!(val = whichsig(s)))
- Perl_croak(aTHX_ "Unrecognized signal name \"%s\"",s);
+ len -= 3;
+ }
+ if ((val = whichsig_pvn(s, len)) < 0)
+ Perl_croak(aTHX_ "Unrecognized signal name \"%"SVf"\"", SVfARG(*mark));
}
else
- val = SvIVx(*mark);
+ val = SvIV(*mark);
APPLY_TAINT_PROPER();
tot = sp - mark;
#ifdef VMS
/* kill() doesn't do process groups (job trees?) under VMS */
if (val < 0) val = -val;
if (val == SIGKILL) {
-# include <starlet.h>
/* Use native sys$delprc() to insure that target process is
* deleted; supervisor-mode images don't pay attention to
* CRTL's emulation of Unix-style signals and kill()
*/
while (++mark <= sp) {
- I32 proc = SvIVx(*mark);
+ I32 proc;
register unsigned long int __vmssts;
+ SvGETMAGIC(*mark);
+ if (!(SvIOK(*mark) || SvNOK(*mark) || looks_like_number(*mark)))
+ Perl_croak(aTHX_ "Can't kill a non-numeric process ID");
+ proc = SvIV_nomg(*mark);
APPLY_TAINT_PROPER();
if (!((__vmssts = sys$delprc(&proc,0)) & 1)) {
tot--;
}
}
}
+ PERL_ASYNC_CHECK();
break;
}
#endif
if (val < 0) {
val = -val;
while (++mark <= sp) {
- I32 proc = SvIVx(*mark);
+ I32 proc;
+ SvGETMAGIC(*mark);
+ if (!(SvIOK(*mark) || SvNOK(*mark) || looks_like_number(*mark)))
+ Perl_croak(aTHX_ "Can't kill a non-numeric process ID");
+ proc = SvIV_nomg(*mark);
APPLY_TAINT_PROPER();
#ifdef HAS_KILLPG
if (PerlProc_killpg(proc,val)) /* BSD */
}
else {
while (++mark <= sp) {
- I32 proc = SvIVx(*mark);
+ I32 proc;
+ SvGETMAGIC(*mark);
+ if (!(SvIOK(*mark) || SvNOK(*mark) || looks_like_number(*mark)))
+ Perl_croak(aTHX_ "Can't kill a non-numeric process ID");
+ proc = SvIV_nomg(*mark);
APPLY_TAINT_PROPER();
if (PerlProc_kill(proc, val))
tot--;
}
}
+ PERL_ASYNC_CHECK();
break;
#endif
case OP_UNLINK:
- what = "unlink";
APPLY_TAINT_PROPER();
tot = sp - mark;
while (++mark <= sp) {
- s = SvPVx(*mark, n_a);
+ s = SvPV_nolen_const(*mark);
APPLY_TAINT_PROPER();
- if (PL_euid || PL_unsafe) {
+ if (PerlProc_geteuid() || PL_unsafe) {
if (UNLINK(s))
tot--;
}
}
}
break;
-#ifdef HAS_UTIME
+#if defined(HAS_UTIME) || defined(HAS_FUTIMES)
case OP_UTIME:
- what = "utime";
APPLY_TAINT_PROPER();
if (sp - mark > 2) {
-#if defined(I_UTIME) || defined(VMS)
+#if defined(HAS_FUTIMES)
+ struct timeval utbuf[2];
+ void *utbufp = utbuf;
+#elif defined(I_UTIME) || defined(VMS)
struct utimbuf utbuf;
+ struct utimbuf *utbufp = &utbuf;
#else
struct {
Time_t actime;
Time_t modtime;
} utbuf;
+ void *utbufp = &utbuf;
#endif
- SV* accessed = *++mark;
- SV* modified = *++mark;
- void * utbufp = &utbuf;
+ SV* const accessed = *++mark;
+ SV* const modified = *++mark;
- /* be like C, and if both times are undefined, let the C
- library figure out what to do. This usually means
- "current time" */
+ /* Be like C, and if both times are undefined, let the C
+ * library figure out what to do. This usually means
+ * "current time". */
if ( accessed == &PL_sv_undef && modified == &PL_sv_undef )
- utbufp = NULL;
-
- Zero(&utbuf, sizeof utbuf, char);
-#ifdef BIG_TIME
- utbuf.actime = (Time_t)SvNVx(accessed); /* time accessed */
- utbuf.modtime = (Time_t)SvNVx(modified); /* time modified */
+ utbufp = NULL;
+ else {
+ Zero(&utbuf, sizeof utbuf, char);
+#ifdef HAS_FUTIMES
+ utbuf[0].tv_sec = (long)SvIV(accessed); /* time accessed */
+ utbuf[0].tv_usec = 0;
+ utbuf[1].tv_sec = (long)SvIV(modified); /* time modified */
+ utbuf[1].tv_usec = 0;
+#elif defined(BIG_TIME)
+ utbuf.actime = (Time_t)SvNV(accessed); /* time accessed */
+ utbuf.modtime = (Time_t)SvNV(modified); /* time modified */
#else
- utbuf.actime = (Time_t)SvIVx(accessed); /* time accessed */
- utbuf.modtime = (Time_t)SvIVx(modified); /* time modified */
+ utbuf.actime = (Time_t)SvIV(accessed); /* time accessed */
+ utbuf.modtime = (Time_t)SvIV(modified); /* time modified */
#endif
+ }
APPLY_TAINT_PROPER();
tot = sp - mark;
while (++mark <= sp) {
- char *name = SvPVx(*mark, n_a);
- APPLY_TAINT_PROPER();
- if (PerlLIO_utime(name, utbufp))
- tot--;
+ GV* gv;
+ if ((gv = MAYBE_DEREF_GV(*mark))) {
+ if (GvIO(gv) && IoIFP(GvIOp(gv))) {
+#ifdef HAS_FUTIMES
+ APPLY_TAINT_PROPER();
+ if (futimes(PerlIO_fileno(IoIFP(GvIOn(gv))),
+ (struct timeval *) utbufp))
+ tot--;
+#else
+ Perl_die(aTHX_ PL_no_func, "futimes");
+#endif
+ }
+ else {
+ tot--;
+ }
+ }
+ else {
+ const char * const name = SvPV_nomg_const_nolen(*mark);
+ APPLY_TAINT_PROPER();
+#ifdef HAS_FUTIMES
+ if (utimes(name, (struct timeval *)utbufp))
+#else
+ if (PerlLIO_utime(name, utbufp))
+#endif
+ tot--;
+ }
+
}
}
else
/* Do the permissions allow some operation? Assumes statcache already set. */
#ifndef VMS /* VMS' cando is in vms.c */
bool
-Perl_cando(pTHX_ Mode_t mode, Uid_t effective, register Stat_t *statbufp)
-/* Note: we use `effective' both for uids and gids.
- * Here we are betting on Uid_t being equal or wider than Gid_t. */
+Perl_cando(pTHX_ Mode_t mode, bool effective, register const Stat_t *statbufp)
+/* effective is a flag, true for EUID, or for checking if the effective gid
+ * is in the list of groups returned from getgroups().
+ */
{
+ dVAR;
+
+ PERL_ARGS_ASSERT_CANDO;
+
#ifdef DOSISH
/* [Comments and code from Len Reed]
* MS-DOS "user" is similar to UNIX's "superuser," but can't write
* to write-protected files. The execute permission bit is set
- * by the Miscrosoft C library stat() function for the following:
+ * by the Microsoft C library stat() function for the following:
* .exe files
* .com files
* .bat files
return (mode & statbufp->st_mode) ? TRUE : FALSE;
#else /* ! DOSISH */
- if ((effective ? PL_euid : PL_uid) == 0) { /* root is special */
+# ifdef __CYGWIN__
+ if (ingroup(544,effective)) { /* member of Administrators */
+# else
+ if ((effective ? PerlProc_geteuid() : PerlProc_getuid()) == 0) { /* root is special */
+# endif
if (mode == S_IXUSR) {
if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
return TRUE;
return TRUE; /* root reads and writes anything */
return FALSE;
}
- if (statbufp->st_uid == (effective ? PL_euid : PL_uid) ) {
+ if (statbufp->st_uid == (effective ? PerlProc_geteuid() : PerlProc_getuid()) ) {
if (statbufp->st_mode & mode)
return TRUE; /* ok as "user" */
}
}
#endif /* ! VMS */
-bool
-Perl_ingroup(pTHX_ Gid_t testgid, Uid_t effective)
+static bool
+S_ingroup(pTHX_ Gid_t testgid, bool effective)
{
-#ifdef MACOS_TRADITIONAL
- /* This is simply not correct for AppleShare, but fix it yerself. */
- return TRUE;
-#else
- if (testgid == (effective ? PL_egid : PL_gid))
+ dVAR;
+ if (testgid == (effective ? PerlProc_getegid() : PerlProc_getgid()))
return TRUE;
#ifdef HAS_GETGROUPS
-#ifndef NGROUPS
-#define NGROUPS 32
-#endif
{
- Groups_t gary[NGROUPS];
+ Groups_t *gary = NULL;
I32 anum;
+ bool rc = FALSE;
- anum = getgroups(NGROUPS,gary);
+ anum = getgroups(0, gary);
+ Newx(gary, anum, Groups_t);
+ anum = getgroups(anum, gary);
while (--anum >= 0)
- if (gary[anum] == testgid)
- return TRUE;
+ if (gary[anum] == testgid) {
+ rc = TRUE;
+ break;
+ }
+
+ Safefree(gary);
+ return rc;
}
-#endif
+#else
return FALSE;
#endif
}
I32
Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
{
- key_t key;
- I32 n, flags;
+ dVAR;
+ const key_t key = (key_t)SvNVx(*++mark);
+ SV *nsv = optype == OP_MSGGET ? NULL : *++mark;
+ const I32 flags = SvIVx(*++mark);
+
+ PERL_ARGS_ASSERT_DO_IPCGET;
+ PERL_UNUSED_ARG(sp);
- key = (key_t)SvNVx(*++mark);
- n = (optype == OP_MSGGET) ? 0 : SvIVx(*++mark);
- flags = SvIVx(*++mark);
SETERRNO(0,0);
switch (optype)
{
#endif
#ifdef HAS_SEM
case OP_SEMGET:
- return semget(key, n, flags);
+ return semget(key, (int) SvIV(nsv), flags);
#endif
#ifdef HAS_SHM
case OP_SHMGET:
- return shmget(key, n, flags);
+ return shmget(key, (size_t) SvUV(nsv), flags);
#endif
#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
default:
+ /* diag_listed_as: msg%s not implemented */
Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
#endif
}
I32
Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp)
{
- SV *astr;
+ dVAR;
char *a;
- I32 id, n, cmd, infosize, getinfo;
I32 ret = -1;
+ const I32 id = SvIVx(*++mark);
+#ifdef Semctl
+ const I32 n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
+#endif
+ const I32 cmd = SvIVx(*++mark);
+ SV * const astr = *++mark;
+ STRLEN infosize = 0;
+ I32 getinfo = (cmd == IPC_STAT);
- id = SvIVx(*++mark);
- n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
- cmd = SvIVx(*++mark);
- astr = *++mark;
- infosize = 0;
- getinfo = (cmd == IPC_STAT);
+ PERL_ARGS_ASSERT_DO_IPCCTL;
+ PERL_UNUSED_ARG(sp);
switch (optype)
{
than guessing about u_?short(_t)? */
}
#else
+ /* diag_listed_as: sem%s not implemented */
Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
#endif
break;
#endif
#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
default:
+ /* diag_listed_as: shm%s not implemented */
Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
#endif
}
if (infosize)
{
- STRLEN len;
if (getinfo)
{
- SvPV_force(astr, len);
+ SvPV_force_nolen(astr);
a = SvGROW(astr, infosize+1);
}
else
{
+ STRLEN len;
a = SvPV(astr, len);
if (len != infosize)
Perl_croak(aTHX_ "Bad arg length for %s, is %lu, should be %ld",
}
else
{
- IV i = SvIV(astr);
+ const IV i = SvIV(astr);
a = INT2PTR(char *,i); /* ouch */
}
SETERRNO(0,0);
#endif
ret = Semctl(id, n, cmd, unsemds);
#else
+ /* diag_listed_as: sem%s not implemented */
Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]);
#endif
}
I32
Perl_do_msgsnd(pTHX_ SV **mark, SV **sp)
{
+ dVAR;
#ifdef HAS_MSG
- SV *mstr;
- char *mbuf;
- I32 id, msize, flags;
STRLEN len;
+ const I32 id = SvIVx(*++mark);
+ SV * const mstr = *++mark;
+ const I32 flags = SvIVx(*++mark);
+ const char * const mbuf = SvPV_const(mstr, len);
+ const I32 msize = len - sizeof(long);
- id = SvIVx(*++mark);
- mstr = *++mark;
- flags = SvIVx(*++mark);
- mbuf = SvPV(mstr, len);
- if ((msize = len - sizeof(long)) < 0)
+ PERL_ARGS_ASSERT_DO_MSGSND;
+ PERL_UNUSED_ARG(sp);
+
+ if (msize < 0)
Perl_croak(aTHX_ "Arg too short for msgsnd");
SETERRNO(0,0);
return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
#else
+ PERL_UNUSED_ARG(sp);
+ PERL_UNUSED_ARG(mark);
+ /* diag_listed_as: msg%s not implemented */
Perl_croak(aTHX_ "msgsnd not implemented");
#endif
}
Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
{
#ifdef HAS_MSG
- SV *mstr;
+ dVAR;
char *mbuf;
long mtype;
- I32 id, msize, flags, ret;
- STRLEN len;
+ I32 msize, flags, ret;
+ const I32 id = SvIVx(*++mark);
+ SV * const mstr = *++mark;
+
+ PERL_ARGS_ASSERT_DO_MSGRCV;
+ PERL_UNUSED_ARG(sp);
- id = SvIVx(*++mark);
- mstr = *++mark;
/* suppress warning when reading into undef var --jhi */
if (! SvOK(mstr))
- sv_setpvn(mstr, "", 0);
+ sv_setpvs(mstr, "");
msize = SvIVx(*++mark);
mtype = (long)SvIVx(*++mark);
flags = SvIVx(*++mark);
- SvPV_force(mstr, len);
+ SvPV_force_nolen(mstr);
mbuf = SvGROW(mstr, sizeof(long)+msize+1);
SETERRNO(0,0);
}
return ret;
#else
+ PERL_UNUSED_ARG(sp);
+ PERL_UNUSED_ARG(mark);
+ /* diag_listed_as: msg%s not implemented */
Perl_croak(aTHX_ "msgrcv not implemented");
#endif
}
Perl_do_semop(pTHX_ SV **mark, SV **sp)
{
#ifdef HAS_SEM
- SV *opstr;
- char *opbuf;
- I32 id;
+ dVAR;
STRLEN opsize;
+ const I32 id = SvIVx(*++mark);
+ SV * const opstr = *++mark;
+ const char * const opbuf = SvPV_const(opstr, opsize);
+
+ PERL_ARGS_ASSERT_DO_SEMOP;
+ PERL_UNUSED_ARG(sp);
- id = SvIVx(*++mark);
- opstr = *++mark;
- opbuf = SvPV(opstr, opsize);
if (opsize < 3 * SHORTSIZE
|| (opsize % (3 * SHORTSIZE))) {
- SETERRNO(EINVAL,LIB$_INVARG);
+ SETERRNO(EINVAL,LIB_INVARG);
return -1;
}
SETERRNO(0,0);
/* We can't assume that sizeof(struct sembuf) == 3 * sizeof(short). */
{
- int nsops = opsize / (3 * sizeof (short));
+ const int nsops = opsize / (3 * sizeof (short));
int i = nsops;
- short *ops = (short *) opbuf;
+ short * const ops = (short *) opbuf;
short *o = ops;
struct sembuf *temps, *t;
I32 result;
- New (0, temps, nsops, struct sembuf);
+ Newx (temps, nsops, struct sembuf);
t = temps;
while (i--) {
t->sem_num = *o++;
return result;
}
#else
+ /* diag_listed_as: sem%s not implemented */
Perl_croak(aTHX_ "semop not implemented");
#endif
}
Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
{
#ifdef HAS_SHM
- SV *mstr;
- char *mbuf, *shm;
- I32 id, mpos, msize;
- STRLEN len;
+ dVAR;
+ char *shm;
struct shmid_ds shmds;
+ const I32 id = SvIVx(*++mark);
+ SV * const mstr = *++mark;
+ const I32 mpos = SvIVx(*++mark);
+ const I32 msize = SvIVx(*++mark);
+
+ PERL_ARGS_ASSERT_DO_SHMIO;
+ PERL_UNUSED_ARG(sp);
- id = SvIVx(*++mark);
- mstr = *++mark;
- mpos = SvIVx(*++mark);
- msize = SvIVx(*++mark);
SETERRNO(0,0);
if (shmctl(id, IPC_STAT, &shmds) == -1)
return -1;
- if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
- SETERRNO(EFAULT,SS$_ACCVIO); /* can't do as caller requested */
+ if (mpos < 0 || msize < 0
+ || (size_t)mpos + msize > (size_t)shmds.shm_segsz) {
+ SETERRNO(EFAULT,SS_ACCVIO); /* can't do as caller requested */
return -1;
}
- shm = (char *)shmat(id, (char*)NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
+ shm = (char *)shmat(id, NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0);
if (shm == (char *)-1) /* I hate System V IPC, I really do */
return -1;
if (optype == OP_SHMREAD) {
+ char *mbuf;
/* suppress warning when reading into undef var (tchrist 3/Mar/00) */
if (! SvOK(mstr))
- sv_setpvn(mstr, "", 0);
- SvPV_force(mstr, len);
- mbuf = SvGROW(mstr, msize+1);
+ sv_setpvs(mstr, "");
+ SvUPGRADE(mstr, SVt_PV);
+ SvPOK_only(mstr);
+ mbuf = SvGROW(mstr, (STRLEN)msize+1);
Copy(shm + mpos, mbuf, msize, char);
SvCUR_set(mstr, msize);
#endif
}
else {
- I32 n;
+ STRLEN len;
- mbuf = SvPV(mstr, len);
- if ((n = len) > msize)
- n = msize;
+ const char *mbuf = SvPV_const(mstr, len);
+ const I32 n = ((I32)len > msize) ? msize : (I32)len;
Copy(mbuf, shm + mpos, n, char);
if (n < msize)
memzero(shm + mpos + n, msize - n);
}
return shmdt(shm);
#else
+ /* diag_listed_as: shm%s not implemented */
Perl_croak(aTHX_ "shm I/O not implemented");
#endif
}
#endif /* SYSV IPC */
/*
+=head1 IO Functions
+
=for apidoc start_glob
Function called by C<do_readline> to spawn a glob (or do the glob inside
perl on VMS). This code used to be inline, but now perl uses C<File::Glob>
-this glob starter is only used by miniperl during the build proccess.
+this glob starter is only used by miniperl during the build process.
Moving it away shrinks pp_hot.c; shrinking pp_hot.c helps speed perl up.
=cut
PerlIO *
Perl_start_glob (pTHX_ SV *tmpglob, IO *io)
{
- SV *tmpcmd = NEWSV(55, 0);
+ dVAR;
+ SV * const tmpcmd = newSV(0);
PerlIO *fp;
+
+ PERL_ARGS_ASSERT_START_GLOB;
+
ENTER;
SAVEFREESV(tmpcmd);
#ifdef VMS /* expand the wildcards right here, rather than opening a pipe, */
/* since spawning off a process is a real performance hit */
- {
-#include <descrip.h>
-#include <lib$routines.h>
-#include <nam.h>
-#include <rmsdef.h>
- char rslt[NAM$C_MAXRSS+1+sizeof(unsigned short int)] = {'\0','\0'};
- char vmsspec[NAM$C_MAXRSS+1];
- char *rstr = rslt + sizeof(unsigned short int), *begin, *end, *cp;
- $DESCRIPTOR(dfltdsc,"SYS$DISK:[]*.*;");
- PerlIO *tmpfp;
- STRLEN i;
- struct dsc$descriptor_s wilddsc
- = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
- struct dsc$descriptor_vs rsdsc
- = {sizeof rslt, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, rslt};
- unsigned long int cxt = 0, sts = 0, ok = 1, hasdir = 0, hasver = 0, isunix = 0;
-
- /* We could find out if there's an explicit dev/dir or version
- by peeking into lib$find_file's internal context at
- ((struct NAM *)((struct FAB *)cxt)->fab$l_nam)->nam$l_fnb
- but that's unsupported, so I don't want to do it now and
- have it bite someone in the future. */
- cp = SvPV(tmpglob,i);
- for (; i; i--) {
- if (cp[i] == ';') hasver = 1;
- if (cp[i] == '.') {
- if (sts) hasver = 1;
- else sts = 1;
- }
- if (cp[i] == '/') {
- hasdir = isunix = 1;
- break;
- }
- if (cp[i] == ']' || cp[i] == '>' || cp[i] == ':') {
- hasdir = 1;
- break;
- }
- }
- if ((tmpfp = PerlIO_tmpfile()) != NULL) {
- Stat_t st;
- if (!PerlLIO_stat(SvPVX(tmpglob),&st) && S_ISDIR(st.st_mode))
- ok = ((wilddsc.dsc$a_pointer = tovmspath(SvPVX(tmpglob),vmsspec)) != NULL);
- else ok = ((wilddsc.dsc$a_pointer = tovmsspec(SvPVX(tmpglob),vmsspec)) != NULL);
- if (ok) wilddsc.dsc$w_length = (unsigned short int) strlen(wilddsc.dsc$a_pointer);
- while (ok && ((sts = lib$find_file(&wilddsc,&rsdsc,&cxt,
- &dfltdsc,NULL,NULL,NULL))&1)) {
- end = rstr + (unsigned long int) *rslt;
- if (!hasver) while (*end != ';') end--;
- *(end++) = '\n'; *end = '\0';
- for (cp = rstr; *cp; cp++) *cp = _tolower(*cp);
- if (hasdir) {
- if (isunix) trim_unixpath(rstr,SvPVX(tmpglob),1);
- begin = rstr;
- }
- else {
- begin = end;
- while (*(--begin) != ']' && *begin != '>') ;
- ++begin;
- }
- ok = (PerlIO_puts(tmpfp,begin) != EOF);
- }
- if (cxt) (void)lib$find_file_end(&cxt);
- if (ok && sts != RMS$_NMF &&
- sts != RMS$_DNF && sts != RMS$_FNF) ok = 0;
- if (!ok) {
- if (!(sts & 1)) {
- SETERRNO((sts == RMS$_SYN ? EINVAL : EVMSERR),sts);
- }
- PerlIO_close(tmpfp);
- fp = NULL;
- }
- else {
- PerlIO_rewind(tmpfp);
- IoTYPE(io) = IoTYPE_RDONLY;
- IoIFP(io) = fp = tmpfp;
- IoFLAGS(io) &= ~IOf_UNTAINT; /* maybe redundant */
- }
- }
- }
+
+PerlIO *
+Perl_vms_start_glob
+ (pTHX_ SV *tmpglob,
+ IO *io);
+
+ fp = Perl_vms_start_glob(aTHX_ tmpglob, io);
+
#else /* !VMS */
-#ifdef MACOS_TRADITIONAL
- sv_setpv(tmpcmd, "glob ");
- sv_catsv(tmpcmd, tmpglob);
- sv_catpv(tmpcmd, " |");
-#else
#ifdef DOSISH
#ifdef OS2
sv_setpv(tmpcmd, "for a in ");
#endif
#endif /* !CSH */
#endif /* !DOSISH */
-#endif /* MACOS_TRADITIONAL */
- (void)do_open(PL_last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd),
- FALSE, O_RDONLY, 0, Nullfp);
+ {
+ GV * const envgv = gv_fetchpvs("ENV", 0, SVt_PVHV);
+ SV ** const home = hv_fetchs(GvHV(envgv), "HOME", 0);
+ if (home && *home) SvGETMAGIC(*home);
+ save_hash(gv_fetchpvs("ENV", 0, SVt_PVHV));
+ if (home && *home) SvSETMAGIC(*home);
+ }
+ (void)do_open(PL_last_in_gv, (char*)SvPVX_const(tmpcmd), SvCUR(tmpcmd),
+ FALSE, O_RDONLY, 0, NULL);
fp = IoIFP(io);
#endif /* !VMS */
LEAVE;
return fp;
}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */