summaryrefslogtreecommitdiff
path: root/src/pkg/syscall/exec_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/syscall/exec_windows.go')
-rw-r--r--src/pkg/syscall/exec_windows.go340
1 files changed, 0 insertions, 340 deletions
diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go
deleted file mode 100644
index 936aeb577..000000000
--- a/src/pkg/syscall/exec_windows.go
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Fork, exec, wait, etc.
-
-package syscall
-
-import (
- "sync"
- "unicode/utf16"
- "unsafe"
-)
-
-var ForkLock sync.RWMutex
-
-// EscapeArg rewrites command line argument s as prescribed
-// in http://msdn.microsoft.com/en-us/library/ms880421.
-// This function returns "" (2 double quotes) if s is empty.
-// Alternatively, these transformations are done:
-// - every back slash (\) is doubled, but only if immediately
-// followed by double quote (");
-// - every double quote (") is escaped by back slash (\);
-// - finally, s is wrapped with double quotes (arg -> "arg"),
-// but only if there is space or tab inside s.
-func EscapeArg(s string) string {
- if len(s) == 0 {
- return "\"\""
- }
- n := len(s)
- hasSpace := false
- for i := 0; i < len(s); i++ {
- switch s[i] {
- case '"', '\\':
- n++
- case ' ', '\t':
- hasSpace = true
- }
- }
- if hasSpace {
- n += 2
- }
- if n == len(s) {
- return s
- }
-
- qs := make([]byte, n)
- j := 0
- if hasSpace {
- qs[j] = '"'
- j++
- }
- slashes := 0
- for i := 0; i < len(s); i++ {
- switch s[i] {
- default:
- slashes = 0
- qs[j] = s[i]
- case '\\':
- slashes++
- qs[j] = s[i]
- case '"':
- for ; slashes > 0; slashes-- {
- qs[j] = '\\'
- j++
- }
- qs[j] = '\\'
- j++
- qs[j] = s[i]
- }
- j++
- }
- if hasSpace {
- for ; slashes > 0; slashes-- {
- qs[j] = '\\'
- j++
- }
- qs[j] = '"'
- j++
- }
- 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)
- if err != nil {
- return "", err
- }
- buf := make([]uint16, 100)
- n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
- if err != nil {
- return "", err
- }
- if n > uint32(len(buf)) {
- // Windows is asking for bigger buffer.
- buf = make([]uint16, n)
- n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
- if err != nil {
- return "", err
- }
- if n > uint32(len(buf)) {
- return "", EINVAL
- }
- }
- 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 "", 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 "", 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 "", 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 "", 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, EWINDOWS
- }
- if attr == nil {
- attr = &zeroProcAttr
- }
- sys := attr.Sys
- if sys == nil {
- sys = &zeroSysProcAttr
- }
-
- if len(attr.Files) > 3 {
- return 0, 0, 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 EWINDOWS
-}