/* doio.c
*
- * Copyright (c) 1991-2000, Larry Wall
+ * Copyright (c) 1991-2002, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
#include <signal.h>
#endif
-/* XXX If this causes problems, set i_unistd=undef in the hint file. */
-#ifdef I_UNISTD
-# include <unistd.h>
-#endif
-
-#if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
-# include <sys/socket.h>
-# if defined(USE_SOCKS) && defined(I_SOCKS)
-# include <socks.h>
-# endif
-# ifdef I_NETBSD
-# include <netdb.h>
-# endif
-# ifndef ENOTSOCK
-# ifdef I_NET_ERRNO
-# include <net/errno.h>
-# endif
-# endif
-#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_open9(gv, name, len, as_raw, rawmode, rawperm,
- supplied_fp, Nullsv, 0);
+ return do_openn(gv, name, len, as_raw, rawmode, rawperm,
+ supplied_fp, (SV **) NULL, 0);
}
bool
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);
+}
+
+bool
+Perl_do_openn(pTHX_ GV *gv, register char *name, 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;
+ int savefd = -1;
char savetype = IoTYPE_CLOSED;
int writing = 0;
PerlIO *fp;
int result;
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.) */
+ SV *namesv;
+ 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;
out_crlf = (flags & OPpOPEN_OUT_CRLF);
}
+ /* If currently open - close before we re-open */
if (IoIFP(io)) {
fd = PerlIO_fileno(IoIFP(io));
- if (IoTYPE(io) == IoTYPE_STD)
+ if (IoTYPE(io) == IoTYPE_STD) {
+ /* This is a clone of one of STD* handles */
result = 0;
- else if (fd <= PL_maxsysfd) {
- saveifp = IoIFP(io);
- saveofp = IoOFP(io);
+ }
+ else if (fd >= 0 && fd <= PL_maxsysfd) {
+ /* This is one of the original STD* handles */
+ saveifp = IoIFP(io);
+ saveofp = IoOFP(io);
savetype = IoTYPE(io);
- result = 0;
+ savefd = fd;
+ result = 0;
}
else if (IoTYPE(io) == IoTYPE_PIPE)
result = PerlProc_pclose(IoIFP(io));
}
else
result = PerlIO_close(IoIFP(io));
- if (result == EOF && fd > PL_maxsysfd)
+ 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));
+ }
IoOFP(io) = IoIFP(io) = Nullfp;
}
if (as_raw) {
-#if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
- rawmode |= O_LARGEFILE;
-#endif
+ /* sysopen style args, i.e. integer mode and permissions */
+ STRLEN ix = 0;
+ int appendtrunc =
+ 0
+#ifdef O_APPEND /* Not fully portable. */
+ |O_APPEND
+#endif
+#ifdef O_TRUNC /* Not fully portable. */
+ |O_TRUNC
+#endif
+ ;
+ int modifyingmode =
+ O_WRONLY|O_RDWR|O_CREAT|appendtrunc;
+ int ismodifying;
+
+ if (num_svs != 0) {
+ Perl_croak(aTHX_ "panic: sysopen with multiple args");
+ }
+ /* 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;
- }
+ It might be (in OS/390 and Mac OS Classic it is)
- writing = (result > 0);
- fd = PerlLIO_open3(name, rawmode, rawperm);
+ O_WRONLY 1
+ O_RDONLY 2
+ O_RDWR 3
- if (fd == -1)
- fp = NULL;
- else {
- char fpmode[4];
- STRLEN ix = 0;
- if (result == O_RDONLY)
- fpmode[ix++] = 'r';
-#ifdef O_APPEND
- else if (rawmode & O_APPEND) {
- fpmode[ix++] = 'a';
- if (result != O_WRONLY)
- fpmode[ix++] = '+';
- }
-#endif
- else {
- if (result == O_WRONLY)
- fpmode[ix++] = 'w';
- else {
- fpmode[ix++] = 'r';
- fpmode[ix++] = '+';
- }
- }
- if (rawmode & O_BINARY)
- fpmode[ix++] = 'b';
- fpmode[ix] = '\0';
- fp = PerlIO_fdopen(fd, fpmode);
- if (!fp)
- PerlLIO_close(fd);
+ 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++] = '#'; /* Marker to openn to use numeric "sysopen" */
+
+#if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
+ rawmode |= O_LARGEFILE; /* Transparently largefiley. */
+#endif
+
+ IoTYPE(io) = PerlIO_intmode2str(rawmode, &mode[ix], &writing);
+
+ namesv = sv_2mortal(newSVpvn(name,strlen(name)));
+ num_svs = 1;
+ svp = &namesv;
+ type = Nullch;
+ fp = PerlIO_openn(aTHX_ type, mode, -1, rawmode, rawperm, NULL, num_svs, svp);
}
else {
- char *type;
+ /* Regular (non-sys) open */
char *oname = name;
- STRLEN tlen;
STRLEN olen = len;
- char mode[4]; /* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */
- int dodup;
+ char *tend;
+ int dodup = 0;
+ PerlIO *that_fp = NULL;
type = savepvn(name, len);
- tlen = len;
+ tend = type+len;
SAVEFREEPV(type);
+
+ /* Lose leading and trailing white space */
+ /*SUPPRESS 530*/
+ for (; isSPACE(*type); type++) ;
+ while (tend > type && isSPACE(tend[-1]))
+ *--tend = '\0';
+
if (num_svs) {
- STRLEN l;
- name = SvPV(svs, l) ;
+ /* 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);
SAVEFREEPV(name);
}
else {
- while (tlen && isSPACE(type[tlen-1]))
- type[--tlen] = '\0';
name = type;
- len = tlen;
+ len = tend-type;
}
- mode[0] = mode[1] = mode[2] = mode[3] = '\0';
IoTYPE(io) = *type;
- if (*type == IoTYPE_RDWR && tlen > 1 && type[tlen-1] != IoTYPE_PIPE) { /* scary */
+ 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");
mode[1] = *type++;
- --tlen;
writing = 1;
}
if (*type == IoTYPE_PIPE) {
- if (num_svs && (tlen != 2 || type[1] != IoTYPE_STD)) {
- unknown_desr:
- Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
+ if (num_svs) {
+ if (type[1] != IoTYPE_STD) {
+ unknown_desr:
+ Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
+ }
+ type++;
}
/*SUPPRESS 530*/
- for (type++, tlen--; isSPACE(*type); type++, tlen--) ;
+ for (type++; isSPACE(*type); type++) ;
if (!num_svs) {
name = type;
- len = tlen;
+ len = tend-type;
}
- if (*name == '\0') { /* command is missing 19990114 */
- dTHR;
+ 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)
TAINT_ENV();
TAINT_PROPER("piped open");
- if (name[len-1] == '|') {
- dTHR;
+ 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");
}
- {
- char *mode;
- if (out_raw)
- mode = "wb";
- else if (out_crlf)
- mode = "wt";
- else
- mode = "w";
+ mode[0] = 'w';
+ writing = 1;
+ if (out_raw)
+ strcat(mode, "b");
+ else if (out_crlf)
+ strcat(mode, "t");
+ if (num_svs > 1) {
+ fp = PerlProc_popen_list(mode, num_svs, svp);
+ }
+ else {
fp = PerlProc_popen(name,mode);
}
- writing = 1;
}
else if (*type == IoTYPE_WRONLY) {
TAINT_PROPER("open");
/* Two IoTYPE_WRONLYs in a row make for an IoTYPE_APPEND. */
mode[0] = IoTYPE(io) = IoTYPE_APPEND;
type++;
- tlen--;
}
- else
+ else {
mode[0] = 'w';
+ }
writing = 1;
if (out_raw)
else if (out_crlf)
strcat(mode, "t");
- if (num_svs && tlen != 1)
- goto unknown_desr;
if (*type == '&') {
- name = type;
duplicity:
- dodup = 1;
- name++;
- if (*name == '=') {
+ dodup = PERLIO_DUP_FD;
+ type++;
+ if (*type == '=') {
dodup = 0;
- name++;
+ type++;
}
- if (!*name && supplied_fp)
+ if (!num_svs && !*type && supplied_fp) {
+ /* "<+&" etc. is used by typemaps */
fp = supplied_fp;
+ }
else {
- /*SUPPRESS 530*/
- for (; isSPACE(*name); name++) ;
- if (isDIGIT(*name))
- fd = atoi(name);
+ if (num_svs > 1) {
+ Perl_croak(aTHX_ "More than one argument to '%c&' open",IoTYPE(io));
+ }
+ if (num_svs && SvIOK(*svp)) {
+ fd = SvUV(*svp);
+ }
+ else if (isDIGIT(*type)) {
+ /*SUPPRESS 530*/
+ for (; isSPACE(*type); type++) ;
+ fd = atoi(type);
+ }
else {
IO* thatio;
- gv = gv_fetchpv(name,FALSE,SVt_PVIO);
- thatio = GvIO(gv);
+ if (num_svs) {
+ thatio = sv_2io(*svp);
+ }
+ else {
+ GV *thatgv;
+ /*SUPPRESS 530*/
+ for (; isSPACE(*type); type++) ;
+ thatgv = gv_fetchpv(type,FALSE,SVt_PVIO);
+ thatio = GvIO(thatgv);
+ }
if (!thatio) {
#ifdef EINVAL
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;
/* sfio fails to clear error on next
sfwrite, contrary to documentation.
-- Nick Clark */
- if (PerlIO_seek(fp, 0, SEEK_CUR) == -1)
- PerlIO_clearerr(fp);
+ 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 (!(fp = PerlIO_fdopen(fd,mode))) {
+ if (!num_svs)
+ type = Nullch;
+ 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)
+ PerlLIO_close(fd);
+ }
}
}
- }
+ } /* & */
else {
/*SUPPRESS 530*/
for (; isSPACE(*type); type++) ;
- if (*type == IoTYPE_STD && !type[1]) {
+ 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) {
+ Perl_croak(aTHX_ "More than one argument to '>%c' open",IoTYPE_STD);
+ }
}
else {
- fp = PerlIO_open((num_svs ? name : type), mode);
+ if (!num_svs) {
+ namesv = sv_2mortal(newSVpvn(type,strlen(type)));
+ num_svs = 1;
+ svp = &namesv;
+ type = Nullch;
+ }
+ fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
}
- }
+ } /* !& */
}
else if (*type == IoTYPE_RDONLY) {
- if (num_svs && tlen != 1)
- goto unknown_desr;
/*SUPPRESS 530*/
for (type++; isSPACE(*type); type++) ;
mode[0] = 'r';
strcat(mode, "t");
if (*type == '&') {
- name = type;
goto duplicity;
}
- if (*type == IoTYPE_STD && !type[1]) {
+ 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) {
+ Perl_croak(aTHX_ "More than one argument to '<%c' open",IoTYPE_STD);
+ }
+ }
+ else {
+ if (!num_svs) {
+ namesv = sv_2mortal(newSVpvn(type,strlen(type)));
+ num_svs = 1;
+ svp = &namesv;
+ type = Nullch;
+ }
+ fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
}
- else
- fp = PerlIO_open((num_svs ? name : type), mode);
}
- else if (tlen > 1 && type[tlen-1] == IoTYPE_PIPE) {
+ else if ((num_svs && type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
+ (!num_svs && tend > type+1 && tend[-1] == IoTYPE_PIPE)) {
if (num_svs) {
- if (tlen != 2 || type[0] != IoTYPE_STD)
- goto unknown_desr;
+ type += 2; /* skip over '-|' */
}
else {
- type[--tlen] = '\0';
- while (tlen && isSPACE(type[tlen-1]))
- type[--tlen] = '\0';
+ *--tend = '\0';
+ while (tend > type && isSPACE(tend[-1]))
+ *--tend = '\0';
/*SUPPRESS 530*/
for (; isSPACE(*type); type++) ;
name = type;
+ len = tend-type;
}
- if (*name == '\0') { /* command is missing 19990114 */
- dTHR;
+ 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)
TAINT_ENV();
TAINT_PROPER("piped open");
- {
- char *mode;
- if (in_raw)
- mode = "rb";
- else if (in_crlf)
- mode = "rt";
- else
- mode = "r";
+ mode[0] = 'r';
+ if (in_raw)
+ strcat(mode, "b");
+ else if (in_crlf)
+ strcat(mode, "t");
+ if (num_svs > 1) {
+ fp = PerlProc_popen_list(mode,num_svs,svp);
+ }
+ else {
fp = PerlProc_popen(name,mode);
}
IoTYPE(io) = IoTYPE_PIPE;
IoTYPE(io) = IoTYPE_RDONLY;
/*SUPPRESS 530*/
for (; isSPACE(*name); name++) ;
+ mode[0] = 'r';
+ if (in_raw)
+ strcat(mode, "b");
+ else if (in_crlf)
+ strcat(mode, "t");
if (strEQ(name,"-")) {
fp = PerlIO_stdin();
IoTYPE(io) = IoTYPE_STD;
}
else {
- char *mode;
- if (in_raw)
- mode = "rb";
- else if (in_crlf)
- mode = "rt";
- else
- mode = "r";
- fp = PerlIO_open(name,mode);
+ if (!num_svs) {
+ namesv = sv_2mortal(newSVpvn(type,strlen(type)));
+ num_svs = 1;
+ svp = &namesv;
+ type = Nullch;
+ }
+ fp = PerlIO_openn(aTHX_ type,mode,-1,0,0,NULL,num_svs,svp);
}
}
}
if (!fp) {
- dTHR;
if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n'))
- Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
+ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
goto say_false;
}
- if (IoTYPE(io) &&
- IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD) {
- dTHR;
- if (PerlLIO_fstat(PerlIO_fileno(fp),&PL_statbuf) < 0) {
- (void)PerlIO_close(fp);
+
+ if (ckWARN(WARN_IO)) {
+ if ((IoTYPE(io) == IoTYPE_RDONLY) &&
+ (fp == PerlIO_stdout() || fp == PerlIO_stderr())) {
+ Perl_warner(aTHX_ packWARN(WARN_IO),
+ "Filehandle STD%s opened only for input",
+ (fp == PerlIO_stdout()) ? "OUT" : "ERR");
+ }
+ else if ((IoTYPE(io) == IoTYPE_WRONLY) && fp == PerlIO_stdin()) {
+ Perl_warner(aTHX_ packWARN(WARN_IO),
+ "Filehandle STDIN opened only for output");
+ }
+ }
+
+ 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 */
+ 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
+#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? */
- fd = PerlIO_fileno(saveifp);
+ /* If fd is less that PL_maxsysfd i.e. STDIN..STDERR
+ then dup the new fileno down
+ */
if (saveofp) {
- PerlIO_flush(saveofp); /* emulate PerlIO_close() */
+ PerlIO_flush(saveofp); /* emulate PerlIO_close() */
if (saveofp != saveifp) { /* was a socket? */
PerlIO_close(saveofp);
- if (fd > 2)
- Safefree(saveofp);
}
}
- if (fd != PerlIO_fileno(fp)) {
- Pid_t pid;
- SV *sv;
-
- PerlLIO_dup2(PerlIO_fileno(fp), fd);
- LOCK_FDPID_MUTEX;
- sv = *av_fetch(PL_fdpid,PerlIO_fileno(fp),TRUE);
- (void)SvUPGRADE(sv, SVt_IV);
- pid = SvIVX(sv);
- SvIVX(sv) = 0;
- sv = *av_fetch(PL_fdpid,fd,TRUE);
- UNLOCK_FDPID_MUTEX;
- (void)SvUPGRADE(sv, SVt_IV);
- SvIVX(sv) = pid;
- if (!was_fdopen)
- PerlIO_close(fp);
+ if (savefd != fd) {
+ /* 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);
+ }
+ }
+#endif
+#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;
+
+ 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);
+ (void)SvUPGRADE(sv, SVt_IV);
+ SvIVX(sv) = pid;
+ UNLOCK_FDPID_MUTEX;
+ }
+#endif
+
+ if (was_fdopen) {
+ /* need to close fp without closing underlying fd */
+ int ofd = PerlIO_fileno(fp);
+ int dupfd = PerlLIO_dup(ofd);
+ PerlIO_close(fp);
+ PerlLIO_dup2(dupfd,ofd);
+ PerlLIO_close(dupfd);
+ }
+ else
+ PerlIO_close(fp);
}
fp = saveifp;
PerlIO_clearerr(fp);
+ fd = PerlIO_fileno(fp);
}
#if defined(HAS_FCNTL) && defined(F_SETFD)
- {
+ if (fd >= 0) {
int save_errno = errno;
- fd = PerlIO_fileno(fp);
fcntl(fd,F_SETFD,fd > PL_maxsysfd); /* can change errno */
errno = save_errno;
}
#endif
IoIFP(io) = fp;
+
IoFLAGS(io) &= ~IOf_NOLINE;
if (writing) {
- dTHR;
if (IoTYPE(io) == IoTYPE_SOCKET
- || (IoTYPE(io) == IoTYPE_WRONLY && S_ISCHR(PL_statbuf.st_mode)) )
- {
- char *mode;
- if (out_raw)
- mode = "wb";
- else if (out_crlf)
- mode = "wt";
- else
- mode = "w";
-
- if (!(IoOFP(io) = PerlIO_fdopen(PerlIO_fileno(fp),mode))) {
+ || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(PL_statbuf.st_mode)) ) {
+ mode[0] = 'w';
+ if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,mode,fd,0,0,NULL,0,svp))) {
PerlIO_close(fp);
IoIFP(io) = Nullfp;
goto say_false;
}
PL_filemode = 0;
while (av_len(GvAV(gv)) >= 0) {
- dTHR;
STRLEN oldlen;
sv = av_shift(GvAV(gv));
SAVEFREESV(sv);
filegid = PL_statbuf.st_gid;
if (!S_ISREG(PL_filemode)) {
if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE),
"Can't do inplace edit: %s is not a regular file",
PL_oldname );
do_close(gv,FALSE);
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(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,
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE),
"Can't do inplace edit: %s would not be unique",
SvPVX(sv));
do_close(gv,FALSE);
}
#endif
#ifdef HAS_RENAME
-#if !defined(DOSISH) && !defined(__CYGWIN__)
+#if !defined(DOSISH) && !defined(__CYGWIN__) && !defined(EPOC)
if (PerlLIO_rename(PL_oldname,SvPVX(sv)) < 0) {
if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE),
"Can't rename %s to %s: %s, skipping file",
PL_oldname, SvPVX(sv), Strerror(errno) );
do_close(gv,FALSE);
(void)UNLINK(SvPVX(sv));
if (link(PL_oldname,SvPVX(sv)) < 0) {
if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE),
"Can't rename %s to %s: %s, skipping file",
PL_oldname, SvPVX(sv), Strerror(errno) );
do_close(gv,FALSE);
# ifndef VMS /* Don't delete; use automatic file versioning */
if (UNLINK(PL_oldname) < 0) {
if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE,
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE),
"Can't remove %s: %s, skipping file",
PL_oldname, Strerror(errno) );
do_close(gv,FALSE);
#endif
{
if (ckWARN_d(WARN_INPLACE))
- Perl_warner(aTHX_ WARN_INPLACE, "Can't do inplace edit on %s: %s",
+ Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit on %s: %s",
PL_oldname, Strerror(errno) );
do_close(gv,FALSE);
continue;
return IoIFP(GvIOp(gv));
}
else {
- dTHR;
if (ckWARN_d(WARN_INPLACE)) {
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));
}
}
io = GvIO(gv);
if (!io) { /* never opened */
if (not_implicit) {
- dTHR;
if (ckWARN(WARN_UNOPENED)) /* no check for closed here */
report_evil_fh(gv, io, PL_op->op_type);
SETERRNO(EBADF,SS$_IVCHAN);
bool
Perl_do_eof(pTHX_ GV *gv)
{
- dTHR;
register IO *io;
int ch;
if (!io)
return TRUE;
- else if (ckWARN(WARN_IO)
- && (IoTYPE(io) == IoTYPE_WRONLY || IoIFP(io) == PerlIO_stdout()
- || IoIFP(io) == PerlIO_stderr()))
- {
- /* 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 (ckWARN(WARN_IO) && (IoTYPE(io) == IoTYPE_WRONLY))
+ report_evil_fh(gv, io, OP_phoney_OUTPUT_ONLY);
while (IoIFP(io)) {
(void)PerlIO_ungetc(IoIFP(io),ch);
return FALSE;
}
+
if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
if (PerlIO_get_cnt(IoIFP(io)) < -1)
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;
+ register IO *io = 0;
register PerlIO *fp;
if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
#endif
return PerlIO_tell(fp);
}
- {
- dTHR;
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- }
+ if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+ report_evil_fh(gv, io, PL_op->op_type);
SETERRNO(EBADF,RMS$_IFI);
return (Off_t)-1;
}
bool
Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
{
- register IO *io;
+ register IO *io = 0;
register PerlIO *fp;
if (gv && (io = GvIO(gv)) && (fp = IoIFP(io))) {
#endif
return PerlIO_seek(fp, pos, whence) >= 0;
}
- {
- dTHR;
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- }
+ if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+ report_evil_fh(gv, io, PL_op->op_type);
SETERRNO(EBADF,RMS$_IFI);
return FALSE;
}
Off_t
Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence)
{
- register IO *io;
+ register IO *io = 0;
register PerlIO *fp;
if (gv && (io = GvIO(gv)) && (fp = IoIFP(io)))
return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence);
- {
- dTHR;
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
- report_evil_fh(gv, io, PL_op->op_type);
- }
+ if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+ report_evil_fh(gv, io, PL_op->op_type);
SETERRNO(EBADF,RMS$_IFI);
return (Off_t)-1;
}
end = strchr(s+1, ':');
if (!end)
end = s+len;
+#ifndef PERLIO_LAYERS
Perl_croak(aTHX_ "Unknown discipline '%.*s'", end-s, s);
+#else
+ s = end;
+#endif
}
}
}
int
Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int mode)
{
-#ifdef DOSISH
-# if defined(atarist) || defined(__MINT__)
- if (!PerlIO_flush(fp)) {
- if (mode & O_BINARY)
- ((FILE*)fp)->_flag |= _IOBIN;
- else
- ((FILE*)fp)->_flag &= ~ _IOBIN;
- return 1;
- }
- return 0;
-# else
- if (PerlLIO_setmode(PerlIO_fileno(fp), mode) != -1) {
-# if defined(WIN32) && defined(__BORLANDC__)
- /* The translation mode of the stream is maintained independent
- * of the translation mode of the fd in the Borland RTL (heavy
- * digging through their runtime sources reveal). User has to
- * set the mode explicitly for the stream (though they don't
- * document this anywhere). GSAR 97-5-24
- */
- PerlIO_seek(fp,0L,0);
- if (mode & O_BINARY)
- ((FILE*)fp)->flags |= _F_BIN;
- else
- ((FILE*)fp)->flags &= ~ _F_BIN;
-# endif
- return 1;
- }
- else
- return 0;
-# endif
-#else
-# if defined(USEMYBINMODE)
- if (my_binmode(fp, iotype, mode) != FALSE)
- return 1;
- else
- return 0;
-# else
- return 1;
-# endif
-#endif
+ /* 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 = ":raw";
+#ifdef PERLIO_USING_CRLF
+ if (!(mode & O_BINARY))
+ name = ":crlf";
+#endif
+ return PerlIO_binmode(aTHX_ fp, iotype, mode, name);
}
#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
}
switch (SvTYPE(sv)) {
case SVt_NULL:
- {
- dTHR;
- if (ckWARN(WARN_UNINITIALIZED))
- report_uninit();
- }
+ if (ckWARN(WARN_UNINITIALIZED))
+ report_uninit();
return TRUE;
case SVt_IV:
if (SvIOK(sv)) {
}
/* 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)
+ && ckWARN_d(WARN_UTF8))
+ {
+ Perl_warner(aTHX_ packWARN(WARN_UTF8), "Wide character in print");
+ }
+ }
tmps = SvPV(sv, len);
break;
}
* 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 || PerlIO_error(fp)))
+ if (len && (PerlIO_write(fp,tmps,len) == 0))
return FALSE;
return !PerlIO_error(fp);
}
I32
Perl_my_stat(pTHX)
{
- djSP;
+ dSP;
IO *io;
GV* gv;
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)
{
- djSP;
+ dSP;
SV *sv;
STRLEN n_a;
if (PL_op->op_flags & OPf_REF) {
Perl_croak(aTHX_ "The stat preceding -l _ wasn't an lstat");
return PL_laststatval;
}
- Perl_croak(aTHX_ "You can't use -l on a filehandle");
+ if (ckWARN(WARN_IO)) {
+ Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
+ GvENAME(cGVOP_gv));
+ return (PL_laststatval = -1);
+ }
}
PL_laststype = OP_LSTAT;
PL_statgv = Nullgv;
sv = POPs;
PUTBACK;
+ if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV && ckWARN(WARN_IO)) {
+ Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
+ GvENAME((GV*) SvRV(sv)));
+ return (PL_laststatval = -1);
+ }
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");
+ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "lstat");
return PL_laststatval;
}
Perl_croak(aTHX_ "exec? I'm not *that* kind of operating system");
#else
register char **a;
- char *tmps;
+ char *tmps = Nullch;
STRLEN n_a;
if (sp > mark) {
- dTHR;
New(401,PL_Argv, sp - mark + 1, char*);
a = PL_Argv;
while (++mark <= sp) {
*a++ = "";
}
*a = Nullch;
- if (*PL_Argv[0] != '/') /* will execvp use PATH? */
+ if (really)
+ tmps = SvPV(really, n_a);
+ if ((!really && *PL_Argv[0] != '/') ||
+ (really && *tmps != '/')) /* will execvp use PATH? */
TAINT_ENV(); /* testing IFS here is overkill, probably */
- if (really && *(tmps = SvPV(really, n_a)))
- PerlProc_execvp(tmps,PL_Argv);
+ if (really && *tmps)
+ PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv));
else
- PerlProc_execvp(PL_Argv[0],PL_Argv);
+ PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
if (ckWARN(WARN_EXEC))
- Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
- PL_Argv[0], Strerror(errno));
+ Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
+ (really ? tmps : PL_Argv[0]), Strerror(errno));
if (do_report) {
int e = errno;
{
register char **a;
register char *s;
- char flags[10];
while (*cmd && isSPACE(*cmd))
cmd++;
/* save an extra exec if possible */
#ifdef CSH
- if (strnEQ(cmd,PL_cshname,PL_cshlen) && strnEQ(cmd+PL_cshlen," -c",3)) {
- strcpy(flags,"-c");
- s = cmd+PL_cshlen+3;
- if (*s == 'f') {
- s++;
- strcat(flags,"f");
- }
- if (*s == ' ')
- s++;
- if (*s++ == '\'') {
- char *ncmd = s;
-
- while (*s)
- s++;
- if (s[-1] == '\n')
- *--s = '\0';
- if (s[-1] == '\'') {
- *--s = '\0';
- PerlProc_execl(PL_cshname,"csh", flags,ncmd,(char*)0);
- *s = '\'';
- return FALSE;
- }
+ {
+ char flags[10];
+ if (strnEQ(cmd,PL_cshname,PL_cshlen) &&
+ strnEQ(cmd+PL_cshlen," -c",3)) {
+ strcpy(flags,"-c");
+ s = cmd+PL_cshlen+3;
+ if (*s == 'f') {
+ s++;
+ strcat(flags,"f");
+ }
+ if (*s == ' ')
+ s++;
+ if (*s++ == '\'') {
+ char *ncmd = s;
+
+ while (*s)
+ s++;
+ if (s[-1] == '\n')
+ *--s = '\0';
+ if (s[-1] == '\'') {
+ *--s = '\0';
+ PerlProc_execl(PL_cshname,"csh", flags, ncmd, (char*)0);
+ *s = '\'';
+ return FALSE;
+ }
+ }
}
}
#endif /* CSH */
goto doshell;
for (s = cmd; *s; s++) {
- if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
+ if (*s != ' ' && !isALPHA(*s) &&
+ strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
if (*s == '\n' && !s[1]) {
*s = '\0';
break;
goto doshell;
}
{
- dTHR;
int e = errno;
if (ckWARN(WARN_EXEC))
- Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
+ Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
PL_Argv[0], Strerror(errno));
if (do_report) {
PerlLIO_write(fd, (void*)&e, sizeof(int));
I32
Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
{
- dTHR;
register I32 val;
register I32 val2;
register I32 tot = 0;
}
break;
#endif
-/*
+/*
XXX Should we make lchown() directly available from perl?
For now, we'll let Configure test for HAS_LCHOWN, but do
nothing in the core.
} utbuf;
#endif
+ SV* accessed = *++mark;
+ SV* modified = *++mark;
+ void * utbufp = &utbuf;
+
+ /* 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(*++mark); /* time accessed */
- utbuf.modtime = (Time_t)SvNVx(*++mark); /* time modified */
+ utbuf.actime = (Time_t)SvNVx(accessed); /* time accessed */
+ utbuf.modtime = (Time_t)SvNVx(modified); /* time modified */
#else
- utbuf.actime = (Time_t)SvIVx(*++mark); /* time accessed */
- utbuf.modtime = (Time_t)SvIVx(*++mark); /* time modified */
+ utbuf.actime = (Time_t)SvIVx(accessed); /* time accessed */
+ utbuf.modtime = (Time_t)SvIVx(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, &utbuf))
+ if (PerlLIO_utime(name, utbufp))
tot--;
}
}
I32
Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp)
{
- dTHR;
key_t key;
I32 n, flags;
I32
Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp)
{
- dTHR;
SV *astr;
char *a;
I32 id, n, cmd, infosize, getinfo;
Perl_do_msgsnd(pTHX_ SV **mark, SV **sp)
{
#ifdef HAS_MSG
- dTHR;
SV *mstr;
char *mbuf;
I32 id, msize, flags;
Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
{
#ifdef HAS_MSG
- dTHR;
SV *mstr;
char *mbuf;
long mtype;
flags = SvIVx(*++mark);
SvPV_force(mstr, len);
mbuf = SvGROW(mstr, sizeof(long)+msize+1);
-
+
SETERRNO(0,0);
ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
if (ret >= 0) {
Perl_do_semop(pTHX_ SV **mark, SV **sp)
{
#ifdef HAS_SEM
- dTHR;
SV *opstr;
char *opbuf;
I32 id;
id = SvIVx(*++mark);
opstr = *++mark;
opbuf = SvPV(opstr, opsize);
- if (opsize < sizeof(struct sembuf)
- || (opsize % sizeof(struct sembuf)) != 0) {
+ if (opsize < 3 * SHORTSIZE
+ || (opsize % (3 * SHORTSIZE))) {
SETERRNO(EINVAL,LIB$_INVARG);
return -1;
}
SETERRNO(0,0);
- return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
+ /* We can't assume that sizeof(struct sembuf) == 3 * sizeof(short). */
+ {
+ int nsops = opsize / (3 * sizeof (short));
+ int i = nsops;
+ short *ops = (short *) opbuf;
+ short *o = ops;
+ struct sembuf *temps, *t;
+ I32 result;
+
+ New (0, temps, nsops, struct sembuf);
+ t = temps;
+ while (i--) {
+ t->sem_num = *o++;
+ t->sem_op = *o++;
+ t->sem_flg = *o++;
+ t++;
+ }
+ result = semop(id, temps, nsops);
+ t = temps;
+ o = ops;
+ i = nsops;
+ while (i--) {
+ *o++ = t->sem_num;
+ *o++ = t->sem_op;
+ *o++ = t->sem_flg;
+ t++;
+ }
+ Safefree(temps);
+ return result;
+ }
#else
Perl_croak(aTHX_ "semop not implemented");
#endif
Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
{
#ifdef HAS_SHM
- dTHR;
SV *mstr;
char *mbuf, *shm;
I32 id, mpos, msize;
#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 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);
+ PerlIO *fp;
+ 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);
+ for (cp=wilddsc.dsc$a_pointer; ok && cp && *cp; cp++)
+ if (*cp == '?') *cp = '%'; /* VMS style single-char wildcard */
+ 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 */
+ }
+ }
+ }
+#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 ");
+ sv_catsv(tmpcmd, tmpglob);
+ sv_catpv(tmpcmd, "; do echo \"$a\\0\\c\"; done |");
+#else
+#ifdef DJGPP
+ sv_setpv(tmpcmd, "/dev/dosglob/"); /* File System Extension */
+ sv_catsv(tmpcmd, tmpglob);
+#else
+ sv_setpv(tmpcmd, "perlglob ");
+ sv_catsv(tmpcmd, tmpglob);
+ sv_catpv(tmpcmd, " |");
+#endif /* !DJGPP */
+#endif /* !OS2 */
+#else /* !DOSISH */
+#if defined(CSH)
+ sv_setpvn(tmpcmd, PL_cshname, PL_cshlen);
+ sv_catpv(tmpcmd, " -cf 'set nonomatch; glob ");
+ sv_catsv(tmpcmd, tmpglob);
+ sv_catpv(tmpcmd, "' 2>/dev/null |");
+#else
+ sv_setpv(tmpcmd, "echo ");
+ sv_catsv(tmpcmd, tmpglob);
+#if 'z' - 'a' == 25
+ sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
+#else
+ sv_catpv(tmpcmd, "|tr -s ' \t\f\r' '\\n\\n\\n\\n'|");
+#endif
+#endif /* !CSH */
+#endif /* !DOSISH */
+#endif /* MACOS_TRADITIONAL */
+ (void)do_open(PL_last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd),
+ FALSE, O_RDONLY, 0, Nullfp);
+ fp = IoIFP(io);
+#endif /* !VMS */
+ LEAVE;
+ return fp;
+}