Merge pull request #18865 from Homebrew/systemd-quote
Fix systemd command line quoting
This commit is contained in:
		
						commit
						2d8a19d260
					
				@ -455,7 +455,7 @@ module Homebrew
 | 
			
		||||
    sig { returns(String) }
 | 
			
		||||
    def to_systemd_unit
 | 
			
		||||
      # command needs to be first because it initializes all other values
 | 
			
		||||
      cmd = command&.map { |arg| Utils::Shell.sh_quote(arg) }
 | 
			
		||||
      cmd = command&.map { |arg| Utils::Service.systemd_quote(arg) }
 | 
			
		||||
                   &.join(" ")
 | 
			
		||||
 | 
			
		||||
      options = []
 | 
			
		||||
 | 
			
		||||
@ -727,7 +727,7 @@ RSpec.describe Homebrew::Service do
 | 
			
		||||
 | 
			
		||||
        [Service]
 | 
			
		||||
        Type=simple
 | 
			
		||||
        ExecStart=#{HOMEBREW_PREFIX}/opt/#{name}/bin/beanstalkd test
 | 
			
		||||
        ExecStart="#{HOMEBREW_PREFIX}/opt/#{name}/bin/beanstalkd" "test"
 | 
			
		||||
        Restart=always
 | 
			
		||||
        RestartSec=30
 | 
			
		||||
        WorkingDirectory=#{HOMEBREW_PREFIX}/var
 | 
			
		||||
@ -760,7 +760,7 @@ RSpec.describe Homebrew::Service do
 | 
			
		||||
 | 
			
		||||
        [Service]
 | 
			
		||||
        Type=oneshot
 | 
			
		||||
        ExecStart=#{HOMEBREW_PREFIX}/opt/#{name}/bin/beanstalkd
 | 
			
		||||
        ExecStart="#{HOMEBREW_PREFIX}/opt/#{name}/bin/beanstalkd"
 | 
			
		||||
      SYSTEMD
 | 
			
		||||
      expect(unit).to eq(unit_expect)
 | 
			
		||||
    end
 | 
			
		||||
@ -783,7 +783,7 @@ RSpec.describe Homebrew::Service do
 | 
			
		||||
 | 
			
		||||
        [Service]
 | 
			
		||||
        Type=simple
 | 
			
		||||
        ExecStart=#{HOMEBREW_PREFIX}/opt/#{name}/bin/beanstalkd
 | 
			
		||||
        ExecStart="#{HOMEBREW_PREFIX}/opt/#{name}/bin/beanstalkd"
 | 
			
		||||
        WorkingDirectory=#{Dir.home}
 | 
			
		||||
      SYSTEMD
 | 
			
		||||
      expect(unit).to eq(unit_expect)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								Library/Homebrew/test/utils/service_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Library/Homebrew/test/utils/service_spec.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "utils/service"
 | 
			
		||||
 | 
			
		||||
RSpec.describe Utils::Service do
 | 
			
		||||
  describe "::systemd_quote" do
 | 
			
		||||
    it "quotes empty strings correctly" do
 | 
			
		||||
      expect(described_class.systemd_quote("")).to eq '""'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "quotes strings with special characters escaped correctly" do
 | 
			
		||||
      expect(described_class.systemd_quote("\a\b\f\n\r\t\v\\"))
 | 
			
		||||
        .to eq '"\\a\\b\\f\\n\\r\\t\\v\\\\"'
 | 
			
		||||
      expect(described_class.systemd_quote("\"' ")).to eq "\"\\\"' \""
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "does not escape characters that do not need escaping" do
 | 
			
		||||
      expect(described_class.systemd_quote("daemon off;")).to eq '"daemon off;"'
 | 
			
		||||
      expect(described_class.systemd_quote("--timeout=3")).to eq '"--timeout=3"'
 | 
			
		||||
      expect(described_class.systemd_quote("--answer=foo bar"))
 | 
			
		||||
        .to eq '"--answer=foo bar"'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -48,5 +48,30 @@ module Utils
 | 
			
		||||
    def self.systemctl?
 | 
			
		||||
      !systemctl.nil?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Quote a string for use in systemd command lines, e.g., in `ExecStart`.
 | 
			
		||||
    # https://www.freedesktop.org/software/systemd/man/latest/systemd.syntax.html#Quoting
 | 
			
		||||
    sig { params(str: String).returns(String) }
 | 
			
		||||
    def self.systemd_quote(str)
 | 
			
		||||
      result = +"\""
 | 
			
		||||
      # No need to escape single quotes and spaces, as we're always double
 | 
			
		||||
      # quoting the entire string.
 | 
			
		||||
      str.each_char do |char|
 | 
			
		||||
        result << case char
 | 
			
		||||
        when "\a" then "\\a"
 | 
			
		||||
        when "\b" then "\\b"
 | 
			
		||||
        when "\f" then "\\f"
 | 
			
		||||
        when "\n" then "\\n"
 | 
			
		||||
        when "\r" then "\\r"
 | 
			
		||||
        when "\t" then "\\t"
 | 
			
		||||
        when "\v" then "\\v"
 | 
			
		||||
        when "\\" then "\\\\"
 | 
			
		||||
        when "\"" then "\\\""
 | 
			
		||||
        else char
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      result << "\""
 | 
			
		||||
      result.freeze
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user