mixlib-shellout 3.1.2 → 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/mixlib/shellout.rb +5 -5
 - data/lib/mixlib/shellout/helper.rb +3 -3
 - data/lib/mixlib/shellout/unix.rb +3 -3
 - data/lib/mixlib/shellout/version.rb +1 -1
 - data/lib/mixlib/shellout/windows.rb +6 -10
 - data/lib/mixlib/shellout/windows/core_ext.rb +107 -12
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 5225855dde6ade866e318af03d650332d97965ea4748b58c872a86e9f8105095
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: d4f96cee9731d0fa4c83e9bbfae7115a7e0398ac1f4a2a8ba889468a86776c69
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 37baa3739c95552ac72de806cbfe02eeef2cc5d2d611c83e335029379dc7d45ffc33a60e0013fbe32bfd2d3d4cacd6b97741656047a08de086adfd7cd9b42f8d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: dcb06b4e91e7c88128e393af4b4691c72dd4f738bc77d27a1fe0ac4cae6fe35609f8726ad560155ecf93fc80079e7e1e0dd9cafd8473a93e08a0b83298f24183
         
     | 
    
        data/lib/mixlib/shellout.rb
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #--
         
     | 
| 
       2 
2 
     | 
    
         
             
            # Author:: Daniel DeLeo (<dan@chef.io>)
         
     | 
| 
       3 
     | 
    
         
            -
            # Copyright:: Copyright (c)  
     | 
| 
      
 3 
     | 
    
         
            +
            # Copyright:: Copyright (c) Chef Software Inc.
         
     | 
| 
       4 
4 
     | 
    
         
             
            # License:: Apache License, Version 2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            #
         
     | 
| 
       6 
6 
     | 
    
         
             
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
         @@ -16,8 +16,8 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
            # limitations under the License.
         
     | 
| 
       17 
17 
     | 
    
         
             
            #
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
            require "etc"
         
     | 
| 
       20 
     | 
    
         
            -
            require "tmpdir"
         
     | 
| 
      
 19 
     | 
    
         
            +
            require "etc" unless defined?(Etc)
         
     | 
| 
      
 20 
     | 
    
         
            +
            require "tmpdir" unless defined?(Dir.mktmpdir)
         
     | 
| 
       21 
21 
     | 
    
         
             
            require "fcntl"
         
     | 
| 
       22 
22 
     | 
    
         
             
            require_relative "shellout/exceptions"
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
         @@ -122,7 +122,7 @@ module Mixlib 
     | 
|
| 
       122 
122 
     | 
    
         
             
                # === Options:
         
     | 
| 
       123 
123 
     | 
    
         
             
                # If the last argument is a Hash, it is removed from the list of args passed
         
     | 
| 
       124 
124 
     | 
    
         
             
                # to exec and used as an options hash. The following options are available:
         
     | 
| 
       125 
     | 
    
         
            -
                # * +user+: the user the  
     | 
| 
      
 125 
     | 
    
         
            +
                # * +user+: the user the command should run as. if an integer is given, it is
         
     | 
| 
       126 
126 
     | 
    
         
             
                #   used as a uid. A string is treated as a username and resolved to a uid
         
     | 
| 
       127 
127 
     | 
    
         
             
                #   with Etc.getpwnam
         
     | 
| 
       128 
128 
     | 
    
         
             
                # * +group+: the group the command should run as. works similarly to +user+
         
     | 
| 
         @@ -248,7 +248,7 @@ module Mixlib 
     | 
|
| 
       248 
248 
     | 
    
         
             
                # running or died without setting an exit status (e.g., terminated by
         
     | 
| 
       249 
249 
     | 
    
         
             
                # `kill -9`).
         
     | 
| 
       250 
250 
     | 
    
         
             
                def exitstatus
         
     | 
| 
       251 
     | 
    
         
            -
                  @status 
     | 
| 
      
 251 
     | 
    
         
            +
                  @status&.exitstatus
         
     | 
| 
       252 
252 
     | 
    
         
             
                end
         
     | 
| 
       253 
253 
     | 
    
         | 
| 
       254 
254 
     | 
    
         
             
                # Run the command, writing the command's standard out and standard error
         
     | 
| 
         @@ -16,7 +16,7 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
            # limitations under the License.
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
            require_relative "../shellout"
         
     | 
| 
       19 
     | 
    
         
            -
            require "chef-utils"
         
     | 
| 
      
 19 
     | 
    
         
            +
            require "chef-utils" unless defined?(ChefUtils)
         
     | 
| 
       20 
20 
     | 
    
         
             
            require "chef-utils/dsl/default_paths"
         
     | 
| 
       21 
21 
     | 
    
         
             
            require "chef-utils/internal"
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
         @@ -30,7 +30,7 @@ module Mixlib 
     | 
|
| 
       30 
30 
     | 
    
         
             
                  # These APIs are considered public for use in ohai and chef (by cookbooks and plugins, etc)
         
     | 
| 
       31 
31 
     | 
    
         
             
                  # but are considered private/experimental for now for the direct users of mixlib-shellout.
         
     | 
| 
       32 
32 
     | 
    
         
             
                  #
         
     | 
| 
       33 
     | 
    
         
            -
                  # You can see an example of how to handle the " 
     | 
| 
      
 33 
     | 
    
         
            +
                  # You can see an example of how to handle the "dependency injection" in the rspec unit test.
         
     | 
| 
       34 
34 
     | 
    
         
             
                  # That backend API is left deliberately undocumented for now and may not follow SemVer and may
         
     | 
| 
       35 
35 
     | 
    
         
             
                  # break at any time (at least for the rest of 2020).
         
     | 
| 
       36 
36 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -157,7 +157,7 @@ module Mixlib 
     | 
|
| 
       157 
157 
     | 
    
         
             
                  end
         
     | 
| 
       158 
158 
     | 
    
         | 
| 
       159 
159 
     | 
    
         
             
                  def __io_for_live_stream
         
     | 
| 
       160 
     | 
    
         
            -
                    if STDOUT. 
     | 
| 
      
 160 
     | 
    
         
            +
                    if !STDOUT.closed? && __log.trace?
         
     | 
| 
       161 
161 
     | 
    
         
             
                      STDOUT
         
     | 
| 
       162 
162 
     | 
    
         
             
                    else
         
     | 
| 
       163 
163 
     | 
    
         
             
                      nil
         
     | 
    
        data/lib/mixlib/shellout/unix.rb
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #
         
     | 
| 
       2 
2 
     | 
    
         
             
            # Author:: Daniel DeLeo (<dan@chef.io>)
         
     | 
| 
       3 
     | 
    
         
            -
            # Copyright:: Copyright (c)  
     | 
| 
      
 3 
     | 
    
         
            +
            # Copyright:: Copyright (c) Chef Software Inc.
         
     | 
| 
       4 
4 
     | 
    
         
             
            # License:: Apache License, Version 2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            #
         
     | 
| 
       6 
6 
     | 
    
         
             
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
         @@ -370,11 +370,11 @@ module Mixlib 
     | 
|
| 
       370 
370 
     | 
    
         
             
                    return if attempt_reap
         
     | 
| 
       371 
371 
     | 
    
         | 
| 
       372 
372 
     | 
    
         
             
                    @terminate_reason = "Command exceeded allowed execution time, process terminated"
         
     | 
| 
       373 
     | 
    
         
            -
                    logger 
     | 
| 
      
 373 
     | 
    
         
            +
                    logger&.error("Command exceeded allowed execution time, sending TERM")
         
     | 
| 
       374 
374 
     | 
    
         
             
                    Process.kill(:TERM, child_pgid)
         
     | 
| 
       375 
375 
     | 
    
         
             
                    sleep 3
         
     | 
| 
       376 
376 
     | 
    
         
             
                    attempt_reap
         
     | 
| 
       377 
     | 
    
         
            -
                    logger 
     | 
| 
      
 377 
     | 
    
         
            +
                    logger&.error("Command exceeded allowed execution time, sending KILL")
         
     | 
| 
       378 
378 
     | 
    
         
             
                    Process.kill(:KILL, child_pgid)
         
     | 
| 
       379 
379 
     | 
    
         
             
                    reap
         
     | 
| 
       380 
380 
     | 
    
         | 
| 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            # Author:: Daniel DeLeo (<dan@chef.io>)
         
     | 
| 
       3 
3 
     | 
    
         
             
            # Author:: John Keiser (<jkeiser@chef.io>)
         
     | 
| 
       4 
4 
     | 
    
         
             
            # Author:: Ho-Sheng Hsiao (<hosh@chef.io>)
         
     | 
| 
       5 
     | 
    
         
            -
            # Copyright:: Copyright (c)  
     | 
| 
      
 5 
     | 
    
         
            +
            # Copyright:: Copyright (c) Chef Software Inc.
         
     | 
| 
       6 
6 
     | 
    
         
             
            # License:: Apache License, Version 2.0
         
     | 
| 
       7 
7 
     | 
    
         
             
            #
         
     | 
| 
       8 
8 
     | 
    
         
             
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
         @@ -89,7 +89,7 @@ module Mixlib 
     | 
|
| 
       89 
89 
     | 
    
         
             
                      # Start the process
         
     | 
| 
       90 
90 
     | 
    
         
             
                      #
         
     | 
| 
       91 
91 
     | 
    
         
             
                      process, profile, token = Process.create3(create_process_args)
         
     | 
| 
       92 
     | 
    
         
            -
                      logger 
     | 
| 
      
 92 
     | 
    
         
            +
                      logger&.debug(format_process(process, app_name, command_line, timeout))
         
     | 
| 
       93 
93 
     | 
    
         
             
                      begin
         
     | 
| 
       94 
94 
     | 
    
         
             
                        # Start pushing data into input
         
     | 
| 
       95 
95 
     | 
    
         
             
                        stdin_write << input if input
         
     | 
| 
         @@ -124,7 +124,7 @@ module Mixlib 
     | 
|
| 
       124 
124 
     | 
    
         
             
                                kill_process_tree(process.process_id, wmi, logger)
         
     | 
| 
       125 
125 
     | 
    
         
             
                                Process.kill(:KILL, process.process_id)
         
     | 
| 
       126 
126 
     | 
    
         
             
                              rescue SystemCallError
         
     | 
| 
       127 
     | 
    
         
            -
                                logger 
     | 
| 
      
 127 
     | 
    
         
            +
                                logger&.warn("Failed to kill timed out process #{process.process_id}")
         
     | 
| 
       128 
128 
     | 
    
         
             
                              end
         
     | 
| 
       129 
129 
     | 
    
         | 
| 
       130 
130 
     | 
    
         
             
                              raise Mixlib::ShellOut::CommandTimeout, [
         
     | 
| 
         @@ -208,7 +208,7 @@ module Mixlib 
     | 
|
| 
       208 
208 
     | 
    
         
             
                  # 4.  if the argument must be quoted by #1 and terminates in a sequence of backslashes then all the backlashes must themselves
         
     | 
| 
       209 
209 
     | 
    
         
             
                  #     be backslash excaped (double the backslashes).
         
     | 
| 
       210 
210 
     | 
    
         
             
                  # 5.  if an interior quote that must be escaped by #2 has a sequence of backslashes before it then all the backslashes must
         
     | 
| 
       211 
     | 
    
         
            -
                  #     themselves be backslash excaped along with the backslash  
     | 
| 
      
 211 
     | 
    
         
            +
                  #     themselves be backslash excaped along with the backslash escape of the interior quote (double plus one backslashes).
         
     | 
| 
       212 
212 
     | 
    
         
             
                  #
         
     | 
| 
       213 
213 
     | 
    
         
             
                  # And to restate.  We are constructing a string which will be parsed by the windows parser into arguments, and we want those
         
     | 
| 
       214 
214 
     | 
    
         
             
                  # arguments to match the *args array we are passed here.  So call the windows parser operation A then we need to apply A^-1 to
         
     | 
| 
         @@ -398,20 +398,16 @@ module Mixlib 
     | 
|
| 
       398 
398 
     | 
    
         | 
| 
       399 
399 
     | 
    
         
             
                  def kill_process(instance, logger)
         
     | 
| 
       400 
400 
     | 
    
         
             
                    child_pid = instance.wmi_ole_object.processid
         
     | 
| 
       401 
     | 
    
         
            -
                     
     | 
| 
       402 
     | 
    
         
            -
                      logger.debug([
         
     | 
| 
      
 401 
     | 
    
         
            +
                    logger&.debug([
         
     | 
| 
       403 
402 
     | 
    
         
             
                        "killing child process #{child_pid}::",
         
     | 
| 
       404 
403 
     | 
    
         
             
                        "#{instance.wmi_ole_object.Name} of parent #{pid}",
         
     | 
| 
       405 
404 
     | 
    
         
             
                      ].join)
         
     | 
| 
       406 
     | 
    
         
            -
                    end
         
     | 
| 
       407 
405 
     | 
    
         
             
                    Process.kill(:KILL, instance.wmi_ole_object.processid)
         
     | 
| 
       408 
406 
     | 
    
         
             
                  rescue SystemCallError
         
     | 
| 
       409 
     | 
    
         
            -
                     
     | 
| 
       410 
     | 
    
         
            -
                      logger.debug([
         
     | 
| 
      
 407 
     | 
    
         
            +
                    logger&.debug([
         
     | 
| 
       411 
408 
     | 
    
         
             
                        "Failed to kill child process #{child_pid}::",
         
     | 
| 
       412 
409 
     | 
    
         
             
                        "#{instance.wmi_ole_object.Name} of parent #{pid}",
         
     | 
| 
       413 
410 
     | 
    
         
             
                      ].join)
         
     | 
| 
       414 
     | 
    
         
            -
                    end
         
     | 
| 
       415 
411 
     | 
    
         
             
                  end
         
     | 
| 
       416 
412 
     | 
    
         | 
| 
       417 
413 
     | 
    
         
             
                  def format_process(process, app_name, command_line, timeout)
         
     | 
| 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
       2 
2 
     | 
    
         
             
            # Author:: Daniel DeLeo (<dan@chef.io>)
         
     | 
| 
       3 
3 
     | 
    
         
             
            # Author:: John Keiser (<jkeiser@chef.io>)
         
     | 
| 
       4 
     | 
    
         
            -
            # Copyright:: Copyright (c)  
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright:: Copyright (c) Chef Software Inc.
         
     | 
| 
       5 
5 
     | 
    
         
             
            # License:: Apache License, Version 2.0
         
     | 
| 
       6 
6 
     | 
    
         
             
            #
         
     | 
| 
       7 
7 
     | 
    
         
             
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
         @@ -18,10 +18,10 @@ 
     | 
|
| 
       18 
18 
     | 
    
         
             
            #
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
            require "win32/process"
         
     | 
| 
      
 21 
     | 
    
         
            +
            require "ffi/win32/extensions"
         
     | 
| 
       21 
22 
     | 
    
         | 
| 
       22 
23 
     | 
    
         
             
            # Add new constants for Logon
         
     | 
| 
       23 
24 
     | 
    
         
             
            module Process::Constants
         
     | 
| 
       24 
     | 
    
         
            -
              private
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
              LOGON32_LOGON_INTERACTIVE = 0x00000002
         
     | 
| 
       27 
27 
     | 
    
         
             
              LOGON32_LOGON_BATCH = 0x00000004
         
     | 
| 
         @@ -45,6 +45,8 @@ module Process::Constants 
     | 
|
| 
       45 
45 
     | 
    
         
             
              WIN32_PROFILETYPE_PT_MANDATORY           = 0x04
         
     | 
| 
       46 
46 
     | 
    
         
             
              WIN32_PROFILETYPE_PT_ROAMING_PREEXISTING = 0x08
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
      
 48 
     | 
    
         
            +
              # The environment block list ends with two nulls (\0\0).
         
     | 
| 
      
 49 
     | 
    
         
            +
              ENVIRONMENT_BLOCK_ENDS = "\0\0".freeze
         
     | 
| 
       48 
50 
     | 
    
         
             
            end
         
     | 
| 
       49 
51 
     | 
    
         | 
| 
       50 
52 
     | 
    
         
             
            # Structs required for data handling
         
     | 
| 
         @@ -78,6 +80,12 @@ module Process::Functions 
     | 
|
| 
       78 
80 
     | 
    
         
             
              attach_pfunc :UnloadUserProfile,
         
     | 
| 
       79 
81 
     | 
    
         
             
                %i{handle handle}, :bool
         
     | 
| 
       80 
82 
     | 
    
         | 
| 
      
 83 
     | 
    
         
            +
              attach_pfunc :CreateEnvironmentBlock,
         
     | 
| 
      
 84 
     | 
    
         
            +
                %i{pointer ulong bool}, :bool
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              attach_pfunc :DestroyEnvironmentBlock,
         
     | 
| 
      
 87 
     | 
    
         
            +
                %i{pointer}, :bool
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
       81 
89 
     | 
    
         
             
              ffi_lib :advapi32
         
     | 
| 
       82 
90 
     | 
    
         | 
| 
       83 
91 
     | 
    
         
             
              attach_pfunc :LogonUserW,
         
     | 
| 
         @@ -148,15 +156,13 @@ module Process 
     | 
|
| 
       148 
156 
     | 
    
         
             
                  si_hash = {}
         
     | 
| 
       149 
157 
     | 
    
         | 
| 
       150 
158 
     | 
    
         
             
                  # If the startup_info key is present, validate its subkeys
         
     | 
| 
       151 
     | 
    
         
            -
                   
     | 
| 
       152 
     | 
    
         
            -
                     
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
                       
     | 
| 
       155 
     | 
    
         
            -
                        raise ArgumentError, "invalid startup_info key '#{key}'"
         
     | 
| 
       156 
     | 
    
         
            -
                      end
         
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
                      si_hash[key] = val
         
     | 
| 
      
 159 
     | 
    
         
            +
                  hash["startup_info"]&.each do |key, val|
         
     | 
| 
      
 160 
     | 
    
         
            +
                    key = key.to_s.downcase
         
     | 
| 
      
 161 
     | 
    
         
            +
                    unless valid_si_keys.include?(key)
         
     | 
| 
      
 162 
     | 
    
         
            +
                      raise ArgumentError, "invalid startup_info key '#{key}'"
         
     | 
| 
       159 
163 
     | 
    
         
             
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                    si_hash[key] = val
         
     | 
| 
       160 
166 
     | 
    
         
             
                  end
         
     | 
| 
       161 
167 
     | 
    
         | 
| 
       162 
168 
     | 
    
         
             
                  # The +command_line+ key is mandatory unless the +app_name+ key
         
     | 
| 
         @@ -172,9 +178,25 @@ module Process 
     | 
|
| 
       172 
178 
     | 
    
         | 
| 
       173 
179 
     | 
    
         
             
                  env = nil
         
     | 
| 
       174 
180 
     | 
    
         | 
| 
      
 181 
     | 
    
         
            +
                  # Retrieve the environment variables for the specified user.
         
     | 
| 
      
 182 
     | 
    
         
            +
                  if hash["with_logon"]
         
     | 
| 
      
 183 
     | 
    
         
            +
                    logon, passwd, domain = format_creds_from_hash(hash)
         
     | 
| 
      
 184 
     | 
    
         
            +
                    logon_type = hash["elevated"] ? LOGON32_LOGON_BATCH : LOGON32_LOGON_INTERACTIVE
         
     | 
| 
      
 185 
     | 
    
         
            +
                    token = logon_user(logon, domain, passwd, logon_type)
         
     | 
| 
      
 186 
     | 
    
         
            +
                    logon_ptr = FFI::MemoryPointer.from_string(logon)
         
     | 
| 
      
 187 
     | 
    
         
            +
                    profile = PROFILEINFO.new.tap do |dat|
         
     | 
| 
      
 188 
     | 
    
         
            +
                      dat[:dwSize]     = dat.size
         
     | 
| 
      
 189 
     | 
    
         
            +
                      dat[:dwFlags]    = 1
         
     | 
| 
      
 190 
     | 
    
         
            +
                      dat[:lpUserName] = logon_ptr
         
     | 
| 
      
 191 
     | 
    
         
            +
                    end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                    load_user_profile(token, profile.pointer)
         
     | 
| 
      
 194 
     | 
    
         
            +
                    env_list = retrieve_environment_variables(token)
         
     | 
| 
      
 195 
     | 
    
         
            +
                  end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
       175 
197 
     | 
    
         
             
                  # The env string should be passed as a string of ';' separated paths.
         
     | 
| 
       176 
198 
     | 
    
         
             
                  if hash["environment"]
         
     | 
| 
       177 
     | 
    
         
            -
                    env = hash["environment"]
         
     | 
| 
      
 199 
     | 
    
         
            +
                    env = env_list.nil? ? hash["environment"] : merge_env_variables(env_list, hash["environment"])
         
     | 
| 
       178 
200 
     | 
    
         | 
| 
       179 
201 
     | 
    
         
             
                    unless env.respond_to?(:join)
         
     | 
| 
       180 
202 
     | 
    
         
             
                      env = hash["environment"].split(File::PATH_SEPARATOR)
         
     | 
| 
         @@ -396,6 +418,33 @@ module Process 
     | 
|
| 
       396 
418 
     | 
    
         
             
                  true
         
     | 
| 
       397 
419 
     | 
    
         
             
                end
         
     | 
| 
       398 
420 
     | 
    
         | 
| 
      
 421 
     | 
    
         
            +
                # Retrieves the environment variables for the specified user.
         
     | 
| 
      
 422 
     | 
    
         
            +
                #
         
     | 
| 
      
 423 
     | 
    
         
            +
                # @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings.
         
     | 
| 
      
 424 
     | 
    
         
            +
                # @param token [Integer] User token handle.
         
     | 
| 
      
 425 
     | 
    
         
            +
                # @return [Boolean] true if successfully retrieves the environment variables for the specified user.
         
     | 
| 
      
 426 
     | 
    
         
            +
                #
         
     | 
| 
      
 427 
     | 
    
         
            +
                def create_environment_block(env_pointer, token)
         
     | 
| 
      
 428 
     | 
    
         
            +
                  unless CreateEnvironmentBlock(env_pointer, token, false)
         
     | 
| 
      
 429 
     | 
    
         
            +
                    raise SystemCallError.new("CreateEnvironmentBlock", FFI.errno)
         
     | 
| 
      
 430 
     | 
    
         
            +
                  end
         
     | 
| 
      
 431 
     | 
    
         
            +
             
     | 
| 
      
 432 
     | 
    
         
            +
                  true
         
     | 
| 
      
 433 
     | 
    
         
            +
                end
         
     | 
| 
      
 434 
     | 
    
         
            +
             
     | 
| 
      
 435 
     | 
    
         
            +
                # Frees environment variables created by the CreateEnvironmentBlock function.
         
     | 
| 
      
 436 
     | 
    
         
            +
                #
         
     | 
| 
      
 437 
     | 
    
         
            +
                # @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings.
         
     | 
| 
      
 438 
     | 
    
         
            +
                # @return [Boolean] true if successfully frees environment variables created by the CreateEnvironmentBlock function.
         
     | 
| 
      
 439 
     | 
    
         
            +
                #
         
     | 
| 
      
 440 
     | 
    
         
            +
                def destroy_environment_block(env_pointer)
         
     | 
| 
      
 441 
     | 
    
         
            +
                  unless DestroyEnvironmentBlock(env_pointer)
         
     | 
| 
      
 442 
     | 
    
         
            +
                    raise SystemCallError.new("DestroyEnvironmentBlock", FFI.errno)
         
     | 
| 
      
 443 
     | 
    
         
            +
                  end
         
     | 
| 
      
 444 
     | 
    
         
            +
             
     | 
| 
      
 445 
     | 
    
         
            +
                  true
         
     | 
| 
      
 446 
     | 
    
         
            +
                end
         
     | 
| 
      
 447 
     | 
    
         
            +
             
     | 
| 
       399 
448 
     | 
    
         
             
                def create_process_as_user(token, app, cmd, process_security,
         
     | 
| 
       400 
449 
     | 
    
         
             
                  thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo)
         
     | 
| 
       401 
450 
     | 
    
         | 
| 
         @@ -530,5 +579,51 @@ module Process 
     | 
|
| 
       530 
579 
     | 
    
         
             
                  [ logon, passwd, domain ]
         
     | 
| 
       531 
580 
     | 
    
         
             
                end
         
     | 
| 
       532 
581 
     | 
    
         | 
| 
      
 582 
     | 
    
         
            +
                # Retrieves the environment variables for the specified user.
         
     | 
| 
      
 583 
     | 
    
         
            +
                #
         
     | 
| 
      
 584 
     | 
    
         
            +
                # @param token [Integer] User token handle.
         
     | 
| 
      
 585 
     | 
    
         
            +
                # @return env_list [Array<String>] Environment variables of specified user.
         
     | 
| 
      
 586 
     | 
    
         
            +
                #
         
     | 
| 
      
 587 
     | 
    
         
            +
                def retrieve_environment_variables(token)
         
     | 
| 
      
 588 
     | 
    
         
            +
                  env_list = []
         
     | 
| 
      
 589 
     | 
    
         
            +
                  env_pointer = FFI::MemoryPointer.new(:pointer)
         
     | 
| 
      
 590 
     | 
    
         
            +
                  create_environment_block(env_pointer, token)
         
     | 
| 
      
 591 
     | 
    
         
            +
                  str_ptr = env_pointer.read_pointer
         
     | 
| 
      
 592 
     | 
    
         
            +
                  offset = 0
         
     | 
| 
      
 593 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 594 
     | 
    
         
            +
                    new_str_pointer = str_ptr + offset
         
     | 
| 
      
 595 
     | 
    
         
            +
                    break if new_str_pointer.read_string(2) == ENVIRONMENT_BLOCK_ENDS
         
     | 
| 
      
 596 
     | 
    
         
            +
             
     | 
| 
      
 597 
     | 
    
         
            +
                    environment = new_str_pointer.read_wstring
         
     | 
| 
      
 598 
     | 
    
         
            +
                    env_list << environment
         
     | 
| 
      
 599 
     | 
    
         
            +
                    offset = offset + environment.length * 2 + 2
         
     | 
| 
      
 600 
     | 
    
         
            +
                  end
         
     | 
| 
      
 601 
     | 
    
         
            +
             
     | 
| 
      
 602 
     | 
    
         
            +
                  # To free the buffer when we have finished with the environment block
         
     | 
| 
      
 603 
     | 
    
         
            +
                  destroy_environment_block(str_ptr)
         
     | 
| 
      
 604 
     | 
    
         
            +
                  env_list
         
     | 
| 
      
 605 
     | 
    
         
            +
                end
         
     | 
| 
      
 606 
     | 
    
         
            +
             
     | 
| 
      
 607 
     | 
    
         
            +
                # Merge environment variables of specified user and current environment variables.
         
     | 
| 
      
 608 
     | 
    
         
            +
                #
         
     | 
| 
      
 609 
     | 
    
         
            +
                # @param fetched_env [Array<String>] environment variables of specified user.
         
     | 
| 
      
 610 
     | 
    
         
            +
                # @param current_env [Array<String>] current environment variables.
         
     | 
| 
      
 611 
     | 
    
         
            +
                # @return [Array<String>] Merged environment variables.
         
     | 
| 
      
 612 
     | 
    
         
            +
                #
         
     | 
| 
      
 613 
     | 
    
         
            +
                def merge_env_variables(fetched_env, current_env)
         
     | 
| 
      
 614 
     | 
    
         
            +
                  env_hash_1 = environment_list_to_hash(fetched_env)
         
     | 
| 
      
 615 
     | 
    
         
            +
                  env_hash_2 = environment_list_to_hash(current_env)
         
     | 
| 
      
 616 
     | 
    
         
            +
                  merged_env = env_hash_2.merge(env_hash_1)
         
     | 
| 
      
 617 
     | 
    
         
            +
                  merged_env.map { |k, v| "#{k}=#{v}" }
         
     | 
| 
      
 618 
     | 
    
         
            +
                end
         
     | 
| 
      
 619 
     | 
    
         
            +
             
     | 
| 
      
 620 
     | 
    
         
            +
                # Convert an array to a hash.
         
     | 
| 
      
 621 
     | 
    
         
            +
                #
         
     | 
| 
      
 622 
     | 
    
         
            +
                # @param env_var [Array<String>] Environment variables.
         
     | 
| 
      
 623 
     | 
    
         
            +
                # @return [Hash] Converted an array to hash.
         
     | 
| 
      
 624 
     | 
    
         
            +
                #
         
     | 
| 
      
 625 
     | 
    
         
            +
                def environment_list_to_hash(env_var)
         
     | 
| 
      
 626 
     | 
    
         
            +
                  Hash[ env_var.map { |pair| pair.split("=", 2) } ]
         
     | 
| 
      
 627 
     | 
    
         
            +
                end
         
     | 
| 
       533 
628 
     | 
    
         
             
              end
         
     | 
| 
       534 
629 
     | 
    
         
             
            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: 3. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.2.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Chef Software Inc.
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2020- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2020-11-16 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: chef-utils
         
     |