Skip to content

Commit c05b6a4

Browse files
committed
enter: improve positional args handling, treat enter command accordingly, improve comments explaining the black magic
Signed-off-by: Luca Di Maio <[email protected]>
1 parent 4c38d6b commit c05b6a4

File tree

1 file changed

+51
-8
lines changed

1 file changed

+51
-8
lines changed

distrobox-enter

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ fi
8787

8888
# Defaults
8989
# by default we use getent to get the login shell of the user and use that
90+
container_custom_command=0
9091
container_command_user="$(echo "${USER}" | sed 's|\\|\\\\|g')"
9192
container_image_default="registry.fedoraproject.org/fedora-toolbox:latest"
9293
container_manager="autodetect"
@@ -249,6 +250,7 @@ while :; do
249250
shift
250251
;;
251252
-e | --exec | --)
253+
container_custom_command=1
252254
shift
253255
# We pass the rest of arguments as $@ at the end
254256
break
@@ -367,7 +369,7 @@ fi
367369
# prints the podman, docker or lilipod command to enter the distrobox container
368370
generate_enter_command()
369371
{
370-
result_command="${container_manager} exec"
372+
result_command="exec"
371373
result_command="${result_command}
372374
--interactive"
373375
result_command="${result_command}
@@ -381,7 +383,7 @@ generate_enter_command()
381383
--user=root"
382384
else
383385
result_command="${result_command}
384-
--user=${USER}"
386+
--user ${USER}"
385387
fi
386388

387389
# For some usage, like use in service, or launched by non-terminal
@@ -412,8 +414,9 @@ generate_enter_command()
412414
# Skipping workdir we just enter $HOME of the container.
413415
workdir="${container_home}"
414416
fi
417+
415418
result_command="${result_command}
416-
--workdir=${workdir}"
419+
--workdir ${workdir}"
417420
result_command="${result_command}
418421
--env CONTAINER_ID=${container_name}"
419422
result_command="${result_command}
@@ -525,7 +528,9 @@ generate_enter_command()
525528
${container_name}"
526529

527530
# Return generated command.
528-
printf "%s" "${result_command}"
531+
# here we remove tabs as an artifact of using indentation in code to improve
532+
# readability
533+
printf "%s\n" "${result_command}" | tr -d '\t'
529534
}
530535

531536
container_home="${HOME}"
@@ -658,12 +663,30 @@ if [ "${container_status}" != "running" ]; then
658663
printf >&2 "\nContainer Setup Complete!\n"
659664
fi
660665

666+
################################################################################
667+
# Execution section, in this section we will manipulate the positional parameters
668+
# in order to generate our long docker/podman/lilipod command to execute.
669+
#
670+
# We use positional parameters in order to have the shell manage escaping and spaces
671+
# so we remove the problem of we having to handle them.
672+
#
673+
# 1 - handle absence of custom command, we will need to add a getent command to
674+
# execute the right container's user's shell
675+
# 2 - in case of unshared groups (or initful) we need to trigger a proper login
676+
# using `su`, so we will need to manipulate these arguments accorodingly
677+
# 3 - prepend our generated command
678+
# to do this, we use `tac` so we reverse loop it and prepend each argument.
679+
# 4 - now that we're done, we can prepend our container_command
680+
# we will need to use `rev` to reverse it as we reverse loop and prepend each
681+
# argument
682+
################################################################################
683+
#
661684
# Setup default commands if none are specified
662685
# execute a getent command using the /bin/sh shell
663686
# to find out the default shell of the user, and
664687
# do a login shell with it (eg: /bin/bash -l)
665-
if [ "$#" -eq 0 ]; then
666-
set "$@" "/bin/sh" "-c" "\$(getent passwd '${container_command_user}' | cut -f 7 -d :) -l"
688+
if [ "${container_custom_command}" -eq 0 ]; then
689+
set - "$@" "/bin/sh" "-c" "\$(getent passwd '${container_command_user}' | cut -f 7 -d :) -l"
667690
fi
668691

669692
# If we have a command and we're unsharing groups, we need to execute those
@@ -681,5 +704,25 @@ if [ "${unshare_groups:-0}" -eq 1 ]; then
681704
fi
682705

683706
# Generate the exec command and run it
684-
cmd="$(generate_enter_command)"
685-
${cmd} "$@"
707+
cmd="$(generate_enter_command | tac)"
708+
# Reverse it with tac so we can reverse loop and prepend the command's arguments
709+
# to our positional parameters
710+
IFS='
711+
'
712+
for arg in ${cmd}; do
713+
if echo "${arg}" | grep -q " "; then
714+
set - "$(echo "${arg}" | cut -d' ' -f1)" "$(echo "${arg}" | cut -d' ' -f2-)" "$@"
715+
else
716+
set - "${arg}" "$@"
717+
fi
718+
done
719+
720+
# Prepend the container manager command
721+
# reverse it first, so we can loop backward as we're prepending not appending
722+
IFS=' '
723+
for arg in $(echo "${container_manager}" | rev); do
724+
arg="$(echo "${arg}" | rev)"
725+
set - "${arg}" "$@"
726+
done
727+
728+
exec "$@"

0 commit comments

Comments
 (0)