Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Nov 2010 12:34:38 +0000
From:      Alexander Best <arundel@FreeBSD.org>
To:        "Ronald F. Guilmette" <rfg@tristatelogic.com>
Cc:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/152154: /bin/csh & /bin/tcsh improperly diddle termios flags
Message-ID:  <20101117123438.GA43700@freebsd.org>
In-Reply-To: <201011171040.oAHAeENN016903@freefall.freebsd.org>
References:  <201011171040.oAHAeENN016903@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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@tristatelogic.com>
> 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20101117123438.GA43700>