📄 tclwinpipe.c
字号:
*/ if (contents != NULL) { DWORD result, length; char *p; for (p = contents; *p != '\0'; p++) { if (*p == '\n') { length = p - contents; if (length > 0) { if (!WriteFile(handle, contents, length, &result, NULL)) { goto error; } } if (!WriteFile(handle, "\r\n", 2, &result, NULL)) { goto error; } contents = p+1; } } length = p - contents; if (length > 0) { if (!WriteFile(handle, contents, length, &result, NULL)) { goto error; } } } if (SetFilePointer(handle, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF) { goto error; } if (namePtr != NULL) { Tcl_DStringAppend(namePtr, name, -1); } /* * Under Win32s a file created with FILE_FLAG_DELETE_ON_CLOSE won't * actually be deleted when it is closed, so we have to do it ourselves. */ if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) { TmpFile *tmpFilePtr = (TmpFile *) ckalloc(sizeof(TmpFile)); tmpFilePtr->file.type = WIN32S_TMPFILE; tmpFilePtr->file.handle = handle; strcpy(tmpFilePtr->name, name); return (TclFile)tmpFilePtr; } else { return MakeFile(handle); } error: TclWinConvertError(GetLastError()); CloseHandle(handle); DeleteFile(name); return NULL;}/* *---------------------------------------------------------------------- * * TclpOpenFile -- * * This function opens files for use in a pipeline. * * Results: * Returns a newly allocated TclFile structure containing the * file handle. * * Side effects: * None. * *---------------------------------------------------------------------- */TclFileTclpOpenFile(path, mode) char *path; int mode;{ HANDLE handle; DWORD accessMode, createMode, shareMode, flags; SECURITY_ATTRIBUTES sec; /* * Map the access bits to the NT access mode. */ switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: accessMode = GENERIC_READ; break; case O_WRONLY: accessMode = GENERIC_WRITE; break; case O_RDWR: accessMode = (GENERIC_READ | GENERIC_WRITE); break; default: TclWinConvertError(ERROR_INVALID_FUNCTION); return NULL; } /* * Map the creation flags to the NT create mode. */ switch (mode & (O_CREAT | O_EXCL | O_TRUNC)) { case (O_CREAT | O_EXCL): case (O_CREAT | O_EXCL | O_TRUNC): createMode = CREATE_NEW; break; case (O_CREAT | O_TRUNC): createMode = CREATE_ALWAYS; break; case O_CREAT: createMode = OPEN_ALWAYS; break; case O_TRUNC: case (O_TRUNC | O_EXCL): createMode = TRUNCATE_EXISTING; break; default: createMode = OPEN_EXISTING; break; } /* * If the file is not being created, use the existing file attributes. */ flags = 0; if (!(mode & O_CREAT)) { flags = GetFileAttributes(path); if (flags == 0xFFFFFFFF) { flags = 0; } } /* * Set up the security attributes so this file is not inherited by * child processes. */ sec.nLength = sizeof(sec); sec.lpSecurityDescriptor = NULL; sec.bInheritHandle = 0; /* * Set up the file sharing mode. We want to allow simultaneous access. */ shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; /* * Now we get to create the file. */ handle = CreateFile(path, accessMode, shareMode, &sec, createMode, flags, (HANDLE) NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if ((err & 0xffffL) == ERROR_OPEN_FAILED) { err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } TclWinConvertError(err); return NULL; } /* * Seek to the end of file if we are writing. */ if (mode & O_WRONLY) { SetFilePointer(handle, 0, NULL, FILE_END); } return MakeFile(handle);}/* *---------------------------------------------------------------------- * * TclpCreatePipe -- * * Creates an anonymous pipe. Under Win32s, creates a temp file * that is used to simulate a pipe. * * Results: * Returns 1 on success, 0 on failure. * * Side effects: * Creates a pipe. * *---------------------------------------------------------------------- */intTclpCreatePipe(readPipe, writePipe) TclFile *readPipe; /* Location to store file handle for * read side of pipe. */ TclFile *writePipe; /* Location to store file handle for * write side of pipe. */{ HANDLE readHandle, writeHandle; if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) { *readPipe = MakeFile(readHandle); *writePipe = MakeFile(writeHandle); return 1; } if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) { WinPipe *readPipePtr, *writePipePtr; char buf[MAX_PATH]; if (TempFileName(buf) != 0) { readPipePtr = (WinPipe *) ckalloc(sizeof(WinPipe)); writePipePtr = (WinPipe *) ckalloc(sizeof(WinPipe)); readPipePtr->file.type = WIN32S_PIPE; readPipePtr->otherPtr = writePipePtr; readPipePtr->fileName = strcpy(ckalloc(strlen(buf) + 1), buf); readPipePtr->file.handle = INVALID_HANDLE_VALUE; writePipePtr->file.type = WIN32S_PIPE; writePipePtr->otherPtr = readPipePtr; writePipePtr->fileName = readPipePtr->fileName; writePipePtr->file.handle = INVALID_HANDLE_VALUE; *readPipe = (TclFile)readPipePtr; *writePipe = (TclFile)writePipePtr; return 1; } } TclWinConvertError(GetLastError()); return 0;}/* *---------------------------------------------------------------------- * * TclpCloseFile -- * * Closes a pipeline file handle. These handles are created by * TclpOpenFile, TclpCreatePipe, or TclpMakeFile. * * Results: * 0 on success, -1 on failure. * * Side effects: * The file is closed and deallocated. * *---------------------------------------------------------------------- */intTclpCloseFile(file) TclFile file; /* The file to close. */{ WinFile *filePtr = (WinFile *) file; WinPipe *pipePtr; switch (filePtr->type) { case WIN_FILE: case WIN32S_TMPFILE: if (CloseHandle(filePtr->handle) == FALSE) { TclWinConvertError(GetLastError()); ckfree((char *) filePtr); return -1; } /* * Simulate deleting the file on close for Win32s. */ if (filePtr->type == WIN32S_TMPFILE) { DeleteFile(((TmpFile*)filePtr)->name); } break; case WIN32S_PIPE: pipePtr = (WinPipe *) file; if (pipePtr->otherPtr != NULL) { pipePtr->otherPtr->otherPtr = NULL; } else { if (pipePtr->file.handle != INVALID_HANDLE_VALUE) { CloseHandle(pipePtr->file.handle); } DeleteFile(pipePtr->fileName); ckfree((char *) pipePtr->fileName); } break; default: panic("Tcl_CloseFile: unexpected file type"); } ckfree((char *) filePtr); return 0;}/* *-------------------------------------------------------------------------- * * TclpGetProcess -- * * Given a process id return the Handle. * * Results: * Return the process handle, if the process id was unknown return 0 * * Side effects: * None. * *-------------------------------------------------------------------------- */HANDLETclpGetProcess(pid) unsigned long pid; { ProcInfo *infoPtr; for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->dwProcessId == pid) { return infoPtr->hProcess; } } return 0;}/* *-------------------------------------------------------------------------- * * TclpGetPid -- * * Given a HANDLE to a child process, return the process id for that * child process. * * Results: * Returns the process id for the child process. If the pid was not * known by Tcl, either because the pid was not created by Tcl or the * child process has already been reaped, -1 is returned. * * Side effects: * None. * *-------------------------------------------------------------------------- */unsigned longTclpGetPid(pid) Tcl_Pid pid; /* The HANDLE of the child process. */{ ProcInfo *infoPtr; for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->hProcess == (HANDLE) pid) { return infoPtr->dwProcessId; } } return (unsigned long) -1;}/* *---------------------------------------------------------------------- * * TclpCreateProcess -- * * Create a child process that has the specified files as its * standard input, output, and error. The child process runs * synchronously under Win32s and asynchronously under Windows NT * and Windows 95, and runs with the same environment variables * as the creating process. * * The complete Windows search path is searched to find the specified * executable. If an executable by the given name is not found, * automatically tries appending ".com", ".exe", and ".bat" to the * executable name. * * Results: * The return value is TCL_ERROR and an error message is left in * interp->result if there was a problem creating the child * process. Otherwise, the return value is TCL_OK and *pidPtr is * filled with the process id of the child process. * * Side effects: * A process is created. * *---------------------------------------------------------------------- */intTclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile, pidPtr) Tcl_Interp *interp; /* Interpreter in which to leave errors that * occurred when creating the child process. * Error messages from the child process * itself are sent to errorFile. */ int argc; /* Number of arguments in following array. */ char **argv; /* Array of argument strings. argv[0] * contains the name of the executable * converted to native format (using the * Tcl_TranslateFileName call). Additional * arguments have not been converted. */ TclFile inputFile; /* If non-NULL, gives the file to use as * input for the child process. If inputFile * file is not readable or is NULL, the child * will receive no standard input. */ TclFile outputFile; /* If non-NULL, gives the file that * receives output from the child process. If * outputFile file is not writeable or is * NULL, output from the child will be * discarded. */ TclFile errorFile; /* If non-NULL, gives the file that * receives errors from the child process. If * errorFile file is not writeable or is NULL, * errors from the child will be discarded. * errorFile may be the same as outputFile. */ Tcl_Pid *pidPtr; /* If this procedure is successful, pidPtr * is filled with the process id of the child * process. */{ int result, applType, createFlags; Tcl_DString cmdLine; STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; SECURITY_ATTRIBUTES secAtts; HANDLE hProcess, h, inputHandle, outputHandle, errorHandle; char execPath[MAX_PATH]; char *originalName; WinFile *filePtr; if (!initialized) { PipeInit(); } applType = ApplicationType(interp, argv[0], execPath); if (applType == APPL_NONE) { return TCL_ERROR; } originalName = argv[0]; argv[0] = execPath; result = TCL_ERROR; Tcl_DStringInit(&cmdLine); if (TclWinGetPlatformId() == VER_PLATFORM_WIN32s) { /* * Under Win32s, there are no pipes. In order to simulate pipe * behavior, the child processes are run synchronously and their * I/O is redirected from/to temporary files before the next * stage of the pipeline is started. */ MSG msg; DWORD status; DWORD args[4]; void *trans[5]; char *inputFileName, *outputFileName; Tcl_DString inputTempFile, outputTempFile; BuildCommandLine(argc, argv, &cmdLine); ZeroMemory(&startInfo, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); Tcl_DStringInit(&inputTempFile); Tcl_DStringInit(&outputTempFile);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -