X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/a2b41d5ca668b3be2860093f464392277e1d0034..0acc85e6b2ff98c833fbca4187dc5cfac982daf9:/doio.c diff --git a/doio.c b/doio.c index 49f1e16..6f4cd84 100644 --- a/doio.c +++ b/doio.c @@ -64,7 +64,6 @@ static IO * S_openn_setup(pTHX_ GV *gv, char *mode, PerlIO **saveifp, PerlIO **saveofp, int *savefd, char *savetype) { - dVAR; IO * const io = GvIOn(gv); PERL_ARGS_ASSERT_OPENN_SETUP; @@ -111,7 +110,8 @@ S_openn_setup(pTHX_ GV *gv, char *mode, PerlIO **saveifp, PerlIO **saveofp, if (result == EOF && old_fd > PL_maxsysfd) { /* Why is this not Perl_warn*() call ? */ PerlIO_printf(Perl_error_log, - "Warning: unable to close filehandle %"HEKf" properly.\n", + "Warning: unable to close filehandle %" HEKf + " properly.\n", HEKfARG(GvENAME_HEK(gv)) ); } @@ -127,7 +127,24 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, int rawmode, int rawperm, PerlIO *supplied_fp, SV **svp, I32 num_svs) { - dVAR; + PERL_ARGS_ASSERT_DO_OPENN; + + if (as_raw) { + /* sysopen style args, i.e. integer mode and permissions */ + + if (num_svs != 0) { + Perl_croak(aTHX_ "panic: sysopen with multiple args, num_svs=%ld", + (long) num_svs); + } + return do_open_raw(gv, oname, len, rawmode, rawperm, NULL); + } + return do_open6(gv, oname, len, supplied_fp, svp, num_svs); +} + +bool +Perl_do_open_raw(pTHX_ GV *gv, const char *oname, STRLEN len, + int rawmode, int rawperm, Stat_t *statbufp) +{ PerlIO *saveifp; PerlIO *saveofp; int savefd; @@ -136,13 +153,11 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, IO * const io = openn_setup(gv, mode, &saveifp, &saveofp, &savefd, &savetype); int writing = 0; PerlIO *fp; - int fd; - bool was_fdopen = FALSE; - char *type = NULL; - PERL_ARGS_ASSERT_DO_OPENN; + PERL_ARGS_ASSERT_DO_OPEN_RAW; - if (as_raw) { + /* For ease of blame back to 5.000, keep the existing indenting. */ + { /* sysopen style args, i.e. integer mode and permissions */ STRLEN ix = 0; const int appendtrunc = @@ -158,10 +173,6 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, int ismodifying; SV *namesv; - if (num_svs != 0) { - Perl_croak(aTHX_ "panic: sysopen with multiple args, num_svs=%ld", - (long) num_svs); - } /* It's not always O_RDONLY 0 @@ -193,10 +204,31 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, IoTYPE(io) = PerlIO_intmode2str(rawmode, &mode[ix], &writing); namesv = newSVpvn_flags(oname, len, SVs_TEMP); - type = NULL; - fp = PerlIO_openn(aTHX_ type, mode, -1, rawmode, rawperm, NULL, 1, &namesv); + fp = PerlIO_openn(aTHX_ NULL, mode, -1, rawmode, rawperm, NULL, 1, &namesv); } - else { + return openn_cleanup(gv, io, fp, mode, oname, saveifp, saveofp, savefd, + savetype, writing, 0, NULL, statbufp); +} + +bool +Perl_do_open6(pTHX_ GV *gv, const char *oname, STRLEN len, + PerlIO *supplied_fp, SV **svp, U32 num_svs) +{ + PerlIO *saveifp; + PerlIO *saveofp; + int savefd; + char savetype; + char mode[PERL_MODE_MAX]; /* file mode ("r\0", "rb\0", "ab\0" etc.) */ + IO * const io = openn_setup(gv, mode, &saveifp, &saveofp, &savefd, &savetype); + int writing = 0; + PerlIO *fp; + bool was_fdopen = FALSE; + char *type = NULL; + + PERL_ARGS_ASSERT_DO_OPEN6; + + /* For ease of blame back to 5.000, keep the existing indenting. */ + { /* Regular (non-sys) open */ char *name; STRLEN olen = len; @@ -234,13 +266,16 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, Perl_warner(aTHX_ packWARN(WARN_IO), "Can't open a reference"); SETERRNO(EINVAL, LIB_INVARG); + fp = NULL; goto say_false; } #endif /* USE_STDIO */ p = (SvOK(*svp) || SvGMAGICAL(*svp)) ? SvPV(*svp, nlen) : NULL; - if (p && !IS_SAFE_PATHNAME(p, nlen, "open")) + if (p && !IS_SAFE_PATHNAME(p, nlen, "open")) { + fp = NULL; goto say_false; + } name = p ? savepvn(p, nlen) : savepvs(""); @@ -279,6 +314,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, if (ckWARN(WARN_PIPE)) Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open"); errno = EPIPE; + fp = NULL; goto say_false; } if (!(*name == '-' && name[1] == '\0') || num_svs) @@ -304,6 +340,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, if (num_svs) { if (*type) { if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) { + fp = NULL; goto say_false; } } @@ -341,6 +378,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, else { PerlIO *that_fp = NULL; int wanted_fd; + UV uv; 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)); @@ -354,8 +392,11 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, wanted_fd = SvUV(*svp); num_svs = 0; } - else if (isDIGIT(*type)) { - wanted_fd = atoi(type); + else if (isDIGIT(*type) + && grok_atoUV(type, &uv, NULL) + && uv <= INT_MAX + ) { + wanted_fd = (int)uv; } else { const IO* thatio; @@ -371,6 +412,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, #ifdef EINVAL SETERRNO(EINVAL,SS_IVCHAN); #endif + fp = NULL; goto say_false; } if ((that_fp = IoIFP(thatio))) { @@ -397,8 +439,11 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, else if (IoTYPE(thatio) == IoTYPE_SOCKET) IoTYPE(io) = IoTYPE_SOCKET; } - else - wanted_fd = -1; + else { + SETERRNO(EBADF, RMS_IFI); + fp = NULL; + goto say_false; + } } if (!num_svs) type = NULL; @@ -497,6 +542,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, if (ckWARN(WARN_PIPE)) Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open"); errno = EPIPE; + fp = NULL; goto say_false; } if (!(*name == '-' && name[1] == '\0') || num_svs) @@ -521,6 +567,7 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, type++; if (*type) { if (PerlIO_apply_layers(aTHX_ fp, mode, type) != 0) { + fp = NULL; goto say_false; } } @@ -556,9 +603,27 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, } } } + + say_false: + return openn_cleanup(gv, io, fp, mode, oname, saveifp, saveofp, savefd, + savetype, writing, was_fdopen, type, NULL); +} + +/* Yes, this is ugly, but it's private, and I don't see a cleaner way to + simplify the two-headed public interface of do_openn. */ +static bool +S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname, + PerlIO *saveifp, PerlIO *saveofp, int savefd, char savetype, + int writing, bool was_fdopen, const char *type, Stat_t *statbufp) +{ + int fd; + Stat_t statbuf; + + PERL_ARGS_ASSERT_OPENN_CLEANUP; + if (!fp) { if (IoTYPE(io) == IoTYPE_RDONLY && ckWARN(WARN_NEWLINE) - && strchr(oname, '\n') + && should_warn_nl(oname) ) { @@ -573,36 +638,36 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, if ((IoTYPE(io) == IoTYPE_RDONLY) && (fp == PerlIO_stdout() || fp == PerlIO_stderr())) { Perl_warner(aTHX_ packWARN(WARN_IO), - "Filehandle STD%s reopened as %"HEKf + "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_ packWARN(WARN_IO), - "Filehandle STDIN reopened as %"HEKf" only for output", + "Filehandle STDIN reopened as %" HEKf " only for output", HEKfARG(GvENAME_HEK(gv)) ); } } 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. + /* Do NOT do: "if (fd < 0) goto say_false;" here. If there is no + * fd 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 (PerlLIO_fstat(fd,&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)) + if (S_ISSOCK(statbuf.st_mode)) IoTYPE(io) = IoTYPE_SOCKET; /* in case a socket was passed in to us */ #ifdef HAS_SOCKET else if ( - !(PL_statbuf.st_mode & S_IFMT) + !(statbuf.st_mode & S_IFMT) && 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 */ @@ -637,7 +702,10 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, is assigned to (say) STDOUT - for now let dup2() fail and provide the error */ - if (PerlLIO_dup2(fd, savefd) < 0) { + if (fd < 0) { + SETERRNO(EBADF,RMS_IFI); + goto say_false; + } else if (PerlLIO_dup2(fd, savefd) < 0) { (void)PerlIO_close(fp); goto say_false; } @@ -673,16 +741,32 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, if (was_fdopen) { /* need to close fp without closing underlying fd */ int ofd = PerlIO_fileno(fp); - int dupfd = PerlLIO_dup(ofd); + int dupfd = ofd >= 0 ? PerlLIO_dup(ofd) : -1; #if defined(HAS_FCNTL) && defined(F_SETFD) - /* Assume if we have F_SETFD we have F_GETFD */ - int coe = fcntl(ofd,F_GETFD); + /* Assume if we have F_SETFD we have F_GETFD. */ + /* Get a copy of all the fd flags. */ + int fd_flags = ofd >= 0 ? fcntl(ofd, F_GETFD) : -1; + if (fd_flags < 0) { + if (dupfd >= 0) + PerlLIO_close(dupfd); + goto say_false; + } #endif + if (ofd < 0 || dupfd < 0) { + if (dupfd >= 0) + PerlLIO_close(dupfd); + goto say_false; + } PerlIO_close(fp); - PerlLIO_dup2(dupfd,ofd); + 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); + /* The dup trick has lost close-on-exec on ofd, + * and possibly any other flags, so restore them. */ + if (fcntl(ofd,F_SETFD, fd_flags) < 0) { + if (dupfd >= 0) + PerlLIO_close(dupfd); + goto say_false; + } #endif PerlLIO_close(dupfd); } @@ -693,11 +777,10 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, PerlIO_clearerr(fp); fd = PerlIO_fileno(fp); } -#if defined(HAS_FCNTL) && defined(F_SETFD) - if (fd >= 0) { - dSAVE_ERRNO; - fcntl(fd,F_SETFD,fd > PL_maxsysfd); /* can change errno */ - RESTORE_ERRNO; +#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) + if (fd >= 0 && fd > PL_maxsysfd && fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { + PerlLIO_close(fd); + goto say_false; } #endif IoIFP(io) = fp; @@ -705,23 +788,25 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw, IoFLAGS(io) &= ~IOf_NOLINE; if (writing) { if (IoTYPE(io) == IoTYPE_SOCKET - || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(PL_statbuf.st_mode)) ) { + || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(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,NULL))) { PerlIO_close(fp); - IoIFP(io) = NULL; goto say_false; } } else IoOFP(io) = fp; } + if (statbufp) + *statbufp = statbuf; + return TRUE; -say_false: + say_false: IoIFP(io) = saveifp; IoOFP(io) = saveofp; IoTYPE(io) = savetype; @@ -729,23 +814,19 @@ say_false: } PerlIO * -Perl_nextargv(pTHX_ GV *gv) +Perl_nextargv(pTHX_ GV *gv, bool nomagicopen) { - dVAR; - SV *sv; -#ifndef FLEXFILENAMES - int filedev; - int fileino; -#endif - Uid_t fileuid; - Gid_t filegid; IO * const io = GvIOp(gv); + SV *const old_out_name = PL_inplace ? newSVsv(GvSV(gv)) : NULL; PERL_ARGS_ASSERT_NEXTARGV; + if (old_out_name) + SAVEFREESV(old_out_name); + if (!PL_argvoutgv) PL_argvoutgv = gv_fetchpvs("ARGVOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO); - if (io && (IoFLAGS(io) & IOf_ARGV) && (IoFLAGS(io) & IOf_START)) { + if (io && (IoFLAGS(io) & (IOf_ARGV|IOf_START)) == (IOf_ARGV|IOf_START)) { IoFLAGS(io) &= ~IOf_START; if (PL_inplace) { assert(PL_defoutgv); @@ -768,14 +849,41 @@ Perl_nextargv(pTHX_ GV *gv) return NULL; while (av_tindex(GvAV(gv)) >= 0) { STRLEN oldlen; - sv = av_shift(GvAV(gv)); + SV *const sv = av_shift(GvAV(gv)); SAVEFREESV(sv); SvTAINTED_off(GvSVn(gv)); /* previous tainting irrelevant */ 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,NULL)) { - if (PL_inplace) { + if (LIKELY(!PL_inplace)) { + if (nomagicopen + ? do_open6(gv, "<", 1, NULL, &GvSV(gv), 1) + : do_open6(gv, PL_oldname, oldlen, NULL, NULL, 0) + ) { + return IoIFP(GvIOp(gv)); + } + } + else { + Stat_t statbuf; + { + IO * const io = GvIOp(PL_argvoutgv); + if (io && IoIFP(io) && old_out_name && !io_close(io, PL_argvoutgv, FALSE, FALSE)) { + Perl_croak(aTHX_ "Failed to close in-place edit file %" + SVf ": %s\n", old_out_name, Strerror(errno)); + } + } + /* This very long block ends with return IoIFP(GvIOp(gv)); + Both this block and the block above fall through on open + failure to the warning code, and then the while loop above tries + the next entry. */ + if (do_open_raw(gv, PL_oldname, oldlen, O_RDONLY, 0, &statbuf)) { +#ifndef FLEXFILENAMES + int filedev; + int fileino; +#endif + Uid_t fileuid; + Gid_t filegid; + TAINT_PROPER("inplace open"); if (oldlen == 1 && *PL_oldname == '-') { setdefout(gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL, @@ -783,12 +891,12 @@ Perl_nextargv(pTHX_ GV *gv) return IoIFP(GvIOp(gv)); } #ifndef FLEXFILENAMES - filedev = PL_statbuf.st_dev; - fileino = PL_statbuf.st_ino; + filedev = statbuf.st_dev; + fileino = statbuf.st_ino; #endif - PL_filemode = PL_statbuf.st_mode; - fileuid = PL_statbuf.st_uid; - filegid = PL_statbuf.st_gid; + PL_filemode = statbuf.st_mode; + fileuid = statbuf.st_uid; + filegid = statbuf.st_gid; if (!S_ISREG(PL_filemode)) { Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit: %s is not a regular file", @@ -800,7 +908,7 @@ Perl_nextargv(pTHX_ GV *gv) const char *star = strchr(PL_inplace, '*'); if (star) { const char *begin = PL_inplace; - sv_setpvs(sv, ""); + SvPVCLEAR(sv); do { sv_catpvn(sv, begin, star - begin); sv_catpvn(sv, PL_oldname, oldlen); @@ -813,16 +921,17 @@ Perl_nextargv(pTHX_ GV *gv) sv_catpv(sv,PL_inplace); } #ifndef FLEXFILENAMES - if ((PerlLIO_stat(SvPVX_const(sv),&PL_statbuf) >= 0 - && PL_statbuf.st_dev == filedev - && PL_statbuf.st_ino == fileino) + if ((PerlLIO_stat(SvPVX_const(sv),&statbuf) >= 0 + && statbuf.st_dev == filedev + && statbuf.st_ino == fileino) #ifdef DJGPP || ((_djstat_fail_bits & _STFAIL_TRUENAME)!=0) #endif ) { Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE), - "Can't do inplace edit: %"SVf" would not be unique", + "Can't do inplace edit: %" + SVf " would not be unique", SVfARG(sv)); do_close(gv,FALSE); continue; @@ -832,8 +941,10 @@ Perl_nextargv(pTHX_ GV *gv) #if !defined(DOSISH) && !defined(__CYGWIN__) 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)); + "Can't rename %s to %" SVf + ": %s, skipping file", + PL_oldname, SVfARG(sv), + Strerror(errno)); do_close(gv,FALSE); continue; } @@ -841,13 +952,13 @@ Perl_nextargv(pTHX_ GV *gv) do_close(gv,FALSE); (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); + do_open_raw(gv, SvPVX_const(sv), SvCUR(sv), O_RDONLY, 0, NULL); #endif /* DOSISH */ #else (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", + "Can't rename %s to %" SVf ": %s, skipping file", PL_oldname, SVfARG(sv), Strerror(errno) ); do_close(gv,FALSE); continue; @@ -856,7 +967,7 @@ Perl_nextargv(pTHX_ GV *gv) #endif } else { -#if !defined(DOSISH) && !defined(AMIGAOS) +#if !defined(DOSISH) && !defined(__amigaos4__) # ifndef VMS /* Don't delete; use automatic file versioning */ if (UNLINK(PL_oldname) < 0) { Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE), @@ -873,14 +984,14 @@ Perl_nextargv(pTHX_ GV *gv) 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, + if (!Perl_do_open_raw(aTHX_ PL_argvoutgv, SvPVX_const(sv), + SvCUR(sv), #ifdef VMS - O_WRONLY|O_CREAT|O_TRUNC,0, + O_WRONLY|O_CREAT|O_TRUNC, 0, #else - O_WRONLY|O_CREAT|OPEN_EXCL,0600, + O_WRONLY|O_CREAT|OPEN_EXCL, 0600, #endif - NULL, NULL, 0)) { + NULL)) { Perl_ck_warner_d(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit on %s: %s", PL_oldname, Strerror(errno) ); do_close(gv,FALSE); @@ -888,47 +999,57 @@ Perl_nextargv(pTHX_ GV *gv) } setdefout(PL_argvoutgv); PL_lastfd = PerlIO_fileno(IoIFP(GvIOp(PL_argvoutgv))); - (void)PerlLIO_fstat(PL_lastfd,&PL_statbuf); + if (PL_lastfd >= 0) { + (void)PerlLIO_fstat(PL_lastfd,&statbuf); #ifdef HAS_FCHMOD - (void)fchmod(PL_lastfd,PL_filemode); + (void)fchmod(PL_lastfd,PL_filemode); #else - (void)PerlLIO_chmod(PL_oldname,PL_filemode); + (void)PerlLIO_chmod(PL_oldname,PL_filemode); #endif - if (fileuid != PL_statbuf.st_uid || filegid != PL_statbuf.st_gid) { - int rc = 0; + if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) { + /* XXX silently ignore failures */ #ifdef HAS_FCHOWN - rc = fchown(PL_lastfd,fileuid,filegid); + PERL_UNUSED_RESULT(fchown(PL_lastfd,fileuid,filegid)); #else #ifdef HAS_CHOWN - rc = PerlLIO_chown(PL_oldname,fileuid,filegid); + PERL_UNUSED_RESULT(PerlLIO_chown(PL_oldname,fileuid,filegid)); #endif #endif - /* XXX silently ignore failures */ - PERL_UNUSED_VAR(rc); - } - } - return IoIFP(GvIOp(gv)); - } - else { - if (ckWARN_d(WARN_INPLACE)) { - const int eno = errno; - if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0 - && !S_ISREG(PL_statbuf.st_mode)) - { - Perl_warner(aTHX_ packWARN(WARN_INPLACE), - "Can't do inplace edit: %s is not a regular file", - PL_oldname); + } } - else - Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't open %s: %s", - PL_oldname, Strerror(eno)); + return IoIFP(GvIOp(gv)); } + } /* successful do_open_raw(), PL_inplace non-NULL */ + + if (ckWARN_d(WARN_INPLACE)) { + const int eno = errno; + Stat_t statbuf; + if (PerlLIO_stat(PL_oldname, &statbuf) >= 0 + && !S_ISREG(statbuf.st_mode)) { + Perl_warner(aTHX_ packWARN(WARN_INPLACE), + "Can't do inplace edit: %s is not a regular file", + PL_oldname); + } + else { + Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't open %s: %s", + PL_oldname, Strerror(eno)); + } } } if (io && (IoFLAGS(io) & IOf_ARGV)) IoFLAGS(io) |= IOf_START; if (PL_inplace) { - (void)do_close(PL_argvoutgv,FALSE); + if (old_out_name) { + IO * const io = GvIOp(PL_argvoutgv); + if (io && IoIFP(io) && !io_close(io, PL_argvoutgv, FALSE, FALSE)) { + Perl_croak(aTHX_ "Failed to close in-place edit file %" SVf ": %s\n", + old_out_name, Strerror(errno)); + } + } + else { + /* maybe this is no longer wanted */ + (void)do_close(PL_argvoutgv,FALSE); + } if (io && (IoFLAGS(io) & IOf_ARGV) && PL_argvout_stack && AvFILLp(PL_argvout_stack) >= 0) { @@ -946,7 +1067,6 @@ Perl_nextargv(pTHX_ GV *gv) bool Perl_do_close(pTHX_ GV *gv, bool not_implicit) { - dVAR; bool retval; IO *io; @@ -965,7 +1085,7 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit) } return FALSE; } - retval = io_close(io, not_implicit); + retval = io_close(io, NULL, not_implicit, FALSE); if (not_implicit) { IoLINES(io) = 0; IoPAGE(io) = 0; @@ -976,9 +1096,8 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit) } bool -Perl_io_close(pTHX_ IO *io, bool not_implicit) +Perl_io_close(pTHX_ IO *io, GV *gv, bool not_implicit, bool warn_on_fail) { - dVAR; bool retval = FALSE; PERL_ARGS_ASSERT_IO_CLOSE; @@ -999,15 +1118,37 @@ Perl_io_close(pTHX_ IO *io, bool not_implicit) else { if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */ const bool prev_err = PerlIO_error(IoOFP(io)); +#ifdef USE_PERLIO + if (prev_err) + PerlIO_restore_errno(IoOFP(io)); +#endif retval = (PerlIO_close(IoOFP(io)) != EOF && !prev_err); PerlIO_close(IoIFP(io)); /* clear stdio, fd already closed */ } else { const bool prev_err = PerlIO_error(IoIFP(io)); +#ifdef USE_PERLIO + if (prev_err) + PerlIO_restore_errno(IoIFP(io)); +#endif retval = (PerlIO_close(IoIFP(io)) != EOF && !prev_err); } } IoOFP(io) = IoIFP(io) = NULL; + + if (warn_on_fail && !retval) { + if (gv) + Perl_ck_warner_d(aTHX_ packWARN(WARN_IO), + "Warning: unable to close filehandle %" + HEKf " properly: %" SVf, + HEKfARG(GvNAME_HEK(gv)), + SVfARG(get_sv("!",GV_ADD))); + else + Perl_ck_warner_d(aTHX_ packWARN(WARN_IO), + "Warning: unable to close filehandle " + "properly: %" SVf, + SVfARG(get_sv("!",GV_ADD))); + } } else if (not_implicit) { SETERRNO(EBADF,SS_IVCHAN); @@ -1019,7 +1160,6 @@ Perl_io_close(pTHX_ IO *io, bool not_implicit) bool Perl_do_eof(pTHX_ GV *gv) { - dVAR; IO * const io = GvIO(gv); PERL_ARGS_ASSERT_DO_EOF; @@ -1052,7 +1192,7 @@ Perl_do_eof(pTHX_ GV *gv) PerlIO_set_cnt(IoIFP(io),-1); } if (PL_op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */ - if (gv != PL_argvgv || !nextargv(gv)) /* get another fp handy */ + if (gv != PL_argvgv || !nextargv(gv, FALSE)) /* get another fp handy */ return TRUE; } else @@ -1064,7 +1204,6 @@ Perl_do_eof(pTHX_ GV *gv) Off_t Perl_do_tell(pTHX_ GV *gv) { - dVAR; IO *const io = GvIO(gv); PerlIO *fp; @@ -1081,7 +1220,6 @@ Perl_do_tell(pTHX_ GV *gv) bool Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence) { - dVAR; IO *const io = GvIO(gv); PerlIO *fp; @@ -1096,14 +1234,20 @@ Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence) Off_t Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence) { - dVAR; IO *const io = GvIO(gv); PerlIO *fp; PERL_ARGS_ASSERT_DO_SYSSEEK; - if (io && (fp = IoIFP(io))) - return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence); + if (io && (fp = IoIFP(io))) { + int fd = PerlIO_fileno(fp); + if (fd < 0 || (whence == SEEK_SET && pos < 0)) { + SETERRNO(EINVAL,LIB_INVARG); + return -1; + } else { + return PerlLIO_lseek(fd, pos, whence); + } + } report_evil_fh(gv); SETERRNO(EBADF,RMS_IFI); return (Off_t)-1; @@ -1113,6 +1257,7 @@ int Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len) { int mode = O_BINARY; + PERL_UNUSED_CONTEXT; if (s) { while (*s) { if (*s == ':') { @@ -1126,7 +1271,7 @@ Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len) len -= 4; break; } - /* FALL THROUGH */ + /* FALLTHROUGH */ case 'c': if (s[2] == 'r' && s[3] == 'l' && s[4] == 'f' && (!s[5] || s[5] == ':' || isSPACE(s[5]))) @@ -1136,7 +1281,7 @@ Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len) len -= 5; break; } - /* FALL THROUGH */ + /* FALLTHROUGH */ default: goto fail_discipline; } @@ -1147,7 +1292,7 @@ Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len) } else { const char *end; -fail_discipline: + fail_discipline: end = strchr(s+1, ':'); if (!end) end = s+len; @@ -1219,8 +1364,6 @@ my_chsize(int fd, Off_t length) bool Perl_do_print(pTHX_ SV *sv, PerlIO *fp) { - dVAR; - PERL_ARGS_ASSERT_DO_PRINT; /* assuming fp is checked earlier */ @@ -1229,9 +1372,9 @@ Perl_do_print(pTHX_ SV *sv, PerlIO *fp) if (SvTYPE(sv) == SVt_IV && SvIOK(sv)) { assert(!SvGMAGICAL(sv)); if (SvIsUV(sv)) - PerlIO_printf(fp, "%"UVuf, (UV)SvUVX(sv)); + PerlIO_printf(fp, "%" UVuf, (UV)SvUVX(sv)); else - PerlIO_printf(fp, "%"IVdf, (IV)SvIVX(sv)); + PerlIO_printf(fp, "%" IVdf, (IV)SvIVX(sv)); return !PerlIO_error(fp); } else { @@ -1292,7 +1435,6 @@ Perl_do_print(pTHX_ SV *sv, PerlIO *fp) I32 Perl_my_stat_flags(pTHX_ const U32 flags) { - dVAR; dSP; IO *io; GV* gv; @@ -1306,10 +1448,16 @@ Perl_my_stat_flags(pTHX_ const U32 flags) do_fstat_have_io: PL_laststype = OP_STAT; PL_statgv = gv ? gv : (GV *)io; - sv_setpvs(PL_statname, ""); - if(io) { + SvPVCLEAR(PL_statname); + if (io) { if (IoIFP(io)) { - return (PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache)); + int fd = PerlIO_fileno(IoIFP(io)); + if (fd < 0) { + /* E.g. PerlIO::scalar has no real fd. */ + return (PL_laststatval = -1); + } else { + return (PL_laststatval = PerlLIO_fstat(fd, &PL_statcache)); + } } else if (IoDIRP(io)) { return (PL_laststatval = PerlLIO_fstat(my_dirfd(IoDIRP(io)), &PL_statcache)); } @@ -1340,7 +1488,7 @@ Perl_my_stat_flags(pTHX_ const U32 flags) 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')) { + if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && should_warn_nl(s)) { GCC_DIAG_IGNORE(-Wformat-nonliteral); /* PL_warn_nl is constant */ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat"); GCC_DIAG_RESTORE; @@ -1353,7 +1501,6 @@ Perl_my_stat_flags(pTHX_ const U32 flags) I32 Perl_my_lstat_flags(pTHX_ const U32 flags) { - dVAR; static const char* const no_prev_lstat = "The stat preceding -l _ wasn't an lstat"; dSP; const char *file; @@ -1369,7 +1516,7 @@ Perl_my_lstat_flags(pTHX_ const U32 flags) if (ckWARN(WARN_IO)) { /* diag_listed_as: Use of -l on filehandle%s */ Perl_warner(aTHX_ packWARN(WARN_IO), - "Use of -l on filehandle %"HEKf, + "Use of -l on filehandle %" HEKf, HEKfARG(GvENAME_HEK(cGVOP_gv))); } return -1; @@ -1396,14 +1543,14 @@ Perl_my_lstat_flags(pTHX_ const U32 flags) else /* diag_listed_as: Use of -l on filehandle%s */ Perl_warner(aTHX_ packWARN(WARN_IO), - "Use of -l on filehandle %"HEKf, - GvENAME_HEK((const GV *) - (SvROK(sv) ? SvRV(sv) : sv))); + "Use of -l on filehandle %" HEKf, + HEKfARG(GvENAME_HEK((const GV *) + (SvROK(sv) ? SvRV(sv) : sv)))); } file = SvPV_flags_const_nolen(sv, flags); sv_setpv(PL_statname,file); PL_laststatval = PerlLIO_lstat(file,&PL_statcache); - if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(file, '\n')) { + if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && should_warn_nl(file)) { GCC_DIAG_IGNORE(-Wformat-nonliteral); /* PL_warn_nl is constant */ Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "lstat"); GCC_DIAG_RESTORE; @@ -1416,13 +1563,13 @@ S_exec_failed(pTHX_ const char *cmd, int fd, int do_report) { 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)); + Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s", + cmd, Strerror(e)); if (do_report) { - int rc = PerlLIO_write(fd, (void*)&e, sizeof(int)); - /* silently ignore failures */ - PERL_UNUSED_VAR(rc); + /* XXX silently ignore failures */ + PERL_UNUSED_RESULT(PerlLIO_write(fd, (void*)&e, sizeof(int))); PerlLIO_close(fd); } } @@ -1455,10 +1602,11 @@ Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp, (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 (really && *tmps) { + PerlProc_execvp(tmps,EXEC_ARGV_CAST(PL_Argv)); + } else { + PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv)); + } PERL_FPU_POST_EXEC S_exec_failed(aTHX_ (really ? tmps : PL_Argv[0]), fd, do_report); } @@ -1470,7 +1618,6 @@ Perl_do_aexec5(pTHX_ SV *really, SV **mark, SV **sp, void Perl_do_execfree(pTHX) { - dVAR; Safefree(PL_Argv); PL_Argv = NULL; Safefree(PL_Cmd); @@ -1505,7 +1652,7 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) { char flags[PERL_FLAGS_MAX]; if (strnEQ(cmd,PL_cshname,PL_cshlen) && - strnEQ(cmd+PL_cshlen," -c",3)) { + strEQs(cmd+PL_cshlen," -c")) { my_strlcpy(flags, "-c", PERL_FLAGS_MAX); s = cmd+PL_cshlen+3; if (*s == 'f') { @@ -1541,7 +1688,7 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) if (*cmd == '.' && isSPACE(cmd[1])) goto doshell; - if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4])) + if (strEQs(cmd,"exec") && isSPACE(cmd[4])) goto doshell; s = cmd; @@ -1573,7 +1720,7 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) } doshell: PERL_FPU_PRE_EXEC - PerlProc_execl(PL_sh_path, "sh", "-c", cmd, (char *)NULL); + 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); @@ -1597,7 +1744,7 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) *a = NULL; if (PL_Argv[0]) { PERL_FPU_PRE_EXEC - PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv)); + PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv)); PERL_FPU_POST_EXEC if (errno == ENOEXEC) { /* for system V NIH syndrome */ do_execfree(); @@ -1612,14 +1759,9 @@ Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report) #endif /* OS2 || WIN32 */ -#ifdef VMS -#include /* for sys$delprc */ -#endif - I32 Perl_apply(pTHX_ I32 type, SV **mark, SV **sp) { - dVAR; I32 val; I32 tot = 0; const char *const what = PL_op_name[type]; @@ -1672,14 +1814,19 @@ Perl_apply(pTHX_ I32 type, SV **mark, SV **sp) if ((gv = MAYBE_DEREF_GV(*mark))) { if (GvIO(gv) && IoIFP(GvIOp(gv))) { #ifdef HAS_FCHMOD + int fd = PerlIO_fileno(IoIFP(GvIOn(gv))); APPLY_TAINT_PROPER(); - if (fchmod(PerlIO_fileno(IoIFP(GvIOn(gv))), val)) - tot--; + if (fd < 0) { + SETERRNO(EBADF,RMS_IFI); + tot--; + } else if (fchmod(fd, val)) + tot--; #else Perl_die(aTHX_ PL_no_func, "fchmod"); #endif } else { + SETERRNO(EBADF,RMS_IFI); tot--; } } @@ -1708,14 +1855,19 @@ Perl_apply(pTHX_ I32 type, SV **mark, SV **sp) if ((gv = MAYBE_DEREF_GV(*mark))) { if (GvIO(gv) && IoIFP(GvIOp(gv))) { #ifdef HAS_FCHOWN + int fd = PerlIO_fileno(IoIFP(GvIOn(gv))); APPLY_TAINT_PROPER(); - if (fchown(PerlIO_fileno(IoIFP(GvIOn(gv))), val, val2)) + if (fd < 0) { + SETERRNO(EBADF,RMS_IFI); + tot--; + } else if (fchown(fd, val, val2)) tot--; #else Perl_die(aTHX_ PL_no_func, "fchown"); #endif } else { + SETERRNO(EBADF,RMS_IFI); tot--; } } @@ -1755,7 +1907,8 @@ nothing in the core. len -= 3; } if ((val = whichsig_pvn(s, len)) < 0) - Perl_croak(aTHX_ "Unrecognized signal name \"%"SVf"\"", SVfARG(*mark)); + Perl_croak(aTHX_ "Unrecognized signal name \"%" SVf "\"", + SVfARG(*mark)); } else { @@ -1768,40 +1921,7 @@ nothing in the core. } APPLY_TAINT_PROPER(); tot = sp - mark; -#ifdef VMS - /* kill() doesn't do process groups (job trees?) under VMS */ - if (val == SIGKILL) { - /* 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; - 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--; - switch (__vmssts) { - case SS$_NONEXPR: - case SS$_NOSUCHNODE: - SETERRNO(ESRCH,__vmssts); - break; - case SS$_NOPRIV: - SETERRNO(EPERM,__vmssts); - break; - default: - SETERRNO(EVMSERR,__vmssts); - } - } - } - PERL_ASYNC_CHECK(); - break; - } -#endif + while (++mark <= sp) { Pid_t proc; SvGETMAGIC(*mark); @@ -1833,18 +1953,47 @@ nothing in the core. } else if (PL_unsafe) { if (UNLINK(s)) + { tot--; + } +#if defined(__amigaos4__) && defined(NEWLIB) + else + { + /* Under AmigaOS4 unlink only 'fails' if the + * filename is invalid. It may not remove the file + * if it's locked, so check if it's still around. */ + if ((access(s,F_OK) != -1)) + { + tot--; + } + } +#endif } else { /* don't let root wipe out directories without -U */ - if (PerlLIO_lstat(s,&PL_statbuf) < 0) + Stat_t statbuf; + if (PerlLIO_lstat(s, &statbuf) < 0) tot--; - else if (S_ISDIR(PL_statbuf.st_mode)) { + else if (S_ISDIR(statbuf.st_mode)) { + SETERRNO(EISDIR, SS_NOPRIV); tot--; - SETERRNO(EISDIR, SS$_NOPRIV); } else { if (UNLINK(s)) - tot--; + { + tot--; + } +#if defined(__amigaos4__) && defined(NEWLIB) + else + { + /* Under AmigaOS4 unlink only 'fails' if the filename is invalid */ + /* It may not remove the file if it's Locked, so check if it's still */ + /* arround */ + if((access(s,F_OK) != -1)) + { + tot--; + } + } +#endif } } } @@ -1898,9 +2047,12 @@ nothing in the core. if ((gv = MAYBE_DEREF_GV(*mark))) { if (GvIO(gv) && IoIFP(GvIOp(gv))) { #ifdef HAS_FUTIMES + int fd = PerlIO_fileno(IoIFP(GvIOn(gv))); APPLY_TAINT_PROPER(); - if (futimes(PerlIO_fileno(IoIFP(GvIOn(gv))), - (struct timeval *) utbufp)) + if (fd < 0) { + SETERRNO(EBADF,RMS_IFI); + tot--; + } else if (futimes(fd, (struct timeval *) utbufp)) tot--; #else Perl_die(aTHX_ PL_no_func, "futimes"); @@ -1937,7 +2089,7 @@ nothing in the core. #undef APPLY_TAINT_PROPER } -/* Do the permissions allow some operation? Assumes statcache already set. */ +/* Do the permissions in *statbufp allow some operation? */ #ifndef VMS /* VMS' cando is in vms.c */ bool Perl_cando(pTHX_ Mode_t mode, bool effective, const Stat_t *statbufp) @@ -1945,9 +2097,8 @@ Perl_cando(pTHX_ Mode_t mode, bool effective, const Stat_t *statbufp) * is in the list of groups returned from getgroups(). */ { - dVAR; - PERL_ARGS_ASSERT_CANDO; + PERL_UNUSED_CONTEXT; #ifdef DOSISH /* [Comments and code from Len Reed] @@ -1971,7 +2122,7 @@ Perl_cando(pTHX_ Mode_t mode, bool effective, const Stat_t *statbufp) /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat * too so it will actually look into the files for magic numbers */ - return (mode & statbufp->st_mode) ? TRUE : FALSE; + return cBOOL(mode & statbufp->st_mode); #else /* ! DOSISH */ # ifdef __CYGWIN__ @@ -2005,7 +2156,10 @@ Perl_cando(pTHX_ Mode_t mode, bool effective, const Stat_t *statbufp) static bool S_ingroup(pTHX_ Gid_t testgid, bool effective) { - dVAR; +#ifndef PERL_IMPLICIT_SYS + /* PERL_IMPLICIT_SYS like Win32: getegid() etc. require the context. */ + PERL_UNUSED_CONTEXT; +#endif if (testgid == (effective ? PerlProc_getegid() : PerlProc_getgid())) return TRUE; #ifdef HAS_GETGROUPS @@ -2015,15 +2169,17 @@ S_ingroup(pTHX_ Gid_t testgid, bool effective) bool rc = FALSE; anum = getgroups(0, gary); - Newx(gary, anum, Groups_t); - anum = getgroups(anum, gary); - while (--anum >= 0) - if (gary[anum] == testgid) { - rc = TRUE; - break; - } + if (anum > 0) { + Newx(gary, anum, Groups_t); + anum = getgroups(anum, gary); + while (--anum >= 0) + if (gary[anum] == testgid) { + rc = TRUE; + break; + } - Safefree(gary); + Safefree(gary); + } return rc; } #else @@ -2036,7 +2192,6 @@ S_ingroup(pTHX_ Gid_t testgid, bool effective) I32 Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp) { - dVAR; const key_t key = (key_t)SvNVx(*++mark); SV *nsv = optype == OP_MSGGET ? NULL : *++mark; const I32 flags = SvIVx(*++mark); @@ -2071,7 +2226,6 @@ Perl_do_ipcget(pTHX_ I32 optype, SV **mark, SV **sp) I32 Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp) { - dVAR; char *a; I32 ret = -1; const I32 id = SvIVx(*++mark); @@ -2205,7 +2359,6 @@ Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp) I32 Perl_do_msgsnd(pTHX_ SV **mark, SV **sp) { - dVAR; #ifdef HAS_MSG STRLEN len; const I32 id = SvIVx(*++mark); @@ -2220,7 +2373,12 @@ Perl_do_msgsnd(pTHX_ SV **mark, SV **sp) if (msize < 0) Perl_croak(aTHX_ "Arg too short for msgsnd"); SETERRNO(0,0); - return msgsnd(id, (struct msgbuf *)mbuf, msize, flags); + if (id >= 0 && flags >= 0) { + return msgsnd(id, (struct msgbuf *)mbuf, msize, flags); + } else { + SETERRNO(EINVAL,LIB_INVARG); + return -1; + } #else PERL_UNUSED_ARG(sp); PERL_UNUSED_ARG(mark); @@ -2234,7 +2392,6 @@ I32 Perl_do_msgrcv(pTHX_ SV **mark, SV **sp) { #ifdef HAS_MSG - dVAR; char *mbuf; long mtype; I32 msize, flags, ret; @@ -2246,7 +2403,7 @@ Perl_do_msgrcv(pTHX_ SV **mark, SV **sp) /* suppress warning when reading into undef var --jhi */ if (! SvOK(mstr)) - sv_setpvs(mstr, ""); + SvPVCLEAR(mstr); msize = SvIVx(*++mark); mtype = (long)SvIVx(*++mark); flags = SvIVx(*++mark); @@ -2254,7 +2411,12 @@ Perl_do_msgrcv(pTHX_ SV **mark, SV **sp) mbuf = SvGROW(mstr, sizeof(long)+msize+1); SETERRNO(0,0); - ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags); + if (id >= 0 && msize >= 0 && flags >= 0) { + ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags); + } else { + SETERRNO(EINVAL,LIB_INVARG); + ret = -1; + } if (ret >= 0) { SvCUR_set(mstr, sizeof(long)+ret); *SvEND(mstr) = '\0'; @@ -2275,7 +2437,6 @@ I32 Perl_do_semop(pTHX_ SV **mark, SV **sp) { #ifdef HAS_SEM - dVAR; STRLEN opsize; const I32 id = SvIVx(*++mark); SV * const opstr = *++mark; @@ -2321,7 +2482,6 @@ I32 Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp) { #ifdef HAS_SHM - dVAR; char *shm; struct shmid_ds shmds; const I32 id = SvIVx(*++mark); @@ -2340,7 +2500,12 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp) SETERRNO(EFAULT,SS_ACCVIO); /* can't do as caller requested */ return -1; } - shm = (char *)shmat(id, NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0); + if (id >= 0) { + shm = (char *)shmat(id, NULL, (optype == OP_SHMREAD) ? SHM_RDONLY : 0); + } else { + SETERRNO(EINVAL,LIB_INVARG); + return -1; + } if (shm == (char *)-1) /* I hate System V IPC, I really do */ return -1; if (optype == OP_SHMREAD) { @@ -2349,7 +2514,7 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp) SvGETMAGIC(mstr); SvUPGRADE(mstr, SVt_PV); if (! SvOK(mstr)) - sv_setpvs(mstr, ""); + SvPVCLEAR(mstr); SvPOK_only(mstr); mbuf = SvGROW(mstr, (STRLEN)msize+1); @@ -2386,8 +2551,9 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp) Function called by C to spawn a glob (or do the glob inside perl on VMS). This code used to be inline, but now perl uses C -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. +this glob starter is only used by miniperl during the build process, +or when PERL_EXTERNAL_GLOB is defined. +Moving it away shrinks F; shrinking F helps speed perl up. =cut */ @@ -2395,7 +2561,6 @@ Moving it away shrinks pp_hot.c; shrinking pp_hot.c helps speed perl up. PerlIO * Perl_start_glob (pTHX_ SV *tmpglob, IO *io) { - dVAR; SV * const tmpcmd = newSV(0); PerlIO *fp; STRLEN len; @@ -2447,17 +2612,14 @@ Perl_vms_start_glob #endif /* !CSH */ #endif /* !DOSISH */ { - GV * const envgv = gv_fetchpvs("ENV", 0, SVt_PVHV); - SV ** const home = hv_fetchs(GvHV(envgv), "HOME", 0); - SV ** const path = hv_fetchs(GvHV(envgv), "PATH", 0); - if (home && *home) SvGETMAGIC(*home); - if (path && *path) SvGETMAGIC(*path); - save_hash(gv_fetchpvs("ENV", 0, SVt_PVHV)); - if (home && *home) SvSETMAGIC(*home); - if (path && *path) SvSETMAGIC(*path); + SV ** const svp = hv_fetchs(GvHVn(PL_envgv), "LS_COLORS", 0); + if (svp && *svp) + save_helem_flags(GvHV(PL_envgv), + newSVpvs_flags("LS_COLORS", SVs_TEMP), svp, + SAVEf_SETMAGIC); } - (void)do_open(PL_last_in_gv, (char*)SvPVX_const(tmpcmd), SvCUR(tmpcmd), - FALSE, O_RDONLY, 0, NULL); + (void)do_open6(PL_last_in_gv, SvPVX_const(tmpcmd), SvCUR(tmpcmd), + NULL, NULL, 0); fp = IoIFP(io); #endif /* !VMS */ LEAVE; @@ -2471,11 +2633,5 @@ Perl_vms_start_glob } /* - * Local variables: - * c-indentation-style: bsd - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - * * ex: set ts=8 sts=4 sw=4 et: */