From 9782d98bb0c4f580d9d4b7c8f3af26549901c839 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 21 Aug 2014 16:07:11 -0700 Subject: [PATCH] go.sys/windows: delete StartProcess and Exec These are being deleted from go.sys because in general they can only be implemented in close coordination with the runtime. LGTM=alex.brainman R=alex.brainman CC=golang-codereviews https://golang.org/cl/132010043 --- windows/exec_windows.go | 238 +--------------------------------------- 1 file changed, 1 insertion(+), 237 deletions(-) diff --git a/windows/exec_windows.go b/windows/exec_windows.go index 9d42248e..b9b4271f 100644 --- a/windows/exec_windows.go +++ b/windows/exec_windows.go @@ -6,14 +6,7 @@ package windows -import ( - "sync" - "syscall" - "unicode/utf16" - "unsafe" -) - -var ForkLock sync.RWMutex +import "syscall" // EscapeArg rewrites command line argument s as prescribed // in http://msdn.microsoft.com/en-us/library/ms880421. @@ -82,54 +75,10 @@ func EscapeArg(s string) string { return string(qs[:j]) } -// makeCmdLine builds a command line out of args by escaping "special" -// characters and joining the arguments with spaces. -func makeCmdLine(args []string) string { - var s string - for _, v := range args { - if s != "" { - s += " " - } - s += EscapeArg(v) - } - return s -} - -// createEnvBlock converts an array of environment strings into -// the representation required by CreateProcess: a sequence of NUL -// terminated strings followed by a nil. -// Last bytes are two UCS-2 NULs, or four NUL bytes. -func createEnvBlock(envv []string) *uint16 { - if len(envv) == 0 { - return &utf16.Encode([]rune("\x00\x00"))[0] - } - length := 0 - for _, s := range envv { - length += len(s) + 1 - } - length += 1 - - b := make([]byte, length) - i := 0 - for _, s := range envv { - l := len(s) - copy(b[i:i+l], []byte(s)) - copy(b[i+l:i+l+1], []byte{0}) - i = i + l + 1 - } - copy(b[i:i+1], []byte{0}) - - return &utf16.Encode([]rune(string(b)))[0] -} - func CloseOnExec(fd Handle) { SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0) } -func SetNonblock(fd Handle, nonblocking bool) (err error) { - return nil -} - // FullPath retrieves the full path of the specified file. func FullPath(name string) (path string, err error) { p, err := UTF16PtrFromString(name) @@ -154,188 +103,3 @@ func FullPath(name string) (path string, err error) { } return UTF16ToString(buf[:n]), nil } - -func isSlash(c uint8) bool { - return c == '\\' || c == '/' -} - -func normalizeDir(dir string) (name string, err error) { - ndir, err := FullPath(dir) - if err != nil { - return "", err - } - if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) { - // dir cannot have \\server\share\path form - return "", syscall.EINVAL - } - return ndir, nil -} - -func volToUpper(ch int) int { - if 'a' <= ch && ch <= 'z' { - ch += 'A' - 'a' - } - return ch -} - -func joinExeDirAndFName(dir, p string) (name string, err error) { - if len(p) == 0 { - return "", syscall.EINVAL - } - if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) { - // \\server\share\path form - return p, nil - } - if len(p) > 1 && p[1] == ':' { - // has drive letter - if len(p) == 2 { - return "", syscall.EINVAL - } - if isSlash(p[2]) { - return p, nil - } else { - d, err := normalizeDir(dir) - if err != nil { - return "", err - } - if volToUpper(int(p[0])) == volToUpper(int(d[0])) { - return FullPath(d + "\\" + p[2:]) - } else { - return FullPath(p) - } - } - } else { - // no drive letter - d, err := normalizeDir(dir) - if err != nil { - return "", err - } - if isSlash(p[0]) { - return FullPath(d[:2] + p) - } else { - return FullPath(d + "\\" + p) - } - } - // we shouldn't be here - return "", syscall.EINVAL -} - -type ProcAttr struct { - Dir string - Env []string - Files []uintptr - Sys *SysProcAttr -} - -type SysProcAttr struct { - HideWindow bool - CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess - CreationFlags uint32 -} - -var zeroProcAttr ProcAttr -var zeroSysProcAttr SysProcAttr - -func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) { - if len(argv0) == 0 { - return 0, 0, syscall.EWINDOWS - } - if attr == nil { - attr = &zeroProcAttr - } - sys := attr.Sys - if sys == nil { - sys = &zeroSysProcAttr - } - - if len(attr.Files) > 3 { - return 0, 0, syscall.EWINDOWS - } - - if len(attr.Dir) != 0 { - // StartProcess assumes that argv0 is relative to attr.Dir, - // because it implies Chdir(attr.Dir) before executing argv0. - // Windows CreateProcess assumes the opposite: it looks for - // argv0 relative to the current directory, and, only once the new - // process is started, it does Chdir(attr.Dir). We are adjusting - // for that difference here by making argv0 absolute. - var err error - argv0, err = joinExeDirAndFName(attr.Dir, argv0) - if err != nil { - return 0, 0, err - } - } - argv0p, err := UTF16PtrFromString(argv0) - if err != nil { - return 0, 0, err - } - - var cmdline string - // Windows CreateProcess takes the command line as a single string: - // use attr.CmdLine if set, else build the command line by escaping - // and joining each argument with spaces - if sys.CmdLine != "" { - cmdline = sys.CmdLine - } else { - cmdline = makeCmdLine(argv) - } - - var argvp *uint16 - if len(cmdline) != 0 { - argvp, err = UTF16PtrFromString(cmdline) - if err != nil { - return 0, 0, err - } - } - - var dirp *uint16 - if len(attr.Dir) != 0 { - dirp, err = UTF16PtrFromString(attr.Dir) - if err != nil { - return 0, 0, err - } - } - - // Acquire the fork lock so that no other threads - // create new fds that are not yet close-on-exec - // before we fork. - ForkLock.Lock() - defer ForkLock.Unlock() - - p, _ := GetCurrentProcess() - fd := make([]Handle, len(attr.Files)) - for i := range attr.Files { - if attr.Files[i] > 0 { - err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS) - if err != nil { - return 0, 0, err - } - defer CloseHandle(Handle(fd[i])) - } - } - si := new(StartupInfo) - si.Cb = uint32(unsafe.Sizeof(*si)) - si.Flags = STARTF_USESTDHANDLES - if sys.HideWindow { - si.Flags |= STARTF_USESHOWWINDOW - si.ShowWindow = SW_HIDE - } - si.StdInput = fd[0] - si.StdOutput = fd[1] - si.StdErr = fd[2] - - pi := new(ProcessInformation) - - flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT - err = CreateProcess(argv0p, argvp, nil, nil, true, flags, createEnvBlock(attr.Env), dirp, si, pi) - if err != nil { - return 0, 0, err - } - defer CloseHandle(Handle(pi.Thread)) - - return int(pi.ProcessId), uintptr(pi.Process), nil -} - -func Exec(argv0 string, argv []string, envv []string) (err error) { - return syscall.EWINDOWS -}