bin/152154: /bin/csh & /bin/tcsh improperly diddle termios flags
Alexander Best
arundel at FreeBSD.org
Wed Nov 17 12:34:38 UTC 2010
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" <rfg at tristatelogic.com>
> To: FreeBSD-gnats-submit at 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
More information about the freebsd-bugs
mailing list