X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/a9a28921a06508e1ec8a1da7fdf58c72faa64c96..658b4a4a328256e2a80066c57ca7866646757dad:/pp_sys.c diff --git a/pp_sys.c b/pp_sys.c index c1ff341..4e2b412 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -1,7 +1,7 @@ /* pp_sys.c * * Copyright (C) 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, 2005, 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. @@ -15,6 +15,15 @@ * a rumour and a trouble as of great engines throbbing and labouring. */ +/* This file contains system pp ("push/pop") functions that + * execute the opcodes that make up a perl program. A typical pp function + * expects to find its arguments on the stack, and usually pushes its + * results onto the stack, hence the 'pp' terminology. Each OP structure + * contains a pointer to the relevant pp_foo() function. + * + * By 'system', we mean ops which interact with the OS, such as pp_open(). + */ + #include "EXTERN.h" #define PERL_IN_PP_SYS_C #include "perl.h" @@ -36,12 +45,6 @@ # include #endif -#ifdef HAS_SYSCALL -#ifdef __cplusplus -extern "C" int syscall(unsigned long,...); -#endif -#endif - #ifdef I_SYS_WAIT # include #endif @@ -116,6 +119,12 @@ extern int h_errno; # undef my_chsize # endif # define my_chsize PerlLIO_chsize +#else +# ifdef HAS_TRUNCATE +# define my_chsize PerlLIO_chsize +# else +I32 my_chsize(int fd, Off_t length); +# endif #endif #ifdef HAS_FLOCK @@ -164,7 +173,7 @@ extern int h_errno; #endif /* no flock() */ #define ZBTLEN 10 -static char zero_but_true[ZBTLEN + 1] = "0 but true"; +static const char zero_but_true[ZBTLEN + 1] = "0 but true"; #if defined(I_SYS_ACCESS) && !defined(R_OK) # include @@ -176,6 +185,18 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true"; #include "reentr.h" +#ifdef __Lynx__ +/* Missing protos on LynxOS */ +void sethostent(int); +void endhostent(void); +void setnetent(int); +void endnetent(void); +void setprotoent(int); +void endprotoent(void); +void setservent(int); +void endservent(void); +#endif + #undef PERL_EFF_ACCESS_R_OK /* EFFective uid/gid ACCESS R_OK */ #undef PERL_EFF_ACCESS_W_OK #undef PERL_EFF_ACCESS_X_OK @@ -288,6 +309,8 @@ S_emulate_eaccess(pTHX_ const char* path, Mode_t mode) STATIC int S_emulate_eaccess(pTHX_ const char* path, Mode_t mode) { + (void)path; + (void)mode; Perl_croak(aTHX_ "switching effective uid is not implemented"); /*NOTREACHED*/ return -1; @@ -298,21 +321,20 @@ PP(pp_backtick) { dSP; dTARGET; PerlIO *fp; - STRLEN n_a; - char *tmps = POPpx; - I32 gimme = GIMME_V; - char *mode = "r"; + const char *tmps = POPpconstx; + const I32 gimme = GIMME_V; + const char *mode = "r"; TAINT_PROPER("``"); if (PL_op->op_private & OPpOPEN_IN_RAW) mode = "rb"; else if (PL_op->op_private & OPpOPEN_IN_CRLF) mode = "rt"; - fp = PerlProc_popen(tmps, mode); + fp = PerlProc_popen((char*)tmps, (char *)mode); if (fp) { - char *type = NULL; + const char *type = NULL; if (PL_curcop->cop_io) { - type = SvPV_nolen(PL_curcop->cop_io); + type = SvPV_nolen_const(PL_curcop->cop_io); } if (type && *type) PerlIO_apply_layers(aTHX_ fp,mode,type); @@ -324,13 +346,14 @@ PP(pp_backtick) ; } else if (gimme == G_SCALAR) { - SV *oldrs = PL_rs; + ENTER; + SAVESPTR(PL_rs); PL_rs = &PL_sv_undef; - sv_setpv(TARG, ""); /* note that this preserves previous buffer */ + sv_setpvn(TARG, "", 0); /* note that this preserves previous buffer */ while (sv_gets(TARG, fp, SvCUR(TARG)) != Nullch) /*SUPPRESS 530*/ ; - PL_rs = oldrs; + LEAVE; XPUSHs(TARG); SvTAINTED_on(TARG); } @@ -345,8 +368,7 @@ PP(pp_backtick) } XPUSHs(sv_2mortal(sv)); if (SvLEN(sv) - SvCUR(sv) > 20) { - SvLEN_set(sv, SvCUR(sv)+1); - Renew(SvPVX(sv), SvLEN(sv), char); + SvPV_shrink_to_cur(sv); } SvTAINTED_on(sv); } @@ -365,6 +387,7 @@ PP(pp_backtick) PP(pp_glob) { + dVAR; OP *result; tryAMAGICunTARGET(iter, -1); @@ -411,7 +434,7 @@ PP(pp_warn) { dSP; dMARK; SV *tmpsv; - char *tmps; + const char *tmps; STRLEN len; if (SP - MARK != 1) { dTARGET; @@ -422,14 +445,14 @@ PP(pp_warn) else { tmpsv = TOPs; } - tmps = SvPV(tmpsv, len); + tmps = SvPV_const(tmpsv, len); if ((!tmps || !len) && PL_errgv) { SV *error = ERRSV; - (void)SvUPGRADE(error, SVt_PV); + SvUPGRADE(error, SVt_PV); if (SvPOK(error) && SvCUR(error)) sv_catpv(error, "\t...caught"); tmpsv = error; - tmps = SvPV(tmpsv, len); + tmps = SvPV_const(tmpsv, len); } if (!tmps || !len) tmpsv = sv_2mortal(newSVpvn("Warning: something's wrong", 26)); @@ -441,7 +464,7 @@ PP(pp_warn) PP(pp_die) { dSP; dMARK; - char *tmps; + const char *tmps; SV *tmpsv; STRLEN len; bool multiarg = 0; @@ -452,17 +475,17 @@ PP(pp_die) dTARGET; do_join(TARG, &PL_sv_no, MARK, SP); tmpsv = TARG; - tmps = SvPV(tmpsv, len); + tmps = SvPV_const(tmpsv, len); multiarg = 1; SP = MARK + 1; } else { tmpsv = TOPs; - tmps = SvROK(tmpsv) ? Nullch : SvPV(tmpsv, len); + tmps = SvROK(tmpsv) ? Nullch : SvPV_const(tmpsv, len); } if (!tmps || !len) { SV *error = ERRSV; - (void)SvUPGRADE(error, SVt_PV); + SvUPGRADE(error, SVt_PV); if (multiarg ? SvROK(error) : SvROK(tmpsv)) { if (!multiarg) SvSetSV(error,tmpsv); @@ -483,13 +506,13 @@ PP(pp_die) sv_setsv(error,*PL_stack_sp--); } } - DIE(aTHX_ Nullformat); + DIE_NULL; } else { if (SvPOK(error) && SvCUR(error)) sv_catpv(error, "\t...propagated"); tmpsv = error; - tmps = SvPV(tmpsv, len); + tmps = SvPV_const(tmpsv, len); } } if (!tmps || !len) @@ -502,13 +525,13 @@ PP(pp_die) PP(pp_open) { - dSP; + dVAR; dSP; dMARK; dORIGMARK; dTARGET; GV *gv; SV *sv; IO *io; - char *tmps; + const char *tmps; STRLEN len; MAGIC *mg; bool ok; @@ -539,8 +562,8 @@ PP(pp_open) sv = GvSV(gv); } - tmps = SvPV(sv, len); - ok = do_openn(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp, MARK+1, (SP-MARK)); + tmps = SvPV_const(sv, len); + ok = do_openn(gv, (char *)tmps, len, FALSE, O_RDONLY, 0, Nullfp, MARK+1, (SP-MARK)); SP = ORIGMARK; if (ok) PUSHi( (I32)PL_forkprocess ); @@ -553,7 +576,7 @@ PP(pp_open) PP(pp_close) { - dSP; + dVAR; dSP; GV *gv; IO *io; MAGIC *mg; @@ -609,8 +632,8 @@ PP(pp_pipe_op) if (PerlProc_pipe(fd) < 0) goto badexit; - IoIFP(rstio) = PerlIO_fdopen(fd[0], "r"PIPESOCK_MODE); - IoOFP(wstio) = PerlIO_fdopen(fd[1], "w"PIPESOCK_MODE); + IoIFP(rstio) = PerlIO_fdopen(fd[0], "r"PIPE_OPEN_MODE); + IoOFP(wstio) = PerlIO_fdopen(fd[1], "w"PIPE_OPEN_MODE); IoOFP(rstio) = IoIFP(rstio); IoIFP(wstio) = IoOFP(wstio); IoTYPE(rstio) = IoTYPE_RDONLY; @@ -638,7 +661,7 @@ badexit: PP(pp_fileno) { - dSP; dTARGET; + dVAR; dSP; dTARGET; GV *gv; IO *io; PerlIO *fp; @@ -676,8 +699,9 @@ PP(pp_fileno) PP(pp_umask) { - dSP; dTARGET; + dSP; #ifdef HAS_UMASK + dTARGET; Mode_t anum; if (MAXARG < 1) { @@ -689,7 +713,7 @@ PP(pp_umask) TAINT_PROPER("umask"); XPUSHi(anum); #else - /* Only DIE if trying to restrict permissions on `user' (self). + /* Only DIE if trying to restrict permissions on "user" (self). * Otherwise it's harmless and more useful to just return undef * since 'group' and 'other' concepts probably don't exist here. */ if (MAXARG >= 1 && (POPi & 0700)) @@ -701,7 +725,7 @@ PP(pp_umask) PP(pp_binmode) { - dSP; + dVAR; dSP; GV *gv; IO *io; PerlIO *fp; @@ -741,7 +765,15 @@ PP(pp_binmode) PUTBACK; if (PerlIO_binmode(aTHX_ fp,IoTYPE(io),mode_from_discipline(discp), - (discp) ? SvPV_nolen(discp) : Nullch)) { + (discp) ? SvPV_nolen_const(discp) : Nullch)) { + if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { + if (!PerlIO_binmode(aTHX_ IoOFP(io),IoTYPE(io), + mode_from_discipline(discp), + (discp) ? SvPV_nolen_const(discp) : Nullch)) { + SPAGAIN; + RETPUSHUNDEF; + } + } SPAGAIN; RETPUSHYES; } @@ -753,14 +785,13 @@ PP(pp_binmode) PP(pp_tie) { - dSP; - dMARK; + dVAR; dSP; dMARK; SV *varsv; HV* stash; GV *gv; SV *sv; - I32 markoff = MARK - PL_stack_base; - char *methname; + const I32 markoff = MARK - PL_stack_base; + const char *methname; int how = PERL_MAGIC_tied; U32 items; @@ -768,7 +799,7 @@ PP(pp_tie) switch(SvTYPE(varsv)) { case SVt_PVHV: methname = "TIEHASH"; - HvEITER((HV *)varsv) = Null(HE *); + HvEITER_set((HV *)varsv, 0); break; case SVt_PVAV: methname = "TIEARRAY"; @@ -843,17 +874,17 @@ PP(pp_tie) PP(pp_untie) { - dSP; + dVAR; dSP; MAGIC *mg; SV *sv = POPs; - char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) + const char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) ? PERL_MAGIC_tied : PERL_MAGIC_tiedscalar; if (SvTYPE(sv) == SVt_PVGV && !(sv = (SV *)GvIOp(sv))) RETPUSHYES; if ((mg = SvTIED_mg(sv, how))) { - SV *obj = SvRV(mg->mg_obj); + SV *obj = SvRV(SvTIED_obj(sv, mg)); GV *gv; CV *cv = NULL; if (obj) { @@ -875,8 +906,8 @@ PP(pp_untie) (UV)SvREFCNT(obj) - 1 ) ; } } - sv_unmagic(sv, how) ; } + sv_unmagic(sv, how) ; RETPUSHYES; } @@ -885,7 +916,7 @@ PP(pp_tied) dSP; MAGIC *mg; SV *sv = POPs; - char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) + const char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV) ? PERL_MAGIC_tied : PERL_MAGIC_tiedscalar; if (SvTYPE(sv) == SVt_PVGV && !(sv = (SV *)GvIOp(sv))) @@ -903,7 +934,7 @@ PP(pp_tied) PP(pp_dbmopen) { - dSP; + dVAR; dSP; HV *hv; dPOPPOPssrl; HV* stash; @@ -978,7 +1009,6 @@ PP(pp_sselect) struct timeval *tbuf = &timebuf; I32 growsize; char *fd_sets[4]; - STRLEN n_a; #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 I32 masksize; I32 offset; @@ -994,9 +1024,16 @@ PP(pp_sselect) SP -= 4; for (i = 1; i <= 3; i++) { - if (!SvPOK(SP[i])) + SV *sv = SP[i]; + if (SvOK(sv) && SvREADONLY(sv)) { + if (SvIsCOW(sv)) + sv_force_normal_flags(sv, 0); + if (SvREADONLY(sv)) + DIE(aTHX_ PL_no_modify); + } + if (!SvPOK(sv)) continue; - j = SvCUR(SP[i]); + j = SvCUR(sv); if (maxlen < j) maxlen = j; } @@ -1016,15 +1053,19 @@ PP(pp_sselect) Zero(&fd_sets[0], 4, char*); #endif -# if SELECT_MIN_BITS > 1 +# if SELECT_MIN_BITS == 1 + growsize = sizeof(fd_set); +# else +# if defined(__GLIBC__) && defined(__FD_SETSIZE) +# undef SELECT_MIN_BITS +# define SELECT_MIN_BITS __FD_SETSIZE +# endif /* If SELECT_MIN_BITS is greater than one we most probably will want * to align the sizes with SELECT_MIN_BITS/8 because for example * in many little-endian (Intel, Alpha) systems (Linux, OS/2, Digital * UNIX, Solaris, NeXT, Darwin) the smallest quantum select() operates * on (sets/tests/clears bits) is 32 bits. */ growsize = maxlen + (SELECT_MIN_BITS/8 - (maxlen % (SELECT_MIN_BITS/8))); -# else - growsize = sizeof(fd_set); # endif sv = SP[4]; @@ -1046,7 +1087,7 @@ PP(pp_sselect) continue; } else if (!SvPOK(sv)) - SvPV_force(sv,n_a); /* force string conversion */ + SvPV_force_nolen(sv); /* force string conversion */ j = SvLEN(sv); if (j < growsize) { Sv_Grow(sv, growsize); @@ -1101,7 +1142,10 @@ PP(pp_sselect) } } - PUSHi(nfound); + if (nfound == -1) + PUSHs(&PL_sv_undef); + else + PUSHi(nfound); if (GIMME == G_ARRAY && tbuf) { value = (NV)(timebuf.tv_sec) + (NV)(timebuf.tv_usec) / 1000000.0; @@ -1127,10 +1171,10 @@ Perl_setdefout(pTHX_ GV *gv) PP(pp_select) { dSP; dTARGET; - GV *newdefout, *egv; + GV *egv; HV *hv; - newdefout = (PL_op->op_private > 0) ? ((GV *) POPs) : (GV *) NULL; + GV * const newdefout = (PL_op->op_private > 0) ? ((GV *) POPs) : (GV *) NULL; egv = GvEGV(PL_defoutgv); if (!egv) @@ -1160,7 +1204,7 @@ PP(pp_select) PP(pp_getc) { - dSP; dTARGET; + dVAR; dSP; dTARGET; GV *gv; IO *io = NULL; MAGIC *mg; @@ -1173,7 +1217,7 @@ PP(pp_getc) if (gv && (io = GvIO(gv)) && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) { - I32 gimme = GIMME_V; + const I32 gimme = GIMME_V; PUSHMARK(SP); XPUSHs(SvTIED_obj((SV*)io, mg)); PUTBACK; @@ -1193,11 +1237,11 @@ PP(pp_getc) RETPUSHUNDEF; } TAINT; - sv_setpv(TARG, " "); + sv_setpvn(TARG, " ", 1); *SvPVX(TARG) = PerlIO_getc(IoIFP(GvIOp(gv))); /* should never be EOF */ if (PerlIO_isutf8(IoIFP(GvIOp(gv)))) { /* Find out how many bytes the char needs */ - Size_t len = UTF8SKIP(SvPVX(TARG)); + Size_t len = UTF8SKIP(SvPVX_const(TARG)); if (len > 1) { SvGROW(TARG,len+1); len = PerlIO_read(IoIFP(GvIOp(gv)),SvPVX(TARG)+1,len-1); @@ -1217,15 +1261,16 @@ PP(pp_read) STATIC OP * S_doform(pTHX_ CV *cv, GV *gv, OP *retop) { + dVAR; register PERL_CONTEXT *cx; - I32 gimme = GIMME_V; + const I32 gimme = GIMME_V; ENTER; SAVETMPS; - push_return(retop); PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp); PUSHFORMAT(cx); + cx->blk_sub.retop = retop; PAD_SET_CUR(CvPADLIST(cv), 1); setdefout(gv); /* locally select filehandle so $% et al work */ @@ -1259,14 +1304,14 @@ PP(pp_enterwrite) cv = GvFORM(fgv); if (!cv) { - char *name = NULL; if (fgv) { - SV *tmpsv = sv_newmortal(); + SV * const tmpsv = sv_newmortal(); + const char *name; gv_efullname4(tmpsv, fgv, Nullch, FALSE); - name = SvPV_nolen(tmpsv); + name = SvPV_nolen_const(tmpsv); + if (name && *name) + DIE(aTHX_ "Undefined format \"%s\" called", name); } - if (name && *name) - DIE(aTHX_ "Undefined format \"%s\" called", name); DIE(aTHX_ "Not a format reference"); } if (CvCLONE(cv)) @@ -1278,7 +1323,7 @@ PP(pp_enterwrite) PP(pp_leavewrite) { - dSP; + dVAR; dSP; GV *gv = cxstack[cxstack_ix].blk_sub.gv; register IO *io = GvIOp(gv); PerlIO *ofp = IoOFP(io); @@ -1303,24 +1348,24 @@ PP(pp_leavewrite) if (!IoTOP_NAME(io)) { if (!IoFMT_NAME(io)) IoFMT_NAME(io) = savepv(GvNAME(gv)); - topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%s_TOP", IoFMT_NAME(io))); - topgv = gv_fetchpv(SvPVX(topname), FALSE, SVt_PVFM); + topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%s_TOP", GvNAME(gv))); + topgv = gv_fetchsv(topname, FALSE, SVt_PVFM); if ((topgv && GvFORM(topgv)) || !gv_fetchpv("top",FALSE,SVt_PVFM)) - IoTOP_NAME(io) = savepv(SvPVX(topname)); + IoTOP_NAME(io) = savesvpv(topname); else - IoTOP_NAME(io) = savepv("top"); + IoTOP_NAME(io) = savepvn("top", 3); } topgv = gv_fetchpv(IoTOP_NAME(io),FALSE, SVt_PVFM); if (!topgv || !GvFORM(topgv)) { - IoLINES_LEFT(io) = 100000000; + IoLINES_LEFT(io) = IoPAGE_LEN(io); goto forget_top; } IoTOP_GV(io) = topgv; } if (IoFLAGS(io) & IOf_DIDTOP) { /* Oh dear. It still doesn't fit. */ I32 lines = IoLINES_LEFT(io); - char *s = SvPVX(PL_formtarget); + const char *s = SvPVX_const(PL_formtarget); if (lines <= 0) /* Yow, header didn't even fit!!! */ goto forget_top; while (lines-- > 0) { @@ -1330,8 +1375,8 @@ PP(pp_leavewrite) s++; } if (s) { - STRLEN save = SvCUR(PL_formtarget); - SvCUR_set(PL_formtarget, s - SvPVX(PL_formtarget)); + const STRLEN save = SvCUR(PL_formtarget); + SvCUR_set(PL_formtarget, s - SvPVX_const(PL_formtarget)); do_print(PL_formtarget, ofp); SvCUR_set(PL_formtarget, save); sv_chop(PL_formtarget, s); @@ -1348,20 +1393,18 @@ PP(pp_leavewrite) if (!fgv) DIE(aTHX_ "bad top format reference"); cv = GvFORM(fgv); - { - char *name = NULL; - if (!cv) { - SV *sv = sv_newmortal(); - gv_efullname4(sv, fgv, Nullch, FALSE); - name = SvPV_nolen(sv); - } + if (!cv) { + SV * const sv = sv_newmortal(); + const char *name; + gv_efullname4(sv, fgv, Nullch, FALSE); + name = SvPV_nolen_const(sv); if (name && *name) - DIE(aTHX_ "Undefined top format \"%s\" called",name); - /* why no: - else - DIE(aTHX_ "Undefined top format called"); - ?*/ + DIE(aTHX_ "Undefined top format \"%s\" called",name); } + /* why no: + else + DIE(aTHX_ "Undefined top format called"); + ?*/ if (CvCLONE(cv)) cv = (CV*)sv_2mortal((SV*)cv_clone(cv)); return doform(cv,gv,PL_op); @@ -1401,12 +1444,12 @@ PP(pp_leavewrite) /* bad_ofp: */ PL_formtarget = PL_bodytarget; PUTBACK; - return pop_return(); + return cx->blk_sub.retop; } PP(pp_prtf) { - dSP; dMARK; dORIGMARK; + dVAR; dSP; dMARK; dORIGMARK; GV *gv; IO *io; PerlIO *fp; @@ -1483,22 +1526,19 @@ PP(pp_sysopen) dSP; GV *gv; SV *sv; - char *tmps; + const char *tmps; STRLEN len; - int mode, perm; + const int perm = (MAXARG > 3) ? POPi : 0666; + const int mode = POPi; - if (MAXARG > 3) - perm = POPi; - else - perm = 0666; - mode = POPi; sv = POPs; gv = (GV *)POPs; /* Need TIEHANDLE method ? */ - tmps = SvPV(sv, len); - if (do_open(gv, tmps, len, TRUE, mode, perm, Nullfp)) { + tmps = SvPV_const(sv, len); + /* FIXME? do_open should do const */ + if (do_open(gv, (char*)tmps, len, TRUE, mode, perm, Nullfp)) { IoLINES(GvIOp(gv)) = 0; PUSHs(&PL_sv_yes); } @@ -1510,7 +1550,7 @@ PP(pp_sysopen) PP(pp_sysread) { - dSP; dMARK; dORIGMARK; dTARGET; + dVAR; dSP; dMARK; dORIGMARK; dTARGET; int offset; GV *gv; IO *io; @@ -1522,12 +1562,13 @@ PP(pp_sysread) STRLEN blen; MAGIC *mg; int fp_utf8; + int buffer_utf8; + SV *read_target; Size_t got = 0; Size_t wanted; bool charstart = FALSE; STRLEN charskip = 0; STRLEN skip = 0; - PerlIO *pio; gv = (GV*)*++MARK; if ((PL_op->op_type == OP_READ || PL_op->op_type == OP_SYSREAD) @@ -1566,25 +1607,15 @@ PP(pp_sysread) SETERRNO(EBADF,RMS_IFI); goto say_undef; } - pio = IoIFP(io); -#ifdef PERLIO_LAYERS - if (PL_op->op_type == OP_SYSREAD) { - /* sysread happens further down the stack - and we need isutf8 of that layer - */ - pio = PerlIO_syslayer(aTHX_ pio); - if (!pio) { - goto say_undef; - } - } -#endif - if ((fp_utf8 = PerlIO_isutf8(pio)) && !IN_BYTES) { + if ((fp_utf8 = PerlIO_isutf8(IoIFP(io))) && !IN_BYTES) { buffer = SvPVutf8_force(bufsv, blen); - /* UTF8 may not have been set if they are all low bytes */ + /* UTF-8 may not have been set if they are all low bytes */ SvUTF8_on(bufsv); + buffer_utf8 = 0; } else { buffer = SvPV_force(bufsv, blen); + buffer_utf8 = !IN_BYTES && SvUTF8(bufsv); } if (length < 0) DIE(aTHX_ "Negative length"); @@ -1608,7 +1639,7 @@ PP(pp_sysread) #endif buffer = SvGROW(bufsv, (STRLEN)(length+1)); /* 'offset' means 'flags' here */ - count = PerlSock_recvfrom(PerlIO_fileno(pio), buffer, length, offset, + count = PerlSock_recvfrom(PerlIO_fileno(IoIFP(io)), buffer, length, offset, (struct sockaddr *)namebuf, &bufsize); if (count < 0) RETPUSHUNDEF; @@ -1645,32 +1676,52 @@ PP(pp_sysread) } if (DO_UTF8(bufsv)) { /* convert offset-as-chars to offset-as-bytes */ - offset = utf8_hop((U8 *)buffer,offset) - (U8 *) buffer; + if (offset >= (int)blen) + offset += SvCUR(bufsv) - blen; + else + offset = utf8_hop((U8 *)buffer,offset) - (U8 *) buffer; } more_bytes: bufsize = SvCUR(bufsv); + /* Allocating length + offset + 1 isn't perfect in the case of reading + bytes from a byte file handle into a UTF8 buffer, but it won't harm us + unduly. + (should be 2 * length + offset + 1, or possibly something longer if + PL_encoding is true) */ buffer = SvGROW(bufsv, (STRLEN)(length+offset+1)); - if (offset > bufsize) { /* Zero any newly allocated space */ + if (offset > 0 && (Sock_size_t)offset > bufsize) { /* Zero any newly allocated space */ Zero(buffer+bufsize, offset-bufsize, char); } buffer = buffer + offset; + if (!buffer_utf8) { + read_target = bufsv; + } else { + /* Best to read the bytes into a new SV, upgrade that to UTF8, then + concatenate it to the current buffer. */ + + /* Truncate the existing buffer to the start of where we will be + reading to: */ + SvCUR_set(bufsv, offset); + + read_target = sv_newmortal(); + SvUPGRADE(read_target, SVt_PV); + buffer = SvGROW(read_target, (STRLEN)(length + 1)); + } -#ifndef PERLIO_LAYERS if (PL_op->op_type == OP_SYSREAD) { #ifdef PERL_SOCK_SYSREAD_IS_RECV if (IoTYPE(io) == IoTYPE_SOCKET) { - count = PerlSock_recv(PerlIO_fileno(pio), + count = PerlSock_recv(PerlIO_fileno(IoIFP(io)), buffer, length, 0); } else #endif { - count = PerlLIO_read(PerlIO_fileno(pio), + count = PerlLIO_read(PerlIO_fileno(IoIFP(io)), buffer, length); } } else -#endif #ifdef HAS_SOCKET__bad_code_maybe if (IoTYPE(io) == IoTYPE_SOCKET) { char namebuf[MAXPATHLEN]; @@ -1679,15 +1730,15 @@ PP(pp_sysread) #else bufsize = sizeof namebuf; #endif - count = PerlSock_recvfrom(PerlIO_fileno(pio), buffer, length, 0, + count = PerlSock_recvfrom(PerlIO_fileno(IoIFP(io)), buffer, length, 0, (struct sockaddr *)namebuf, &bufsize); } else #endif { - count = PerlIO_read(pio, buffer, length); + count = PerlIO_read(IoIFP(io), buffer, length); /* PerlIO_read() - like fread() returns 0 on both error and EOF */ - if (count == 0 && PerlIO_error(pio)) + if (count == 0 && PerlIO_error(IoIFP(io))) count = -1; } if (count < 0) { @@ -1695,12 +1746,12 @@ PP(pp_sysread) report_evil_fh(gv, io, OP_phoney_OUTPUT_ONLY); goto say_undef; } - SvCUR_set(bufsv, count+(buffer - SvPVX(bufsv))); - *SvEND(bufsv) = '\0'; - (void)SvPOK_only(bufsv); + SvCUR_set(read_target, count+(buffer - SvPVX_const(read_target))); + *SvEND(read_target) = '\0'; + (void)SvPOK_only(read_target); if (fp_utf8 && !IN_BYTES) { /* Look at utf8 we got back and count the characters */ - char *bend = buffer + count; + const char *bend = buffer + count; while (buffer < bend) { if (charstart) { skip = UTF8SKIP(buffer); @@ -1709,7 +1760,7 @@ PP(pp_sysread) if (buffer - charskip + skip > bend) { /* partial character - try for rest of it */ length = skip - (bend-buffer); - offset = bend - SvPVX(bufsv); + offset = bend - SvPVX_const(bufsv); charstart = FALSE; charskip += count; goto more_bytes; @@ -1726,13 +1777,18 @@ PP(pp_sysread) */ if (got < wanted && count == length) { length = wanted - got; - offset = bend - SvPVX(bufsv); + offset = bend - SvPVX_const(bufsv); goto more_bytes; } /* return value is character count */ count = got; SvUTF8_on(bufsv); } + else if (buffer_utf8) { + /* Let svcatsv upgrade the bytes we read in to utf8. + The buffer is a mortal so will be freed soon. */ + sv_catsv_nomg(bufsv, read_target); + } SvSETMAGIC(bufsv); /* This should not be marked tainted if the fp is marked clean */ if (!(IoFLAGS(io) & IOf_UNTAINT)) @@ -1748,8 +1804,8 @@ PP(pp_sysread) PP(pp_syswrite) { - dSP; - int items = (SP - PL_stack_base) - TOPMARK; + dVAR; dSP; + const int items = (SP - PL_stack_base) - TOPMARK; if (items == 2) { SV *sv; EXTEND(SP, 1); @@ -1762,11 +1818,11 @@ PP(pp_syswrite) PP(pp_send) { - dSP; dMARK; dORIGMARK; dTARGET; + dVAR; dSP; dMARK; dORIGMARK; dTARGET; GV *gv; IO *io; SV *bufsv; - char *buffer; + const char *buffer; Size_t length; SSize_t retval; STRLEN blen; @@ -1811,12 +1867,19 @@ PP(pp_send) } if (PerlIO_isutf8(IoIFP(io))) { - buffer = SvPVutf8(bufsv, blen); + if (!SvUTF8(bufsv)) { + bufsv = sv_2mortal(newSVsv(bufsv)); + buffer = sv_2pvutf8(bufsv, &blen); + } else + buffer = SvPV_const(bufsv, blen); } else { - if (DO_UTF8(bufsv)) - sv_utf8_downgrade(bufsv, FALSE); - buffer = SvPV(bufsv, blen); + if (DO_UTF8(bufsv)) { + /* Not modifying source SV, so making a temporary copy. */ + bufsv = sv_2mortal(newSVsv(bufsv)); + sv_utf8_downgrade(bufsv, FALSE); + } + buffer = SvPV_const(bufsv, blen); } if (PL_op->op_type == OP_SYSWRITE) { @@ -1838,7 +1901,7 @@ PP(pp_send) if (length > blen - offset) length = blen - offset; if (DO_UTF8(bufsv)) { - buffer = (char*)utf8_hop((U8 *)buffer, offset); + buffer = (const char*)utf8_hop((const U8 *)buffer, offset); length = utf8_hop((U8 *)buffer, length) - (U8 *)buffer; } else { @@ -1859,9 +1922,8 @@ PP(pp_send) } #ifdef HAS_SOCKET else if (SP > MARK) { - char *sockbuf; STRLEN mlen; - sockbuf = SvPVx(*++MARK, mlen); + char * const sockbuf = SvPVx(*++MARK, mlen); /* length is really flags */ retval = PerlSock_sendto(PerlIO_fileno(IoIFP(io)), buffer, blen, length, (struct sockaddr *)sockbuf, mlen); @@ -1897,7 +1959,7 @@ PP(pp_recv) PP(pp_eof) { - dSP; + dVAR; dSP; GV *gv; IO *io; MAGIC *mg; @@ -1911,7 +1973,7 @@ PP(pp_eof) if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) { IoLINES(io) = 0; IoFLAGS(io) &= ~IOf_START; - do_open(gv, "-", 1, FALSE, O_RDONLY, 0, Nullfp); + do_open(gv, (char *)"-", 1, FALSE, O_RDONLY, 0, Nullfp); sv_setpvn(GvSV(gv), "-", 1); SvSETMAGIC(GvSV(gv)); } @@ -1944,7 +2006,7 @@ PP(pp_eof) PP(pp_tell) { - dSP; dTARGET; + dVAR; dSP; dTARGET; GV *gv; IO *io; MAGIC *mg; @@ -1982,10 +2044,10 @@ PP(pp_seek) PP(pp_sysseek) { - dSP; + dVAR; dSP; GV *gv; IO *io; - int whence = POPi; + const int whence = POPi; #if LSEEKSIZE > IVSIZE Off_t offset = (Off_t)SvNVx(POPs); #else @@ -2053,15 +2115,13 @@ PP(pp_truncate) * might not be signed: if it is not, clever compilers will moan. */ /* XXX Configure probe for the signedness of the length type of *truncate() needed? XXX */ SETERRNO(0,0); -#if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) || defined(F_FREESP) { - STRLEN n_a; int result = 1; GV *tmpgv; IO *io; if (PL_op->op_flags & OPf_SPECIAL) { - tmpgv = gv_fetchpv(POPpx, FALSE, SVt_PVIO); + tmpgv = gv_fetchsv(POPs, FALSE, SVt_PVIO); do_ftruncate_gv: if (!GvIO(tmpgv)) @@ -2087,8 +2147,8 @@ PP(pp_truncate) } else { SV *sv = POPs; - char *name; - + const char *name; + if (SvTYPE(sv) == SVt_PVGV) { tmpgv = (GV*)sv; /* *main::FRED for example */ goto do_ftruncate_gv; @@ -2102,7 +2162,7 @@ PP(pp_truncate) goto do_ftruncate_io; } - name = SvPV(sv, n_a); + name = SvPV_nolen_const(sv); TAINT_PROPER("truncate"); #ifdef HAS_TRUNCATE if (truncate(name, len) < 0) @@ -2128,9 +2188,6 @@ PP(pp_truncate) SETERRNO(EBADF,RMS_IFI); RETPUSHUNDEF; } -#else - DIE(aTHX_ "truncate not implemented"); -#endif } PP(pp_fcntl) @@ -2142,8 +2199,8 @@ PP(pp_ioctl) { dSP; dTARGET; SV *argsv = POPs; - unsigned int func = POPu; - int optype = PL_op->op_type; + const unsigned int func = POPu; + const int optype = PL_op->op_type; char *s; IV retval; GV *gv = (GV*)POPs; @@ -2283,8 +2340,8 @@ PP(pp_socket) fd = PerlSock_socket(domain, type, protocol); if (fd < 0) RETPUSHUNDEF; - IoIFP(io) = PerlIO_fdopen(fd, "r"PIPESOCK_MODE); /* stdio gets confused about sockets */ - IoOFP(io) = PerlIO_fdopen(fd, "w"PIPESOCK_MODE); + IoIFP(io) = PerlIO_fdopen(fd, "r"SOCKET_OPEN_MODE); /* stdio gets confused about sockets */ + IoOFP(io) = PerlIO_fdopen(fd, "w"SOCKET_OPEN_MODE); IoTYPE(io) = IoTYPE_SOCKET; if (!IoIFP(io) || !IoOFP(io)) { if (IoIFP(io)) PerlIO_close(IoIFP(io)); @@ -2345,11 +2402,11 @@ PP(pp_sockpair) TAINT_PROPER("socketpair"); if (PerlSock_socketpair(domain, type, protocol, fd) < 0) RETPUSHUNDEF; - IoIFP(io1) = PerlIO_fdopen(fd[0], "r"PIPESOCK_MODE); - IoOFP(io1) = PerlIO_fdopen(fd[0], "w"PIPESOCK_MODE); + IoIFP(io1) = PerlIO_fdopen(fd[0], "r"SOCKET_OPEN_MODE); + IoOFP(io1) = PerlIO_fdopen(fd[0], "w"SOCKET_OPEN_MODE); IoTYPE(io1) = IoTYPE_SOCKET; - IoIFP(io2) = PerlIO_fdopen(fd[1], "r"PIPESOCK_MODE); - IoOFP(io2) = PerlIO_fdopen(fd[1], "w"PIPESOCK_MODE); + IoIFP(io2) = PerlIO_fdopen(fd[1], "r"SOCKET_OPEN_MODE); + IoOFP(io2) = PerlIO_fdopen(fd[1], "w"SOCKET_OPEN_MODE); IoTYPE(io2) = IoTYPE_SOCKET; if (!IoIFP(io1) || !IoOFP(io1) || !IoIFP(io2) || !IoOFP(io2)) { if (IoIFP(io1)) PerlIO_close(IoIFP(io1)); @@ -2380,7 +2437,8 @@ PP(pp_bind) extern void GETUSERMODE(); #endif SV *addrsv = POPs; - char *addr; + /* OK, so on what platform does bind modify addr? */ + const char *addr; GV *gv = (GV*)POPs; register IO *io = GvIOn(gv); STRLEN len; @@ -2392,7 +2450,7 @@ PP(pp_bind) if (!io || !IoIFP(io)) goto nuts; - addr = SvPV(addrsv, len); + addr = SvPV_const(addrsv, len); TAINT_PROPER("bind"); #ifdef MPE /* Deal with MPE bind() peculiarities */ if (((struct sockaddr *)addr)->sa_family == AF_INET) { @@ -2435,7 +2493,7 @@ PP(pp_connect) #ifdef HAS_SOCKET dSP; SV *addrsv = POPs; - char *addr; + const char *addr; GV *gv = (GV*)POPs; register IO *io = GvIOn(gv); STRLEN len; @@ -2443,7 +2501,7 @@ PP(pp_connect) if (!io || !IoIFP(io)) goto nuts; - addr = SvPV(addrsv, len); + addr = SvPV_const(addrsv, len); TAINT_PROPER("connect"); if (PerlSock_connect(PerlIO_fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0) RETPUSHYES; @@ -2494,8 +2552,12 @@ PP(pp_accept) GV *ggv; register IO *nstio; register IO *gstio; - struct sockaddr saddr; /* use a struct to avoid alignment problems */ - Sock_size_t len = sizeof saddr; + char namebuf[MAXPATHLEN]; +#if (defined(VMS_DO_SOCKETS) && defined(DECCRTL_SOCKETS)) || defined(MPE) || defined(__QNXNTO__) + Sock_size_t len = sizeof (struct sockaddr_in); +#else + Sock_size_t len = sizeof namebuf; +#endif int fd; ggv = (GV*)POPs; @@ -2511,13 +2573,13 @@ PP(pp_accept) goto nuts; nstio = GvIOn(ngv); - fd = PerlSock_accept(PerlIO_fileno(IoIFP(gstio)), (struct sockaddr *)&saddr, &len); + fd = PerlSock_accept(PerlIO_fileno(IoIFP(gstio)), (struct sockaddr *) namebuf, &len); if (fd < 0) goto badexit; if (IoIFP(nstio)) do_close(ngv, FALSE); - IoIFP(nstio) = PerlIO_fdopen(fd, "r"PIPESOCK_MODE); - IoOFP(nstio) = PerlIO_fdopen(fd, "w"PIPESOCK_MODE); + IoIFP(nstio) = PerlIO_fdopen(fd, "r"SOCKET_OPEN_MODE); + IoOFP(nstio) = PerlIO_fdopen(fd, "w"SOCKET_OPEN_MODE); IoTYPE(nstio) = IoTYPE_SOCKET; if (!IoIFP(nstio) || !IoOFP(nstio)) { if (IoIFP(nstio)) PerlIO_close(IoIFP(nstio)); @@ -2530,14 +2592,14 @@ PP(pp_accept) #endif #ifdef EPOC - len = sizeof saddr; /* EPOC somehow truncates info */ + len = sizeof (struct sockaddr_in); /* EPOC somehow truncates info */ setbuf( IoIFP(nstio), NULL); /* EPOC gets confused about sockets */ #endif #ifdef __SCO_VERSION__ - len = sizeof saddr; /* OpenUNIX 8 somehow truncates info */ + len = sizeof (struct sockaddr_in); /* OpenUNIX 8 somehow truncates info */ #endif - PUSHp((char *)&saddr, len); + PUSHp(namebuf, len); RETURN; nuts: @@ -2626,16 +2688,16 @@ PP(pp_ssockopt) PUSHs(sv); break; case OP_SSOCKOPT: { - char *buf; + const char *buf; int aint; if (SvPOKp(sv)) { STRLEN l; - buf = SvPV(sv, l); + buf = SvPV_const(sv, l); len = l; } else { aint = (int)SvIV(sv); - buf = (char*)&aint; + buf = (const char*)&aint; len = sizeof(int); } if (PerlSock_setsockopt(fd, lvl, optname, buf, len) < 0) @@ -2699,8 +2761,8 @@ PP(pp_getpeername) { static const char nowhere[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; /* If the call succeeded, make sure we don't have a zeroed port/addr */ - if (((struct sockaddr *)SvPVX(sv))->sa_family == AF_INET && - !memcmp((char *)SvPVX(sv) + sizeof(u_short), nowhere, + if (((struct sockaddr *)SvPVX_const(sv))->sa_family == AF_INET && + !memcmp((char *)SvPVX_const(sv) + sizeof(u_short), nowhere, sizeof(u_short) + sizeof(struct in_addr))) { goto nuts2; } @@ -2744,7 +2806,6 @@ PP(pp_stat) GV *gv; I32 gimme; I32 max = 13; - STRLEN n_a; if (PL_op->op_flags & OPf_REF) { gv = cGVOP_gv; @@ -2761,7 +2822,7 @@ PP(pp_stat) if (gv != PL_defgv) { PL_laststype = OP_STAT; PL_statgv = gv; - sv_setpv(PL_statname, ""); + sv_setpvn(PL_statname, "", 0); PL_laststatval = (GvIO(gv) && IoIFP(GvIOp(gv)) ? PerlLIO_fstat(PerlIO_fileno(IoIFP(GvIOn(gv))), &PL_statcache) : -1); } @@ -2784,17 +2845,15 @@ PP(pp_stat) "lstat() on filehandle %s", GvENAME(gv)); goto do_fstat; } - sv_setpv(PL_statname, SvPV(sv,n_a)); + sv_setpv(PL_statname, SvPV_nolen_const(sv)); PL_statgv = Nullgv; -#ifdef HAS_LSTAT PL_laststype = PL_op->op_type; if (PL_op->op_type == OP_LSTAT) - PL_laststatval = PerlLIO_lstat(SvPV(PL_statname, n_a), &PL_statcache); + PL_laststatval = PerlLIO_lstat(SvPV_nolen_const(PL_statname), &PL_statcache); else -#endif - PL_laststatval = PerlLIO_stat(SvPV(PL_statname, n_a), &PL_statcache); + PL_laststatval = PerlLIO_stat(SvPV_nolen_const(PL_statname), &PL_statcache); if (PL_laststatval < 0) { - if (ckWARN(WARN_NEWLINE) && strchr(SvPV(PL_statname, n_a), '\n')) + if (ckWARN(WARN_NEWLINE) && strchr(SvPV_nolen_const(PL_statname), '\n')) Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat"); max = 0; } @@ -2861,12 +2920,21 @@ PP(pp_stat) RETURN; } +/* This macro is used by the stacked filetest operators : + * if the previous filetest failed, short-circuit and pass its value. + * Else, discard it from the stack and continue. --rgs + */ +#define STACKED_FTEST_CHECK if (PL_op->op_private & OPpFT_STACKED) { \ + if (TOPs == &PL_sv_no || TOPs == &PL_sv_undef) { RETURN; } \ + else { (void)POPs; PUTBACK; } \ + } + PP(pp_ftrread) { I32 result; dSP; + STACKED_FTEST_CHECK; #if defined(HAS_ACCESS) && defined(R_OK) - STRLEN n_a; if ((PL_op->op_private & OPpFT_ACCESS) && SvPOK(TOPs)) { result = access(POPpx, R_OK); if (result == 0) @@ -2892,8 +2960,8 @@ PP(pp_ftrwrite) { I32 result; dSP; + STACKED_FTEST_CHECK; #if defined(HAS_ACCESS) && defined(W_OK) - STRLEN n_a; if ((PL_op->op_private & OPpFT_ACCESS) && SvPOK(TOPs)) { result = access(POPpx, W_OK); if (result == 0) @@ -2919,8 +2987,8 @@ PP(pp_ftrexec) { I32 result; dSP; + STACKED_FTEST_CHECK; #if defined(HAS_ACCESS) && defined(X_OK) - STRLEN n_a; if ((PL_op->op_private & OPpFT_ACCESS) && SvPOK(TOPs)) { result = access(POPpx, X_OK); if (result == 0) @@ -2946,8 +3014,8 @@ PP(pp_fteread) { I32 result; dSP; + STACKED_FTEST_CHECK; #ifdef PERL_EFF_ACCESS_R_OK - STRLEN n_a; if ((PL_op->op_private & OPpFT_ACCESS) && SvPOK(TOPs)) { result = PERL_EFF_ACCESS_R_OK(POPpx); if (result == 0) @@ -2973,8 +3041,8 @@ PP(pp_ftewrite) { I32 result; dSP; + STACKED_FTEST_CHECK; #ifdef PERL_EFF_ACCESS_W_OK - STRLEN n_a; if ((PL_op->op_private & OPpFT_ACCESS) && SvPOK(TOPs)) { result = PERL_EFF_ACCESS_W_OK(POPpx); if (result == 0) @@ -3000,8 +3068,8 @@ PP(pp_fteexec) { I32 result; dSP; + STACKED_FTEST_CHECK; #ifdef PERL_EFF_ACCESS_X_OK - STRLEN n_a; if ((PL_op->op_private & OPpFT_ACCESS) && SvPOK(TOPs)) { result = PERL_EFF_ACCESS_X_OK(POPpx); if (result == 0) @@ -3025,8 +3093,11 @@ PP(pp_fteexec) PP(pp_ftis) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; RETPUSHYES; @@ -3039,8 +3110,11 @@ PP(pp_fteowned) PP(pp_ftrowned) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (PL_statcache.st_uid == (PL_op->op_type == OP_FTEOWNED ? @@ -3051,8 +3125,11 @@ PP(pp_ftrowned) PP(pp_ftzero) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (PL_statcache.st_size == 0) @@ -3062,8 +3139,11 @@ PP(pp_ftzero) PP(pp_ftsize) { - I32 result = my_stat(); + I32 result; dSP; dTARGET; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; #if Off_t_size > IVSIZE @@ -3076,38 +3156,50 @@ PP(pp_ftsize) PP(pp_ftmtime) { - I32 result = my_stat(); + I32 result; dSP; dTARGET; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; - PUSHn( (PL_basetime - PL_statcache.st_mtime) / 86400.0 ); + PUSHn( (((NV)PL_basetime - PL_statcache.st_mtime)) / 86400.0 ); RETURN; } PP(pp_ftatime) { - I32 result = my_stat(); + I32 result; dSP; dTARGET; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; - PUSHn( (PL_basetime - PL_statcache.st_atime) / 86400.0 ); + PUSHn( (((NV)PL_basetime - PL_statcache.st_atime)) / 86400.0 ); RETURN; } PP(pp_ftctime) { - I32 result = my_stat(); + I32 result; dSP; dTARGET; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; - PUSHn( (PL_basetime - PL_statcache.st_ctime) / 86400.0 ); + PUSHn( (((NV)PL_basetime - PL_statcache.st_ctime)) / 86400.0 ); RETURN; } PP(pp_ftsock) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (S_ISSOCK(PL_statcache.st_mode)) @@ -3117,8 +3209,11 @@ PP(pp_ftsock) PP(pp_ftchr) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (S_ISCHR(PL_statcache.st_mode)) @@ -3128,8 +3223,11 @@ PP(pp_ftchr) PP(pp_ftblk) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (S_ISBLK(PL_statcache.st_mode)) @@ -3139,8 +3237,11 @@ PP(pp_ftblk) PP(pp_ftfile) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (S_ISREG(PL_statcache.st_mode)) @@ -3150,8 +3251,11 @@ PP(pp_ftfile) PP(pp_ftdir) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (S_ISDIR(PL_statcache.st_mode)) @@ -3161,8 +3265,11 @@ PP(pp_ftdir) PP(pp_ftpipe) { - I32 result = my_stat(); + I32 result; dSP; + STACKED_FTEST_CHECK; + result = my_stat(); + SPAGAIN; if (result < 0) RETPUSHUNDEF; if (S_ISFIFO(PL_statcache.st_mode)) @@ -3185,7 +3292,9 @@ PP(pp_ftsuid) { dSP; #ifdef S_ISUID - I32 result = my_stat(); + I32 result; + STACKED_FTEST_CHECK; + result = my_stat(); SPAGAIN; if (result < 0) RETPUSHUNDEF; @@ -3199,7 +3308,9 @@ PP(pp_ftsgid) { dSP; #ifdef S_ISGID - I32 result = my_stat(); + I32 result; + STACKED_FTEST_CHECK; + result = my_stat(); SPAGAIN; if (result < 0) RETPUSHUNDEF; @@ -3213,7 +3324,9 @@ PP(pp_ftsvtx) { dSP; #ifdef S_ISVTX - I32 result = my_stat(); + I32 result; + STACKED_FTEST_CHECK; + result = my_stat(); SPAGAIN; if (result < 0) RETPUSHUNDEF; @@ -3228,8 +3341,9 @@ PP(pp_fttty) dSP; int fd; GV *gv; - char *tmps = Nullch; - STRLEN n_a; + SV *tmpsv = Nullsv; + + STACKED_FTEST_CHECK; if (PL_op->op_flags & OPf_REF) gv = cGVOP_gv; @@ -3238,12 +3352,17 @@ PP(pp_fttty) else if (SvROK(TOPs) && isGV(SvRV(TOPs))) gv = (GV*)SvRV(POPs); else - gv = gv_fetchpv(tmps = POPpx, FALSE, SVt_PVIO); + gv = gv_fetchsv(tmpsv = POPs, FALSE, SVt_PVIO); if (GvIO(gv) && IoIFP(GvIOp(gv))) fd = PerlIO_fileno(IoIFP(GvIOp(gv))); - else if (tmps && isDIGIT(*tmps)) - fd = atoi(tmps); + else if (tmpsv && SvOK(tmpsv)) { + const char *tmps = SvPV_nolen_const(tmpsv); + if (isDIGIT(*tmps)) + fd = atoi(tmps); + else + RETPUSHUNDEF; + } else RETPUSHUNDEF; if (PerlLIO_isatty(fd)) @@ -3270,9 +3389,10 @@ PP(pp_fttext) register IO *io; register SV *sv; GV *gv; - STRLEN n_a; PerlIO *fp; + STACKED_FTEST_CHECK; + if (PL_op->op_flags & OPf_REF) gv = cGVOP_gv; else if (isGV(TOPs)) @@ -3295,7 +3415,7 @@ PP(pp_fttext) else { PL_statgv = gv; PL_laststatval = -1; - sv_setpv(PL_statname, ""); + sv_setpvn(PL_statname, "", 0); io = GvIO(PL_statgv); } if (io && IoIFP(io)) { @@ -3336,11 +3456,11 @@ PP(pp_fttext) sv = POPs; really_filename: PL_statgv = Nullgv; - PL_laststatval = -1; PL_laststype = OP_STAT; - sv_setpv(PL_statname, SvPV(sv, n_a)); - if (!(fp = PerlIO_open(SvPVX(PL_statname), "r"))) { - if (ckWARN(WARN_NEWLINE) && strchr(SvPV(sv, n_a), '\n')) + sv_setpv(PL_statname, SvPV_nolen_const(sv)); + if (!(fp = PerlIO_open(SvPVX_const(PL_statname), "r"))) { + if (ckWARN(WARN_NEWLINE) && strchr(SvPV_nolen_const(PL_statname), + '\n')) Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open"); RETPUSHUNDEF; } @@ -3424,12 +3544,11 @@ PP(pp_ftbinary) PP(pp_chdir) { dSP; dTARGET; - char *tmps; + const char *tmps; SV **svp; - STRLEN n_a; if( MAXARG == 1 ) - tmps = POPpx; + tmps = POPpconstx; else tmps = 0; @@ -3443,7 +3562,7 @@ PP(pp_chdir) { if( MAXARG == 1 ) deprecate("chdir('') or chdir(undef) as chdir()"); - tmps = SvPV(*svp, n_a); + tmps = SvPV_nolen_const(*svp); } else { PUSHi(0); @@ -3480,7 +3599,6 @@ PP(pp_chroot) { #ifdef HAS_CHROOT dSP; dTARGET; - STRLEN n_a; char *tmps = POPpx; TAINT_PROPER("chroot"); PUSHi( chroot(tmps) >= 0 ); @@ -3524,10 +3642,8 @@ PP(pp_rename) { dSP; dTARGET; int anum; - STRLEN n_a; - - char *tmps2 = POPpx; - char *tmps = SvPV(TOPs, n_a); + const char *tmps2 = POPpconstx; + const char *tmps = SvPV_nolen_const(TOPs); TAINT_PROPER("rename"); #ifdef HAS_RENAME anum = PerlLIO_rename(tmps, tmps2); @@ -3551,9 +3667,8 @@ PP(pp_link) { #ifdef HAS_LINK dSP; dTARGET; - STRLEN n_a; - char *tmps2 = POPpx; - char *tmps = SvPV(TOPs, n_a); + const char *tmps2 = POPpconstx; + const char *tmps = SvPV_nolen_const(TOPs); TAINT_PROPER("link"); SETi( PerlLIO_link(tmps, tmps2) >= 0 ); RETURN; @@ -3566,9 +3681,8 @@ PP(pp_symlink) { #ifdef HAS_SYMLINK dSP; dTARGET; - STRLEN n_a; - char *tmps2 = POPpx; - char *tmps = SvPV(TOPs, n_a); + const char *tmps2 = POPpconstx; + const char *tmps = SvPV_nolen_const(TOPs); TAINT_PROPER("symlink"); SETi( symlink(tmps, tmps2) >= 0 ); RETURN; @@ -3582,15 +3696,14 @@ PP(pp_readlink) dSP; #ifdef HAS_SYMLINK dTARGET; - char *tmps; + const char *tmps; char buf[MAXPATHLEN]; int len; - STRLEN n_a; #ifndef INCOMPLETE_TAINTS TAINT; #endif - tmps = POPpx; + tmps = POPpconstx; len = readlink(tmps, buf, sizeof(buf) - 1); EXTEND(SP, 1); if (len < 0) @@ -3605,9 +3718,9 @@ PP(pp_readlink) #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR) STATIC int -S_dooneliner(pTHX_ char *cmd, char *filename) +S_dooneliner(pTHX_ const char *cmd, const char *filename) { - char *save_filename = filename; + char * const save_filename = filename; char *cmdline; char *s; PerlIO *myfp; @@ -3701,7 +3814,7 @@ S_dooneliner(pTHX_ char *cmd, char *filename) * -d, chdir(), chmod(), chown(), chroot(), fcntl()?, * (mkdir()), opendir(), rename(), rmdir(), stat(). --jhi */ -#define TRIMSLASHES(tmps,len,copy) (tmps) = SvPV(TOPs, (len)); \ +#define TRIMSLASHES(tmps,len,copy) (tmps) = SvPV_const(TOPs, (len)); \ if ((len) > 1 && (tmps)[(len)-1] == '/') { \ do { \ (len)--; \ @@ -3718,7 +3831,7 @@ PP(pp_mkdir) int oldumask; #endif STRLEN len; - char *tmps; + const char *tmps; bool copy = FALSE; if (MAXARG > 1) @@ -3746,7 +3859,7 @@ PP(pp_rmdir) { dSP; dTARGET; STRLEN len; - char *tmps; + const char *tmps; bool copy = FALSE; TRIMSLASHES(tmps,len,copy); @@ -3767,8 +3880,7 @@ PP(pp_open_dir) { #if defined(Direntry_t) && defined(HAS_READDIR) dSP; - STRLEN n_a; - char *dirname = POPpx; + const char *dirname = POPpconstx; GV *gv = (GV*)POPs; register IO *io = GvIOn(gv); @@ -3792,48 +3904,43 @@ nope: PP(pp_readdir) { -#if defined(Direntry_t) && defined(HAS_READDIR) - dSP; +#if !defined(Direntry_t) || !defined(HAS_READDIR) + DIE(aTHX_ PL_no_dir_func, "readdir"); +#else #if !defined(I_DIRENT) && !defined(VMS) Direntry_t *readdir (DIR *); #endif + dSP; + + SV *sv; + const I32 gimme = GIMME; + GV *gv = (GV *)POPs; register Direntry_t *dp; - GV *gv = (GV*)POPs; register IO *io = GvIOn(gv); - SV *sv; if (!io || !IoDIRP(io)) goto nope; - if (GIMME == G_ARRAY) { - /*SUPPRESS 560*/ - while ((dp = (Direntry_t *)PerlDir_read(IoDIRP(io)))) { -#ifdef DIRNAMLEN - sv = newSVpvn(dp->d_name, dp->d_namlen); -#else - sv = newSVpv(dp->d_name, 0); -#endif -#ifndef INCOMPLETE_TAINTS - if (!(IoFLAGS(io) & IOf_UNTAINT)) - SvTAINTED_on(sv); -#endif - XPUSHs(sv_2mortal(sv)); - } - } - else { - if (!(dp = (Direntry_t *)PerlDir_read(IoDIRP(io)))) - goto nope; + do { + dp = (Direntry_t *)PerlDir_read(IoDIRP(io)); + if (!dp) + break; #ifdef DIRNAMLEN - sv = newSVpvn(dp->d_name, dp->d_namlen); + sv = newSVpvn(dp->d_name, dp->d_namlen); #else - sv = newSVpv(dp->d_name, 0); + sv = newSVpv(dp->d_name, 0); #endif #ifndef INCOMPLETE_TAINTS - if (!(IoFLAGS(io) & IOf_UNTAINT)) - SvTAINTED_on(sv); + if (!(IoFLAGS(io) & IOf_UNTAINT)) + SvTAINTED_on(sv); #endif - XPUSHs(sv_2mortal(sv)); + XPUSHs(sv_2mortal(sv)); } + while (gimme == G_ARRAY); + + if (!dp && gimme != G_ARRAY) + goto nope; + RETURN; nope: @@ -3843,15 +3950,13 @@ nope: RETURN; else RETPUSHUNDEF; -#else - DIE(aTHX_ PL_no_dir_func, "readdir"); #endif } PP(pp_telldir) { #if defined(HAS_TELLDIR) || defined(telldir) - dSP; dTARGET; + dVAR; dSP; dTARGET; /* XXX does _anyone_ need this? --AD 2/20/1998 */ /* XXX netbsd still seemed to. XXX HAS_TELLDIR_PROTO is new style, NEED_TELLDIR_PROTO is old style. @@ -4028,27 +4133,28 @@ PP(pp_waitpid) { #if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL) dSP; dTARGET; - Pid_t childpid; + Pid_t pid; + Pid_t result; int optype; int argflags; optype = POPi; - childpid = TOPi; + pid = TOPi; if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) - childpid = wait4pid(childpid, &argflags, optype); + result = wait4pid(pid, &argflags, optype); else { - while ((childpid = wait4pid(childpid, &argflags, optype)) == -1 && + while ((result = wait4pid(pid, &argflags, optype)) == -1 && errno == EINTR) { PERL_ASYNC_CHECK(); } } # if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS) /* 0 and -1 are both error returns (the former applies to WNOHANG case) */ - STATUS_NATIVE_SET((childpid && childpid != -1) ? argflags : -1); + STATUS_NATIVE_SET((result && result != -1) ? argflags : -1); # else - STATUS_NATIVE_SET((childpid > 0) ? argflags : -1); + STATUS_NATIVE_SET((result > 0) ? argflags : -1); # endif - SETi(childpid); + SETi(result); RETURN; #else DIE(aTHX_ PL_no_func, "waitpid"); @@ -4059,14 +4165,12 @@ PP(pp_system) { dSP; dMARK; dORIGMARK; dTARGET; I32 value; - STRLEN n_a; int result; - I32 did_pipes = 0; if (PL_tainting) { TAINT_ENV(); while (++MARK <= SP) { - (void)SvPV_nolen(*MARK); /* stringify for taint check */ + (void)SvPV_nolen_const(*MARK); /* stringify for taint check */ if (PL_tainted) break; } @@ -4078,6 +4182,7 @@ PP(pp_system) { Pid_t childpid; int pp[2]; + I32 did_pipes = 0; if (PerlProc_pipe(pp) >= 0) did_pipes = 1; @@ -4150,7 +4255,7 @@ PP(pp_system) else if (SP - MARK != 1) value = (I32)do_aexec5(Nullsv, MARK, SP, pp[1], did_pipes); else { - value = (I32)do_exec3(SvPVx(sv_mortalcopy(*SP), n_a), pp[1], did_pipes); + value = (I32)do_exec3(SvPVx_nolen(sv_mortalcopy(*SP)), pp[1], did_pipes); } PerlProc__exit(-1); } @@ -4159,21 +4264,21 @@ PP(pp_system) result = 0; if (PL_op->op_flags & OPf_STACKED) { SV *really = *++MARK; -# ifdef WIN32 +# if defined(WIN32) || defined(OS2) || defined(SYMBIAN) value = (I32)do_aspawn(really, MARK, SP); # else value = (I32)do_aspawn(really, (void **)MARK, (void **)SP); # endif } else if (SP - MARK != 1) { -# ifdef WIN32 +# if defined(WIN32) || defined(OS2) || defined(SYMBIAN) value = (I32)do_aspawn(Nullsv, MARK, SP); # else value = (I32)do_aspawn(Nullsv, (void **)MARK, (void **)SP); # endif } else { - value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), n_a)); + value = (I32)do_spawn(SvPVx_nolen(sv_mortalcopy(*SP))); } if (PL_statusvalue == -1) /* hint that value must be returned as is */ result = 1; @@ -4189,12 +4294,11 @@ PP(pp_exec) { dSP; dMARK; dORIGMARK; dTARGET; I32 value; - STRLEN n_a; if (PL_tainting) { TAINT_ENV(); while (++MARK <= SP) { - (void)SvPV_nolen(*MARK); /* stringify for taint check */ + (void)SvPV_nolen_const(*MARK); /* stringify for taint check */ if (PL_tainted) break; } @@ -4221,13 +4325,13 @@ PP(pp_exec) #endif else { #ifdef VMS - value = (I32)vms_do_exec(SvPVx(sv_mortalcopy(*SP), n_a)); + value = (I32)vms_do_exec(SvPVx_nolen(sv_mortalcopy(*SP))); #else # ifdef __OPEN_VM - (void) do_spawn(SvPVx(sv_mortalcopy(*SP), n_a)); + (void) do_spawn(SvPVx_nolen(sv_mortalcopy(*SP))); value = 0; # else - value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), n_a)); + value = (I32)do_exec(SvPVx_nolen(sv_mortalcopy(*SP))); # endif #endif } @@ -4256,6 +4360,9 @@ PP(pp_getppid) #ifdef HAS_GETPPID dSP; dTARGET; # ifdef THREADS_HAVE_PIDS + if (PL_ppid != 1 && getppid() == 1) + /* maybe the parent process has died. Refresh ppid cache */ + PL_ppid = 1; XPUSHi( PL_ppid ); # else XPUSHi( getppid() ); @@ -4385,7 +4492,19 @@ PP(pp_tms) } RETURN; #else +# ifdef PERL_MICRO + dSP; + PUSHs(sv_2mortal(newSVnv((NV)0.0))); + EXTEND(SP, 4); + if (GIMME == G_ARRAY) { + PUSHs(sv_2mortal(newSVnv((NV)0.0))); + PUSHs(sv_2mortal(newSVnv((NV)0.0))); + PUSHs(sv_2mortal(newSVnv((NV)0.0))); + } + RETURN; +# else DIE(aTHX_ "times not implemented"); +# endif #endif /* HAS_TIMES */ } @@ -4398,10 +4517,12 @@ PP(pp_gmtime) { dSP; Time_t when; - struct tm *tmbuf; - static char *dayname[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - static char *monname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + const struct tm *tmbuf; + static const char * const dayname[] = + {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + static const char * const monname[] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; if (MAXARG < 1) (void)time(&when); @@ -4637,7 +4758,6 @@ PP(pp_ghostent) #endif struct hostent *hent; unsigned long len; - STRLEN n_a; EXTEND(SP, 10); if (which == OP_GHBYNAME) { @@ -4753,7 +4873,6 @@ PP(pp_gnetent) struct netent *getnetent(void); #endif struct netent *nent; - STRLEN n_a; if (which == OP_GNBYNAME){ #ifdef HAS_GETNETBYNAME @@ -4854,7 +4973,6 @@ PP(pp_gprotoent) struct protoent *getprotoent(void); #endif struct protoent *pent; - STRLEN n_a; if (which == OP_GPBYNAME) { #ifdef HAS_GETPROTOBYNAME @@ -4941,7 +5059,6 @@ PP(pp_gservent) struct servent *getservent(void); #endif struct servent *sent; - STRLEN n_a; if (which == OP_GSBYNAME) { #ifdef HAS_GETSERVBYNAME @@ -5137,7 +5254,6 @@ PP(pp_gpwent) dSP; I32 which = PL_op->op_type; register SV *sv; - STRLEN n_a; struct passwd *pwent = NULL; /* * We currently support only the SysV getsp* shadow password interface. @@ -5149,7 +5265,7 @@ PP(pp_gpwent) * AIX getpwnam() is clever enough to return the encrypted password * only if the caller (euid?) is root. * - * There are at least two other shadow password APIs. Many platforms + * There are at least three other shadow password APIs. Many platforms * seem to contain more than one interface for accessing the shadow * password databases, possibly for compatibility reasons. * The getsp*() is by far he simplest one, the other two interfaces @@ -5171,6 +5287,12 @@ PP(pp_gpwent) * char *(getespw*(...).ufld.fd_encrypt) * Mention HAS_GETESPWNAM here so that Configure probes for it. * + * (AIX) + * struct userpw *getuserpw(); + * The password is in + * char *(getuserpw(...)).spw_upw_passwd + * (but the de facto standard getpwnam() should work okay) + * * Mention I_PROT here so that Configure probes for it. * * In HP-UX for getprpw*() the manual page claims that one should include @@ -5193,6 +5315,12 @@ PP(pp_gpwent) * --jhi */ +# if defined(__CYGWIN__) && defined(USE_REENTRANT_API) + /* Cygwin 1.5.3-1 has buggy getpwnam_r() and getpwuid_r(): + * the pw_comment is left uninitialized. */ + PL_reentrant_buffer->_pwent_struct.pw_comment = NULL; +# endif + switch (which) { case OP_GPWNAM: { @@ -5256,7 +5384,9 @@ PP(pp_gpwent) * Divert the urge to writing an extension instead. * * --jhi */ -# ifdef HAS_GETSPNAM + /* Some AIX setups falsely(?) detect some getspnam(), which + * has a different API than the Solaris/IRIX one. */ +# if defined(HAS_GETSPNAM) && !defined(_AIX) { struct spwd *spwent; int saverrno; /* Save and restore errno so that @@ -5402,7 +5532,6 @@ PP(pp_ggrent) register char **elem; register SV *sv; struct group *grent; - STRLEN n_a; if (which == OP_GGRNAM) { char* name = POPpbytex; @@ -5514,7 +5643,6 @@ PP(pp_syscall) unsigned long a[20]; register I32 i = 0; I32 retval = -1; - STRLEN n_a; if (PL_tainting) { while (++MARK <= SP) { @@ -5537,7 +5665,7 @@ PP(pp_syscall) else if (*MARK == &PL_sv_undef) a[i++] = 0; else - a[i++] = (unsigned long)SvPV_force(*MARK, n_a); + a[i++] = (unsigned long)SvPV_force_nolen(*MARK); if (i > 15) break; } @@ -5720,3 +5848,13 @@ lockf_emulate_flock(int fd, int operation) } #endif /* LOCKF_EMULATE_FLOCK */ + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + * + * ex: set ts=8 sts=4 sw=4 noet: + */