X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=doio.c;h=ceb83214f34efb111e016780233fc495dcfd72b0;hb=5a49ee455a6d068697635b12375f31af98486866;hp=d818185c4882e46c47180b018d1bf98e3c5114e2;hpb=c890dc6c586a442573099f83869005d8d2629877;p=p5sagit%2Fp5-mst-13.2.git diff --git a/doio.c b/doio.c index d818185..ceb8321 100644 --- a/doio.c +++ b/doio.c @@ -93,12 +93,22 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, int fd; int result; bool was_fdopen = FALSE; + bool in_raw = 0, in_crlf = 0, out_raw = 0, out_crlf = 0; PL_forkprocess = 1; /* assume true if no fork */ + if (PL_op && PL_op->op_type == OP_OPEN) { + /* set up disciplines */ + U8 flags = PL_op->op_private; + in_raw = (flags & OPpOPEN_IN_RAW); + in_crlf = (flags & OPpOPEN_IN_CRLF); + out_raw = (flags & OPpOPEN_OUT_RAW); + out_crlf = (flags & OPpOPEN_OUT_CRLF); + } + if (IoIFP(io)) { fd = PerlIO_fileno(IoIFP(io)); - if (IoTYPE(io) == '-') + if (IoTYPE(io) == IoTYPE_STD) result = 0; else if (fd <= PL_maxsysfd) { saveifp = IoIFP(io); @@ -106,7 +116,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, savetype = IoTYPE(io); result = 0; } - else if (IoTYPE(io) == '|') + else if (IoTYPE(io) == IoTYPE_PIPE) result = PerlProc_pclose(IoIFP(io)); else if (IoIFP(io) != IoOFP(io)) { if (IoOFP(io)) { @@ -136,14 +146,14 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, switch (result = rawmode & O_ACCMODE) { case O_RDONLY: - IoTYPE(io) = '<'; + IoTYPE(io) = IoTYPE_RDONLY; break; case O_WRONLY: - IoTYPE(io) = '>'; + IoTYPE(io) = IoTYPE_WRONLY; break; case O_RDWR: default: - IoTYPE(io) = '+'; + IoTYPE(io) = IoTYPE_RDWR; break; } @@ -153,15 +163,28 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, if (fd == -1) fp = NULL; else { - char *fpmode; + char fpmode[4]; + STRLEN ix = 0; if (result == O_RDONLY) - fpmode = "r"; + fpmode[ix++] = 'r'; #ifdef O_APPEND - else if (rawmode & O_APPEND) - fpmode = (result == O_WRONLY) ? "a" : "a+"; + else if (rawmode & O_APPEND) { + fpmode[ix++] = 'a'; + if (result != O_WRONLY) + fpmode[ix++] = '+'; + } #endif - else - fpmode = (result == O_WRONLY) ? "w" : "r+"; + 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); @@ -172,7 +195,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, char *oname = name; STRLEN tlen; STRLEN olen = len; - char mode[3]; /* stdio file mode ("r\0" or "r+\0") */ + char mode[4]; /* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */ int dodup; type = savepvn(name, len); @@ -191,7 +214,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, name = type; len = tlen; } - mode[0] = mode[1] = mode[2] = '\0'; + mode[0] = mode[1] = mode[2] = mode[3] = '\0'; IoTYPE(io) = *type; if (*type == '+' && tlen > 1 && type[tlen-1] != '|') { /* scary */ mode[1] = *type++; @@ -226,14 +249,23 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, if (ckWARN(WARN_PIPE)) Perl_warner(aTHX_ WARN_PIPE, "Can't open bidirectional pipe"); } - fp = PerlProc_popen(name,"w"); + { + char *mode; + if (out_raw) + mode = "wb"; + else if (out_crlf) + mode = "wt"; + else + mode = "w"; + fp = PerlProc_popen(name,mode); + } writing = 1; } else if (*type == '>') { TAINT_PROPER("open"); type++; if (*type == '>') { - mode[0] = IoTYPE(io) = 'a'; + mode[0] = IoTYPE(io) = IoTYPE_APPEND; type++; tlen--; } @@ -241,6 +273,11 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, mode[0] = 'w'; writing = 1; + if (out_raw) + strcat(mode, "b"); + else if (out_crlf) + strcat(mode, "t"); + if (num_svs && tlen != 1) goto unknown_desr; if (*type == '&') { @@ -283,8 +320,8 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, * fsetpos(src)+fgetpos(dst)? --nik */ PerlIO_flush(fp); fd = PerlIO_fileno(fp); - if (IoTYPE(thatio) == 's') - IoTYPE(io) = 's'; + if (IoTYPE(thatio) == IoTYPE_SOCKET) + IoTYPE(io) = IoTYPE_SOCKET; } else fd = -1; @@ -304,7 +341,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, for (; isSPACE(*type); type++) ; if (strEQ(type,"-")) { fp = PerlIO_stdout(); - IoTYPE(io) = '-'; + IoTYPE(io) = IoTYPE_STD; } else { fp = PerlIO_open((num_svs ? name : type), mode); @@ -317,13 +354,18 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, /*SUPPRESS 530*/ for (type++; isSPACE(*type); type++) ; mode[0] = 'r'; + if (in_raw) + strcat(mode, "b"); + else if (in_crlf) + strcat(mode, "t"); + if (*type == '&') { name = type; goto duplicity; } if (strEQ(type,"-")) { fp = PerlIO_stdin(); - IoTYPE(io) = '-'; + IoTYPE(io) = IoTYPE_STD; } else fp = PerlIO_open((num_svs ? name : type), mode); @@ -351,39 +393,56 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, if (strNE(name,"-") || num_svs) TAINT_ENV(); TAINT_PROPER("piped open"); - fp = PerlProc_popen(name,"r"); - IoTYPE(io) = '|'; + { + char *mode; + if (in_raw) + mode = "rb"; + else if (in_crlf) + mode = "rt"; + else + mode = "r"; + fp = PerlProc_popen(name,mode); + } + IoTYPE(io) = IoTYPE_PIPE; } else { if (num_svs) goto unknown_desr; name = type; - IoTYPE(io) = '<'; + IoTYPE(io) = IoTYPE_RDONLY; /*SUPPRESS 530*/ for (; isSPACE(*name); name++) ; if (strEQ(name,"-")) { fp = PerlIO_stdin(); - IoTYPE(io) = '-'; + 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); } - else - fp = PerlIO_open(name,"r"); } } if (!fp) { dTHR; - if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == '<' && strchr(name, '\n')) + if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n')) Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open"); goto say_false; } if (IoTYPE(io) && - IoTYPE(io) != '|' && IoTYPE(io) != '-') { + IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD) { dTHR; if (PerlLIO_fstat(PerlIO_fileno(fp),&PL_statbuf) < 0) { (void)PerlIO_close(fp); goto say_false; } if (S_ISSOCK(PL_statbuf.st_mode)) - IoTYPE(io) = 's'; /* in case a socket was passed in to us */ + IoTYPE(io) = IoTYPE_SOCKET; /* in case a socket was passed in to us */ #ifdef HAS_SOCKET else if ( #ifdef S_IFMT @@ -397,7 +456,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, if (PerlSock_getsockname(PerlIO_fileno(fp), (struct sockaddr *)tmpbuf, &buflen) >= 0 || errno != ENOTSOCK) - IoTYPE(io) = 's'; /* some OS's return 0 on fstat()ed socket */ + IoTYPE(io) = IoTYPE_SOCKET; /* some OS's return 0 on fstat()ed socket */ /* but some return 0 for streams too, sigh */ } #endif @@ -417,11 +476,13 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, 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) @@ -443,9 +504,18 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw, IoFLAGS(io) &= ~IOf_NOLINE; if (writing) { dTHR; - if (IoTYPE(io) == 's' - || (IoTYPE(io) == '>' && S_ISCHR(PL_statbuf.st_mode)) ) { - if (!(IoOFP(io) = PerlIO_fdopen(PerlIO_fileno(fp),"w"))) { + 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))) { PerlIO_close(fp); IoIFP(io) = Nullfp; goto say_false; @@ -646,13 +716,17 @@ Perl_nextargv(pTHX_ register GV *gv) else { dTHR; if (ckWARN_d(WARN_INPLACE)) { - if (!S_ISREG(PL_statbuf.st_mode)) + int eno = errno; + if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0 + && !S_ISREG(PL_statbuf.st_mode)) + { Perl_warner(aTHX_ 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", - PL_oldname, Strerror(errno)); + PL_oldname, Strerror(eno)); } } } @@ -699,8 +773,8 @@ Perl_do_pipe(pTHX_ SV *sv, GV *rgv, GV *wgv) IoIFP(rstio) = PerlIO_fdopen(fd[0], "r"); IoOFP(wstio) = PerlIO_fdopen(fd[1], "w"); IoIFP(wstio) = IoOFP(wstio); - IoTYPE(rstio) = '<'; - IoTYPE(wstio) = '>'; + IoTYPE(rstio) = IoTYPE_RDONLY; + IoTYPE(wstio) = IoTYPE_WRONLY; if (!IoIFP(rstio) || !IoOFP(wstio)) { if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio)); else PerlLIO_close(fd[0]); @@ -736,9 +810,8 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit) if (!io) { /* never opened */ if (not_implicit) { dTHR; - if (ckWARN(WARN_UNOPENED)) - Perl_warner(aTHX_ WARN_UNOPENED, - "Close on unopened file <%s>",GvENAME(gv)); + if (ckWARN(WARN_UNOPENED)) /* no check for closed here */ + report_evil_fh(gv, io, PL_op->op_type); SETERRNO(EBADF,SS$_IVCHAN); } return FALSE; @@ -749,7 +822,7 @@ Perl_do_close(pTHX_ GV *gv, bool not_implicit) IoPAGE(io) = 0; IoLINES_LEFT(io) = IoPAGE_LEN(io); } - IoTYPE(io) = ' '; + IoTYPE(io) = IoTYPE_CLOSED; return retval; } @@ -760,7 +833,7 @@ Perl_io_close(pTHX_ IO *io, bool not_implicit) int status; if (IoIFP(io)) { - if (IoTYPE(io) == '|') { + if (IoTYPE(io) == IoTYPE_PIPE) { status = PerlProc_pclose(IoIFP(io)); if (not_implicit) { STATUS_NATIVE_SET(status); @@ -770,7 +843,7 @@ Perl_io_close(pTHX_ IO *io, bool not_implicit) retval = (status != -1); } } - else if (IoTYPE(io) == '-') + else if (IoTYPE(io) == IoTYPE_STD) retval = TRUE; else { if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { /* a socket */ @@ -801,13 +874,22 @@ Perl_do_eof(pTHX_ GV *gv) if (!io) return TRUE; else if (ckWARN(WARN_IO) - && (IoTYPE(io) == '>' || IoIFP(io) == PerlIO_stdout() + && (IoTYPE(io) == IoTYPE_WRONLY || IoIFP(io) == PerlIO_stdout() || IoIFP(io) == PerlIO_stderr())) { - SV* sv = sv_newmortal(); - gv_efullname3(sv, gv, Nullch); - Perl_warner(aTHX_ WARN_IO, "Filehandle %s opened only for output", - SvPV_nolen(sv)); + /* 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"); } while (IoIFP(io)) { @@ -851,8 +933,8 @@ Perl_do_tell(pTHX_ GV *gv) } { dTHR; - if (ckWARN(WARN_UNOPENED)) - Perl_warner(aTHX_ WARN_UNOPENED, "tell() on unopened file"); + if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) + report_evil_fh(gv, io, PL_op->op_type); } SETERRNO(EBADF,RMS$_IFI); return (Off_t)-1; @@ -873,8 +955,8 @@ Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence) } { dTHR; - if (ckWARN(WARN_UNOPENED)) - Perl_warner(aTHX_ WARN_UNOPENED, "seek() on unopened file"); + if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) + report_evil_fh(gv, io, PL_op->op_type); } SETERRNO(EBADF,RMS$_IFI); return FALSE; @@ -890,27 +972,80 @@ Perl_do_sysseek(pTHX_ GV *gv, Off_t pos, int whence) return PerlLIO_lseek(PerlIO_fileno(fp), pos, whence); { dTHR; - if (ckWARN(WARN_UNOPENED)) - Perl_warner(aTHX_ WARN_UNOPENED, "sysseek() on unopened file"); + if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) + report_evil_fh(gv, io, PL_op->op_type); } SETERRNO(EBADF,RMS$_IFI); return (Off_t)-1; } int -Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int flag) +Perl_mode_from_discipline(pTHX_ SV *discp) +{ + int mode = O_BINARY; + if (discp) { + STRLEN len; + char *s = SvPV(discp,len); + while (*s) { + if (*s == ':') { + switch (s[1]) { + case 'r': + if (len > 3 && strnEQ(s+1, "raw", 3) + && (!s[4] || s[4] == ':' || isSPACE(s[4]))) + { + mode = O_BINARY; + s += 4; + len -= 4; + break; + } + /* FALL THROUGH */ + case 'c': + if (len > 4 && strnEQ(s+1, "crlf", 4) + && (!s[5] || s[5] == ':' || isSPACE(s[5]))) + { + mode = O_TEXT; + s += 5; + len -= 5; + break; + } + /* FALL THROUGH */ + default: + goto fail_discipline; + } + } + else if (isSPACE(*s)) { + ++s; + --len; + } + else { + char *end; +fail_discipline: + end = strchr(s+1, ':'); + if (!end) + end = s+len; + Perl_croak(aTHX_ "Unknown discipline '%.*s'", end-s, s); + } + } + } + return mode; +} + +int +Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int mode) { - if (flag != TRUE) - Perl_croak(aTHX_ "panic: unsetting binmode"); /* Not implemented yet */ #ifdef DOSISH -#if defined(atarist) || defined(__MINT__) - if (!PerlIO_flush(fp) && (fp->_flag |= _IOBIN)) +# if defined(atarist) || defined(__MINT__) + if (!PerlIO_flush(fp)) { + if (mode & O_BINARY) + ((FILE*)fp)->_flag |= _IOBIN; + else + ((FILE*)fp)->_flag &= ~ _IOBIN; return 1; - else - return 0; -#else - if (PerlLIO_setmode(PerlIO_fileno(fp), OP_BINARY) != -1) { -#if defined(WIN32) && defined(__BORLANDC__) + } + 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 @@ -918,22 +1053,25 @@ Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int flag) * document this anywhere). GSAR 97-5-24 */ PerlIO_seek(fp,0L,0); - ((FILE*)fp)->flags |= _F_BIN; -#endif + if (mode & O_BINARY) + ((FILE*)fp)->flags |= _F_BIN; + else + ((FILE*)fp)->flags &= ~ _F_BIN; +# endif return 1; } else return 0; -#endif +# endif #else -#if defined(USEMYBINMODE) - if (my_binmode(fp,iotype) != FALSE) +# if defined(USEMYBINMODE) + if (my_binmode(fp, iotype, mode) != FALSE) return 1; else return 0; -#else +# else return 1; -#endif +# endif #endif } @@ -1049,25 +1187,24 @@ Perl_my_stat(pTHX) { djSP; IO *io; - GV* tmpgv; + GV* gv; if (PL_op->op_flags & OPf_REF) { EXTEND(SP,1); - tmpgv = cGVOP_gv; + gv = cGVOP_gv; do_fstat: - io = GvIO(tmpgv); + io = GvIO(gv); if (io && IoIFP(io)) { - PL_statgv = tmpgv; + PL_statgv = gv; sv_setpv(PL_statname,""); PL_laststype = OP_STAT; return (PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache)); } else { - if (tmpgv == PL_defgv) + if (gv == PL_defgv) return PL_laststatval; - if (ckWARN(WARN_UNOPENED)) - Perl_warner(aTHX_ WARN_UNOPENED, "Stat on unopened file <%s>", - GvENAME(tmpgv)); + if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) + report_evil_fh(gv, io, PL_op->op_type); PL_statgv = Nullgv; sv_setpv(PL_statname,""); return (PL_laststatval = -1); @@ -1079,11 +1216,11 @@ Perl_my_stat(pTHX) STRLEN n_a; PUTBACK; if (SvTYPE(sv) == SVt_PVGV) { - tmpgv = (GV*)sv; + gv = (GV*)sv; goto do_fstat; } else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) { - tmpgv = (GV*)SvRV(sv); + gv = (GV*)SvRV(sv); goto do_fstat; } @@ -1666,8 +1803,11 @@ Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp) { struct semid_ds semds; union semun semun; - +#ifdef EXTRA_F_IN_SEMUN_BUF + semun.buff = &semds; +#else semun.buf = &semds; +#endif getinfo = (cmd == GETALL); if (Semctl(id, 0, IPC_STAT, semun) == -1) return -1; @@ -1722,7 +1862,11 @@ Perl_do_ipcctl(pTHX_ I32 optype, SV **mark, SV **sp) #ifdef Semctl union semun unsemds; +#ifdef EXTRA_F_IN_SEMUN_BUF + unsemds.buff = (struct semid_ds *)a; +#else unsemds.buf = (struct semid_ds *)a; +#endif ret = Semctl(id, n, cmd, unsemds); #else Perl_croak(aTHX_ "%s not implemented", PL_op_desc[optype]); @@ -1780,6 +1924,9 @@ Perl_do_msgrcv(pTHX_ SV **mark, SV **sp) id = SvIVx(*++mark); mstr = *++mark; + /* suppress warning when reading into undef var --jhi */ + if (! SvOK(mstr)) + sv_setpvn(mstr, "", 0); msize = SvIVx(*++mark); mtype = (long)SvIVx(*++mark); flags = SvIVx(*++mark); @@ -1791,6 +1938,10 @@ Perl_do_msgrcv(pTHX_ SV **mark, SV **sp) if (ret >= 0) { SvCUR_set(mstr, sizeof(long)+ret); *SvEND(mstr) = '\0'; +#ifndef INCOMPLETE_TAINTS + /* who knows who has been playing with this message? */ + SvTAINTED_on(mstr); +#endif } return ret; #else @@ -1849,6 +2000,9 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp) if (shm == (char *)-1) /* I hate System V IPC, I really do */ return -1; if (optype == OP_SHMREAD) { + /* suppress warning when reading into undef var (tchrist 3/Mar/00) */ + if (! SvOK(mstr)) + sv_setpvn(mstr, "", 0); SvPV_force(mstr, len); mbuf = SvGROW(mstr, msize+1); @@ -1856,6 +2010,10 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp) SvCUR_set(mstr, msize); *SvEND(mstr) = '\0'; SvSETMAGIC(mstr); +#ifndef INCOMPLETE_TAINTS + /* who knows who has been playing with this shared memory? */ + SvTAINTED_on(mstr); +#endif } else { I32 n;