📄 tclunixchan.c
字号:
ttyPtr->data = (data == CS5) ? 5 : (data == CS6) ? 6 : (data == CS7) ? 7 : 8; ttyPtr->stop = (termio.c_cflag & CSTOPB) ? 2 : 1;#else /* !USE_TERMIO */#ifdef USE_SGTTY int parity; struct sgttyb sgttyb; ioctl(fd, TIOCGETP, &sgttyb); ttyPtr->baud = TtyGetBaud(sgttyb.sg_ospeed); parity = 'n'; if (sgttyb.sg_flags & EVENP) { parity = 'e'; } else if (sgttyb.sg_flags & ODDP) { parity = 'o'; } ttyPtr->parity = parity; ttyPtr->data = (sgttyb.sg_flags & (EVENP | ODDP)) ? 7 : 8; ttyPtr->stop = 1;#else /* !USE_SGTTY */ ttyPtr->baud = 0; ttyPtr->parity = 'n'; ttyPtr->data = 0; ttyPtr->stop = 0;#endif /* !USE_SGTTY */#endif /* !USE_TERMIO */#endif /* !USE_TERMIOS */}/* *--------------------------------------------------------------------------- * * TtySetAttributes -- * * Set the current attributes of the specified serial device. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static voidTtySetAttributes(fd, ttyPtr) int fd; /* Open file descriptor for serial port to * be modified. */ TtyAttrs *ttyPtr; /* Buffer containing new attributes for * serial port. */{#ifdef USE_TERMIOS int parity, data, flag; struct termios termios; tcgetattr(fd, &termios); cfsetospeed(&termios, TtyGetSpeed(ttyPtr->baud)); cfsetispeed(&termios, TtyGetSpeed(ttyPtr->baud)); flag = 0; parity = ttyPtr->parity; if (parity != 'n') { flag |= PARENB;#ifdef PAREXT termios.c_cflag &= ~PAREXT; if ((parity == 'm') || (parity == 's')) { flag |= PAREXT; }#endif if ((parity == 'm') || (parity == 'o')) { flag |= PARODD; } } data = ttyPtr->data; flag |= (data == 5) ? CS5 : (data == 6) ? CS6 : (data == 7) ? CS7 : CS8; if (ttyPtr->stop == 2) { flag |= CSTOPB; } termios.c_cflag &= ~(PARENB | PARODD | CSIZE | CSTOPB); termios.c_cflag |= flag; tcsetattr(fd, TCSANOW, &termios);#else /* !USE_TERMIOS */#ifdef USE_TERMIO int parity, data, flag; struct termio termio; ioctl(fd, TCGETA, &termio); termio.c_cflag &= ~CBAUD; termio.c_cflag |= TtyGetSpeed(ttyPtr->baud); flag = 0; parity = ttyPtr->parity; if (parity != 'n') { flag |= PARENB; if ((parity == 'm') || (parity == 's')) { flag |= PAREXT; } if ((parity == 'm') || (parity == 'o')) { flag |= PARODD; } } data = ttyPtr->data; flag |= (data == 5) ? CS5 : (data == 6) ? CS6 : (data == 7) ? CS7 : CS8; if (ttyPtr->stop == 2) { flag |= CSTOPB; } termio.c_cflag &= ~(PARENB | PARODD | PAREXT | CSIZE | CSTOPB); termio.c_cflag |= flag; ioctl(fd, TCSETAW, &termio);#else /* !USE_TERMIO */#ifdef USE_SGTTY int parity; struct sgttyb sgttyb; ioctl(fd, TIOCGETP, &sgttyb); sgttyb.sg_ospeed = TtyGetSpeed(ttyPtr->baud); sgttyb.sg_ispeed = TtyGetSpeed(ttyPtr->baud); parity = ttyPtr->parity; if (parity == 'e') { sgttyb.sg_flags &= ~ODDP; sgttyb.sg_flags |= EVENP; } else if (parity == 'o') { sgttyb.sg_flags &= ~EVENP; sgttyb.sg_flags |= ODDP; } ioctl(fd, TIOCSETP, &sgttyb);#endif /* USE_SGTTY */#endif /* !USE_TERMIO */#endif /* !USE_TERMIOS */}/* *--------------------------------------------------------------------------- * * TtyParseMode -- * * Parse the "-mode" argument to the fconfigure command. The argument * is of the form baud,parity,data,stop. * * Results: * The return value is TCL_OK if the argument was successfully * parsed, TCL_ERROR otherwise. If TCL_ERROR is returned, an * error message is left in interp->result (if interp is non-NULL). * * Side effects: * None. * *--------------------------------------------------------------------------- */ static intTtyParseMode(interp, mode, speedPtr, parityPtr, dataPtr, stopPtr) 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. */{ int i, end; char parity; static char *bad = "bad value for -mode"; i = sscanf(mode, "%d,%c,%d,%d%n", speedPtr, &parity, dataPtr, stopPtr, &end); if ((i != 4) || (mode[end] != '\0')) { if (interp != NULL) { Tcl_AppendResult(interp, bad, ": should be baud,parity,data,stop", NULL); } return TCL_ERROR; } if (strchr("noems", parity) == NULL) { if (interp != NULL) { Tcl_AppendResult(interp, bad, " parity: should be n, o, e, m, or s", NULL); } return TCL_ERROR; } *parityPtr = parity; if ((*dataPtr < 5) || (*dataPtr > 8)) { if (interp != NULL) { Tcl_AppendResult(interp, bad, " data: should be 5, 6, 7, or 8", NULL); } return TCL_ERROR; } if ((*stopPtr < 0) || (*stopPtr > 2)) { if (interp != NULL) { Tcl_AppendResult(interp, bad, " stop: should be 1 or 2", NULL); } return TCL_ERROR; } return TCL_OK;}/* *---------------------------------------------------------------------- * * TclpOpenFileChannel -- * * Open an file based channel on Unix systems. * * Results: * The new channel or NULL. If NULL, the output argument * errorCodePtr is set to a POSIX error and an error message is * left in interp->result if interp is not NULL. * * Side effects: * May open the channel and may cause creation of a file on the * file system. * *---------------------------------------------------------------------- */Tcl_ChannelTclpOpenFileChannel(interp, fileName, modeString, permissions) Tcl_Interp *interp; /* Interpreter for error reporting; * can be NULL. */ char *fileName; /* Name of file to open. */ char *modeString; /* A list of POSIX open modes or * a string such as "rw". */ int permissions; /* If the open involves creating a * file, with what modes to create * it? */{ int fd, seekFlag, mode, channelPermissions; FileState *fsPtr; char *nativeName, channelName[20]; Tcl_DString buffer; Tcl_ChannelType *channelTypePtr; mode = TclGetOpenMode(interp, modeString, &seekFlag); if (mode == -1) { return NULL; } switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: channelPermissions = TCL_READABLE; break; case O_WRONLY: channelPermissions = TCL_WRITABLE; break; case O_RDWR: channelPermissions = (TCL_READABLE | TCL_WRITABLE); break; default: /* * This may occurr if modeString was "", for example. */ panic("TclpOpenFileChannel: invalid mode value"); return NULL; } nativeName = Tcl_TranslateFileName(interp, fileName, &buffer); if (nativeName == NULL) { return NULL; } fd = open(nativeName, mode, permissions); /* * If nativeName is not NULL, the buffer is valid and we must free * the storage. */ Tcl_DStringFree(&buffer); if (fd < 0) { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "couldn't open \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); } return NULL; } /* * Set close-on-exec flag on the fd so that child processes will not * inherit this fd. */ fcntl(fd, F_SETFD, FD_CLOEXEC); sprintf(channelName, "file%d", fd); fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState)); fsPtr->nextPtr = firstFilePtr; firstFilePtr = fsPtr; fsPtr->validMask = channelPermissions | TCL_EXCEPTION; fsPtr->fd = fd; if (isatty(fd)) { /* * Initialize the serial port to a set of sane parameters. * Especially important if the remote device is set to echo and * the serial port driver was also set to echo -- as soon as a char * were sent to the serial port, the remote device would echo it, * then the serial driver would echo it back to the device, etc. */ TtyInit(fd); channelTypePtr = &ttyChannelType; } else { channelTypePtr = &fileChannelType; } fsPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName, (ClientData) fsPtr, channelPermissions); if (seekFlag) { if (Tcl_Seek(fsPtr->channel, 0, SEEK_END) < 0) { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "couldn't seek to end of file on \"", channelName, "\": ", Tcl_PosixError(interp), NULL); } Tcl_Close(NULL, fsPtr->channel); return NULL; } } if (channelTypePtr == &ttyChannelType) { /* * Gotcha. Most modems need a "\r" at the end of the command * sequence. If you just send "at\n", the modem will not respond * with "OK" because it never got a "\r" to actually invoke the * command. So, by default, newlines are translated to "\r\n" on * output to avoid "bug" reports that the serial port isn't working. */ if (Tcl_SetChannelOption(interp, fsPtr->channel, "-translation", "auto crlf") != TCL_OK) { Tcl_Close(NULL, fsPtr->channel); return NULL; } } return fsPtr->channel;}/* *---------------------------------------------------------------------- * * Tcl_MakeFileChannel -- * * Makes a Tcl_Channel from an existing OS level file handle. * * Results: * The Tcl_Channel created around the preexisting OS level file handle. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_MakeFileChannel(handle, mode) ClientData handle; /* OS level handle. */ int mode; /* ORed combination of TCL_READABLE and * TCL_WRITABLE to indicate file mode. */{ FileState *fsPtr; char channelName[20]; int fd = (int) handle; if (mode == 0) { return NULL; } sprintf(channelName, "file%d", fd); /* * Look to see if a channel with this fd and the same mode already exists. * If the fd is used, but the mode doesn't match, return NULL. */ for (fsPtr = firstFilePtr; fsPtr != NULL; fsPtr = fsPtr->nextPtr) { if (fsPtr->fd == fd) { return (mode == fsPtr->validMask) ? fsPtr->channel : NULL; } } fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState)); fsPtr->nextPtr = firstFilePtr; firstFilePtr = fsPtr; fsPtr->fd = fd; fsPtr->validMask = mode | TCL_EXCEPTION; fsPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName, (ClientData) fsPtr, mode); return fsPtr->channel;}/* *---------------------------------------------------------------------- * * TcpBlockModeProc -- * * This procedure is invoked by the generic IO level to set blocking * and nonblocking mode on a TCP socket based channel. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or nonblocking mode. * *---------------------------------------------------------------------- */ /* ARGSUSED */static intTcpBlockModeProc(instanceData, mode) ClientData instanceData; /* Socket state. */ int mode; /* The mode to set. Can be one of * TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */{ TcpState *statePtr = (TcpState *) instanceData; int setting; #ifndef USE_FIONBIO setting = fcntl(statePtr->fd, F_GETFL); if (mode == TCL_MODE_BLOCKING) { statePtr->flags &= (~(TCP_ASYNC_SOCKET)); setting &= (~(O_NONBLOCK)); } else { statePtr->flags |= TCP_ASYNC_SOCKET; setting |= O_NONBLOCK; } if (fcntl(statePtr->fd, F_SETFL, setting) < 0) { return errno; }#endif#ifdef USE_FIONBIO if (mode == TCL_MODE_BLOCKING) { statePtr->flags &= (~(TCP_ASYNC_SOCKET)); setting = 0; if (ioctl(statePtr->fd, (int) FIONBIO, &setting) == -1) { return errno; } } else { statePtr->flags |= TCP_ASYNC_SOCKET; setting = 1; if (ioctl(statePtr->fd, (int) FIONBIO, &setting) == -1) { return errno; } }#endif return 0;}/* *---------------------------------------------------------------------- * * WaitForConnect -- * * Waits for a connection on an asynchronously opened socket to * be completed. * * Results: * None. * * Side effects: * The socket is connected after this function returns.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -