⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclwinpipe.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
    int mode;			/* TCL_MODE_BLOCKING or                                 * TCL_MODE_NONBLOCKING. */{    PipeInfo *infoPtr = (PipeInfo *) instanceData;        /*     * Pipes on Windows can not be switched between blocking and nonblocking,     * hence we have to emulate the behavior. This is done in the input     * function by checking against a bit in the state. We set or unset the     * bit here to cause the input function to emulate the correct behavior.     */    if (mode == TCL_MODE_NONBLOCKING) {	infoPtr->flags |= PIPE_ASYNC;    } else {	infoPtr->flags &= ~(PIPE_ASYNC);    }    return 0;}/* *---------------------------------------------------------------------- * * PipeCloseProc -- * *	Closes a pipe based IO channel. * * Results: *	0 on success, errno otherwise. * * Side effects: *	Closes the physical channel. * *---------------------------------------------------------------------- */static intPipeCloseProc(instanceData, interp)    ClientData instanceData;	/* Pointer to PipeInfo structure. */    Tcl_Interp *interp;		/* For error reporting. */{    PipeInfo *pipePtr = (PipeInfo *) instanceData;    Tcl_Channel errChan;    int errorCode, result;    PipeInfo *infoPtr, **nextPtrPtr;    /*     * Remove the file from the list of watched files.     */    for (nextPtrPtr = &firstPipePtr, infoPtr = *nextPtrPtr; infoPtr != NULL;	    nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) {	if (infoPtr == (PipeInfo *)pipePtr) {	    *nextPtrPtr = infoPtr->nextPtr;	    break;	}    }    errorCode = 0;    if (pipePtr->readFile != NULL) {	if (TclpCloseFile(pipePtr->readFile) != 0) {	    errorCode = errno;	}    }    if (pipePtr->writeFile != NULL) {	if (TclpCloseFile(pipePtr->writeFile) != 0) {	    if (errorCode == 0) {		errorCode = errno;	    }	}    }        /*     * Wrap the error file into a channel and give it to the cleanup     * routine.  If we are running in Win32s, just delete the error file     * immediately, because it was never used.     */    if (pipePtr->errorFile) {	WinFile *filePtr;	OSVERSIONINFO os;	os.dwOSVersionInfoSize = sizeof(os);	GetVersionEx(&os);	if (os.dwPlatformId == VER_PLATFORM_WIN32s) {	    TclpCloseFile(pipePtr->errorFile);	    errChan = NULL;	} else {	    filePtr = (WinFile*)pipePtr->errorFile;	    errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle,		    TCL_READABLE);	}    } else {        errChan = NULL;    }    result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,            errChan);    if (pipePtr->numPids > 0) {        ckfree((char *) pipePtr->pidPtr);    }    ckfree((char*) pipePtr);    if (errorCode == 0) {        return result;    }    return errorCode;}/* *---------------------------------------------------------------------- * * PipeInputProc -- * *	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 intPipeInputProc(instanceData, buf, bufSize, errorCode)    ClientData instanceData;		/* Pipe 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. */{    PipeInfo *infoPtr = (PipeInfo *) instanceData;    WinFile *filePtr = (WinFile*) infoPtr->readFile;    DWORD count;    DWORD bytesRead;    *errorCode = 0;    if (filePtr->type == WIN32S_PIPE) {	if (((WinPipe *)filePtr)->otherPtr != NULL) {	    panic("PipeInputProc: child process isn't finished writing");	}	if (filePtr->handle == INVALID_HANDLE_VALUE) {	    filePtr->handle = CreateFile(((WinPipe *)filePtr)->fileName,		    GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,		    NULL);	}	if (filePtr->handle == INVALID_HANDLE_VALUE) {	    goto error;	}    } else {	/*	 * Pipes will block until the requested number of bytes has been	 * read.  To avoid blocking unnecessarily, we look ahead and only	 * read as much as is available.	 */	if (PeekNamedPipe(filePtr->handle, (LPVOID) NULL, (DWORD) 0,		(LPDWORD) NULL, &count, (LPDWORD) NULL) == TRUE) {	    if ((count != 0) && ((DWORD) bufSize > count)) {		bufSize = (int) count;		/*		 * This code is commented out because on Win95 we don't get		 * notifier of eof on a pipe unless we try to read it.		 * The correct solution is to move to threads.		 *//* 	    } else if ((count == 0) && (infoPtr->flags & PIPE_ASYNC)) { *//* 		errno = *errorCode = EAGAIN; *//* 		return -1; */	    } else if ((count == 0) && !(infoPtr->flags & PIPE_ASYNC)) {		bufSize = 1;	    }	} else {	    goto error;	}    }    /*     * 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.     */    if (ReadFile(filePtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead,            (LPOVERLAPPED) NULL) == FALSE) {	goto error;    }        return bytesRead;    error:    TclWinConvertError(GetLastError());    if (errno == EPIPE) {	return 0;    }    *errorCode = errno;    return -1;}/* *---------------------------------------------------------------------- * * PipeOutputProc -- * *	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 intPipeOutputProc(instanceData, buf, toWrite, errorCode)    ClientData instanceData;		/* Pipe state. */    char *buf;				/* The data buffer. */    int toWrite;			/* How many bytes to write? */    int *errorCode;			/* Where to store error code. */{    PipeInfo *infoPtr = (PipeInfo *) instanceData;    WinFile *filePtr = (WinFile*) infoPtr->writeFile;    DWORD bytesWritten;        *errorCode = 0;    if (WriteFile(filePtr->handle, (LPVOID) buf, (DWORD) toWrite,	    &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) {        TclWinConvertError(GetLastError());        if (errno == EPIPE) {            return 0;        }        *errorCode = errno;        return -1;    }    return bytesWritten;}/* *---------------------------------------------------------------------- * * PipeEventProc -- * *	This function is invoked by Tcl_ServiceEvent when a file event *	reaches the front of the event queue.  This procedure invokes *	Tcl_NotifyChannel on the pipe. * * Results: *	Returns 1 if the event was handled, meaning it should be removed *	from the queue.  Returns 0 if the event was not handled, meaning *	it should stay on the queue.  The only time the event isn't *	handled is if the TCL_FILE_EVENTS flag bit isn't set. * * Side effects: *	Whatever the notifier callback does. * *---------------------------------------------------------------------- */static intPipeEventProc(evPtr, flags)    Tcl_Event *evPtr;		/* Event to service. */    int flags;			/* Flags that indicate what events to				 * handle, such as TCL_FILE_EVENTS. */{    PipeEvent *pipeEvPtr = (PipeEvent *)evPtr;    PipeInfo *infoPtr;    WinFile *filePtr;    int mask;/*    DWORD count;*/    if (!(flags & TCL_FILE_EVENTS)) {	return 0;    }    /*     * Search through the list of watched pipes for the one whose handle     * matches the event.  We do this rather than simply dereferencing     * the handle in the event so that pipes can be deleted while the     * event is in the queue.     */    for (infoPtr = firstPipePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {	if (pipeEvPtr->infoPtr == infoPtr) {	    infoPtr->flags &= ~(PIPE_PENDING);	    break;	}    }    /*     * Remove stale events.     */    if (!infoPtr) {	return 1;    }    /*     * If we aren't on Win32s, check to see if the pipe is readable.  Note     * that we can't tell if a pipe is writable, so we always report it     * as being writable.     */    filePtr = (WinFile*) ((PipeInfo*)infoPtr)->readFile;    if (filePtr->type != WIN32S_PIPE) {	/*	 * On windows 95, PeekNamedPipe returns 0 on eof so we can't	 * distinguish underflow from eof.  The correct solution is to	 * switch to the threaded implementation.	 */	mask = TCL_WRITABLE|TCL_READABLE;/* 	if (PeekNamedPipe(filePtr->handle, (LPVOID) NULL, (DWORD) 0, *//* 		(LPDWORD) NULL, &count, (LPDWORD) NULL) == TRUE) { *//* 	    if (count != 0) { *//* 		mask |= TCL_READABLE; *//* 	    } *//* 	} else { */	    /*	     * If the pipe has been closed by the other side, then 	     * mark the pipe as readable, but not writable.	     *//* 	    if (GetLastError() == ERROR_BROKEN_PIPE) { *//* 		mask = TCL_READABLE; *//* 	    } *//* 	} */    } else {	mask = TCL_READABLE | TCL_WRITABLE;    }    /*     * Inform the channel of the events.     */    Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask);    return 1;}/* *---------------------------------------------------------------------- * * PipeWatchProc -- * *	Called by the notifier to set up to watch for events on this *	channel. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidPipeWatchProc(instanceData, mask)    ClientData instanceData;		/* Pipe state. */    int mask;				/* What events to watch for; OR-ed                                         * combination of TCL_READABLE,                                         * TCL_WRITABLE and TCL_EXCEPTION. */{    PipeInfo **nextPtrPtr, *ptr;    PipeInfo *infoPtr = (PipeInfo *) instanceData;    int oldMask = infoPtr->watchMask;    /*     * For now, we just send a message to ourselves so we can poll the     * channel for readable events.     */    infoPtr->watchMask = mask & infoPtr->validMask;    if (infoPtr->watchMask) {	Tcl_Time blockTime = { 0, 0 };	if (!oldMask) {	    infoPtr->nextPtr = firstPipePtr;	    firstPipePtr = infoPtr;	}	Tcl_SetMaxBlockTime(&blockTime);    } else {	if (oldMask) {	    /*	     * Remove the pipe from the list of watched pipes.	     */	    for (nextPtrPtr = &firstPipePtr, ptr = *nextPtrPtr;		 ptr != NULL;		 nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) {		if (infoPtr == ptr) {		    *nextPtrPtr = ptr->nextPtr;		    break;		}	    }	}    }}/* *---------------------------------------------------------------------- * * PipeGetHandleProc -- * *	Called from Tcl_GetChannelHandle to retrieve OS handles from *	inside a command pipeline 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 intPipeGetHandleProc(instanceData, direction, handlePtr)    ClientData instanceData;	/* The pipe state. */    int direction;		/* TCL_READABLE or TCL_WRITABLE */    ClientData *handlePtr;	/* Where to store the handle.  */{    PipeInfo *infoPtr = (PipeInfo *) instanceData;    WinFile *filePtr;     if (direction == TCL_READABLE && infoPtr->readFile) {	filePtr = (WinFile*) infoPtr->readFile;	if (filePtr->type == WIN32S_PIPE) {	    if (filePtr->handle == INVALID_HANDLE_VALUE) {		filePtr->handle = CreateFile(((WinPipe *)filePtr)->fileName,			GENERIC_READ, 0, NULL, OPEN_ALWAYS,			FILE_ATTRIBUTE_NORMAL, NULL);	    }	    if (filePtr->handle == INVALID_HANDLE_VALUE) {		return TCL_ERROR;	    }	}	*handlePtr = (ClientData) filePtr->handle;	return TCL_OK;    }    if (direction == TCL_WRITABLE && infoPtr->writeFile) {	filePtr = (WinFile*) infoPtr->writeFile;	*handlePtr = (ClientData) filePtr->handle;	return TCL_OK;    }    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * Tcl_WaitPid -- * *	Emulates the waitpid system call. * * Results: *	Returns 0 if the process is still alive, -1 on an error, or *	the pid on a clean close.   * * Side effects: *	Unless WNOHANG is set and the wait times out, the process *	in

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -