leo@philmds.UUCP (Leo de Wit) (10/04/88)
When porting a database application to Ultrix (Oracle dbms), I found out we had to use System V libraries (grrr 8-), since the Oracle libraries depended upon them. I don't want to discuss whether Oracle's decision to not use the native libraries is a correct one (maybe some other time 8-), but you can imagine some of our code had to be rewritten (most of the Unix specific stuff had already been written before we had Oracle running on Ultrix and were aware of this problem). The problem: I want to read characters from a terminal, without echo and not having to wait for a newline. After each character I might do some processing, based on the character read. The old solution did something along the lines of: #include <sgtty.h> struct sgttyb newbuf, oldbuf; /* oldbuf needed for restoring afterwards */ ioctl(0,TIOCGETP,&oldbuf); newbuf = oldbuf; newbuf.sg_flags &= ~ECHO; newbuf.sg_flags |= CBREAK; ioctl(0,TIOCSETP,&newbuf); and now filedescriptor 0 is OK for my purposes (I can use stdio or whatever from now on and all works great). Using System V's terminal modes there seems to be no real equivalent of 'cbreak'; so I had to use non-canonical mode to be able to read on a per character basis (right ?). We don't have System V manuals around and the Ultrix manuals weren't such great help on this point; most things I found out using Sun manuals and include files (e.g. termio(4V)). I got this far: #include <sys/termio.h> struct termio newbuf, oldbuf; /* oldbuf needed for restoring afterwards */ ioctl(0,TCGETA,&oldbuf); newbuf = oldbuf; newbuf.c_lflag &= ~(ECHO|ICANON); ioctl(0,TCSETA,&newbuf); Input is indeed not echoed and on a per character basis. However, the newlines printed to my terminal (using fd 1 via printf's) are not translated; so I get a simple newline, instead of newline & carriage return. I tried to solve this by specifying newbuf.c_oflag |= OPOST|ONLRET; but setting this and reinspecting with TCGETA revealed that the OPOST bit was cleared! (and of course the output again cluttered over the screen). Experimenting with ICANON and OPOST showed that whenever the ICANON bit was off in the local flag, the OPOST bit was cleared in the output flag, so it seems to be impossible to do post-processing whenever the mode is non-canonical. I also tried ioctl's on filedescriptor 1, but they have the same effect (setting fd 0 sets also fd 1 and vice versa, which is perhaps reasonable if you consider they affect the same device). I also tried using TIOCSETP and sgttyb structs (they seem to be defined in the include files if the symbol SYSTEM_FIVE is defined) but to no avail. I compile and link using the -Y flag of /bin/cc which should be sufficient to select the correct parts of include files and the correct libraries. Any help is very much appreciated! Leo.
asmodeus@tree.UUCP (Jonathan Ballard) (10/06/88)
In article <829@philmds.UUCP>, leo@philmds.UUCP (Leo de Wit) writes: > > When porting a database application to Ultrix (Oracle dbms), I found > out we had to use System V libraries (grrr 8-), since the Oracle > libraries depended upon them. I don't want to discuss whether Oracle's ... [stuff deleted] > The problem: > I want to read characters from a terminal, without echo and not having > to wait for a newline. After each character I might do some processing, > based on the character read. The old solution did something along the ...[more stuff deleted] This code here is what I used also... > > #include <sys/termio.h> > > struct termio newbuf, oldbuf; /* oldbuf needed for restoring afterwards */ > > ioctl(0,TCGETA,&oldbuf); > newbuf = oldbuf; > newbuf.c_lflag &= ~(ECHO|ICANON); > ioctl(0,TCSETA,&newbuf); > Have you triing using a switch() to post process what you need? This is what i use. If your just looking for a return you could do something like... c=getchar(); switch(c) { case RETURN : printf("\n"); break; default : printf(c); break; } RETURN could be the real value or '\n' if you want to go by how the compiler would implement it. This is how I get the terminal set... #include <termio.h> /* include needed */ struct termio save, term; /* global varibles used */ /* check and see if terminal */ if ( ioctl (0, TCGETA, &term) == -1 ) { fprintf (stderr, "standard input not a tty\n"); exit (1); } /* set terminal for one-char input */ save = term; term.c_lflag &= ~ICANON; /* single key input ready */ term.c_lflag &= ~ECHO; /* turn off echo */ term.c_cc[VMIN] = 1; /* minimal of one key for input being ready */ term.c_cc[VTIME] = 0; /* turn off time-out */ ioctl (0, TCSETA, &term); /* to reset old tty state */ ioctl (0, TCSETA, &save); That seems to be the usual way other programmers use too... Well.. hope it helps... -- _ | | \ UUCP e-mail: ..!{csusac,pacbell}!sactoh0!jhballar | |-< ..!{csusac,pacbell}!sactoh0!tree!asmodeus |__|on |_/allard ..!csusac!tree!asmodeus