cmd/run: Unbreak 'enter' if the shell had exited with 127

Currently, 'toolbox enter' can get into a loop if the user tried to
run something inside the shell that didn't exist, and quit immediately
afterwards:
  $ toolbox enter
  ⬢$ foo
  bash: foo: command not found
  ⬢$
  logout
  Error: command /bin/bash not found in container fedora-toolbox-34
  Using /bin/bash instead.
  ⬢$

This is because:

  * The shell forwards the exit code of the last command that was
    invoked as its own exit code. If the last command that was
    attempted was absent then this exit code is 127.

  * 'podman exec' uses 127 as the exit code when it can't invoke the
    command. If it's able to successfully invoke the command, it
    forwards the exit code of the command itself.

Therefore, in the above example 'podman exec' itself returns with an
exit code of 127 even though both the working directory and the command
that were passed to it were present. Hence, it's necessary to
explicitly check if the requested command was really absent before
attempting the fallbacks.

Fallout from 4536e2c8c2

https://github.com/containers/toolbox/pull/872
This commit is contained in:
Debarshi Ray 2021-09-09 19:29:10 +02:00
parent 208d553cec
commit d6b1fbea4c
1 changed files with 22 additions and 1 deletions

View File

@ -343,7 +343,7 @@ func runCommandWithFallbacks(container string, command []string, emitEscapeSeque
} else {
return fmt.Errorf("directory %s not found in container %s", workDir, container)
}
} else {
} else if _, err := isCommandPresent(container, command[0]); err != nil {
if fallbackToBash && runFallbackCommandsIndex < len(runFallbackCommands) {
fmt.Fprintf(os.Stderr,
"Error: command %s not found in container %s\n",
@ -357,6 +357,8 @@ func runCommandWithFallbacks(container string, command []string, emitEscapeSeque
} else {
return fmt.Errorf("command %s not found in container %s", command[0], container)
}
} else {
return nil
}
default:
return nil
@ -489,6 +491,25 @@ func getEntryPointAndPID(container string) (string, int, error) {
return entryPoint, entryPointPIDInt, nil
}
func isCommandPresent(container, command string) (bool, error) {
logrus.Debugf("Looking for command %s in container %s", command, container)
logLevelString := podman.LogLevel.String()
args := []string{
"--log-level", logLevelString,
"exec",
"--user", currentUser.Username,
container,
"sh", "-c", "command -v \"$1\"", "sh", command,
}
if err := shell.Run("podman", nil, nil, nil, args...); err != nil {
return false, err
}
return true, nil
}
func isPathPresent(container, path string) (bool, error) {
logrus.Debugf("Looking for path %s in container %s", path, container)