earle%prophet@SUN.COM (Greg Earle) (10/18/88)
Index: gcc v 1.29, Sun-3, SunOS 4.0 Description: It appears that when programs are built with gcc, and they contain segments of code that first save the terminal parameters (via a TIOCGETP ioctl(2)) and then set the terminal into CBREAK mode, the resulting executables do not handle the ioctl properly, and the ioctl fails with errno ENOTTY. Repeat-By: Compile the public domain programs `less' and `top' on a 4.3BSD-based machine, such as a Sun running SunOS 4.0 (well, close anyway (^: ). Note that `top' only displays one set of output and it exits; when the ioctl in question fails, `top' assumes that the terminal must be a `dumb' terminal and only runs itself once. Commenting out the code that sets it to `dumb' removes this problem, but leaves `top' (and, similarly, `less') not responding properly in CBREAK mode - i.e., an input character in either should cause immediate action (e.g., `q' for `quit'), but instead the character is echoed, and action waits until a Newline is entered - i.e., the terminal isn't really in CBREAK mode at all. The same programs, compiled with PCC-based `cc', do not have this problem. For specifics, refer to the `screen.c' module (same name) in each program. Look for the line with `TIOCGETP' and the following code, in each. Fix: Unknown; though I have a suspicion that perhaps one of the include files in /usr/local/lib/gcc-include that are installed with the `fixincludes' script could be the culprit. Here's a sample chunk of the assembler output for the `init_screen' function (in `top', file `screen.c'), which does this ioctl almost immediately. Note how the value pushed for the ioctl is different from that pushed by the PCC-based `cc', by one bit; also, note that from doing just a preprocessor phase, both appear to be generating the same C, so it appears to be an error in the code generation phase. [ The PCC `cpp' output is: ] if (ioctl(1, (0x40000000|((sizeof(struct sgttyb)&0xff)<<16)|('t'<<8)| 8), &old_settings) != 0) [ The GCC `cpp' output is: ] if (ioctl(1 , ( 0x40000000 |((sizeof(struct sgttyb)&0xff )<<16)|('x'<<8)| 8) , &old_settings) != 0) ==== PCC: ==== .text .stabn 0104,0,161,LL44 LL44: .proc |#PROC# 04 .globl _init_screen _init_screen: |#PROLOGUE# 0 link a6,#0 addl #-LF100,sp moveml #LS100,sp@ |#PROLOGUE# 1 .stabn 0104,0,161,LL45 LL45: .stabn 0104,0,163,LL46 LL46: clrl _errno .stabn 0104,0,165,LL47 LL47: pea _old_settings pea 0x40067408 <=== *** Note this value pea 0x1 jbsr _ioctl lea sp@(0xc),sp tstl d0 jeq L102 .stabn 0104,0,168,LL48 LL48: clrb _smart_terminal ======== Gnu GCC: ======== LC17: .ascii "TIOCGETP ioctl(init_screen)\0" .even .globl _init_screen _init_screen: .stabd 68,0,161 link a6,#0 .stabd 68,0,163 clrl _errno .stabd 68,0,165 pea _old_settings movel #1074165768,sp@- <=== *** THIS IS 0x40067808, pea 1:w NOT 0x40067408 AS jbsr _ioctl IN THE ABOVE movel d0,d0 <=== ??? Huh? addw #12,sp tstl d0 jeq L16 .stabd 68,0,168 clrb _smart_terminal Submitted-by: Greg Earle Sun Los Angeles Consulting earle@Sun.COM