mixlib-shellout 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +12 -0
- data/Rakefile +24 -0
- data/lib/mixlib/shellout/version.rb +1 -1
- data/lib/mixlib/shellout/windows/core_ext.rb +243 -250
- data/mixlib-shellout-windows.gemspec +7 -0
- data/mixlib-shellout.gemspec +24 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 304f772cea76b9913e4354ee216f9171d89df4b0
|
4
|
+
data.tar.gz: a6d5cf525447578c32e64aaed36d64a322e103e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69933eb3b6dbb1f9877e1b1c7eacd3062426d30482917217b597584241e2c0582cbc3822a3e35e81248ab2b1c2ec1c492bdc72fe6724a98f43ed6d68d33d8f3e
|
7
|
+
data.tar.gz: 2333d801858fa0a2dffca808a900ca7d0570dfeb5acc889914eb91f03c4f3a9d7b5d1dba31456b904d1d37570e1e2bf3cecb3fecdd1fb8c4f6c64e798f1209fc
|
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'mixlib/shellout/version'
|
4
|
+
|
5
|
+
Dir[File.expand_path("../*gemspec", __FILE__)].reverse.each do |gemspec_path|
|
6
|
+
gemspec = eval(IO.read(gemspec_path))
|
7
|
+
Gem::PackageTask.new(gemspec).define
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Run all specs in spec directory"
|
11
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
12
|
+
t.pattern = FileList['spec/**/*_spec.rb']
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Build it and ship it"
|
16
|
+
task ship: [:clobber_package, :gem] do
|
17
|
+
sh("git tag #{Mixlib::ShellOut::VERSION}")
|
18
|
+
sh("git push opscode --tags")
|
19
|
+
Dir[File.expand_path("../pkg/*.gem", __FILE__)].reverse.each do |built_gem|
|
20
|
+
sh("gem push #{built_gem}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
task default: :spec
|
@@ -21,6 +21,8 @@ require 'win32/process'
|
|
21
21
|
|
22
22
|
# Add new constants for Logon
|
23
23
|
module Process::Constants
|
24
|
+
private
|
25
|
+
|
24
26
|
LOGON32_LOGON_INTERACTIVE = 0x00000002
|
25
27
|
LOGON32_PROVIDER_DEFAULT = 0x00000000
|
26
28
|
UOI_NAME = 0x00000002
|
@@ -34,16 +36,6 @@ end
|
|
34
36
|
|
35
37
|
# Define the functions needed to check with Service windows station
|
36
38
|
module Process::Functions
|
37
|
-
module FFI::Library
|
38
|
-
# Wrapper method for attach_function + private
|
39
|
-
def attach_pfunc(*args)
|
40
|
-
attach_function(*args)
|
41
|
-
private args[0]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
extend FFI::Library
|
46
|
-
|
47
39
|
ffi_lib :advapi32
|
48
40
|
|
49
41
|
attach_pfunc :LogonUserW,
|
@@ -64,315 +56,316 @@ end
|
|
64
56
|
|
65
57
|
# Override Process.create to check for running in the Service window station and doing
|
66
58
|
# a full logon with LogonUser, instead of a CreateProcessWithLogon
|
59
|
+
# Cloned from https://github.com/djberg96/win32-process/blob/ffi/lib/win32/process.rb
|
60
|
+
# as of 2015-10-15 from commit cc066e5df25048f9806a610f54bf5f7f253e86f7
|
67
61
|
module Process
|
68
|
-
include Process::Constants
|
69
|
-
include Process::Structs
|
70
62
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
app_name command_line inherit creation_flags cwd environment
|
78
|
-
startup_info thread_inherit process_inherit close_handles with_logon
|
79
|
-
domain password
|
80
|
-
]
|
81
|
-
|
82
|
-
valid_si_keys = %w[
|
83
|
-
startf_flags desktop title x y x_size y_size x_count_chars
|
84
|
-
y_count_chars fill_attribute sw_flags stdin stdout stderr
|
85
|
-
]
|
86
|
-
|
87
|
-
# Set default values
|
88
|
-
hash = {
|
89
|
-
'app_name' => nil,
|
90
|
-
'creation_flags' => 0,
|
91
|
-
'close_handles' => true
|
92
|
-
}
|
93
|
-
|
94
|
-
# Validate the keys, and convert symbols and case to lowercase strings.
|
95
|
-
args.each{ |key, val|
|
96
|
-
key = key.to_s.downcase
|
97
|
-
unless valid_keys.include?(key)
|
98
|
-
raise ArgumentError, "invalid key '#{key}'"
|
63
|
+
# Explicitly reopen singleton class so that class/constant declarations from
|
64
|
+
# extensions are visible in Modules.nesting.
|
65
|
+
class << self
|
66
|
+
def create(args)
|
67
|
+
unless args.kind_of?(Hash)
|
68
|
+
raise TypeError, 'hash keyword arguments expected'
|
99
69
|
end
|
100
|
-
hash[key] = val
|
101
|
-
}
|
102
70
|
|
103
|
-
|
71
|
+
valid_keys = %w[
|
72
|
+
app_name command_line inherit creation_flags cwd environment
|
73
|
+
startup_info thread_inherit process_inherit close_handles with_logon
|
74
|
+
domain password
|
75
|
+
]
|
76
|
+
|
77
|
+
valid_si_keys = %w[
|
78
|
+
startf_flags desktop title x y x_size y_size x_count_chars
|
79
|
+
y_count_chars fill_attribute sw_flags stdin stdout stderr
|
80
|
+
]
|
81
|
+
|
82
|
+
# Set default values
|
83
|
+
hash = {
|
84
|
+
'app_name' => nil,
|
85
|
+
'creation_flags' => 0,
|
86
|
+
'close_handles' => true
|
87
|
+
}
|
104
88
|
|
105
|
-
|
106
|
-
|
107
|
-
hash['startup_info'].each{ |key, val|
|
89
|
+
# Validate the keys, and convert symbols and case to lowercase strings.
|
90
|
+
args.each{ |key, val|
|
108
91
|
key = key.to_s.downcase
|
109
|
-
unless
|
110
|
-
raise ArgumentError, "invalid
|
92
|
+
unless valid_keys.include?(key)
|
93
|
+
raise ArgumentError, "invalid key '#{key}'"
|
111
94
|
end
|
112
|
-
|
95
|
+
hash[key] = val
|
113
96
|
}
|
114
|
-
end
|
115
97
|
|
116
|
-
|
117
|
-
# is specified.
|
118
|
-
unless hash['command_line']
|
119
|
-
if hash['app_name']
|
120
|
-
hash['command_line'] = hash['app_name']
|
121
|
-
hash['app_name'] = nil
|
122
|
-
else
|
123
|
-
raise ArgumentError, 'command_line or app_name must be specified'
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
env = nil
|
98
|
+
si_hash = {}
|
128
99
|
|
129
|
-
|
130
|
-
|
131
|
-
|
100
|
+
# If the startup_info key is present, validate its subkeys
|
101
|
+
if hash['startup_info']
|
102
|
+
hash['startup_info'].each{ |key, val|
|
103
|
+
key = key.to_s.downcase
|
104
|
+
unless valid_si_keys.include?(key)
|
105
|
+
raise ArgumentError, "invalid startup_info key '#{key}'"
|
106
|
+
end
|
107
|
+
si_hash[key] = val
|
108
|
+
}
|
109
|
+
end
|
132
110
|
|
133
|
-
unless
|
134
|
-
|
111
|
+
# The +command_line+ key is mandatory unless the +app_name+ key
|
112
|
+
# is specified.
|
113
|
+
unless hash['command_line']
|
114
|
+
if hash['app_name']
|
115
|
+
hash['command_line'] = hash['app_name']
|
116
|
+
hash['app_name'] = nil
|
117
|
+
else
|
118
|
+
raise ArgumentError, 'command_line or app_name must be specified'
|
119
|
+
end
|
135
120
|
end
|
136
121
|
|
137
|
-
env =
|
138
|
-
env.to_wide_string! if hash['with_logon']
|
139
|
-
end
|
122
|
+
env = nil
|
140
123
|
|
141
|
-
|
142
|
-
|
124
|
+
# The env string should be passed as a string of ';' separated paths.
|
125
|
+
if hash['environment']
|
126
|
+
env = hash['environment']
|
143
127
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
process_security[:bInheritHandle] = true
|
148
|
-
end
|
128
|
+
unless env.respond_to?(:join)
|
129
|
+
env = hash['environment'].split(File::PATH_SEPARATOR)
|
130
|
+
end
|
149
131
|
|
150
|
-
|
151
|
-
|
132
|
+
env = env.map{ |e| e + 0.chr }.join('') + 0.chr
|
133
|
+
env.to_wide_string! if hash['with_logon']
|
134
|
+
end
|
152
135
|
|
153
|
-
|
154
|
-
|
155
|
-
thread_security[:nLength] = 12
|
156
|
-
thread_security[:bInheritHandle] = true
|
157
|
-
end
|
136
|
+
# Process SECURITY_ATTRIBUTE structure
|
137
|
+
process_security = nil
|
158
138
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
['stdin', 'stdout', 'stderr'].each{ |io|
|
165
|
-
if si_hash[io]
|
166
|
-
if si_hash[io].respond_to?(:fileno)
|
167
|
-
handle = get_osfhandle(si_hash[io].fileno)
|
168
|
-
else
|
169
|
-
handle = get_osfhandle(si_hash[io])
|
170
|
-
end
|
139
|
+
if hash['process_inherit']
|
140
|
+
process_security = SECURITY_ATTRIBUTES.new
|
141
|
+
process_security[:nLength] = 12
|
142
|
+
process_security[:bInheritHandle] = 1
|
143
|
+
end
|
171
144
|
|
172
|
-
|
173
|
-
|
145
|
+
# Thread SECURITY_ATTRIBUTE structure
|
146
|
+
thread_security = nil
|
174
147
|
|
175
|
-
|
176
|
-
|
148
|
+
if hash['thread_inherit']
|
149
|
+
thread_security = SECURITY_ATTRIBUTES.new
|
150
|
+
thread_security[:nLength] = 12
|
151
|
+
thread_security[:bInheritHandle] = 1
|
152
|
+
end
|
153
|
+
|
154
|
+
# Automatically handle stdin, stdout and stderr as either IO objects
|
155
|
+
# or file descriptors. This won't work for StringIO, however. It also
|
156
|
+
# will not work on JRuby because of the way it handles internal file
|
157
|
+
# descriptors.
|
158
|
+
#
|
159
|
+
['stdin', 'stdout', 'stderr'].each{ |io|
|
160
|
+
if si_hash[io]
|
161
|
+
if si_hash[io].respond_to?(:fileno)
|
162
|
+
handle = get_osfhandle(si_hash[io].fileno)
|
177
163
|
else
|
178
|
-
|
164
|
+
handle = get_osfhandle(si_hash[io])
|
179
165
|
end
|
180
166
|
|
181
|
-
|
182
|
-
|
167
|
+
if handle == INVALID_HANDLE_VALUE
|
168
|
+
ptr = FFI::MemoryPointer.new(:int)
|
183
169
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
HANDLE_FLAG_INHERIT
|
190
|
-
)
|
170
|
+
if windows_version >= 6 && get_errno(ptr) == 0
|
171
|
+
errno = ptr.read_int
|
172
|
+
else
|
173
|
+
errno = FFI.errno
|
174
|
+
end
|
191
175
|
|
192
|
-
|
176
|
+
raise SystemCallError.new("get_osfhandle", errno)
|
177
|
+
end
|
193
178
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
procinfo = PROCESS_INFORMATION.new
|
202
|
-
startinfo = STARTUPINFO.new
|
203
|
-
|
204
|
-
unless si_hash.empty?
|
205
|
-
startinfo[:cb] = startinfo.size
|
206
|
-
startinfo[:lpDesktop] = si_hash['desktop'] if si_hash['desktop']
|
207
|
-
startinfo[:lpTitle] = si_hash['title'] if si_hash['title']
|
208
|
-
startinfo[:dwX] = si_hash['x'] if si_hash['x']
|
209
|
-
startinfo[:dwY] = si_hash['y'] if si_hash['y']
|
210
|
-
startinfo[:dwXSize] = si_hash['x_size'] if si_hash['x_size']
|
211
|
-
startinfo[:dwYSize] = si_hash['y_size'] if si_hash['y_size']
|
212
|
-
startinfo[:dwXCountChars] = si_hash['x_count_chars'] if si_hash['x_count_chars']
|
213
|
-
startinfo[:dwYCountChars] = si_hash['y_count_chars'] if si_hash['y_count_chars']
|
214
|
-
startinfo[:dwFillAttribute] = si_hash['fill_attribute'] if si_hash['fill_attribute']
|
215
|
-
startinfo[:dwFlags] = si_hash['startf_flags'] if si_hash['startf_flags']
|
216
|
-
startinfo[:wShowWindow] = si_hash['sw_flags'] if si_hash['sw_flags']
|
217
|
-
startinfo[:cbReserved2] = 0
|
218
|
-
startinfo[:hStdInput] = si_hash['stdin'] if si_hash['stdin']
|
219
|
-
startinfo[:hStdOutput] = si_hash['stdout'] if si_hash['stdout']
|
220
|
-
startinfo[:hStdError] = si_hash['stderr'] if si_hash['stderr']
|
221
|
-
end
|
179
|
+
# Most implementations of Ruby on Windows create inheritable
|
180
|
+
# handles by default, but some do not. RF bug #26988.
|
181
|
+
bool = SetHandleInformation(
|
182
|
+
handle,
|
183
|
+
HANDLE_FLAG_INHERIT,
|
184
|
+
HANDLE_FLAG_INHERIT
|
185
|
+
)
|
222
186
|
|
223
|
-
|
224
|
-
cmd = nil
|
187
|
+
raise SystemCallError.new("SetHandleInformation", FFI.errno) unless bool
|
225
188
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
cmd = hash['command_line'].to_wide_string
|
233
|
-
end
|
189
|
+
si_hash[io] = handle
|
190
|
+
si_hash['startf_flags'] ||= 0
|
191
|
+
si_hash['startf_flags'] |= STARTF_USESTDHANDLES
|
192
|
+
hash['inherit'] = true
|
193
|
+
end
|
194
|
+
}
|
234
195
|
|
235
|
-
|
236
|
-
|
237
|
-
|
196
|
+
procinfo = PROCESS_INFORMATION.new
|
197
|
+
startinfo = STARTUPINFO.new
|
198
|
+
|
199
|
+
unless si_hash.empty?
|
200
|
+
startinfo[:cb] = startinfo.size
|
201
|
+
startinfo[:lpDesktop] = si_hash['desktop'] if si_hash['desktop']
|
202
|
+
startinfo[:lpTitle] = si_hash['title'] if si_hash['title']
|
203
|
+
startinfo[:dwX] = si_hash['x'] if si_hash['x']
|
204
|
+
startinfo[:dwY] = si_hash['y'] if si_hash['y']
|
205
|
+
startinfo[:dwXSize] = si_hash['x_size'] if si_hash['x_size']
|
206
|
+
startinfo[:dwYSize] = si_hash['y_size'] if si_hash['y_size']
|
207
|
+
startinfo[:dwXCountChars] = si_hash['x_count_chars'] if si_hash['x_count_chars']
|
208
|
+
startinfo[:dwYCountChars] = si_hash['y_count_chars'] if si_hash['y_count_chars']
|
209
|
+
startinfo[:dwFillAttribute] = si_hash['fill_attribute'] if si_hash['fill_attribute']
|
210
|
+
startinfo[:dwFlags] = si_hash['startf_flags'] if si_hash['startf_flags']
|
211
|
+
startinfo[:wShowWindow] = si_hash['sw_flags'] if si_hash['sw_flags']
|
212
|
+
startinfo[:cbReserved2] = 0
|
213
|
+
startinfo[:hStdInput] = si_hash['stdin'] if si_hash['stdin']
|
214
|
+
startinfo[:hStdOutput] = si_hash['stdout'] if si_hash['stdout']
|
215
|
+
startinfo[:hStdError] = si_hash['stderr'] if si_hash['stderr']
|
216
|
+
end
|
238
217
|
|
239
|
-
|
218
|
+
app = nil
|
219
|
+
cmd = nil
|
240
220
|
|
241
|
-
|
242
|
-
|
221
|
+
# Convert strings to wide character strings if present
|
222
|
+
if hash['app_name']
|
223
|
+
app = hash['app_name'].to_wide_string
|
224
|
+
end
|
243
225
|
|
244
|
-
if hash['
|
245
|
-
|
246
|
-
else
|
247
|
-
raise ArgumentError, 'password must be specified if with_logon is used'
|
226
|
+
if hash['command_line']
|
227
|
+
cmd = hash['command_line'].to_wide_string
|
248
228
|
end
|
249
229
|
|
250
|
-
if hash['
|
251
|
-
|
230
|
+
if hash['cwd']
|
231
|
+
cwd = hash['cwd'].to_wide_string
|
252
232
|
end
|
253
233
|
|
254
|
-
hash['
|
234
|
+
inherit = hash['inherit'] ? 1 : 0
|
255
235
|
|
256
|
-
|
257
|
-
|
236
|
+
if hash['with_logon']
|
237
|
+
logon = hash['with_logon'].to_wide_string
|
258
238
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
return_size # Size filled into buffer
|
265
|
-
)
|
239
|
+
if hash['password']
|
240
|
+
passwd = hash['password'].to_wide_string
|
241
|
+
else
|
242
|
+
raise ArgumentError, 'password must be specified if with_logon is used'
|
243
|
+
end
|
266
244
|
|
267
|
-
|
268
|
-
|
269
|
-
|
245
|
+
if hash['domain']
|
246
|
+
domain = hash['domain'].to_wide_string
|
247
|
+
end
|
248
|
+
|
249
|
+
hash['creation_flags'] |= CREATE_UNICODE_ENVIRONMENT
|
270
250
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
token = FFI::MemoryPointer.new(:ulong)
|
281
|
-
|
282
|
-
bool = LogonUserW(
|
283
|
-
logon, # User
|
284
|
-
domain, # Domain
|
285
|
-
passwd, # Password
|
286
|
-
LOGON32_LOGON_INTERACTIVE, # Logon Type
|
287
|
-
LOGON32_PROVIDER_DEFAULT, # Logon Provider
|
288
|
-
token # User token handle
|
251
|
+
winsta_name = FFI::MemoryPointer.new(:char, 256)
|
252
|
+
return_size = FFI::MemoryPointer.new(:ulong)
|
253
|
+
|
254
|
+
bool = GetUserObjectInformationA(
|
255
|
+
GetProcessWindowStation(), # Window station handle
|
256
|
+
UOI_NAME, # Information to get
|
257
|
+
winsta_name, # Buffer to receive information
|
258
|
+
winsta_name.size, # Size of buffer
|
259
|
+
return_size # Size filled into buffer
|
289
260
|
)
|
290
261
|
|
291
262
|
unless bool
|
292
|
-
raise SystemCallError.new("
|
263
|
+
raise SystemCallError.new("GetUserObjectInformationA", FFI.errno)
|
293
264
|
end
|
294
265
|
|
295
|
-
|
266
|
+
winsta_name = winsta_name.read_string(return_size.read_ulong)
|
267
|
+
|
268
|
+
# If running in the service windows station must do a log on to get
|
269
|
+
# to the interactive desktop. Running process user account must have
|
270
|
+
# the 'Replace a process level token' permission. This is necessary as
|
271
|
+
# the logon (which happens with CreateProcessWithLogon) must have an
|
272
|
+
# interactive windows station to attach to, which is created with the
|
273
|
+
# LogonUser cann with the LOGON32_LOGON_INTERACTIVE flag.
|
274
|
+
if winsta_name =~ /^Service-0x0-.*$/i
|
275
|
+
token = FFI::MemoryPointer.new(:ulong)
|
276
|
+
|
277
|
+
bool = LogonUserW(
|
278
|
+
logon, # User
|
279
|
+
domain, # Domain
|
280
|
+
passwd, # Password
|
281
|
+
LOGON32_LOGON_INTERACTIVE, # Logon Type
|
282
|
+
LOGON32_PROVIDER_DEFAULT, # Logon Provider
|
283
|
+
token # User token handle
|
284
|
+
)
|
285
|
+
|
286
|
+
unless bool
|
287
|
+
raise SystemCallError.new("LogonUserW", FFI.errno)
|
288
|
+
end
|
296
289
|
|
297
|
-
|
298
|
-
|
299
|
-
|
290
|
+
token = token.read_ulong
|
291
|
+
|
292
|
+
begin
|
293
|
+
bool = CreateProcessAsUserW(
|
294
|
+
token, # User token handle
|
295
|
+
app, # App name
|
296
|
+
cmd, # Command line
|
297
|
+
process_security, # Process attributes
|
298
|
+
thread_security, # Thread attributes
|
299
|
+
inherit, # Inherit handles
|
300
|
+
hash['creation_flags'], # Creation Flags
|
301
|
+
env, # Environment
|
302
|
+
cwd, # Working directory
|
303
|
+
startinfo, # Startup Info
|
304
|
+
procinfo # Process Info
|
305
|
+
)
|
306
|
+
ensure
|
307
|
+
CloseHandle(token)
|
308
|
+
end
|
309
|
+
|
310
|
+
unless bool
|
311
|
+
raise SystemCallError.new("CreateProcessAsUserW (You must hold the 'Replace a process level token' permission)", FFI.errno)
|
312
|
+
end
|
313
|
+
else
|
314
|
+
bool = CreateProcessWithLogonW(
|
315
|
+
logon, # User
|
316
|
+
domain, # Domain
|
317
|
+
passwd, # Password
|
318
|
+
LOGON_WITH_PROFILE, # Logon flags
|
300
319
|
app, # App name
|
301
320
|
cmd, # Command line
|
302
|
-
|
303
|
-
thread_security, # Thread attributes
|
304
|
-
inherit, # Inherit handles
|
305
|
-
hash['creation_flags'], # Creation Flags
|
321
|
+
hash['creation_flags'], # Creation flags
|
306
322
|
env, # Environment
|
307
323
|
cwd, # Working directory
|
308
324
|
startinfo, # Startup Info
|
309
325
|
procinfo # Process Info
|
310
326
|
)
|
311
|
-
ensure
|
312
|
-
CloseHandle(token)
|
313
|
-
end
|
314
327
|
|
315
|
-
|
316
|
-
|
328
|
+
unless bool
|
329
|
+
raise SystemCallError.new("CreateProcessWithLogonW", FFI.errno)
|
330
|
+
end
|
317
331
|
end
|
318
332
|
else
|
319
|
-
bool =
|
320
|
-
logon, # User
|
321
|
-
domain, # Domain
|
322
|
-
passwd, # Password
|
323
|
-
LOGON_WITH_PROFILE, # Logon flags
|
333
|
+
bool = CreateProcessW(
|
324
334
|
app, # App name
|
325
335
|
cmd, # Command line
|
336
|
+
process_security, # Process attributes
|
337
|
+
thread_security, # Thread attributes
|
338
|
+
inherit, # Inherit handles?
|
326
339
|
hash['creation_flags'], # Creation flags
|
327
340
|
env, # Environment
|
328
341
|
cwd, # Working directory
|
329
342
|
startinfo, # Startup Info
|
330
343
|
procinfo # Process Info
|
331
344
|
)
|
332
|
-
end
|
333
345
|
|
334
|
-
|
335
|
-
|
346
|
+
unless bool
|
347
|
+
raise SystemCallError.new("CreateProcessW", FFI.errno)
|
348
|
+
end
|
336
349
|
end
|
337
|
-
else
|
338
|
-
bool = CreateProcessW(
|
339
|
-
app, # App name
|
340
|
-
cmd, # Command line
|
341
|
-
process_security, # Process attributes
|
342
|
-
thread_security, # Thread attributes
|
343
|
-
inherit, # Inherit handles?
|
344
|
-
hash['creation_flags'], # Creation flags
|
345
|
-
env, # Environment
|
346
|
-
cwd, # Working directory
|
347
|
-
startinfo, # Startup Info
|
348
|
-
procinfo # Process Info
|
349
|
-
)
|
350
350
|
|
351
|
-
|
352
|
-
|
351
|
+
# Automatically close the process and thread handles in the
|
352
|
+
# PROCESS_INFORMATION struct unless explicitly told not to.
|
353
|
+
if hash['close_handles']
|
354
|
+
CloseHandle(procinfo[:hProcess])
|
355
|
+
CloseHandle(procinfo[:hThread])
|
356
|
+
# Clear these fields so callers don't attempt to close the handle
|
357
|
+
# which can result in the wrong handle being closed or an
|
358
|
+
# exception in some circumstances.
|
359
|
+
procinfo[:hProcess] = 0
|
360
|
+
procinfo[:hThread] = 0
|
353
361
|
end
|
354
|
-
end
|
355
362
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
# Set fields to nil so callers don't attempt to close the handle
|
363
|
-
# which can result in the wrong handle being closed or an
|
364
|
-
# exception in some circumstances
|
365
|
-
procinfo[:hProcess] = nil
|
366
|
-
procinfo[:hThread] = nil
|
363
|
+
ProcessInfo.new(
|
364
|
+
procinfo[:hProcess],
|
365
|
+
procinfo[:hThread],
|
366
|
+
procinfo[:dwProcessId],
|
367
|
+
procinfo[:dwThreadId]
|
368
|
+
)
|
367
369
|
end
|
368
|
-
|
369
|
-
ProcessInfo.new(
|
370
|
-
procinfo[:hProcess],
|
371
|
-
procinfo[:hThread],
|
372
|
-
procinfo[:dwProcessId],
|
373
|
-
procinfo[:dwThreadId]
|
374
|
-
)
|
375
370
|
end
|
376
|
-
|
377
|
-
module_function :create
|
378
371
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/lib')
|
2
|
+
require 'mixlib/shellout/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'mixlib-shellout'
|
6
|
+
s.version = Mixlib::ShellOut::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.extra_rdoc_files = ["README.md", "LICENSE" ]
|
9
|
+
s.summary = "Run external commands on Unix or Windows"
|
10
|
+
s.description = s.summary
|
11
|
+
s.author = "Opscode"
|
12
|
+
s.email = "info@opscode.com"
|
13
|
+
s.homepage = "http://wiki.opscode.com/"
|
14
|
+
|
15
|
+
s.required_ruby_version = ">= 1.9.3"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
18
|
+
|
19
|
+
s.bindir = "bin"
|
20
|
+
s.executables = []
|
21
|
+
s.require_path = 'lib'
|
22
|
+
s.files = %w(Gemfile Rakefile LICENSE README.md) + Dir.glob("*.gemspec") +
|
23
|
+
Dir.glob("lib/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
|
24
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixlib-shellout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Opscode
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -32,14 +32,18 @@ extra_rdoc_files:
|
|
32
32
|
- README.md
|
33
33
|
- LICENSE
|
34
34
|
files:
|
35
|
+
- Gemfile
|
35
36
|
- LICENSE
|
36
37
|
- README.md
|
38
|
+
- Rakefile
|
37
39
|
- lib/mixlib/shellout.rb
|
38
40
|
- lib/mixlib/shellout/exceptions.rb
|
39
41
|
- lib/mixlib/shellout/unix.rb
|
40
42
|
- lib/mixlib/shellout/version.rb
|
41
43
|
- lib/mixlib/shellout/windows.rb
|
42
44
|
- lib/mixlib/shellout/windows/core_ext.rb
|
45
|
+
- mixlib-shellout-windows.gemspec
|
46
|
+
- mixlib-shellout.gemspec
|
43
47
|
homepage: http://wiki.opscode.com/
|
44
48
|
licenses: []
|
45
49
|
metadata: {}
|
@@ -59,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
63
|
version: '0'
|
60
64
|
requirements: []
|
61
65
|
rubyforge_project:
|
62
|
-
rubygems_version: 2.4.
|
66
|
+
rubygems_version: 2.4.6
|
63
67
|
signing_key:
|
64
68
|
specification_version: 4
|
65
69
|
summary: Run external commands on Unix or Windows
|