diff options
author | joe <joe> | 2013-03-03 17:57:45 (GMT) |
---|---|---|
committer | joe <joe> | 2013-03-03 17:57:45 (GMT) |
commit | 69607b4155c25df2b10866bc98b77661a846374c (patch) | |
tree | e1136405929aa268361a8243796ca0006ba81bcf /unix/tclUnixChan.c | |
parent | 2e7dd9a8aae2880a577342d8dad1b7f4ad89fbbb (diff) | |
parent | 643ff20ea533a98beebb47faea61a461f43576c1 (diff) | |
download | tcl-69607b4155c25df2b10866bc98b77661a846374c.zip tcl-69607b4155c25df2b10866bc98b77661a846374c.tar.gz tcl-69607b4155c25df2b10866bc98b77661a846374c.tar.bz2 |
Unix terminal and serial port I/O: retire obsolete termio and sgtty code,
general cleanup. See SF [Bug 3606258] for details.
Diffstat (limited to 'unix/tclUnixChan.c')
-rw-r--r-- | unix/tclUnixChan.c | 412 |
1 files changed, 98 insertions, 314 deletions
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index 9ee37f1..fdc9d1d 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -14,16 +14,9 @@ #include "tclInt.h" /* Internal definitions for Tcl. */ #include "tclIO.h" /* To get Channel type declaration. */ -#define SUPPORTS_TTY - -#undef DIRECT_BAUD -#ifdef B4800 -# if (B4800 == 4800) -# define DIRECT_BAUD -# endif /* B4800 == 4800 */ -#endif /* B4800 */ - -#ifdef USE_TERMIOS +#undef SUPPORTS_TTY +#if defined(HAVE_TERMIOS_H) +# define SUPPORTS_TTY 1 # include <termios.h> # ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> @@ -31,60 +24,29 @@ # ifdef HAVE_SYS_MODEM_H # include <sys/modem.h> # endif /* HAVE_SYS_MODEM_H */ -# define IOSTATE struct termios -# define GETIOSTATE(fd, statePtr) tcgetattr((fd), (statePtr)) -# define SETIOSTATE(fd, statePtr) tcsetattr((fd), TCSADRAIN, (statePtr)) -# define GETCONTROL(fd, intPtr) ioctl((fd), TIOCMGET, (intPtr)) -# define SETCONTROL(fd, intPtr) ioctl((fd), TIOCMSET, (intPtr)) # ifdef FIONREAD # define GETREADQUEUE(fd, int) ioctl((fd), FIONREAD, &(int)) # elif defined(FIORDCHK) # define GETREADQUEUE(fd, int) int = ioctl((fd), FIORDCHK, NULL) -# endif /* FIONREAD */ +# else +# define GETREADQUEUE(fd, int) int = 0 +# endif + # ifdef TIOCOUTQ # define GETWRITEQUEUE(fd, int) ioctl((fd), TIOCOUTQ, &(int)) -# endif /* TIOCOUTQ */ -# if defined(TIOCSBRK) && defined(TIOCCBRK) - -/* - * Can't use ?: operator below because that messes up types on either Linux or - * Solaris (the two are mutually exclusive!) - */ +# else +# define GETWRITEQUEUE(fd, int) int = 0 +# endif -# define SETBREAK(fd, flag) \ - if (flag) { \ - ioctl((fd), TIOCSBRK, NULL); \ - } else { \ - ioctl((fd), TIOCCBRK, NULL); \ - } -# endif /* TIOCSBRK&TIOCCBRK */ # if !defined(CRTSCTS) && defined(CNEW_RTSCTS) # define CRTSCTS CNEW_RTSCTS # endif /* !CRTSCTS&CNEW_RTSCTS */ # if !defined(PAREXT) && defined(CMSPAR) # define PAREXT CMSPAR # endif /* !PAREXT&&CMSPAR */ -#else /* !USE_TERMIOS */ - -#ifdef USE_TERMIO -# include <termio.h> -# define IOSTATE struct termio -# define GETIOSTATE(fd, statePtr) ioctl((fd), TCGETA, (statePtr)) -# define SETIOSTATE(fd, statePtr) ioctl((fd), TCSETAW, (statePtr)) -#else /* !USE_TERMIO */ - -#ifdef USE_SGTTY -# include <sgtty.h> -# define IOSTATE struct sgttyb -# define GETIOSTATE(fd, statePtr) ioctl((fd), TIOCGETP, (statePtr)) -# define SETIOSTATE(fd, statePtr) ioctl((fd), TIOCSETP, (statePtr)) -#else /* !USE_SGTTY */ -# undef SUPPORTS_TTY -#endif /* !USE_SGTTY */ - -#endif /* !USE_TERMIO */ -#endif /* !USE_TERMIOS */ + +#endif /* HAVE_TERMIOS_H */ /* * Helper macros to make parts of this file clearer. The macros do exactly @@ -110,18 +72,6 @@ typedef struct FileState { #ifdef SUPPORTS_TTY /* - * The following structure describes per-instance state of a tty-based - * channel. - */ - -typedef struct TtyState { - FileState fs; /* Per-instance state of the file descriptor. - * Must be the first field. */ - IOSTATE savedState; /* Initial state of device. Used to reset - * state when device closed. */ -} TtyState; - -/* * The following structure is used to set or get the serial port attributes in * a platform-independant manner. */ @@ -167,15 +117,12 @@ static void TtyGetAttributes(int fd, TtyAttrs *ttyPtr); static int TtyGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); -#ifndef DIRECT_BAUD -static int TtyGetBaud(unsigned long speed); -static unsigned long TtyGetSpeed(int baud); -#endif /* DIRECT_BAUD */ -static FileState * TtyInit(int fd, int initialize); +static int TtyGetBaud(speed_t speed); +static speed_t TtyGetSpeed(int baud); +static void TtyInit(int fd); static void TtyModemStatusStr(int status, Tcl_DString *dsPtr); static int TtyParseMode(Tcl_Interp *interp, const char *mode, - int *speedPtr, int *parityPtr, int *dataPtr, - int *stopPtr); + TtyAttrs *ttyPtr); static void TtySetAttributes(int fd, TtyAttrs *ttyPtr); static int TtySetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, @@ -573,7 +520,6 @@ FileGetHandleProc( } #ifdef SUPPORTS_TTY -#ifdef USE_TERMIOS /* *---------------------------------------------------------------------- * @@ -606,7 +552,6 @@ TtyModemStatusStr( Tcl_DStringAppendElement(dsPtr, (status & TIOCM_CD) ? "1" : "0"); #endif /* TIOCM_CD */ } -#endif /* USE_TERMIOS */ /* *---------------------------------------------------------------------- @@ -636,11 +581,9 @@ TtySetOptionProc( FileState *fsPtr = instanceData; unsigned int len, vlen; TtyAttrs tty; -#ifdef USE_TERMIOS - int flag, control, argc; + int argc; const char **argv; - IOSTATE iostate; -#endif /* USE_TERMIOS */ + struct termios iostate; len = strlen(optionName); vlen = strlen(value); @@ -650,8 +593,7 @@ TtySetOptionProc( */ if ((len > 2) && (strncmp(optionName, "-mode", len) == 0)) { - if (TtyParseMode(interp, value, &tty.baud, &tty.parity, &tty.data, - &tty.stop) != TCL_OK) { + if (TtyParseMode(interp, value, &tty) != TCL_OK) { return TCL_ERROR; } @@ -663,7 +605,6 @@ TtySetOptionProc( return TCL_OK; } -#ifdef USE_TERMIOS /* * Option -handshake none|xonxoff|rtscts|dtrdsr @@ -674,25 +615,25 @@ TtySetOptionProc( * Reset all handshake options. DTR and RTS are ON by default. */ - GETIOSTATE(fsPtr->fd, &iostate); + tcgetattr(fsPtr->fd, &iostate); CLEAR_BITS(iostate.c_iflag, IXON | IXOFF | IXANY); #ifdef CRTSCTS CLEAR_BITS(iostate.c_cflag, CRTSCTS); #endif /* CRTSCTS */ - if (strncasecmp(value, "NONE", vlen) == 0) { + if (Tcl_UtfNcasecmp(value, "NONE", vlen) == 0) { /* * Leave all handshake options disabled. */ - } else if (strncasecmp(value, "XONXOFF", vlen) == 0) { + } else if (Tcl_UtfNcasecmp(value, "XONXOFF", vlen) == 0) { SET_BITS(iostate.c_iflag, IXON | IXOFF | IXANY); - } else if (strncasecmp(value, "RTSCTS", vlen) == 0) { + } else if (Tcl_UtfNcasecmp(value, "RTSCTS", vlen) == 0) { #ifdef CRTSCTS SET_BITS(iostate.c_cflag, CRTSCTS); #else /* !CRTSTS */ UNSUPPORTED_OPTION("-handshake RTSCTS"); return TCL_ERROR; #endif /* CRTSCTS */ - } else if (strncasecmp(value, "DTRDSR", vlen) == 0) { + } else if (Tcl_UtfNcasecmp(value, "DTRDSR", vlen) == 0) { UNSUPPORTED_OPTION("-handshake DTRDSR"); return TCL_ERROR; } else { @@ -705,7 +646,7 @@ TtySetOptionProc( } return TCL_ERROR; } - SETIOSTATE(fsPtr->fd, &iostate); + tcsetattr(fsPtr->fd, TCSADRAIN, &iostate); return TCL_OK; } @@ -730,7 +671,7 @@ TtySetOptionProc( return TCL_ERROR; } - GETIOSTATE(fsPtr->fd, &iostate); + tcgetattr(fsPtr->fd, &iostate); Tcl_UtfToExternalDString(NULL, argv[0], -1, &ds); iostate.c_cc[VSTART] = *(const cc_t *) Tcl_DStringValue(&ds); @@ -741,7 +682,7 @@ TtySetOptionProc( Tcl_DStringFree(&ds); ckfree(argv); - SETIOSTATE(fsPtr->fd, &iostate); + tcsetattr(fsPtr->fd, TCSADRAIN, &iostate); return TCL_OK; } @@ -752,22 +693,22 @@ TtySetOptionProc( if ((len > 2) && (strncmp(optionName, "-timeout", len) == 0)) { int msec; - GETIOSTATE(fsPtr->fd, &iostate); + tcgetattr(fsPtr->fd, &iostate); if (Tcl_GetInt(interp, value, &msec) != TCL_OK) { return TCL_ERROR; } iostate.c_cc[VMIN] = 0; iostate.c_cc[VTIME] = (msec==0) ? 0 : (msec<100) ? 1 : (msec+50)/100; - SETIOSTATE(fsPtr->fd, &iostate); + tcsetattr(fsPtr->fd, TCSADRAIN, &iostate); return TCL_OK; } /* * Option -ttycontrol {DTR 1 RTS 0 BREAK 0} */ - if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) { - int i; +#if defined(TIOCMGET) && defined(TIOCMSET) + int i, control, flag; if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; @@ -784,44 +725,36 @@ TtySetOptionProc( return TCL_ERROR; } - GETCONTROL(fsPtr->fd, &control); + ioctl(fsPtr->fd, TIOCMGET, &control); for (i = 0; i < argc-1; i += 2) { if (Tcl_GetBoolean(interp, argv[i+1], &flag) == TCL_ERROR) { ckfree(argv); return TCL_ERROR; } - if (strncasecmp(argv[i], "DTR", strlen(argv[i])) == 0) { -#ifdef TIOCM_DTR + if (Tcl_UtfNcasecmp(argv[i], "DTR", strlen(argv[i])) == 0) { if (flag) { SET_BITS(control, TIOCM_DTR); } else { CLEAR_BITS(control, TIOCM_DTR); } -#else /* !TIOCM_DTR */ - UNSUPPORTED_OPTION("-ttycontrol DTR"); - ckfree(argv); - return TCL_ERROR; -#endif /* TIOCM_DTR */ - } else if (strncasecmp(argv[i], "RTS", strlen(argv[i])) == 0) { -#ifdef TIOCM_RTS + } else if (Tcl_UtfNcasecmp(argv[i], "RTS", strlen(argv[i])) == 0) { if (flag) { SET_BITS(control, TIOCM_RTS); } else { CLEAR_BITS(control, TIOCM_RTS); } -#else /* !TIOCM_RTS*/ - UNSUPPORTED_OPTION("-ttycontrol RTS"); - ckfree(argv); - return TCL_ERROR; -#endif /* TIOCM_RTS*/ - } else if (strncasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) { -#ifdef SETBREAK - SETBREAK(fsPtr->fd, flag); -#else /* !SETBREAK */ + } else if (Tcl_UtfNcasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) { +#if defined(TIOCSBRK) && defined(TIOCCBRK) + if (flag) { + ioctl(fsPtr->fd, TIOCSBRK, NULL); + } else { + ioctl(fsPtr->fd, TIOCCBRK, NULL); + } +#else /* TIOCSBRK & TIOCCBRK */ UNSUPPORTED_OPTION("-ttycontrol BREAK"); ckfree(argv); return TCL_ERROR; -#endif /* SETBREAK */ +#endif /* TIOCSBRK & TIOCCBRK */ } else { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -835,17 +768,16 @@ TtySetOptionProc( } } /* -ttycontrol options loop */ - SETCONTROL(fsPtr->fd, &control); + ioctl(fsPtr->fd, TIOCMSET, &control); ckfree(argv); return TCL_OK; +#else /* TIOCMGET&TIOCMSET */ + UNSUPPORTED_OPTION("-ttycontrol"); +#endif /* TIOCMGET&TIOCMSET */ } return Tcl_BadChannelOption(interp, optionName, "mode handshake timeout ttycontrol xchar"); - -#else /* !USE_TERMIOS */ - return Tcl_BadChannelOption(interp, optionName, "mode"); -#endif /* USE_TERMIOS */ } /* @@ -860,12 +792,8 @@ TtySetOptionProc( * * Results: * A standard Tcl result. Also sets the supplied DString to the string - * value of the option(s) returned. - * - * Side effects: - * The string returned by this function is in static storage and may be - * reused at any time subsequent to the call. Sets error message if - * needed (by calling Tcl_BadChannelOption). + * value of the option(s) returned. Sets error message if needed + * (by calling Tcl_BadChannelOption). * *---------------------------------------------------------------------- */ @@ -899,7 +827,6 @@ TtyGetOptionProc( Tcl_DStringAppendElement(dsPtr, buf); } -#ifdef USE_TERMIOS /* * Get option -xchar */ @@ -909,11 +836,11 @@ TtyGetOptionProc( Tcl_DStringStartSublist(dsPtr); } if (len==0 || (len>1 && strncmp(optionName, "-xchar", len)==0)) { - IOSTATE iostate; + struct termios iostate; Tcl_DString ds; valid = 1; - GETIOSTATE(fsPtr->fd, &iostate); + tcgetattr(fsPtr->fd, &iostate); Tcl_DStringInit(&ds); Tcl_ExternalToUtfDString(NULL, (char *) &iostate.c_cc[VSTART], 1, &ds); @@ -938,12 +865,8 @@ TtyGetOptionProc( int inQueue=0, outQueue=0, inBuffered, outBuffered; valid = 1; -#ifdef GETREADQUEUE GETREADQUEUE(fsPtr->fd, inQueue); -#endif /* GETREADQUEUE */ -#ifdef GETWRITEQUEUE GETWRITEQUEUE(fsPtr->fd, outQueue); -#endif /* GETWRITEQUEUE */ inBuffered = Tcl_InputBuffered(fsPtr->channel); outBuffered = Tcl_OutputBuffered(fsPtr->channel); @@ -953,37 +876,31 @@ TtyGetOptionProc( Tcl_DStringAppendElement(dsPtr, buf); } +#if defined(TIOCMGET) /* * Get option -ttystatus * Option is readonly and returned by [fconfigure chan -ttystatus] but not * returned by unnamed [fconfigure chan]. */ - if ((len > 4) && (strncmp(optionName, "-ttystatus", len) == 0)) { int status; valid = 1; - GETCONTROL(fsPtr->fd, &status); + ioctl(fsPtr->fd, TIOCMGET, &status); TtyModemStatusStr(status, dsPtr); } -#endif /* USE_TERMIOS */ +#endif /* TIOCMGET */ if (valid) { return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, "mode" -#ifdef USE_TERMIOS " queue ttystatus xchar" -#endif /* USE_TERMIOS */ ); } -#ifdef DIRECT_BAUD -# define TtyGetSpeed(baud) ((unsigned) (baud)) -# define TtyGetBaud(speed) ((int) (speed)) -#else /* !DIRECT_BAUD */ -static const struct {int baud; unsigned long speed;} speeds[] = { +static const struct {int baud; speed_t speed;} speeds[] = { #ifdef B0 {0, B0}, #endif @@ -1079,20 +996,16 @@ static const struct {int baud; unsigned long speed;} speeds[] = { * * TtyGetSpeed -- * - * Given a baud rate, get the mask value that should be stored in the - * termios, termio, or sgttyb structure in order to select that baud - * rate. + * Given an integer baud rate, get the speed_t value that should be + * used to select that baud rate. * * Results: * As above. * - * Side effects: - * None. - * *--------------------------------------------------------------------------- */ -static unsigned long +static speed_t TtyGetSpeed( int baud) /* The baud rate to look up. */ { @@ -1125,21 +1038,17 @@ TtyGetSpeed( * * TtyGetBaud -- * - * Given a speed mask value from a termios, termio, or sgttyb structure, - * get the baus rate that corresponds to that mask value. + * Return the integer baud rate corresponding to a given speed_t value. * * Results: * As above. If the mask value was not recognized, 0 is returned. * - * Side effects: - * None. - * *--------------------------------------------------------------------------- */ static int TtyGetBaud( - unsigned long speed) /* Speed mask value to look up. */ + speed_t speed) /* Speed mask value to look up. */ { int i; @@ -1150,7 +1059,6 @@ TtyGetBaud( } return 0; } -#endif /* !DIRECT_BAUD */ /* *--------------------------------------------------------------------------- @@ -1175,12 +1083,11 @@ TtyGetAttributes( TtyAttrs *ttyPtr) /* Buffer filled with serial port * attributes. */ { - IOSTATE iostate; + struct termios iostate; int baud, parity, data, stop; - GETIOSTATE(fd, &iostate); + tcgetattr(fd, &iostate); -#ifdef USE_TERMIOS baud = TtyGetBaud(cfgetospeed(&iostate)); parity = 'n'; @@ -1202,39 +1109,6 @@ TtyGetAttributes( data = (data == CS5) ? 5 : (data == CS6) ? 6 : (data == CS7) ? 7 : 8; stop = (iostate.c_cflag & CSTOPB) ? 2 : 1; -#endif /* USE_TERMIOS */ - -#ifdef USE_TERMIO - baud = TtyGetBaud(iostate.c_cflag & CBAUD); - - parity = 'n'; - switch (iostate.c_cflag & (PARENB | PARODD | PAREXT)) { - case PARENB : parity = 'e'; break; - case PARENB | PARODD : parity = 'o'; break; - case PARENB | PAREXT : parity = 's'; break; - case PARENB | PARODD | PAREXT : parity = 'm'; break; - } - - data = iostate.c_cflag & CSIZE; - data = (data == CS5) ? 5 : (data == CS6) ? 6 : (data == CS7) ? 7 : 8; - - stop = (iostate.c_cflag & CSTOPB) ? 2 : 1; -#endif /* USE_TERMIO */ - -#ifdef USE_SGTTY - baud = TtyGetBaud(iostate.sg_ospeed); - - parity = 'n'; - if (iostate.sg_flags & EVENP) { - parity = 'e'; - } else if (iostate.sg_flags & ODDP) { - parity = 'o'; - } - - data = (iostate.sg_flags & (EVENP | ODDP)) ? 7 : 8; - - stop = 1; -#endif /* USE_SGTTY */ ttyPtr->baud = baud; ttyPtr->parity = parity; @@ -1265,12 +1139,10 @@ TtySetAttributes( TtyAttrs *ttyPtr) /* Buffer containing new attributes for serial * port. */ { - IOSTATE iostate; - -#ifdef USE_TERMIOS + struct termios iostate; int parity, data, flag; - GETIOSTATE(fd, &iostate); + tcgetattr(fd, &iostate); cfsetospeed(&iostate, TtyGetSpeed(ttyPtr->baud)); cfsetispeed(&iostate, TtyGetSpeed(ttyPtr->baud)); @@ -1300,58 +1172,7 @@ TtySetAttributes( CLEAR_BITS(iostate.c_cflag, PARENB | PARODD | CSIZE | CSTOPB); SET_BITS(iostate.c_cflag, flag); -#endif /* USE_TERMIOS */ - -#ifdef USE_TERMIO - int parity, data, flag; - - GETIOSTATE(fd, &iostate); - CLEAR_BITS(iostate.c_cflag, CBAUD); - SET_BITS(iostate.c_cflag, TtyGetSpeed(ttyPtr->baud)); - - flag = 0; - parity = ttyPtr->parity; - if (parity != 'n') { - SET_BITS(flag, PARENB); - if ((parity == 'm') || (parity == 's')) { - SET_BITS(flag, PAREXT); - } - if ((parity == 'm') || (parity == 'o')) { - SET_BITS(flag, PARODD); - } - } - data = ttyPtr->data; - SET_BITS(flag, - (data == 5) ? CS5 : - (data == 6) ? CS6 : - (data == 7) ? CS7 : CS8); - if (ttyPtr->stop == 2) { - SET_BITS(flag, CSTOPB); - } - - CLEAR_BITS(iostate.c_cflag, PARENB | PARODD | PAREXT | CSIZE | CSTOPB); - SET_BITS(iostate.c_cflag, flag); - -#endif /* USE_TERMIO */ - -#ifdef USE_SGTTY - int parity; - - GETIOSTATE(fd, &iostate); - iostate.sg_ospeed = TtyGetSpeed(ttyPtr->baud); - iostate.sg_ispeed = TtyGetSpeed(ttyPtr->baud); - - parity = ttyPtr->parity; - if (parity == 'e') { - CLEAR_BITS(iostate.sg_flags, ODDP); - SET_BITS(iostate.sg_flags, EVENP); - } else if (parity == 'o') { - CLEAR_BITS(iostate.sg_flags, EVENP); - SET_BITS(iostate.sg_flags, ODDP); - } -#endif /* USE_SGTTY */ - - SETIOSTATE(fd, &iostate); + tcsetattr(fd, TCSADRAIN, &iostate); } /* @@ -1367,9 +1188,6 @@ TtySetAttributes( * TCL_ERROR otherwise. If TCL_ERROR is returned, an error message is * left in the interp's result (if interp is non-NULL). * - * Side effects: - * None. - * *--------------------------------------------------------------------------- */ @@ -1377,17 +1195,17 @@ static int TtyParseMode( Tcl_Interp *interp, /* If non-NULL, interp for error return. */ const char *mode, /* Mode string to be parsed. */ - int *speedPtr, /* Filled with baud rate from mode string. */ - int *parityPtr, /* Filled with parity from mode string. */ - int *dataPtr, /* Filled with data bits from mode string. */ - int *stopPtr) /* Filled with stop bits from mode string. */ + TtyAttrs *ttyPtr) /* Filled with data from mode string */ { int i, end; char parity; - static const char *bad = "bad value for -mode"; + const char *bad = "bad value for -mode"; - i = sscanf(mode, "%d,%c,%d,%d%n", speedPtr, &parity, dataPtr, - stopPtr, &end); + i = sscanf(mode, "%d,%c,%d,%d%n", + &ttyPtr->baud, + &parity, + &ttyPtr->data, + &ttyPtr->stop, &end); if ((i != 4) || (mode[end] != '\0')) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -1407,27 +1225,27 @@ TtyParseMode( */ if ( -#if defined(PAREXT) || defined(USE_TERMIO) +#if defined(PAREXT) strchr("noems", parity) #else strchr("noe", parity) -#endif /* PAREXT|USE_TERMIO */ +#endif /* PAREXT */ == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s parity: should be %s", bad, -#if defined(PAREXT) || defined(USE_TERMIO) +#if defined(PAREXT) "n, o, e, m, or s" #else "n, o, or e" -#endif /* PAREXT|USE_TERMIO */ +#endif /* PAREXT */ )); Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL); } return TCL_ERROR; } - *parityPtr = parity; - if ((*dataPtr < 5) || (*dataPtr > 8)) { + ttyPtr->parity = parity; + if ((ttyPtr->data < 5) || (ttyPtr->data > 8)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s data: should be 5, 6, 7, or 8", bad)); @@ -1435,7 +1253,7 @@ TtyParseMode( } return TCL_ERROR; } - if ((*stopPtr < 0) || (*stopPtr > 2)) { + if ((ttyPtr->stop < 0) || (ttyPtr->stop > 2)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s stop: should be 1 or 2", bad)); @@ -1453,71 +1271,38 @@ TtyParseMode( * * Given file descriptor that refers to a serial port, initialize the * serial port to a set of sane values so that Tcl can talk to a device - * located on the serial port. Note that no initialization happens if the - * initialize flag is not set; this is necessary for the correct handling - * of UNIX console TTYs at startup. - * - * Results: - * A pointer to a FileState suitable for use with Tcl_CreateChannel and - * the ttyChannelType structure. + * located on the serial port. * * Side effects: * Serial device initialized to non-blocking raw mode, similar to sockets - * (if initialize flag is non-zero.) All other modes can be simulated on - * top of this in Tcl. + * All other modes can be simulated on top of this in Tcl. * *--------------------------------------------------------------------------- */ -static FileState * +static void TtyInit( - int fd, /* Open file descriptor for serial port to be - * initialized. */ - int initialize) + int fd) /* Open file descriptor for serial port to be initialized. */ { - TtyState *ttyPtr = ckalloc(sizeof(TtyState)); - int stateUpdated = 0; - - GETIOSTATE(fd, &ttyPtr->savedState); - if (initialize) { - IOSTATE iostate = ttyPtr->savedState; - -#if defined(USE_TERMIOS) || defined(USE_TERMIO) - if (iostate.c_iflag != IGNBRK - || iostate.c_oflag != 0 - || iostate.c_lflag != 0 - || iostate.c_cflag & CREAD - || iostate.c_cc[VMIN] != 1 - || iostate.c_cc[VTIME] != 0) { - stateUpdated = 1; - } + struct termios iostate; + tcgetattr(fd, &iostate); + + if (iostate.c_iflag != IGNBRK + || iostate.c_oflag != 0 + || iostate.c_lflag != 0 + || iostate.c_cflag & CREAD + || iostate.c_cc[VMIN] != 1 + || iostate.c_cc[VTIME] != 0) + { iostate.c_iflag = IGNBRK; iostate.c_oflag = 0; iostate.c_lflag = 0; - SET_BITS(iostate.c_cflag, CREAD); + iostate.c_cflag |= CREAD; iostate.c_cc[VMIN] = 1; iostate.c_cc[VTIME] = 0; -#endif /* USE_TERMIOS|USE_TERMIO */ - -#ifdef USE_SGTTY - if ((iostate.sg_flags & (EVENP | ODDP)) - || !(iostate.sg_flags & RAW)) { - ttyPtr->stateUpdated = 1; - } - iostate.sg_flags &= EVENP | ODDP; - SET_BITS(iostate.sg_flags, RAW); -#endif /* USE_SGTTY */ - - /* - * Only update if we're changing anything to avoid possible blocking. - */ - if (stateUpdated) { - SETIOSTATE(fd, &iostate); - } + tcsetattr(fd, TCSADRAIN, &iostate); } - - return &ttyPtr->fs; } #endif /* SUPPORTS_TTY */ @@ -1621,15 +1406,15 @@ TclpOpenFileChannel( translation = "auto crlf"; channelTypePtr = &ttyChannelType; - fsPtr = TtyInit(fd, 1); + TtyInit(fd); } else #endif /* SUPPORTS_TTY */ { translation = NULL; channelTypePtr = &fileChannelType; - fsPtr = ckalloc(sizeof(FileState)); } + fsPtr = ckalloc(sizeof(FileState)); fsPtr->validMask = channelPermissions | TCL_EXCEPTION; fsPtr->fd = fd; @@ -1692,7 +1477,6 @@ Tcl_MakeFileChannel( #ifdef SUPPORTS_TTY if (isatty(fd)) { - fsPtr = TtyInit(fd, 0); channelTypePtr = &ttyChannelType; sprintf(channelName, "serial%d", fd); } else @@ -1703,10 +1487,10 @@ Tcl_MakeFileChannel( return TclpMakeTcpClientChannelMode(INT2PTR(fd), mode); } else { channelTypePtr = &fileChannelType; - fsPtr = ckalloc(sizeof(FileState)); sprintf(channelName, "file%d", fd); } + fsPtr = ckalloc(sizeof(FileState)); fsPtr->fd = fd; fsPtr->validMask = mode | TCL_EXCEPTION; fsPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName, |