From owner-freebsd-bugs@FreeBSD.ORG Wed Nov 17 12:34:38 2010 Return-Path: Delivered-To: freebsd-bugs@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8E3B81065670 for ; Wed, 17 Nov 2010 12:34:38 +0000 (UTC) (envelope-from arundel@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 5EA488FC0A; Wed, 17 Nov 2010 12:34:38 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id oAHCYcWo044147; Wed, 17 Nov 2010 12:34:38 GMT (envelope-from arundel@freefall.freebsd.org) Received: (from arundel@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oAHCYcEk044146; Wed, 17 Nov 2010 12:34:38 GMT (envelope-from arundel) Date: Wed, 17 Nov 2010 12:34:38 +0000 From: Alexander Best To: "Ronald F. Guilmette" Message-ID: <20101117123438.GA43700@freebsd.org> References: <201011171040.oAHAeENN016903@freefall.freebsd.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <201011171040.oAHAeENN016903@freefall.freebsd.org> Cc: freebsd-bugs@FreeBSD.org Subject: Re: bin/152154: /bin/csh & /bin/tcsh improperly diddle termios flags X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Nov 2010 12:34:38 -0000 On Wed Nov 17 10, Ronald F. Guilmette wrote: > The following reply was made to PR bin/152154; it has been noted by GNATS. > > From: "Ronald F. Guilmette" > To: FreeBSD-gnats-submit@freebsd.org > Cc: > Subject: Re: bin/152154: /bin/csh & /bin/tcsh improperly diddle termios flags > Date: Wed, 17 Nov 2010 02:36:20 -0800 > > Gentlemen, > > Thanks for the discussion of this problem. > > As someone else just pointed out to me (via the tcsh discussion list) > _any_ shell that allows command line editing (not just tcsh but also > bash and zsh) are going to put the pseudo terminal into character-at-a-time > non-echo mode, and thus, one will get doubled characters in the typescript > file when using "script -k" in conjunction with any such shell. > > So I guess we should say that the REAL non-feature (aka "bug") here is not > really in tcsh but rather in the way that script(1) decides whether or > not to write input characters to the typescript file when operating in > the -k mode. > > Here is the code which involves that decision: > > if (cc > 0) { > (void)write(master, ibuf, cc); > if (kflg && (tcgetattr(master, &stt) >= 0) && > ((stt.c_lflag & ECHO) == 0)) { > (void)fwrite(ibuf, 1, cc, fscript); > } > } > > My feeling now is that I should withdraw/cancel this PR (bin/152154) which > is on tcsh and instead file a new & different one on script(1), because > it is clear now that -k, as implemented, just won't work in conjunction > with shells that allow command line editing. > > (Can someone plesse instruct me how to cancel a PR? I've never done it > before, and I'm ignorant.) hello ronald, no need to close this PR and open up a new one. please simply tell me how the new PR subject line should look like and i'll change it. cheers. alex > > I want to say also that I do believe that there is a solution to this > problem. I cannot be 100% sure yet that there will never be any circumstances > under which it might perhaps malfunction slightly, but my early (and so far > minimal) testing has not shown any signs of any malfunctions, so I am hopeful > that this may be a solution that will work OK, even for the shells that > allow command line editing. > > So anyway, here's my idea... > > Right now, script(1) is simply writing 100% of all characters which the > child shell (or its children) write to stdout/stderr into the typescript > file. In the -k case however, this is augmented by script also writing > any characters that are INPUT (to the stdin of the child shell) to the > typescript file also, but only (as shown by the code above) when the > the child shell (or any of its children) has set its pseudo-tty to _not_ > ECHO. Clearly, as we now know, this approach won't work consistantly > across all shells. > > So instead of this approach, I propose that script(1) be modified so that > when -k mode is in effect, it will write 100% of all INPUT characters to > the typescript file, but then each time it receives a block of characters > that are comming _out_ from the shell, instead of writing 100% of those > OUTPUT characters to the typescript file, script(1) would instead compare > the buffer full of output bytes it just received (frm the child shell and/or > its children) to the last buffer full of input bytes that script(1) sent > down to the child shell. If the contents of the two buffers are equal, > then the current block of output characters that are coming up from the > child shell would simply be suppressed and NOT written to the typescript > file, thus, in efffect, nixing any echoed characters which simply duplicate > characters that were already added to the typescript file. > > A patch implementing the change I have just described is included below. > I would appreciate any and all comments on it. I've just tried it out > a little and it does seem to work OK, at least with tcsh. > > Of course, the whole idea here is, admittedly, based upon a presumption > which may or may not be true in all circumstances and/or in all contexts, > i.e. that any input from the _actual_ controlling tty... which will usually > be, you know, one character at a time, especially for a hunt-and-pecker > like me... will be echoed back before more input comes in, i.e. if it is > going to be echoed back at all. And I am allowing here for even the super > duper input rate that may come from doing, e.g. a cut-and-paste, where many > characters may be read from the real terminal device in one glup. As long > as those all get echoed back, immediately, in one single glup too, then this > approach to implementing -k still works. (I did try some cut-and-pasting > and that also seemed to work OK with the patche below.) > > The only thing that isn't all that clear to me (and that frankly, I haven't > tested yet) is what would happen if input is coming from something non- > interactive, like, you know, a file. I actually don't know what would > happen in that case, but I suspect that this patch should work OK even for > that case. > > I guess that the possibility that something might cause some characters (e.g > control characters and/or terminal control sequences) not to "echo" back > verbatim, as themselves, might also be an issue, but in this case I rather > doubt that the patch below make things any worse/stranger than they already > are, when/if such oddities are being logged in the (current) script-k+/bin/sh > case. > > > Regards, > rfg > > > P.S. My apologies to Bruce Evans about the local blacklisting of your ISP. > It was nothing personal, believe me. Just got too much spam from them, > that's all. Anyway, I have removed that local blacklist entry now so for > the time being at least, please do feel free to mail me direct, if you are > so inclined. > > > > *** script.c.orig 2004-02-15 09:30:13.000000000 -0800 > --- script.c 2010-11-14 16:22:15.000000000 -0800 > *************** > *** 82,86 **** > main(int argc, char *argv[]) > { > ! int cc; > struct termios rtt, stt; > struct winsize win; > --- 82,86 ---- > main(int argc, char *argv[]) > { > ! int icc = 0, occ; > struct termios rtt, stt; > struct winsize win; > *************** > *** 178,200 **** > break; > if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) { > ! cc = read(STDIN_FILENO, ibuf, BUFSIZ); > ! if (cc < 0) > break; > ! if (cc == 0) > (void)write(master, ibuf, 0); > ! if (cc > 0) { > ! (void)write(master, ibuf, cc); > ! if (kflg && tcgetattr(master, &stt) >= 0 && > ! ((stt.c_lflag & ECHO) == 0)) { > ! (void)fwrite(ibuf, 1, cc, fscript); > ! } > } > } > if (n > 0 && FD_ISSET(master, &rfd)) { > ! cc = read(master, obuf, sizeof (obuf)); > ! if (cc <= 0) > break; > ! (void)write(STDOUT_FILENO, obuf, cc); > ! (void)fwrite(obuf, 1, cc, fscript); > } > tvec = time(0); > --- 178,201 ---- > break; > if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) { > ! icc = read(STDIN_FILENO, ibuf, BUFSIZ); > ! if (icc < 0) > break; > ! if (icc == 0) > (void)write(master, ibuf, 0); > ! if (icc > 0) { > ! (void)write(master, ibuf, icc); > ! if (kflg) > ! (void)fwrite(ibuf, 1, icc, fscript); > } > } > if (n > 0 && FD_ISSET(master, &rfd)) { > ! occ = read(master, obuf, sizeof (obuf)); > ! if (occ <= 0) > break; > ! (void)write(STDOUT_FILENO, obuf, occ); > ! if (!kflg || (occ != icc) || memcmp (obuf, ibuf, occ)) { > ! (void)fwrite(obuf, 1, occ, fscript); > ! icc = 0; > ! } > } > tvec = time(0); > > -- a13x