From nemesis!uhclem@fw.ast.com  Mon Feb 19 20:17:13 1996
Received: from fw.ast.com (fw.ast.com [165.164.6.25])
          by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id UAA18207
          for <FreeBSD-gnats-submit@freebsd.org>; Mon, 19 Feb 1996 20:17:12 -0800 (PST)
Received: from nemesis by fw.ast.com with uucp
	(Smail3.1.29.1 #2) id m0tojRJ-0007zaC; Mon, 19 Feb 96 22:12 CST
Received: by nemesis.lonestar.org (Smail3.1.27.1 #20)
	id m0tojOB-000CiCC; Mon, 19 Feb 96 22:09 WET
Message-Id: <m0tojOB-000CiCC@nemesis.lonestar.org>
Date: Mon, 19 Feb 96 22:09 WET
From: uhclem@nemesis.lonestar.org
Reply-To: uhclem@nemesis.lonestar.org
To: FreeBSD-gnats-submit@freebsd.org
Subject: 2.x telnetd handles CTRL-M differently than other ttys		FDIV044
X-Send-Pr-Version: 3.2

>Number:         1037
>Category:       bin
>Synopsis:       2.x telnetd handles CTRL-M differently than other ttys		FDIV044
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 19 20:20:01 PST 1996
>Closed-Date:    Mon Oct 20 19:54:23 PDT 1997
>Last-Modified:  Mon Oct 20 19:55:10 PDT 1997
>Originator:     Frank Durda IV
>Release:        FreeBSD 2.1-STABLE i386
>Organization:
That's extra
>Environment:

FreeBSD 2.1.0 stock system, using various applications that place
tty in character-at-a-time modes.

>Description:

Some applications that ran correctly under BSD43 on vaxen, and later on
SYSIII, SYS5 and 1.1.5.1 PC systems break when used via telnet in 2.0.5
or 2.1.0.  

When these programs are running, they interactively parse each character
received, including [ENTER], which is received as 0x0a when the program
is run from the console (syscons), from a terminal attached to a sio port,
or when connected using via telnet using telnetd from 1.1.5.1.

When the telnetd from 2.0.5 or 2.1.0 is used, instead of a 0x0a,
the program receives a 0x0d character, which it does not expect (never
sees anywhere else) and treats as an not-valid-here character.

>How-To-Repeat:

The attached code fragment can be compiled to demonstrate the problem.
Simply run it from terminals, the console, and from telnet sessions to
see the difference in performance.  (I have stripped out the SYS3-specific
code, but can provide it if needed.)  Follow the instructions in the
program source.

-----enterbug.c-----
/*	This program is peeled out of a much larger program called
	xmail.  When run in 2.1.0 over telnet, pressing ENTER
	is no longer detected by the program as receiving a 0x0a
	as it did in 1.1.5.1 telnet sessions, or from ttys, or
	from the console, or on other platforms (BSD43, SYS3, SYSV) 
	that this program has been used on.

	Start the program, and press at least the following keys:
	[ENTER] [CTRL][J] [CTRL][M]  Press Capital Q to exit.

	Here is what I see here:	(This is a 2.1.0 system)

			System	sio 	telnetd	telnetd
			console	tty	2.1.0	1.1.5.1*
	[ENTER]		0a	0a    **0d**	0a
	[CTRL][J]	0a	0a	0a	0a
	[CTRL][M]	0a	0a    **0d**	0a

	* By replacing the 2.1.0 telnetd with the telnetd from 1.1.5.1
	(but still running on a 2.1.0 system), the correct character
	(0x0a) is returned when ENTER is presed.

	Run this program from the console, from terminals, and then
	via telnet to see the difference in behavior.
*/

#include	<stdio.h>
#include	<sgtty.h>
#include	<sys/stat.h>
#include	<sys/file.h>
#define TRUE 1
#define FALSE 0
#define	EOT	'\004'

static  struct sgttyb	old, new;
static struct  stat	ttystatus;
static int	eof=EOT,  killc=CTRL('U'),  erase=CTRL('H'),  werase=CTRL('W');
char	*ttynam_stdout;
int	stdin_isatty, stdout_isatty;

main()
{	
	char c;

	save_tty();
	set_tty();

	clearerr(stdin);
	do {
		c = getchar();
		printf("%02x ",c);
	} while (c != 'Q');
	
	restore_tty();
	exit(0);
}


save_tty()
{
	struct tchars	tc;

	fstat(fileno(stdout), &ttystatus);
	ttynam_stdout = (char*) ttyname(fileno(stdout));
	stdout_isatty = (ioctl(fileno(stdout), TIOCGETP, &old) >= 0);
	stdin_isatty = (ioctl(fileno(stdin), TIOCGETP, &old) >= 0);

	printf("stdin is%s a tty\n",stdin_isatty?"":" not");
	printf("stdout is%s a tty\n",stdout_isatty?"":" not");

	killc = (int)old.sg_kill;
	erase = (int)old.sg_erase;
	if (ioctl(fileno(stdin), TIOCGETC, &tc) == 0)
		eof = (int)tc.t_eofc;

	new = old;
	new.sg_flags |= CBREAK;
	new.sg_flags &= ~ECHO;
}

set_tty()
{
	ioctl(fileno(stdin), TIOCSETN, &new);
}

restore_tty()
{
	if (stdout_isatty)
		chmod(ttynam_stdout, (int)ttystatus.st_mode&0777);
	if (stdin_isatty)
		ioctl(fileno(stdin), TIOCSETP, &old);
}
-----end of enterbug.c-----


>Fix:
	
The workaround is to replace the telnetd in 2.1.0 or 2.0.5
with the telnetd from 1.1.5.1.  This solves this problem and allows
these legacy applications to be used on FreeBSD 2.x.

*END*

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: scrappy 
State-Changed-When: Mon Oct 21 23:07:38 PDT 1996 
State-Changed-Why:  

Dust off the cobwebs - Confirm Status 

From: Garrett Wollman <wollman@lcs.mit.edu>
To: uhclem@nemesis.lonestar.org (Frank Durda IV)
Cc: freebsd-gnats-submit@freefall.freebsd.org
Subject: bin/1037
Date: Sat, 7 Dec 1996 14:54:00 -0500

 <<On Fri, 6 Dec 96 22:52 CST, uhclem@nemesis.lonestar.org (Frank Durda IV) said:
 
 > 5.	Telnet self
 > 6.	login (same csh/filec login used in steps 1-5)
 > 7.	cd directory where above programs reside.
 > 8.	Type [c][CTRL][D]
 > 	system should display files that match, but instead, simply
 > 	echos ^D.  MALFUNCTION
 > As above, replacing telnetd with the one shipped with 1.1.5.1 fixes
 > this problem.
 
 This is because the TELNET in 1.x had a broken LINEMODE.  2.x has a
 working LINEMODE, but this is sometimes not what programs expect.
 
 To wit:
 
 LINEMODE provides for remote interpretation of control characters, so
 that keyboard `commands' like `interrupt', `are-you-there', and others
 can be sent out-of-band.  (Actually, this is a simplification.)  This
 has the beneficial effect that `interrupt', `are-you-there', `abort
 output' and such actually work no matter how much data is buffered in
 the socket layer.
 
 LINEMODE also provides for local line-at-a-time input with editing
 controls defined by the remote host, in the same way as these
 `commands' are defined.  This can be enabled independently of the
 `command' processing.
 
 The `telnet' daemon and client cooperate to provide LINEMODE with
 line-at-a-time input when the remote TTY's input mode is ICANON|ISIG.
 When the input mode is ISIG without ICANON, LINEMODE without the
 line-oriented input is used.
 
 Some programs attempt to ``hijack'' plain ISIG mode in an attempt to
 get the system to do more of their work for them.  For example, Emacs
 in certain input modes will program the TTY driver to disable all of
 the special characters except VINTR which is set to control-G.  Then,
 Emacs gets a SIGINT whenever the user types control-G.  When Emacs
 needs to actually read a sequence containing the control-G character
 (because, for example, the user invoked quoted-insert [C-q]), it knows
 to interpret the following SIGINT as if the user had actually typed a
 control-G.
 
 Now you see the problem: when running through TELNET, the signals that
 programs expect to get can be delivered out-of-order with respect to
 the input, which can cause them to become confused or malfunction
 entirely, depending on how detailed their model of how ttys work
 actually is.  This is particularly true in the case of ICANON|ISIG
 mode, which /bin/csh uses.  In Frank's case, the end-of-file
 ``signal'' (actually a zero-length-read) is not delivered until after
 the line he is composing (including its end-of-line character) has
 been forwarded to the server, so `csh' never sees the incomplete line
 he is trying to complete.
 
 The TELNET daemon interprets the unsetting of the EXTPROC bit in the
 termios state (e.g., by `stty -extproc') as a request to disable
 LINEMODE, which is why this causes such applications to work properly.
 
 -GAWollman
 
 --
 Garrett A. Wollman   | O Siem / We are all family / O Siem / We're all the same
 wollman@lcs.mit.edu  | O Siem / The fires of freedom 
 Opinions not those of| Dance in the burning flame
 MIT, LCS, ANA, or NSA|                     - Susan Aglukark and Chad Irschick

From: uhclem@nemesis.lonestar.org (Frank Durda IV)
To: wollman@lcs.mit.edu, freebsd-gnats-submit@freefall.freebsd.org
Cc: uhclem@nemesis.lonestar.org
Subject: bin/1037  
Date: Sat, 7 Dec 96 17:06 CST

 [0]uhclem@nemesis.lonestar.org (Frank Durda IV) said:
 [0]1.	Login to stock shell with stock .cshrc/.login (csh with filec
 [0]	enabled)
 [0]2.	cd directory where above programs reside.
 [0]3.	Type [c][CTRL][D]
 [0]	system should display files that match, including chars.c. NORMAL
 [0]4.	[CTRL][C].
 [0]5.	Telnet self
 [0]6.	login (same csh/filec login used in steps 1-5)
 [0]7.	cd directory where above programs reside.
 [0]8.	Type [c][CTRL][D]
 [0]	system should display files that match, but instead, simply
 [0]	echos ^D.  MALFUNCTION
 [0]As above, replacing telnetd with the one shipped with 1.1.5.1 fixes
 [0]this problem.
 
 [1] wollman@lcs.mit.edu then said:
 [1]This is because the TELNET in 1.x had a broken LINEMODE.  2.x has a
 [1]working LINEMODE, but this is sometimes not what programs expect.
 
 Hmm, this logic isn't obvious to me.  It seems the goal is to have
 the telnet session provide functionality identical of what you get
 at the console or at any serial/dialup port.  I don't understand
 why "working" means to break what seems to be a basic compatibility
 function of character I/O.
 
 In 1.1.5.1 and earlier plus BSD 4.3 and earlier, telnet sessions behaved
 the same as serial and console sessions.  In 2.x and later, telnet
 sessions behave differently than serial and console sessions.  The
 current state is considered "working"? 
 
 In my opinion, current functionality of telnet is incompatible with
 previous versions and non-telnet operation, and that means telnetd
 is broken.
 
 In my opinion, applications should not have to be written to detect
 and handle serial, telnet and console sessions differently.  Starting
 with 2.x applications apparently now have to make distinctions 
 if they are to provide an identical functional user-interface on
 console, serial and telnet logins.
 
 If telnet isn't broken, is anybody planning to fix csh so CTRL-D behaves
 as documented when csh is used from a telnet session on FreeBSD 2.x?
 
 Frank Durda IV <uhclem@nemesis.lonestar.org>|"If the choices are "right"
 or uhclem%nemesis@rwsystr.nkn.net           | or "tidy", I'll go with 
 					    | "right" every time."
 or ...letni!rwsys!nemesis!uhclem	    |
 

From: Garrett Wollman <wollman@lcs.mit.edu>
To: uhclem@nemesis.lonestar.org (Frank Durda IV)
Cc: freebsd-gnats-submit@freefall.freebsd.org
Subject: bin/1037  
Date: Mon, 9 Dec 1996 09:43:04 -0500

 <<On Sat, 7 Dec 96 17:06 CST, uhclem@nemesis.lonestar.org (Frank Durda IV) said:
 
 > [1] wollman@lcs.mit.edu then said:
 > [1]This is because the TELNET in 1.x had a broken LINEMODE.  2.x has a
 > [1]working LINEMODE, but this is sometimes not what programs expect.
 
 > Hmm, this logic isn't obvious to me.  It seems the goal is to have
 > the telnet session provide functionality identical of what you get
 > at the console or at any serial/dialup port.  I don't understand
 > why "working" means to break what seems to be a basic compatibility
 > function of character I/O.
 
 ``Working'' in the quoted sentence means ``implemented according to
 the standard''.  The brokenness in 1.x was so bad that we simply
 disabled it.
 
 -GAWollman
 
 --
 Garrett A. Wollman   | O Siem / We are all family / O Siem / We're all the same
 wollman@lcs.mit.edu  | O Siem / The fires of freedom 
 Opinions not those of| Dance in the burning flame
 MIT, LCS, ANA, or NSA|                     - Susan Aglukark and Chad Irschick

From: uhclem@nemesis.lonestar.org (Frank Durda IV)
To: mpp@freefall.freebsd.org, bugs@freebsd.org,
        FreeBSD-gnats-submit@freebsd.org
Cc: uhclem@nemesis.lonestar.org
Subject: re: bin/1037 and bin/771  Patch included
Date: Tue, 11 Mar 97 23:26 CST

 [0]Are you still seeing the problem reported in your FreeBSD problem
 [0]report # 1037?  Have you tried later versions of FreeBSD, such as 
 [0]FreeBSD 2.2 GAMMA or FreeBSD 3.0-current?  Any other information 
 [0]you could provide would be helpful.  If you are still seeing the 
 [0]problem, what version of FreeBSD are you running right now?
 [0]Mike Pritchard
 
 Regarding:
 bin/1037:
 Synopsis:       2.x telnetd handles CTRL-M differently than other ttys	FDIV044
 bin/771:
 Synopsis:	telnet character mode not set and broken when set - FDIV034
 
 
 No, these items remain broken in 2.2-GAMMA, and all releases back to
 at least the 2.1.0-RELEASE.  It worked correctly in 1.1.5.1.
 
 I've been hoping somebody would quit stalling over the religious issues
 here and fix this, but apparently that won't happen after a year on the
 books, so here is a patch that solves the religious issue with a
 technical fix:
 
 
 -----FIX BEGINS-----
 *** telnetd.c.00	Sun Jan 12 15:56:33 1997
 --- telnetd.c	Wed Feb 26 16:07:15 1997
 ***************
 *** 179,184 ****
 --- 179,187 ----
   
   	progname = *argv;
   
 + 	linemode=1;			/*Default to mode that all brands
 + 					  of telnets handle correctly*/
 + 
   #ifdef CRAY
   	/*
   	 * Get number of pty's before trying to process options,
 -----FIX ENDS-----
 
 
 That's it.  The patch works on all telnetds released from 2.1.0
 thru 2.2-GAMMAs and would close bin/771 and bin/1037 if applied.
 It might even resolve bin/1073, but I don't have a way to test that.
 
 
 Discussion
 
 The problem was, is, and apparently will always be that starting with
 2.x, telnetd has wanted to run in LINEMODE by default, because it
 is more efficient in using the TCP/IP transport media than the
 character-at-a-time modes used previously in 1.1.5.1 and earlier
 as well as BSD 4.3.
 
 The problem with that was, is, and will always be that not all TELNET
 clients on all known platforms implement LINEMODE correctly in that
 they don't know about what to do for various action (wakeup)
 control-characters, such as the ones available in csh for command editing
 and completion.  ^D, ^W, ^R, <ESC>, ^U, etc.   These commands break in
 the presence of LINEMODE in various ways.   To demonstrate, try this simple
 test.
 
 Login into a csh session on a FreeBSD target via the console or
 a serial connection and follow this command sequence:
 
 	% set filec
 	% cd /stand
 	% ls i<CTRL-D>		should display
 	ifconfig*
 	% ls i<ESC>		should finish command string:  % ls ifconfig
 	% ls ifconfig<CTRL-W>	should erase "ifconfig": % ls 
 	% ls <CTRL-R>		should redraw on next line: ls
 	ls f<CTRL-D>		should display
 	find* fsck* ft*
 	% ls fs<CTRL-D>		should finish "fsck": % ls fsck
 	% ls fsck<CTRL-U>	should erase: %
 	%
 
 Now telnet into the same system (try "telnet ." if you like and
 see the behavior difference).   Login as the same user and repeat
 the sequence above.
 
 I don't care if you telnet from any FreeBSD 2.x release, SCO UNIX 3.2,
 DEC OSF 3.2G or 4.0B, IRIX V.4, from NETBSD 1.x, Windows '95 TELNET,
 or from NCSA Telnet 2.3.07 (I've tested all of these), they will all
 malfunction telnetting to FreeBSD 2.x, at least until you apply the patch.
 
 The other aspect of the bad behavior of telnetd was shown by two different
 programs provided previously, but I'll repeat one here.  This is code
 pulled from an existing application written in the BSD 4.2/3 days, which
 ran fine on 1.1.5.1 and works on 2.x from the console or serial
 ports, but not via telnet, unless you apply the patch:
 
 -----chars.c-----
 #include <stdio.h>
 #include  <sgtty.h>
 #include <sys/stat.h>
 extern char	*ttyname();
 
 static	struct  stat	ttystatus;
 int	stdin_isatty, stdout_isatty;
 char	*ttynam_stdout;
 static  struct	sgttyb	old, new;
 static	struct  stat	ttystatus;
 int	stdin_isatty, stdout_isatty;
 char	*ttynam_stdout;
 
 #define	EOT	'\004'
 static int	eof=EOT,  killc=CTRL('U'),  erase=CTRL('H'),  werase=CTRL('W');
 
 main()
 {
 	char c;
 	printf("Press these keys  [T] [E] [S] [T] [Enter] [CTRL][J] [CTRL][M] [Esc]\n");
 	save_tty();
 	set_tty();
 
 	while((c=getchar())!=EOF && c!=0x1b) {
 		printf("%02x ",c);
 	}
 
 	restore_tty();
 	printf("\nYou should see 74 65 73 74 0a 0a 0a\n");
 }
 
 
 save_tty()
 {
 	struct tchars	tc;
 	struct ltchars t;
 
 	fstat(fileno(stdout), &ttystatus);
 	ttynam_stdout = ttyname(fileno(stdout));
 	stdout_isatty = (ioctl(fileno(stdout), TIOCGETP, &old) >= 0);
 	stdin_isatty = (ioctl(fileno(stdin), TIOCGETP, &old) >= 0);
 	if (ioctl(fileno(stdin), TIOCGLTC, &t) == 0)
 		werase = (int)t.t_werasc;
 
 	killc = (int)old.sg_kill;
 	erase = (int)old.sg_erase;
 	if (ioctl(fileno(stdin), TIOCGETC, &tc) == 0)
 		eof = (int)tc.t_eofc;
 
 	new = old;
 	new.sg_flags |= CBREAK;
 	new.sg_flags &= ~ECHO;
 }
 
 set_tty()
 {
 	ioctl(fileno(stdin), TIOCSETN, &new);
 }
 
 restore_tty()
 {
 	if (stdout_isatty)
 		chmod(ttynam_stdout, (int)ttystatus.st_mode&0777);
 	if (stdin_isatty)
 		ioctl(fileno(stdin), TIOCSETP, &old);
 }
 
 -----END of chars.c-----
 
 Compile this program on FreeBSD, and then execute it and follow
 the instructions.  Telnetting into FreeBSD 2.x without the above
 patch will give incorrect results in that CTRL-J/CTRL-M entered by
 the telnet user are not read as 0x0a by the program as they are when
 the same program is run on a console or serial session.
 
 Running the program with a telnetd that is patched, OR from the console
 or serial ports will work correctly CTRL-M/CTRL-J both are read as 0x0a.
 
 The program also behaves correctly when compiled and run on
 the other platforms mentioned, demonstrating that the problem is in the
 FreeBSD telnetd because it tries to force a mode that the clients can't
 handle correctly.
 
 
 All the patch does is instruct telnetd to negotiate a character mode by
 default that all of the above telnet clients handle correctly.
 If the user wants additional link efficiency at the cost of the
 problems shown above, then by all means he/she can switch to
 LINEMODE once the telnet connection is started if that mode can be used.
 No feature or capability is taken away by the patch.
 
 Yes, we could simply have everybody using every telnet client
 everywhere have to turn off LINEMODE each time they use telnet
 to a FreeBSD platform in order for existing shells and applications
 to work via telnet.  This is the religious argument that all the
 clients everywhere are broken and the FreeBSD telnetd isn't.
 Sorry, but I don't buy this.  We must fit in with the rest of the
 universe.
 
 It still seems that the default setting should provide maximum
 compatibility, which is the case with this patch installed.
 
 
 I recommend that this change be included in 2.2-RELEASE.
 
 
 Frank Durda IV <uhclem@nemesis.lonestar.org>|"The Knights who say "LETNi"
 or uhclem%nemesis@rwsystr.nkn.net           | demand...  A SEGMENT REGISTER!!!"
 					    |"A what?"
 or ...letni!rwsys!nemesis!uhclem	    |"LETNi! LETNi! LETNi!"  - 1983
 
State-Changed-From-To: feedback->closed 
State-Changed-By: phk 
State-Changed-When: Thu Sep 18 23:40:10 PDT 1997 
State-Changed-Why:  

timed out. 
State-Changed-From-To: closed->open 
State-Changed-By: peter 
State-Changed-When: Fri Sep 19 21:31:03 PDT 1997 
State-Changed-Why:  
This is still a problem. 
State-Changed-From-To: open->closed 
State-Changed-By: uhclem 
State-Changed-When: Mon Oct 20 19:54:23 PDT 1997 
State-Changed-Why:  
bin/1037 and a relative, bin/771, are concealed (if not fixed) by a 
change to libexec/telnetd in -current. 


>Unformatted:
