📄 tclwinpipe.c
字号:
{ WinFile *filePtr; filePtr = (WinFile *) ckalloc(sizeof(WinFile)); filePtr->type = WIN_FILE; filePtr->handle = handle; return (TclFile)filePtr;}/* *---------------------------------------------------------------------- * * TempFileName -- * * Gets a temporary file name and deals with the fact that the * temporary file path provided by Windows may not actually exist * if the TMP or TEMP environment variables refer to a * non-existent directory. * * Results: * 0 if error, non-zero otherwise. If non-zero is returned, the * name buffer will be filled with a name that can be used to * construct a temporary file. * * Side effects: * None. * *---------------------------------------------------------------------- */static intTempFileName(name) WCHAR name[MAX_PATH]; /* Buffer in which name for temporary * file gets stored. */{ TCHAR *prefix; prefix = (tclWinProcs->useWide) ? (TCHAR *) L"TCL" : (TCHAR *) "TCL"; if ((*tclWinProcs->getTempPathProc)(MAX_PATH, name) != 0) { if ((*tclWinProcs->getTempFileNameProc)((TCHAR *) name, prefix, 0, name) != 0) { return 1; } } if (tclWinProcs->useWide) { ((WCHAR *) name)[0] = '.'; ((WCHAR *) name)[1] = '\0'; } else { ((char *) name)[0] = '.'; ((char *) name)[1] = '\0'; } return (*tclWinProcs->getTempFileNameProc)((TCHAR *) name, prefix, 0, name);}/* *---------------------------------------------------------------------- * * TclpMakeFile -- * * Make a TclFile from a channel. * * Results: * Returns a new TclFile or NULL on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */TclFileTclpMakeFile(channel, direction) Tcl_Channel channel; /* Channel to get file from. */ int direction; /* Either TCL_READABLE or TCL_WRITABLE. */{ HANDLE handle; if (Tcl_GetChannelHandle(channel, direction, (ClientData *) &handle) == TCL_OK) { return TclWinMakeFile(handle); } else { return (TclFile) 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) CONST char *path; /* The name of the file to open. */ int mode; /* In what mode to open the file? */{ HANDLE handle; DWORD accessMode, createMode, shareMode, flags; Tcl_DString ds; CONST TCHAR *nativePath; /* * 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; } nativePath = Tcl_WinUtfToTChar(path, -1, &ds); /* * If the file is not being created, use the existing file attributes. */ flags = 0; if (!(mode & O_CREAT)) { flags = (*tclWinProcs->getFileAttributesProc)(nativePath); if (flags == 0xFFFFFFFF) { flags = 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 = (*tclWinProcs->createFileProc)(nativePath, accessMode, shareMode, NULL, createMode, flags, NULL); Tcl_DStringFree(&ds); if (handle == INVALID_HANDLE_VALUE) { DWORD err; 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 TclWinMakeFile(handle);}/* *---------------------------------------------------------------------- * * TclpCreateTempFile -- * * This function opens a unique file with the property that it * will be deleted when its file handle is closed. The temporary * file is created in the system temporary directory. * * Results: * Returns a valid TclFile, or NULL on failure. * * Side effects: * Creates a new temporary file. * *---------------------------------------------------------------------- */TclFileTclpCreateTempFile(contents) CONST char *contents; /* String to write into temp file, or NULL. */{ WCHAR name[MAX_PATH]; CONST char *native; Tcl_DString dstring; HANDLE handle; if (TempFileName(name) == 0) { return NULL; } handle = (*tclWinProcs->createFileProc)((TCHAR *) name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, NULL); if (handle == INVALID_HANDLE_VALUE) { goto error; } /* * Write the file out, doing line translations on the way. */ if (contents != NULL) { DWORD result, length; CONST char *p; /* * Convert the contents from UTF to native encoding */ native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); for (p = native; *p != '\0'; p++) { if (*p == '\n') { length = p - native; if (length > 0) { if (!WriteFile(handle, native, length, &result, NULL)) { goto error; } } if (!WriteFile(handle, "\r\n", 2, &result, NULL)) { goto error; } native = p+1; } } length = p - native; if (length > 0) { if (!WriteFile(handle, native, length, &result, NULL)) { goto error; } } Tcl_DStringFree(&dstring); if (SetFilePointer(handle, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF) { goto error; } } return TclWinMakeFile(handle); error: /* Free the native representation of the contents if necessary */ if (contents != NULL) { Tcl_DStringFree(&dstring); } TclWinConvertError(GetLastError()); CloseHandle(handle); (*tclWinProcs->deleteFileProc)((TCHAR *) name); return NULL;}/* *---------------------------------------------------------------------- * * TclpTempFileName -- * * This function returns a unique filename. * * Results: * Returns a valid Tcl_Obj* with refCount 0, or NULL on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_Obj* TclpTempFileName(){ WCHAR fileName[MAX_PATH]; if (TempFileName(fileName) == 0) { return NULL; } return TclpNativeToNormalized((ClientData) fileName);}/* *---------------------------------------------------------------------- * * TclpCreatePipe -- * * Creates an anonymous pipe. * * Results: * Returns 1 on success, 0 on failure. * * Side effects: * Creates a pipe. * *---------------------------------------------------------------------- */intTclpCreatePipe( 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 = TclWinMakeFile(readHandle); *writePipe = TclWinMakeFile(writeHandle); 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( TclFile file) /* The file to close. */{ WinFile *filePtr = (WinFile *) file; switch (filePtr->type) { case WIN_FILE: /* * Don't close the Win32 handle if the handle is a standard channel * during the exit process. Otherwise, one thread may kill the * stdio of another. */ if (!TclInExit() || ((GetStdHandle(STD_INPUT_HANDLE) != filePtr->handle) && (GetStdHandle(STD_OUTPUT_HANDLE) != filePtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != filePtr->handle))) { if (filePtr->handle != NULL && CloseHandle(filePtr->handle) == FALSE) { TclWinConvertError(GetLastError()); ckfree((char *) filePtr); return -1; } } break; default: panic("TclpCloseFile: unexpected file type"); } ckfree((char *) filePtr); 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( Tcl_Pid pid) /* The HANDLE of the child process. */{ ProcInfo *infoPtr; Tcl_MutexLock(&pipeMutex); for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->hProcess == (HANDLE) pid) { Tcl_MutexUnlock(&pipeMutex); return infoPtr->dwProcessId; } } Tcl_MutexUnlock(&pipeMutex); 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 * asynchronously under Windows NT and Windows 9x, 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 * the interp's result if there was a problem creating the child * process. Otherwise, the return value is TCL_OK and *pidPtr is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -