This is the mail archive of the cygwin@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

termios.ECHO problems


This might be already discussed here, but I could not find the evidence
from mail archive. So I present my findings here. See attachment.
I tested this under NT4.0 sp3 + cygwinb20.1. Since I don't have SDK,
I didn't go further to find out true cause(s) of the symptom.

Briefly stated, resetting ECHO flag from termios.c_lflag destroys the
whole content and cannot recover back to ICANON|ECHO state.
 This results in:

o fgets appears to hang if large buffer is given.
o the result string is not cooked.
o .../src/newlib/unix/getpass.c never returns since it cannot find '\n'.

The most serious is that termios doesn't have the way to restore
previous states. Does anyone have workaround aginst this ?


horio shoichi


/*-------------------------------------------------------------------------
  usage: .../a.out [-bufsiz] [-e] [-v] [-g]
        -bufsize        size of buffer to test input overflow
        -e              test echo on condition
        -g              test getc effect
        -v              watch termios.c_lflag
 
-------------------------------------------------------------------------
  */
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <termios.h>

int
main(int argc, char **argv) {
struct termios  ttydef ;
struct termios  v_ttydef ;
FILE    *tty = stdin;
char    abuff[BUFSIZ] ;
char    *p;
int     eflag = 1 ;
int     gflag = 0 ;
int     vflag = 0 ;
int     i ;
char    **a = argv + 1 ;
int     s = BUFSIZ ;
int     c_lflag ;

for (i = 1 ; i < argc ; i++, a++) {
        if (**a != '-')
                break ;
        switch (*++*a) {
        case 'e' :
                eflag = 0 ;
                break ;
                eflag = 0 ;
                break ;
        case 'g' :
                gflag = 1 ;
                break ;
        case 'v' :
                vflag = 1 ;
                break ;
        default :
                /* pick up buffer size - first doubt if it's numeric */
                for (p = *a ; *p ; p++)
                        if (*p < '0' || *p > '9')
                                fprintf(stderr, "bad buffer size\n"),
                                exit(1) ;
                /* now get buffer size */
                s = atoi(*a) ;
                if (!s || s >= BUFSIZ - 1)
                        fprintf(stderr, "bad buffer size\n"),
                        exit(1) ;
                }
        }

if (tcgetattr(fileno(tty), &ttydef) == -1)
        pperror(__LINE__) ;

if (eflag && (eflag = ttydef.c_lflag & ECHO)) {
        ttydef.c_lflag &= ~ECHO;
        if (tcsetattr(fileno(tty), TCSANOW, &ttydef) == -1)
                        /* TCSADRAIN, TCSAFLUSH give the same result */
                pperror(__LINE__) ;
        }
if (vflag) {
        c_lflag = ttydef.c_lflag ;
        printf("initial lflag = %08.8x\n", ttydef.c_lflag) ;

        memset(&v_ttydef, 0xff, sizeof(v_ttydef)) ;
        if (tcgetattr(fileno(tty), &v_ttydef) == -1)
                pperror(__LINE__) ;
        if (v_ttydef.c_lflag ^ c_lflag)
                printf("changed lflag = %08.8x\n", v_ttydef.c_lflag) ;
        }

fputs("enter any string:", stderr);
fflush(stderr);

memset(abuff, 0, sizeof(abuff)) ;
if (gflag) {
        for (p = abuff ; (i = getc(tty)) != EOF && i != '\n' && i !=
'\r' ; )
                if (p < abuff + BUFSIZ)
                        *p++ = i ;
        /* look at terminator */
        *p = i ;
        }
else {
        fgets(abuff, s, tty);
        if (feof(tty))
                pperror(__LINE__) ;
        if (ferror(tty))
                pperror(__LINE__) ;
        }

printf("strlen(abuff) = %d\n", strlen(abuff)) ;
for (p = abuff ; *p ; p++)
        printf("%02.2x", *p) ;
putchar('\n') ;

if (eflag) {
        ttydef.c_lflag |= ECHO;
        if (tcsetattr(fileno(tty), TCSANOW, &ttydef) == -1)
                pperror(__LINE__) ;
        if (vflag)
                printf("last lflag = %08.8x\n", ttydef.c_lflag) ;
        }

if (vflag) {
        if (tcgetattr(fileno(tty), &v_ttydef) == -1)
                pperror(__LINE__) ;
        printf("final lflag = %08.8x\n", v_ttydef.c_lflag) ;
#if 1
        /* is ECHO flag not recovered -- i.e., is lflag reported
correctly ? */
        fgets(abuff, s, tty);
                /* hm, still echo off. report seems true ! */
#endif
        }
}
/*----------------------------------------------------------------------------*/
int
pperror(int l) {
char    b[BUFSIZ] ;
sprintf(b, "%d", l) ;
perror(b) ;
exit(0) ;
}
/*----------------------------------------------------------------------------*/

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]