~ubuntu-branches/ubuntu/trusty/puppet/trusty

« back to all changes in this revision

Viewing changes to lib/puppet/provider/exec/posix.rb

  • Committer: Package Import Robot
  • Author(s): Stig Sandbeck Mathisen
  • Date: 2011-10-22 14:08:22 UTC
  • mfrom: (1.1.25) (3.1.32 sid)
  • Revision ID: package-import@ubuntu.com-20111022140822-odxde5lohc45yhuz
Tags: 2.7.6-1
* New upstream release (CVE-2011-3872)
* Remove cherry-picked "groupadd_aix_warning" patch
* Install all new manpages

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Puppet::Type.type(:exec).provide :posix do
2
 
  include Puppet::Util::Execution
 
1
require 'puppet/provider/exec'
3
2
 
 
3
Puppet::Type.type(:exec).provide :posix, :parent => Puppet::Provider::Exec do
4
4
  confine :feature => :posix
5
5
  defaultfor :feature => :posix
6
6
 
7
 
  desc "Execute external binaries directly, on POSIX systems.
8
 
This does not pass through a shell, or perform any interpolation, but
9
 
only directly calls the command with the arguments given."
10
 
 
11
 
  def run(command, check = false)
12
 
    output = nil
13
 
    status = nil
14
 
    dir = nil
15
 
 
16
 
    checkexe(command)
17
 
 
18
 
    if dir = resource[:cwd]
19
 
      unless File.directory?(dir)
20
 
        if check
21
 
          dir = nil
22
 
        else
23
 
          self.fail "Working directory '#{dir}' does not exist"
24
 
        end
25
 
      end
26
 
    end
27
 
 
28
 
    dir ||= Dir.pwd
29
 
 
30
 
    debug "Executing#{check ? " check": ""} '#{command}'"
31
 
    begin
32
 
      # Do our chdir
33
 
      Dir.chdir(dir) do
34
 
        environment = {}
35
 
 
36
 
        environment[:PATH] = resource[:path].join(":") if resource[:path]
37
 
 
38
 
        if envlist = resource[:environment]
39
 
          envlist = [envlist] unless envlist.is_a? Array
40
 
          envlist.each do |setting|
41
 
            if setting =~ /^(\w+)=((.|\n)+)$/
42
 
              env_name = $1
43
 
              value = $2
44
 
              if environment.include?(env_name) || environment.include?(env_name.to_sym)
45
 
                warning "Overriding environment setting '#{env_name}' with '#{value}'"
46
 
              end
47
 
              environment[env_name] = value
48
 
            else
49
 
              warning "Cannot understand environment setting #{setting.inspect}"
50
 
            end
51
 
          end
52
 
        end
53
 
 
54
 
        withenv environment do
55
 
          Timeout::timeout(resource[:timeout]) do
56
 
            output, status = Puppet::Util::SUIDManager.
57
 
              run_and_capture([command], resource[:user], resource[:group])
58
 
          end
59
 
          # The shell returns 127 if the command is missing.
60
 
          if status.exitstatus == 127
61
 
            raise ArgumentError, output
62
 
          end
63
 
        end
64
 
      end
65
 
    rescue Errno::ENOENT => detail
66
 
      self.fail detail.to_s
67
 
    end
68
 
 
69
 
    return output, status
70
 
  end
 
7
  desc <<-EOT
 
8
    Executes external binaries directly, without passing through a shell or
 
9
    performing any interpolation. This is a safer and more predictable way
 
10
    to execute most commands, but prevents the use of globbing and shell
 
11
    built-ins (including control logic like "for" and "if" statements).
 
12
  EOT
71
13
 
72
14
  # Verify that we have the executable
73
15
  def checkexe(command)
74
16
    exe = extractexe(command)
75
17
 
 
18
    if File.expand_path(exe) == exe
 
19
      if !File.exists?(exe)
 
20
        raise ArgumentError, "Could not find command '#{exe}'"
 
21
      elsif !File.file?(exe)
 
22
        raise ArgumentError, "'#{exe}' is a #{File.ftype(exe)}, not a file"
 
23
      elsif !File.executable?(exe)
 
24
        raise ArgumentError, "'#{exe}' is not executable"
 
25
      end
 
26
      return
 
27
    end
 
28
 
76
29
    if resource[:path]
77
 
      if Puppet.features.posix? and !File.exists?(exe)
78
 
        withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do
79
 
          exe = which(exe) || raise(ArgumentError,"Could not find command '#{exe}'")
80
 
        end
81
 
      elsif Puppet.features.microsoft_windows? and !File.exists?(exe)
82
 
        resource[:path].each do |path|
83
 
          [".exe", ".ps1", ".bat", ".com", ""].each do |extension|
84
 
            file = File.join(path, exe+extension)
85
 
            return if File.exists?(file)
86
 
          end
87
 
        end
 
30
      withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do
 
31
        return if which(exe)
88
32
      end
89
33
    end
90
34
 
91
 
    raise ArgumentError, "Could not find command '#{exe}'" unless File.exists?(exe)
92
 
    unless File.executable?(exe)
93
 
      raise ArgumentError,
94
 
      "'#{exe}' is not executable"
95
 
    end
96
 
  end
97
 
 
98
 
  def extractexe(command)
99
 
    # easy case: command was quoted
100
 
    if command =~ /^"([^"]+)"/
101
 
      $1
102
 
    else
103
 
      command.split(/ /)[0]
104
 
    end
105
 
  end
106
 
 
107
 
  def validatecmd(command)
108
 
    exe = extractexe(command)
109
 
    # if we're not fully qualified, require a path
110
 
    self.fail "'#{command}' is not qualified and no path was specified. Please qualify the command or specify a path." if File.expand_path(exe) != exe and resource[:path].nil?
 
35
    # 'which' will only return the command if it's executable, so we can't
 
36
    # distinguish not found from not executable
 
37
    raise ArgumentError, "Could not find command '#{exe}'"
111
38
  end
112
39
end