📄 tclwinchan.c
字号:
FileWatchProc(instanceData, 0); if (CloseHandle(fileInfoPtr->handle) == FALSE) { TclWinConvertError(GetLastError()); errorCode = errno; } for (nextPtrPtr = &firstFilePtr; (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == fileInfoPtr) { (*nextPtrPtr) = fileInfoPtr->nextPtr; break; } } ckfree((char *)fileInfoPtr); return errorCode;}/* *---------------------------------------------------------------------- * * FileSeekProc -- * * Seeks on a file-based channel. Returns the new position. * * Results: * -1 if failed, the new position if successful. If failed, it * also sets *errorCodePtr to the error code. * * 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? */ int *errorCodePtr; /* To store error code. */{ FileInfo *infoPtr = (FileInfo *) instanceData; DWORD moveMethod; DWORD newPos; *errorCodePtr = 0; if (mode == SEEK_SET) { moveMethod = FILE_BEGIN; } else if (mode == SEEK_CUR) { moveMethod = FILE_CURRENT; } else { moveMethod = FILE_END; } newPos = SetFilePointer(infoPtr->handle, offset, NULL, moveMethod); if (newPos == 0xFFFFFFFF) { TclWinConvertError(GetLastError()); return -1; } return newPos;}/* *---------------------------------------------------------------------- * * FileInputProc -- * * Reads input from the IO channel into the buffer given. Returns * count of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */static intFileInputProc(instanceData, buf, bufSize, errorCode) ClientData instanceData; /* File state. */ char *buf; /* Where to store data read. */ int bufSize; /* How much space is available * in the buffer? */ int *errorCode; /* Where to store error code. */{ FileInfo *infoPtr; DWORD bytesRead; *errorCode = 0; infoPtr = (FileInfo *) instanceData; /* * Note that we will block on reads from a console buffer until a * full line has been entered. The only way I know of to get * around this is to write a console driver. We should probably * do this at some point, but for now, we just block. The same * problem exists for files being read over the network. */ if (ReadFile(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead, (LPOVERLAPPED) NULL) != FALSE) { return bytesRead; } TclWinConvertError(GetLastError()); *errorCode = errno; if (errno == EPIPE) { return 0; } return -1;}/* *---------------------------------------------------------------------- * * FileOutputProc -- * * Writes the given output on the IO channel. Returns count of how * many characters were actually written, and an error indication. * * Results: * A count of how many characters were written is returned and an * error indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. * *---------------------------------------------------------------------- */static intFileOutputProc(instanceData, buf, toWrite, errorCode) ClientData instanceData; /* File state. */ char *buf; /* The data buffer. */ int toWrite; /* How many bytes to write? */ int *errorCode; /* Where to store error code. */{ FileInfo *infoPtr = (FileInfo *) instanceData; DWORD bytesWritten; *errorCode = 0; /* * If we are writing to a file that was opened with O_APPEND, we need to * seek to the end of the file before writing the current buffer. */ if (infoPtr->flags & FILE_APPEND) { SetFilePointer(infoPtr->handle, 0, NULL, FILE_END); } if (WriteFile(infoPtr->handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { TclWinConvertError(GetLastError()); *errorCode = errno; return -1; } FlushFileBuffers(infoPtr->handle); return bytesWritten;}/* *---------------------------------------------------------------------- * * FileWatchProc -- * * Called by the notifier to set up to watch for events on this * channel. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidFileWatchProc(instanceData, mask) ClientData instanceData; /* File state. */ int mask; /* What events to watch for; OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */{ FileInfo *infoPtr = (FileInfo *) instanceData; Tcl_Time blockTime = { 0, 0 }; /* * Since the file is always ready for events, we set the block time * to zero so we will poll. */ infoPtr->watchMask = mask & infoPtr->validMask; if (infoPtr->watchMask) { Tcl_SetMaxBlockTime(&blockTime); }}/* *---------------------------------------------------------------------- * * FileGetHandleProc -- * * Called from Tcl_GetChannelFile 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. */{ FileInfo *infoPtr = (FileInfo *) instanceData; if (direction & infoPtr->validMask) { *handlePtr = (ClientData) infoPtr->handle; return TCL_OK; } else { return TCL_ERROR; }}/* *---------------------------------------------------------------------- * * ComInputProc -- * * Reads input from the IO channel into the buffer given. Returns * count of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */static intComInputProc(instanceData, buf, bufSize, errorCode) ClientData instanceData; /* File state. */ char *buf; /* Where to store data read. */ int bufSize; /* How much space is available * in the buffer? */ int *errorCode; /* Where to store error code. */{ FileInfo *infoPtr; DWORD bytesRead; DWORD dw; COMSTAT cs; *errorCode = 0; infoPtr = (FileInfo *) instanceData; if (ClearCommError(infoPtr->handle, &dw, &cs)) { if (dw != 0) { *errorCode = EIO; return -1; } if (cs.cbInQue != 0) { if ((DWORD) bufSize > cs.cbInQue) { bufSize = cs.cbInQue; } } else { if (infoPtr->flags & FILE_ASYNC) { errno = *errorCode = EAGAIN; return -1; } else { bufSize = 1; } } } if (ReadFile(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead, (LPOVERLAPPED) NULL) == FALSE) { TclWinConvertError(GetLastError()); *errorCode = errno; return -1; } return bytesRead;}/* *---------------------------------------------------------------------- * * ComSetOptionProc -- * * Sets an option on a channel. * * Results: * A standard Tcl result. Also sets interp->result on error if * interp is not NULL. * * Side effects: * May modify an option on a device. * *---------------------------------------------------------------------- */static int ComSetOptionProc(instanceData, interp, optionName, value) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - can be NULL. */ char *optionName; /* Which option to set? */ char *value; /* New value for option. */{ FileInfo *infoPtr; DCB dcb; int len; infoPtr = (FileInfo *) instanceData; len = strlen(optionName); if ((len > 1) && (strncmp(optionName, "-mode", len) == 0)) { if (GetCommState(infoPtr->handle, &dcb)) { if ((BuildCommDCB(value, &dcb) == FALSE) || (SetCommState(infoPtr->handle, &dcb) == FALSE)) { /* * one should separate the 2 errors... */ if (interp) { Tcl_AppendResult(interp, "bad value for -mode: should be ", "baud,parity,data,stop", NULL); } return TCL_ERROR; } else { return TCL_OK; } } else { if (interp) { Tcl_AppendResult(interp, "can't get comm state", NULL); } return TCL_ERROR; } } else { return Tcl_BadChannelOption(interp, optionName, "mode"); }}/* *---------------------------------------------------------------------- * * ComGetOptionProc -- * * Gets a mode associated with an IO channel. If the optionName arg * is non NULL, retrieves the value of that option. If the optionName * arg is NULL, retrieves a list of alternating option names and * values for the given channel. * * 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. * *---------------------------------------------------------------------- */static int ComGetOptionProc(instanceData, interp, optionName, dsPtr) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - can be NULL. */ char *optionName; /* Option to get. */ Tcl_DString *dsPtr; /* Where to store value(s). */{ FileInfo *infoPtr; DCB dcb; int len; infoPtr = (FileInfo *) instanceData; if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-mode"); len = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -