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

📄 tclwinpipe.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	The return value is one of APPL_DOS, APPL_WIN3X, or APPL_WIN32 *	if the filename referred to the corresponding application type. *	If the file name could not be found or did not refer to any known  *	application type, APPL_NONE is returned and an error message is  *	left in interp.  .bat files are identified as APPL_DOS. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intApplicationType(interp, originalName, fullPath)    Tcl_Interp *interp;		/* Interp, for error message. */    const char *originalName;	/* Name of the application to find. */    char fullPath[MAX_PATH];	/* Filled with complete path to 				 * application. */{    int applType, i;    HANDLE hFile;    char *ext, *rest;    char buf[2];    DWORD read;    IMAGE_DOS_HEADER header;    static char extensions[][5] = {"", ".com", ".exe", ".bat"};    /* Look for the program as an external program.  First try the name     * as it is, then try adding .com, .exe, and .bat, in that order, to     * the name, looking for an executable.     *     * Using the raw SearchPath() procedure doesn't do quite what is      * necessary.  If the name of the executable already contains a '.'      * character, it will not try appending the specified extension when     * searching (in other words, SearchPath will not find the program      * "a.b.exe" if the arguments specified "a.b" and ".exe").        * So, first look for the file as it is named.  Then manually append      * the extensions, looking for a match.       */    applType = APPL_NONE;    for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {	lstrcpyn(fullPath, originalName, MAX_PATH - 5);        lstrcat(fullPath, extensions[i]);		SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, &rest);	/*	 * Ignore matches on directories or data files, return if identified	 * a known type.	 */	if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) {	    continue;	}	ext = strrchr(fullPath, '.');	if ((ext != NULL) && (strcmpi(ext, ".bat") == 0)) {	    applType = APPL_DOS;	    break;	}	hFile = CreateFile(fullPath, GENERIC_READ, FILE_SHARE_READ, NULL, 		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);	if (hFile == INVALID_HANDLE_VALUE) {	    continue;	}	header.e_magic = 0;	ReadFile(hFile, (void *) &header, sizeof(header), &read, NULL);	if (header.e_magic != IMAGE_DOS_SIGNATURE) {	    /* 	     * Doesn't have the magic number for relocatable executables.  If 	     * filename ends with .com, assume it's a DOS application anyhow.	     * Note that we didn't make this assumption at first, because some	     * supposed .com files are really 32-bit executables with all the	     * magic numbers and everything.  	     */	    CloseHandle(hFile);	    if ((ext != NULL) && (strcmpi(ext, ".com") == 0)) {		applType = APPL_DOS;		break;	    }	    continue;	}	if (header.e_lfarlc != sizeof(header)) {	    /* 	     * All Windows 3.X and Win32 and some DOS programs have this value	     * set here.  If it doesn't, assume that since it already had the 	     * other magic number it was a DOS application.	     */	    CloseHandle(hFile);	    applType = APPL_DOS;	    break;	}	/* 	 * The DWORD at header.e_lfanew points to yet another magic number.	 */	buf[0] = '\0';	SetFilePointer(hFile, header.e_lfanew, NULL, FILE_BEGIN);	ReadFile(hFile, (void *) buf, 2, &read, NULL);	CloseHandle(hFile);	if ((buf[0] == 'N') && (buf[1] == 'E')) {	    applType = APPL_WIN3X;	} else if ((buf[0] == 'P') && (buf[1] == 'E')) {	    applType = APPL_WIN32;	} else {	    /*	     * Strictly speaking, there should be a test that there	     * is an 'L' and 'E' at buf[0..1], to identify the type as 	     * DOS, but of course we ran into a DOS executable that 	     * _doesn't_ have the magic number -- specifically, one	     * compiled using the Lahey Fortran90 compiler.	     */	    applType = APPL_DOS;	}	break;    }    if (applType == APPL_NONE) {	TclWinConvertError(GetLastError());	Tcl_AppendResult(interp, "couldn't execute \"", originalName,		"\": ", Tcl_PosixError(interp), (char *) NULL);	return APPL_NONE;    }    if ((applType == APPL_DOS) || (applType == APPL_WIN3X)) {	/* 	 * Replace long path name of executable with short path name for 	 * 16-bit applications.  Otherwise the application may not be able	 * to correctly parse its own command line to separate off the 	 * application name from the arguments.	 */	GetShortPathName(fullPath, fullPath, MAX_PATH);    }    return applType;}/*     *---------------------------------------------------------------------- * * BuildCommandLine -- * *	The command line arguments are stored in linePtr separated *	by spaces, in a form that CreateProcess() understands.  Special  *	characters in individual arguments from argv[] must be quoted  *	when being stored in cmdLine. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidBuildCommandLine(argc, argv, linePtr)    int argc;			/* Number of arguments. */    char **argv;		/* Argument strings. */    Tcl_DString *linePtr;	/* Initialized Tcl_DString that receives the				 * command line. */{    char *start, *special;    int quote, i;    for (i = 0; i < argc; i++) {	if (i > 0) {	    Tcl_DStringAppend(linePtr, " ", 1);		}	quote = 0;	if (argv[i][0] == '\0') {	    quote = 1;	} else {	    for (start = argv[i]; *start != '\0'; start++) {		if (isspace(*start)) {		    quote = 1;		    break;		}	    }	}	if (quote) {	    Tcl_DStringAppend(linePtr, "\"", 1);	}	start = argv[i];	    	for (special = argv[i]; ; ) {	    if ((*special == '\\') && 		    (special[1] == '\\' || special[1] == '"')) {		Tcl_DStringAppend(linePtr, start, special - start);		start = special;		while (1) {		    special++;		    if (*special == '"') {			/* 			 * N backslashes followed a quote -> insert 			 * N * 2 + 1 backslashes then a quote.			 */			Tcl_DStringAppend(linePtr, start, special - start);			break;		    }		    if (*special != '\\') {			break;		    }		}		Tcl_DStringAppend(linePtr, start, special - start);		start = special;	    }	    if (*special == '"') {		Tcl_DStringAppend(linePtr, start, special - start);		Tcl_DStringAppend(linePtr, "\\\"", 2);		start = special + 1;	    }	    if (*special == '\0') {		break;	    }	    special++;	}	Tcl_DStringAppend(linePtr, start, special - start);	if (quote) {	    Tcl_DStringAppend(linePtr, "\"", 1);	}    }}/* *---------------------------------------------------------------------- * * MakeTempFile -- * *	Helper function for TclpCreateProcess under Win32s.  Makes a  *	temporary file that _won't_ go away automatically when it's file *	handle is closed.  Used for simulated pipes, which are written *	in one pass and reopened and read in the next pass. * * Results: *	namePtr is filled with the name of the temporary file. * * Side effects: *	A temporary file with the name specified by namePtr is created.   *	The caller is responsible for deleting this temporary file. * *---------------------------------------------------------------------- */static char *MakeTempFile(namePtr)    Tcl_DString *namePtr;	/* Initialized Tcl_DString that is filled 				 * with the name of the temporary file that 				 * was created. */{    char name[MAX_PATH];    if (TempFileName(name) == 0) {	return NULL;    }    Tcl_DStringAppend(namePtr, name, -1);    return Tcl_DStringValue(namePtr);}/* *---------------------------------------------------------------------- * * CopyChannel -- * *	Helper function used by TclpCreateProcess under Win32s.  Copies *	what remains of source file to destination file; source file  *	pointer need not be positioned at the beginning of the file if *	all of source file is not desired, but data is copied up to end  *	of source file. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidCopyChannel(dst, src)    HANDLE dst;			/* Destination file. */    HANDLE src;			/* Source file. */{    char buf[8192];    DWORD dwRead, dwWrite;    while (ReadFile(src, buf, sizeof(buf), &dwRead, NULL) != FALSE) {	if (dwRead == 0) {	    break;	}	if (WriteFile(dst, buf, dwRead, &dwWrite, NULL) == FALSE) {	    break;	}    }}/* *---------------------------------------------------------------------- * * TclpCreateCommandChannel -- * *	This function is called by Tcl_OpenCommandChannel to perform *	the platform specific channel initialization for a command *	channel. * * Results: *	Returns a new channel or NULL on failure. * * Side effects: *	Allocates a new channel. * *---------------------------------------------------------------------- */Tcl_ChannelTclpCreateCommandChannel(readFile, writeFile, errorFile, numPids, pidPtr)    TclFile readFile;		/* If non-null, gives the file for reading. */    TclFile writeFile;		/* If non-null, gives the file for writing. */    TclFile errorFile;		/* If non-null, gives the file where errors				 * can be read. */    int numPids;		/* The number of pids in the pid array. */    Tcl_Pid *pidPtr;		/* An array of process identifiers. */{    char channelName[20];    int channelId;    PipeInfo *infoPtr = (PipeInfo *) ckalloc((unsigned) sizeof(PipeInfo));    if (!initialized) {	PipeInit();    }    infoPtr->watchMask = 0;    infoPtr->flags = 0;    infoPtr->readFile = readFile;    infoPtr->writeFile = writeFile;    infoPtr->errorFile = errorFile;    infoPtr->numPids = numPids;    infoPtr->pidPtr = pidPtr;    /*     * Use one of the fds associated with the channel as the     * channel id.     */    if (readFile) {	WinPipe *pipePtr = (WinPipe *) readFile;	if (pipePtr->file.type == WIN32S_PIPE		&& pipePtr->file.handle == INVALID_HANDLE_VALUE) {	    pipePtr->file.handle = CreateFile(pipePtr->fileName, GENERIC_READ,		    0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);	}	channelId = (int) pipePtr->file.handle;    } else if (writeFile) {	channelId = (int) ((WinFile*)writeFile)->handle;    } else if (errorFile) {	channelId = (int) ((WinFile*)errorFile)->handle;    } else {	channelId = 0;    }    infoPtr->validMask = 0;    if (readFile != NULL) {        infoPtr->validMask |= TCL_READABLE;    }    if (writeFile != NULL) {        infoPtr->validMask |= TCL_WRITABLE;    }    /*     * For backward compatibility with previous versions of Tcl, we     * use "file%d" as the base name for pipes even though it would     * be more natural to use "pipe%d".     */    sprintf(channelName, "file%d", channelId);    infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,            (ClientData) infoPtr, infoPtr->validMask);    /*     * Pipes have AUTO translation mode on Windows and ^Z eof char, which     * means that a ^Z will be appended to them at close. This is needed     * for Windows programs that expect a ^Z at EOF.     */    Tcl_SetChannelOption((Tcl_Interp *) NULL, infoPtr->channel,	    "-translation", "auto");    Tcl_SetChannelOption((Tcl_Interp *) NULL, infoPtr->channel,	    "-eofchar", "\032 {}");    return infoPtr->channel;}/* *---------------------------------------------------------------------- * * TclGetAndDetachPids -- * *	Stores a list of the command PIDs for a command channel in *	interp->result. * * Results: *	None. * * Side effects: *	Modifies interp->result. * *---------------------------------------------------------------------- */voidTclGetAndDetachPids(interp, chan)    Tcl_Interp *interp;    Tcl_Channel chan;{    PipeInfo *pipePtr;    Tcl_ChannelType *chanTypePtr;    int i;    char buf[20];    /*     * Punt if the channel is not a command channel.     */    chanTypePtr = Tcl_GetChannelType(chan);    if (chanTypePtr != &pipeChannelType) {        return;    }    pipePtr = (PipeInfo *) Tcl_GetChannelInstanceData(chan);    for (i = 0; i < pipePtr->numPids; i++) {        sprintf(buf, "%lu", TclpGetPid(pipePtr->pidPtr[i]));        Tcl_AppendElement(interp, buf);        Tcl_DetachPids(1, &(pipePtr->pidPtr[i]));    }    if (pipePtr->numPids > 0) {        ckfree((char *) pipePtr->pidPtr);        pipePtr->numPids = 0;    }}/* *---------------------------------------------------------------------- * * PipeBlockModeProc -- * *	Set blocking or non-blocking mode on channel. * * Results: *	0 if successful, errno when failed. * * Side effects: *	Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */static intPipeBlockModeProc(instanceData, mode)    ClientData instanceData;	/* Instance data for channel. */

⌨️ 快捷键说明

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