📄 tclunixchan.c
字号:
* or zero. * * Side effects: * Writes output on the output device of the channel. * *---------------------------------------------------------------------- */static intFileOutputProc(instanceData, buf, toWrite, errorCodePtr) ClientData instanceData; /* File state. */ CONST char *buf; /* The data buffer. */ int toWrite; /* How many bytes to write? */ int *errorCodePtr; /* Where to store error code. */{ FileState *fsPtr = (FileState *) instanceData; int written; *errorCodePtr = 0; if (toWrite == 0) { /* * SF Tcl Bug 465765. * Do not try to write nothing into a file. STREAM based * implementations will considers this as EOF (if there is a * pipe behind the file). */ return 0; } written = write(fsPtr->fd, buf, (size_t) toWrite); if (written > -1) { return written; } *errorCodePtr = errno; return -1;}/* *---------------------------------------------------------------------- * * FileCloseProc -- * * This procedure is called from the generic IO level to perform * channel-type-specific cleanup when a file based channel is closed. * * Results: * 0 if successful, errno if failed. * * Side effects: * Closes the device of the channel. * *---------------------------------------------------------------------- */static intFileCloseProc(instanceData, interp) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - unused. */{ FileState *fsPtr = (FileState *) instanceData; int errorCode = 0;#ifdef DEPRECATED FileState **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);#endif /* DEPRECATED */ Tcl_DeleteFileHandler(fsPtr->fd); /* * Do not close standard channels while in thread-exit. */ if (!TclInThreadExit() || ((fsPtr->fd != 0) && (fsPtr->fd != 1) && (fsPtr->fd != 2))) { if (close(fsPtr->fd) < 0) { errorCode = errno; } } ckfree((char *) fsPtr); return errorCode;}/* *---------------------------------------------------------------------- * * FileSeekProc -- * * This procedure is called by the generic IO level to move the * access point in a file based channel. * * Results: * -1 if failed, the new position if successful. An output * argument contains the POSIX error code if an error occurred, * or zero. * * Side effects: * Moves the location at which the channel will be accessed in * future operations. * *---------------------------------------------------------------------- */static intFileSeekProc(instanceData, offset, mode, errorCodePtr) ClientData instanceData; /* File state. */ long offset; /* Offset to seek to. */ int mode; /* Relative to where should we seek? Can be * one of SEEK_START, SEEK_SET or SEEK_END. */ int *errorCodePtr; /* To store error code. */{ FileState *fsPtr = (FileState *) instanceData; Tcl_WideInt oldLoc, newLoc; /* * Save our current place in case we need to roll-back the seek. */ oldLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) 0, SEEK_CUR); if (oldLoc == Tcl_LongAsWide(-1)) { /* * Bad things are happening. Error out... */ *errorCodePtr = errno; return -1; } newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode); /* * Check for expressability in our return type, and roll-back otherwise. */ if (newLoc > Tcl_LongAsWide(INT_MAX)) { *errorCodePtr = EOVERFLOW; TclOSseek(fsPtr->fd, (Tcl_SeekOffset) oldLoc, SEEK_SET); return -1; } else { *errorCodePtr = (newLoc == Tcl_LongAsWide(-1)) ? errno : 0; } return (int) Tcl_WideAsLong(newLoc);}/* *---------------------------------------------------------------------- * * FileWideSeekProc -- * * This procedure is called by the generic IO level to move the * access point in a file based channel, with offsets expressed * as wide integers. * * Results: * -1 if failed, the new position if successful. An output * argument contains the POSIX error code if an error occurred, * or zero. * * Side effects: * Moves the location at which the channel will be accessed in * future operations. * *---------------------------------------------------------------------- */static Tcl_WideIntFileWideSeekProc(instanceData, offset, mode, errorCodePtr) ClientData instanceData; /* File state. */ Tcl_WideInt offset; /* Offset to seek to. */ int mode; /* Relative to where should we seek? Can be * one of SEEK_START, SEEK_CUR or SEEK_END. */ int *errorCodePtr; /* To store error code. */{ FileState *fsPtr = (FileState *) instanceData; Tcl_WideInt newLoc; newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode); *errorCodePtr = (newLoc == -1) ? errno : 0; return newLoc;}/* *---------------------------------------------------------------------- * * FileWatchProc -- * * Initialize the notifier to watch the fd from this channel. * * Results: * None. * * Side effects: * Sets up the notifier so that a future event on the channel will * be seen by Tcl. * *---------------------------------------------------------------------- */static voidFileWatchProc(instanceData, mask) ClientData instanceData; /* The file state. */ int mask; /* Events of interest; an OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */{ FileState *fsPtr = (FileState *) instanceData; /* * Make sure we only register for events that are valid on this file. * Note that we are passing Tcl_NotifyChannel directly to * Tcl_CreateFileHandler with the channel pointer as the client data. */ mask &= fsPtr->validMask; if (mask) { Tcl_CreateFileHandler(fsPtr->fd, mask, (Tcl_FileProc *) Tcl_NotifyChannel, (ClientData) fsPtr->channel); } else { Tcl_DeleteFileHandler(fsPtr->fd); }}/* *---------------------------------------------------------------------- * * FileGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS handles from * a file based channel. * * Results: * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if * there is no handle for the specified direction. * * Side effects: * None. * *---------------------------------------------------------------------- */static intFileGetHandleProc(instanceData, direction, handlePtr) ClientData instanceData; /* The file state. */ int direction; /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr; /* Where to store the handle. */{ FileState *fsPtr = (FileState *) instanceData; if (direction & fsPtr->validMask) { *handlePtr = (ClientData) fsPtr->fd; return TCL_OK; } else { return TCL_ERROR; }}#ifdef SUPPORTS_TTY /* *---------------------------------------------------------------------- * * TtyCloseProc -- * * This procedure is called from the generic IO level to perform * channel-type-specific cleanup when a tty based channel is closed. * * Results: * 0 if successful, errno if failed. * * Side effects: * Closes the device of the channel. * *---------------------------------------------------------------------- */static intTtyCloseProc(instanceData, interp) ClientData instanceData; /* Tty state. */ Tcl_Interp *interp; /* For error reporting - unused. */{#if BAD_TIP35_FLUSH TtyState *ttyPtr = (TtyState *) instanceData;#endif /* BAD_TIP35_FLUSH */#ifdef TTYFLUSH TTYFLUSH(ttyPtr->fs.fd);#endif /* TTYFLUSH */#if 0 /* * TIP#35 agreed to remove the unsave so that TCL could be used as a * simple stty. * It would be cleaner to remove all the stuff related to * TtyState.stateUpdated * TtyState.savedState * Then the structure TtyState would be the same as FileState. * IMO this cleanup could better be done for the final 8.4 release * after nobody complained about the missing unsave. -- schroedter */ if (ttyPtr->stateUpdated) { SETIOSTATE(ttyPtr->fs.fd, &ttyPtr->savedState); }#endif return FileCloseProc(instanceData, interp);}/* *---------------------------------------------------------------------- * * TtyOutputProc-- * * This procedure is invoked from the generic IO level to write * output to a TTY channel. * * Results: * The number of bytes written is returned or -1 on error. An * output argument contains a POSIX error code if an error occurred, * or zero. * * Side effects: * Writes output on the output device of the channel * if the channel is not designated to be closed. * *---------------------------------------------------------------------- */#if BAD_TIP35_FLUSHstatic intTtyOutputProc(instanceData, buf, toWrite, errorCodePtr) ClientData instanceData; /* File state. */ CONST char *buf; /* The data buffer. */ int toWrite; /* How many bytes to write? */ int *errorCodePtr; /* Where to store error code. */{ if (TclInExit()) { /* * Do not write data during Tcl exit. * Serial port may block preventing Tcl from exit. */ return toWrite; } else { return FileOutputProc(instanceData, buf, toWrite, errorCodePtr); }}#endif /* BAD_TIP35_FLUSH */#ifdef USE_TERMIOS/* *---------------------------------------------------------------------- * * TtyModemStatusStr -- * * Converts a RS232 modem status list of readable flags * *---------------------------------------------------------------------- */static voidTtyModemStatusStr(status, dsPtr) int status; /* RS232 modem status */ Tcl_DString *dsPtr; /* Where to store string */{#ifdef TIOCM_CTS Tcl_DStringAppendElement(dsPtr, "CTS"); Tcl_DStringAppendElement(dsPtr, (status & TIOCM_CTS) ? "1" : "0");#endif /* TIOCM_CTS */#ifdef TIOCM_DSR Tcl_DStringAppendElement(dsPtr, "DSR"); Tcl_DStringAppendElement(dsPtr, (status & TIOCM_DSR) ? "1" : "0");#endif /* TIOCM_DSR */#ifdef TIOCM_RNG Tcl_DStringAppendElement(dsPtr, "RING"); Tcl_DStringAppendElement(dsPtr, (status & TIOCM_RNG) ? "1" : "0");#endif /* TIOCM_RNG */#ifdef TIOCM_CD Tcl_DStringAppendElement(dsPtr, "DCD"); Tcl_DStringAppendElement(dsPtr, (status & TIOCM_CD) ? "1" : "0");#endif /* TIOCM_CD */}#endif /* USE_TERMIOS *//* *---------------------------------------------------------------------- * * TtySetOptionProc -- * * Sets an option on a channel. * * Results: * A standard Tcl result. Also sets the interp's result on error if * interp is not NULL. * * Side effects: * May modify an option on a device. * Sets Error message if needed (by calling Tcl_BadChannelOption). * *---------------------------------------------------------------------- */static int TtySetOptionProc(instanceData, interp, optionName, value) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - can be NULL. */ CONST char *optionName; /* Which option to set? */ CONST char *value; /* New value for option. */{ FileState *fsPtr = (FileState *) instanceData; unsigned int len, vlen; TtyAttrs tty;#ifdef USE_TERMIOS int flag, control, argc; CONST char **argv; IOSTATE iostate;#endif /* USE_TERMIOS */ len = strlen(optionName); vlen = strlen(value); /* * Option -mode baud,parity,databits,stopbits */ if ((len > 2) && (strncmp(optionName, "-mode", len) == 0)) { if (TtyParseMode(interp, value, &tty.baud, &tty.parity, &tty.data, &tty.stop) != TCL_OK) { return TCL_ERROR; } /* * system calls results should be checked there. -- dl */ TtySetAttributes(fsPtr->fd, &tty); ((TtyState *) fsPtr)->stateUpdated = 1; return TCL_OK; }#ifdef USE_TERMIOS /* * Option -handshake none|xonxoff|rtscts|dtrdsr */ if ((len > 1) && (strncmp(optionName, "-handshake", len) == 0)) { /* * Reset all handshake options * DTR and RTS are ON by default */ GETIOSTATE(fsPtr->fd, &iostate); iostate.c_iflag &= ~(IXON | IXOFF | IXANY);#ifdef CRTSCTS iostate.c_cflag &= ~CRTSCTS;#endif /* CRTSCTS */ if (strncasecmp(value, "NONE", vlen) == 0) { /* leave all handshake options disabled */ } else if (strncasecmp(value, "XONXOFF", vlen) == 0) { iostate.c_iflag |= (IXON | IXOFF | IXANY); } else if (strncasecmp(value, "RTSCTS", vlen) == 0) {#ifdef CRTSCTS iostate.c_cflag |= CRTSCTS;#else /* !CRTSTS */ UNSUPPORTED_OPTION("-handshake RTSCTS"); return TCL_ERROR;#endif /* CRTSCTS */ } else if (strncasecmp(value, "DTRDSR", vlen) == 0) { UNSUPPORTED_OPTION("-handshake DTRDSR"); return TCL_ERROR; } else { if (interp) { Tcl_AppendResult(interp, "bad value for -handshake: ", "must be one of xonxoff, rtscts, dtrdsr or none", (char *) NULL); } return TCL_ERROR; } SETIOSTATE(fsPtr->fd, &iostate); return TCL_OK; } /* * Option -xchar {\x11 \x13} */ if ((len > 1) && (strncmp(optionName, "-xchar", len) == 0)) { GETIOSTATE(fsPtr->fd, &iostate); if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 2) { iostate.c_cc[VSTART] = argv[0][0]; iostate.c_cc[VSTOP] = argv[1][0]; } else { if (interp) { Tcl_AppendResult(interp,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -