From owner-freebsd-bugs@FreeBSD.ORG Wed Nov 17 10:40:15 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6FE1110656C7 for ; Wed, 17 Nov 2010 10:40:15 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 3FC2A8FC13 for ; Wed, 17 Nov 2010 10:40:15 +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 oAHAeE5k016906 for ; Wed, 17 Nov 2010 10:40:14 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oAHAeENN016903; Wed, 17 Nov 2010 10:40:14 GMT (envelope-from gnats) Date: Wed, 17 Nov 2010 10:40:14 GMT Message-Id: <201011171040.oAHAeENN016903@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: "Ronald F. Guilmette" Cc: 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 Reply-To: "Ronald F. Guilmette" List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Nov 2010 10:40:15 -0000 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.) 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);