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

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

Issue 1578041: code review 1578041: add Windows ForkExec, Syscall12 (Closed)
Left Patch Set: code review 1578041: add Windows ForkExec, Syscall12, Syscall15 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 "utf16"
11 ) 12 )
12 13
13 // 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.
14 // However, the kernel32 CreateProcess does a good job with 15 // However, the kernel32 CreateProcess does a good job with
15 // ForkExec. 16 // ForkExec.
16 17
17 var ForkLock sync.RWMutex 18 var ForkLock sync.RWMutex
18 19
19 // Joins an array of string with sep 20 // Joins an array of string with sep
20 // From the "strings" package. Modified. 21 // From the "strings" package. Modified.
(...skipping 22 matching lines...) Expand all
43 s = sep 44 s = sep
44 for j := 0; j < len(s); j++ { 45 for j := 0; j < len(s); j++ {
45 b[bp] = s[j] 46 b[bp] = s[j]
46 bp++ 47 bp++
47 } 48 }
48 } 49 }
49 } 50 }
50 return string(b) 51 return string(b)
51 } 52 }
52 53
54 //Env block is a sequence of null terminated strings followed by a null.
55 //Last bytes are two unicode nulls, or four null bytes.
56 func createEnvBlock(envv []string) *uint16 {
57 if len(envv) == 0 {
58 return &utf16.Encode([]int("\x00\x00"))[0]
59 }
60 length := 0
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]
77 }
78
53 type escapeFunc func(s string) string 79 type escapeFunc func(s string) string
54 80
55 //escapes quotes by " -> "" 81 //escapes quotes by " -> ""
56 //Also string -> "string" 82 //Also string -> "string"
57 func escapeAddQuotes(s string) string { 83 func escapeAddQuotes(s string) string {
58 //normal ascii char, one byte wide 84 //normal ascii char, one byte wide
59 rune := byte('"') 85 rune := byte('"')
60 l := len(s) 86 l := len(s)
61 n := 0 87 n := 0
62 for i := 0; i < l; i++ { 88 for i := 0; i < l; i++ {
(...skipping 19 matching lines...) Expand all
82 108
83 func CloseOnExec(fd int) { 109 func CloseOnExec(fd int) {
84 return 110 return
85 } 111 }
86 112
87 func SetNonblock(fd int, nonblocking bool) (errno int) { 113 func SetNonblock(fd int, nonblocking bool) (errno int) {
88 return 0 114 return 0
89 } 115 }
90 116
91 117
92 // TODO(kardia): Add trace, env, and fd 118 // TODO(kardia): Add trace
93 // Windows requires a valid dir. Maybe detect empty 119 //The command and arguments are passed via the Command line parameter.
94 // string and use current dir if it is. 120 //Thus, repeating the exec name in the first argument is unneeded.
95 // The command and arguments are passed via the Command line parameter.
96 // Thus, repeating the exec name in the first argument is unneeded.
97 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) {
98 if traceme == true { 122 if traceme == true {
99 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 }
100 } 136 }
101 137
102 startupInfo := new(StartupInfo) 138 startupInfo := new(StartupInfo)
brainman 2010/06/09 09:18:34 Aren't you supposed to at lease set startupInfo.Cb
103 processInfo := new(ProcessInformation) 139 processInfo := new(ProcessInformation)
104 140
105 GetStartupInfo(startupInfo) 141 GetStartupInfo(startupInfo)
106 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
107 // argv0 must not be longer then 256 chars 165 // argv0 must not be longer then 256 chars
108 // 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)
109 » // 0x00000400 = UNICODE env 167 » ok, err := CreateProcess(
brainman 2010/06/09 09:18:34 Instead of the comment, I would have const: CREAT
110 » _, err = CreateProcess(0, 168 » » nil,
111 StringToUTF16Ptr(escapeAddQuotes(argv0)+" "+stringJoin(argv, " " , escapeAddQuotes)), 169 StringToUTF16Ptr(escapeAddQuotes(argv0)+" "+stringJoin(argv, " " , escapeAddQuotes)),
112 » » 0, 0, 0, 170 » » nil, //ptr to struct lpProcessAttributes
113 » » 0x00000400, 171 » » nil, //ptr to struct lpThreadAttributes
114 » » 0, //env block, NULL uses parent env 172 » » true, //bInheritHandles
173 » » CREATE_UNICODE_ENVIRONMENT, //Flags
174 » » createEnvBlock(envv), //env block, NULL uses parent env
115 StringToUTF16Ptr(dir), 175 StringToUTF16Ptr(dir),
116 startupInfo, 176 startupInfo,
117 processInfo) 177 processInfo)
118 178
119 » if err == 0 { 179 » if ok {
120 » » pid = int(processInfo.Pid) 180 » » pid = int(processInfo.ProcessId)
121 » » CloseHandle(processInfo.ProcessHandle) 181 » » CloseHandle(processInfo.Process)
122 » » CloseHandle(processInfo.ThreadHandle) 182 » » CloseHandle(processInfo.Thread)
123 } 183 }
124 return 184 return
125 } 185 }
126 186
127 // Combination of fork and exec, careful to be thread safe.
128 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) {
129 return forkExec(argv0, argv, envv, false, dir, fd) 188 return forkExec(argv0, argv, envv, false, dir, fd)
130 } 189 }
131 190
132 // 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.
133 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) {
134 return forkExec(argv0, argv, envv, true, dir, fd) 193 return forkExec(argv0, argv, envv, true, dir, fd)
135 } 194 }
136 195
137 // Ordinary exec. 196 // Ordinary exec.
138 func Exec(argv0 string, argv []string, envv []string) (err int) { 197 func Exec(argv0 string, argv []string, envv []string) (err int) {
139 return EWINDOWS 198 return EWINDOWS
140 } 199 }
LEFTRIGHT

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