Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1877)

Delta Between Two Patch Sets: src/pkg/syscall/exec_windows.go

Issue 1578041: code review 1578041: add Windows ForkExec, Syscall12 (Closed)
Left Patch Set: Created 13 years, 9 months ago
Right Patch Set: code review 1578041: add Windows ForkExec, Syscall12 Created 13 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/syscall/exec_unix.go ('k') | src/pkg/syscall/mksyscall_windows.sh » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Fork, exec, wait, etc. 5 // Fork, exec, wait, etc.
6 6
7 package syscall 7 package syscall
8 8
9 import ( 9 import (
10 "sync" 10 "sync"
11 » //"unsafe" 11 » "utf16"
12 » //"utf16"
13 ) 12 )
14 13
15 // Windows doesn't have a good concept of just Exec in the documented API. 14 // Windows doesn't have a good concept of just Exec in the documented API.
16 // However, the kernel32 CreateProcess does a good job with 15 // However, the kernel32 CreateProcess does a good job with
17 // ForkExec. 16 // ForkExec.
18 17
19 var ForkLock sync.RWMutex 18 var ForkLock sync.RWMutex
20 19
21 // Joins an array of string with sep 20 // Joins an array of string with sep
22 // From the "strings" package 21 // From the "strings" package. Modified.
23 func stringJoin(a []string, sep string) string { 22 func stringJoin(a []string, sep string, escape escapeFunc) string {
24 if len(a) == 0 { 23 if len(a) == 0 {
25 return "" 24 return ""
26 } 25 }
27 if len(a) == 1 { 26 if len(a) == 1 {
28 return a[0] 27 return a[0]
29 } 28 }
30 n := len(sep) * (len(a) - 1) 29 n := len(sep) * (len(a) - 1)
31 for i := 0; i < len(a); i++ { 30 for i := 0; i < len(a); i++ {
31 a[i] = escape(a[i])
32 n += len(a[i]) 32 n += len(a[i])
33 } 33 }
34 34
35 b := make([]byte, n) 35 b := make([]byte, n)
36 bp := 0 36 bp := 0
37 for i := 0; i < len(a); i++ { 37 for i := 0; i < len(a); i++ {
38 s := a[i] 38 s := a[i]
39 for j := 0; j < len(s); j++ { 39 for j := 0; j < len(s); j++ {
40 b[bp] = s[j] 40 b[bp] = s[j]
41 bp++ 41 bp++
42 } 42 }
43 if i+1 < len(a) { 43 if i+1 < len(a) {
44 s = sep 44 s = sep
45 for j := 0; j < len(s); j++ { 45 for j := 0; j < len(s); j++ {
46 b[bp] = s[j] 46 b[bp] = s[j]
47 bp++ 47 bp++
48 } 48 }
49 } 49 }
50 } 50 }
51 return string(b) 51 return string(b)
52 } 52 }
53 53
54 // Convert array of string to array 54 //Env block is a sequence of null terminated strings followed by a null.
55 // of NUL-terminated pointer. 55 //Last bytes are two unicode nulls, or four null bytes.
56 func StringArrayPtr(ss []string) []*uint16 { 56 func createEnvBlock(envv []string) *uint16 {
57 » bb := make([]*uint16, len(ss)+1) 57 » if len(envv) == 0 {
58 » for i := 0; i < len(ss); i++ { 58 » » return &utf16.Encode([]int("\x00\x00"))[0]
59 » » bb[i] = StringToUTF16Ptr(ss[i])
60 } 59 }
61 » bb[len(ss)] = nil 60 » length := 0
62 » return bb 61 » for _, s := range envv {
62 » » length += len(s) + 1
63 » }
64 » length += 1
65
66 » b := make([]byte, length)
67 » i := 0
68 » for _, s := range envv {
69 » » l := len(s)
70 » » copy(b[i:i+l], []byte(s))
71 » » copy(b[i+l:i+l+1], []byte{0})
72 » » i = i + l + 1
73 » }
74 » copy(b[i:i+1], []byte{0})
75
76 » return &utf16.Encode([]int(string(b)))[0]
63 } 77 }
64 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
65 78
66 func SetNonblock(fd int, nonblocking bool) (errno int) { 79 type escapeFunc func(s string) string
67 » flag, err := fcntl(fd, F_GETFL, 0) 80
68 » if err != 0 { 81 //escapes quotes by " -> ""
69 » » return err 82 //Also string -> "string"
83 func escapeAddQuotes(s string) string {
84 » //normal ascii char, one byte wide
85 » rune := byte('"')
86 » l := len(s)
87 » n := 0
88 » for i := 0; i < l; i++ {
89 » » if s[i] == rune {
90 » » » n++
91 » » }
70 } 92 }
71 » if nonblocking { 93 » qs := make([]byte, l+n+2)
72 » » flag |= O_NONBLOCK 94
73 » } else { 95 » qs[0] = rune
74 » » flag &= ^O_NONBLOCK 96 » j := 1
97 » for i := 0; i < l; i++ {
98 » » qs[i+j] = s[i]
99 » » if s[i] == rune {
100 » » » j++
101 » » » qs[i+j] = rune
102 » » }
75 } 103 }
76 » _, err = fcntl(fd, F_SETFL, flag) 104 » qs[len(qs)-1] = rune
77 » return err 105 » return string(qs)
78 } 106 }
79 107
80 108
81 // TODO(kardia): Add trace, env, and fd 109 func CloseOnExec(fd int) {
110 » return
111 }
112
113 func SetNonblock(fd int, nonblocking bool) (errno int) {
114 » return 0
115 }
116
117
118 // TODO(kardia): Add trace
119 //The command and arguments are passed via the Command line parameter.
120 //Thus, repeating the exec name in the first argument is unneeded.
82 func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri ng, fd []int) (pid int, err int) { 121 func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri ng, fd []int) (pid int, err int) {
83 if traceme == true { 122 if traceme == true {
84 return 0, EWINDOWS 123 return 0, EWINDOWS
124 }
125
126 if len(fd) > 3 {
127 return 0, EWINDOWS
128 }
129
130 //CreateProcess will throw an error if the dir is not set to a valid dir
131 // thus get the working dir if dir is empty.
132 if len(dir) == 0 {
133 if wd, ok := Getwd(); ok == 0 {
134 dir = wd
135 }
85 } 136 }
86 137
87 startupInfo := new(StartupInfo) 138 startupInfo := new(StartupInfo)
88 processInfo := new(ProcessInformation) 139 processInfo := new(ProcessInformation)
89 140
90 GetStartupInfo(startupInfo) 141 GetStartupInfo(startupInfo)
91 142
143 startupInfo.Flags = STARTF_USESTDHANDLES
144 startupInfo.StdInput = 0
145 startupInfo.StdOutput = 0
146 startupInfo.StdErr = 0
147
148 var currentProc, _ = GetCurrentProcess()
149 if len(fd) > 0 && fd[0] > 0 {
150 if ok, err := DuplicateHandle(currentProc, int32(fd[0]), current Proc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
151 return 0, err
152 }
153 }
154 if len(fd) > 1 && fd[1] > 0 {
155 if ok, err := DuplicateHandle(currentProc, int32(fd[1]), current Proc, &startupInfo.StdOutput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
156 return 0, err
157 }
158 }
159 if len(fd) > 2 && fd[2] > 0 {
160 if ok, err := DuplicateHandle(currentProc, int32(fd[2]), current Proc, &startupInfo.StdErr, 0, true, DUPLICATE_SAME_ACCESS); !ok {
161 return 0, err
162 }
163 }
164
92 // argv0 must not be longer then 256 chars 165 // argv0 must not be longer then 256 chars
93 // but the entire cmd line can have up to 32k chars (msdn) 166 // but the entire cmd line can have up to 32k chars (msdn)
94 » // 0x00000400 = UNICODE env 167 » ok, err := CreateProcess(
95 » _, err = CreateProcess(0, 168 » » nil,
96 » » StringToUTF16Ptr("\""+argv0+"\" "+stringJoin(argv, " ")), 169 » » StringToUTF16Ptr(escapeAddQuotes(argv0)+" "+stringJoin(argv, " " , escapeAddQuotes)),
97 » » 0, 0, 0, 170 » » nil, //ptr to struct lpProcessAttributes
98 » » 0x00000400, 171 » » nil, //ptr to struct lpThreadAttributes
99 » » 0, //env block, NULL uses parent env 172 » » true, //bInheritHandles
173 » » CREATE_UNICODE_ENVIRONMENT, //Flags
174 » » createEnvBlock(envv), //env block, NULL uses parent env
100 StringToUTF16Ptr(dir), 175 StringToUTF16Ptr(dir),
101 startupInfo, 176 startupInfo,
102 processInfo) 177 processInfo)
103 178
104 » if err == 0 { 179 » if ok {
105 » » pid = int(processInfo.Pid) 180 » » pid = int(processInfo.ProcessId)
106 » » CloseHandle(processInfo.ProcessHandle) 181 » » CloseHandle(processInfo.Process)
107 » » CloseHandle(processInfo.ThreadHandle) 182 » » CloseHandle(processInfo.Thread)
108 } 183 }
109 return 184 return
110 } 185 }
111 186
112 // Combination of fork and exec, careful to be thread safe.
113 func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) { 187 func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
114 return forkExec(argv0, argv, envv, false, dir, fd) 188 return forkExec(argv0, argv, envv, false, dir, fd)
115 } 189 }
116 190
117 // PtraceForkExec is like ForkExec, but starts the child in a traced state. 191 // PtraceForkExec is like ForkExec, but starts the child in a traced state.
118 func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd [ ]int) (pid int, err int) { 192 func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd [ ]int) (pid int, err int) {
119 return forkExec(argv0, argv, envv, true, dir, fd) 193 return forkExec(argv0, argv, envv, true, dir, fd)
120 } 194 }
121 195
122 // Ordinary exec. 196 // Ordinary exec.
123 func Exec(argv0 string, argv []string, envv []string) (err int) { 197 func Exec(argv0 string, argv []string, envv []string) (err int) {
124 return EWINDOWS 198 return EWINDOWS
125 } 199 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b