Skip to content

Commit 77cbbda

Browse files
authored
Merge pull request #2874 from jandubois/bash-quotes
Use printf instead of $'' to pass a multi-line string to bash
2 parents 8ce2869 + b4252cc commit 77cbbda

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

pkg/hostagent/requirements.go

+16-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package hostagent
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67
"time"
78

89
"github.com/lima-vm/lima/pkg/limayaml"
@@ -61,14 +62,17 @@ func (a *HostAgent) waitForRequirements(label string, requirements []requirement
6162
// EOF
6263
// /usr/bin/env ruby
6364
//
64-
// ssh.ExecuteScript will strip the `#!` prefix from the first line and invoke the rest
65-
// of the line as the command. The full script is then passed via STDIN. We use the $' '
66-
// form of shell quoting to be able to use \n as newline escapes to fit everything on a
65+
// ssh.ExecuteScript will strip the `#!` prefix from the first line and invoke the
66+
// rest of the line as the command. The full script is then passed via STDIN. We use
67+
// "$(printf '…')" to be able to use \n as newline escapes, to fit everything on a
6768
// single line:
6869
//
69-
// #!/bin/bash -c $'while … done<<EOF\n$(sudo …)\nEOF\n/usr/bin/env ruby'
70+
// #!/bin/bash -c "$(printf 'while … done<<EOF\n$(sudo …)\nEOF\n/usr/bin/env ruby')"
7071
// #!/usr/bin/env ruby
7172
// …
73+
//
74+
// An earlier implementation used $'…' for quoting, but that isn't supported if the
75+
// user switched the default shell to fish.
7276
func prefixExportParam(script string) (string, error) {
7377
interpreter, err := ssh.ParseScriptInterpreter(script)
7478
if err != nil {
@@ -77,7 +81,14 @@ func prefixExportParam(script string) (string, error) {
7781

7882
// TODO we should have a symbolic constant for `/mnt/lima-cidata`
7983
exportParam := `while read -r line; do [ -n "$line" ] && export "$line"; done<<EOF\n$(sudo cat /mnt/lima-cidata/param.env)\nEOF\n`
80-
return fmt.Sprintf("#!/bin/bash -c $'%s%s'\n%s", exportParam, interpreter, script), nil
84+
85+
// double up all '%' characters so we can pass them through unchanged in the format string of printf
86+
interpreter = strings.ReplaceAll(interpreter, "%", "%%")
87+
exportParam = strings.ReplaceAll(exportParam, "%", "%%")
88+
// strings will be interpolated into single-quoted strings, so protect any existing single quotes
89+
interpreter = strings.ReplaceAll(interpreter, "'", `'"'"'`)
90+
exportParam = strings.ReplaceAll(exportParam, "'", `'"'"'`)
91+
return fmt.Sprintf("#!/bin/bash -c \"$(printf '%s%s')\"\n%s", exportParam, interpreter, script), nil
8192
}
8293

8394
func (a *HostAgent) waitForRequirement(r requirement) error {

0 commit comments

Comments
 (0)