guy@sun.uucp (Guy Harris) (08/10/85)
Everybody should read this; it contains a brief summary of the two main terminal drivers out there - V7 (of which 4.xBSD is a derivative) and S3/S5. With any luck this will answer all questions on this topic that would otherwise have been posted to the net - at least for the next few months. > Everything seems to work except for a few ioctl system calls in the > main routine. (Which, BTW, is nice to hear after all the flaming about incompatibilities between V7/4.xBSD and S3/S5 systems; see, it doesn't *have* to be that bad...) > I changed tchars to termio structs. Also, I had to change TIOCGETs to > TCGETs, TIOCSETs to TCSETs. The problem I'm having is with the TIOCSETN > call - this call returns -1 and I can't seem to track the problem down. TIOCSETP waits till any queued-up output drains, flushes any queued-up input, and sets the modes. TIOCSETN doesn't wait for the output to drain or flush the input. You have to convert TIOCSETN to TCSETA, just as you convert TIOCSETP to TCSETAF (not TCSETA - TCSETA neither waits nor flushes, TCSETAW waits but doesn't flush, and TCSETAF waits and flushes - no, you didn't stumble into net.plumbing by mistake :-)). I presume you were issuing TIOCSETN calls under RTU (which is S3/S5 based); they aren't implementeded in S3/S5 systems. TIOCGETP and TIOCSETP are implemented, but are not compatible with V7 and should not be used. Any TIOCGETP or TIOCSETP calls (or any "gtty" or "stty" calls) should be converted. The rules for "straightforward" calls: V7/4.xBSD: TIOCGETP and TIOCGETC get the modes and some special characters, and the rest of the special characters, respectively. Similarly, TIOCSETP and TIOCSETC set what the matching TIOCGETs get. TIOC[GS]ETP uses a "struct sgttyb", included by "sgtty.h" or "sys/ioctl.h", and TIOC[GS]ETC uses a "struct tchars", included by one or the other of those include files. S3/S5: TCGETA and TCSETA get and set all the modes and special characters, respectively. They use a "struct termio" included by "termio.h". The items you can set and get are: 1) Baud rates. The names for the baud rates are the same (B1200, B2400, B9600, etc.). In the "sgttyb" structure, there are two speeds - one for input and one for output. They are in "sg_ispeed" and "sg_ospeed". In the "termio" structure, they are part of the "c_cflag" word. The bit mask for the baud rate portion is CBAUD, so the baud rate is "c_cflag&CBAUD". You set the baud rate by doing "c_cflag &= ~CBAUD" and then ORing in the baud rate. 2) Special characters. The erase and kill characters are in the "sgttyb" structure in "sg_erase" and "sg_kill". The other characters are in the "tchars" structure: interrupt in "t_intrc", the quit character in "t_quitc", the end-of-file character in "t_eofc", and the "secondary EOL character" in "t_brkc". There is an array "c_cc" in the "termio" structure which holds all the special characters. The #defines for the indices into this array are: VERASE erase character VKILL kill character VINTR interrupt character VQUIT quit character VEOF end-of-file character VEOL "secondary EOL character" 3) Modes. This is the tricky part. Instead of describing all the bits, I'll just list common modes and how they're set in both drivers. No-echo mode - i.e., what the user types isn't echoed by the operating system, but is either echoed by the application (like a screen editor) or not at all (like when typing in a password). To go into no-echo mode in the V7 driver, clear the ECHO bit in the "sg_flags" word. To go into no-echo mode in the S3/S5 driver, clear the ECHO bit in the "c_lflag" word. Carriage-return/new-line mapping. To turn on mapping of CR to NL on input, and NL to CR/LF on output, turn on the CRMOD bit in the "sg_flags" word in V7, and turn on: the ICRNL bit in the "c_iflag" word the OPOST and ONLCR bits in the "c_oflag" word in the S3/S5 driver. To turn this mapping off, turn off the CRMOD bit in the V7 driver, and turn off ICRNL and ONLCR, but *not* necessarily OPOST, in S3/S5. Case-mapping (for those of you with 19th century upper-case-only terminals). To turn case-mappng on, turn on the LCASE bit in the "sg_flags" word in V7, and turn on: the IUCLC bit in the "c_iflag" word the OPOST and OLCUC bit in the "c_oflag" word the XCASE bit in the "c_lflag" word in S3/S5. To turn it off, turn LCASE off in V7, and turn IUCLC, OLCUC, and XCASE, but again *not* necessarily OPOST, in S3/S5. Tab-expansion. To turn off tab expansion, select any "tab delay" value (which is stored in part of the "sg_flags" word in V7 and part of the "c_oflag" word in S3/S5) other than XTABS in V7 and other than TAB3 in S3/S5. To turn tab expansion on, select XTABS in V7 and select TAB3 and turn on OPOST in S3/S5. Turning off *all* output processing - used, for example, when you're running a full-screen application and want every character you output to go to the terminal as is. You have to turn LCASE, CRMOD, and tab-expansion and (possibly) delays off individually in V7. You can just turn off OPOST in the "c_oflag" word in S3/S5 - in fact, this is the way it should be done, because it's faster than turning off the individual mappings and delays. Turning off the interrupt characters. Set them to '\377' in V7; you can also do this in S3/S5, but a better way to do it is to turn off the ISIG bit in the "c_lflag" word. Turning off erase/kill handling and getting each character as type - the mode that most full-screen programs, like "vi", run in. To do this, just turn on the CBREAK bit in the "sg_flags" word in V7. Turn *off* the ICANON bit in the "c_lflag" word in S3/S5. You should also save the values of the VEOF and VEOL characters (but then you're probably saving the whole mode structure anyway), because they change their meanings if ICANON is turned off, and their old values cause problems. Set "c_cc[VMIN]" to 1 and "c_cc[VTIME]" to 0. (Other values may be more efficient, but this is just as good as V7's and is nice and simple.) Getting 8-bit raw data, such as when talking to another computer. To do this just turn on the RAW bit in the "sg_flags" word in V7. It's more complicated in S3/S5. First, save the "termio" structure if you plan to restore the modes; it's simpler that way. Then: clear the ISTRIP, INLCR, IGNCR, ICRNL, IUCLC, and IXON bits in the "c_iflag" word. (If you don't want "break"s to interrupt you, turn off BRKINT as well.) clear the OPOST bit in the "c_oflag" word. clear the "character size" portion of the "c_cflag" word, as well as the PARENB and PARODD bits (i.e., do an & ~flags with "flags" equal to CSIZE|PARENB|PARODD) and OR in CS8 (to request 8 bits per character and no parity bit). clear the ISIG, ICANON, and XCASE bits in the "c_lflag" word. Also set VMIN to 1 and VTIME to 0. Guy Harris