1
0
Fork 0
env/.local/bin/toolbox

2164 lines
66 KiB
Plaintext
Raw Normal View History

2019-11-03 15:43:22 +08:00
#!/usr/bin/sh
#
# Copyright © 2018 2019 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
exec 3>/dev/null
arguments=""
assume_yes=false
base_toolbox_command=$(basename "$0" 2>&3)
base_toolbox_image=""
# Based on the nameRegex value in:
# https://github.com/containers/libpod/blob/master/libpod/options.go
container_name_regexp="[a-zA-Z0-9][a-zA-Z0-9_.-]*"
environment=$(set)
environment_variables="COLORTERM \
COLUMNS \
DBUS_SESSION_BUS_ADDRESS \
DBUS_SYSTEM_BUS_ADDRESS \
DESKTOP_SESSION \
DISPLAY \
LANG \
LINES \
SHELL \
SSH_AUTH_SOCK \
TERM \
TOOLBOX_PATH \
VTE_VERSION \
WAYLAND_DISPLAY \
XDG_CURRENT_DESKTOP \
XDG_DATA_DIRS \
XDG_MENU_PREFIX \
XDG_RUNTIME_DIR \
XDG_SEAT \
XDG_SESSION_DESKTOP \
XDG_SESSION_ID \
XDG_SESSION_TYPE \
XDG_VTNR"
fgc=""
prefix_sudo=""
registry="registry.fedoraproject.org"
registry_candidate="candidate-registry.fedoraproject.org"
release=""
release_default=""
spinner_animation="[>----] [=>---] [==>--] [===>-] [====>] [----<] [---<=] [--<==] [-<===] [<====]"
spinner_template="toolbox-spinner-XXXXXXXXXX"
tab="$(printf '\t')"
toolbox_command_path=""
toolbox_container=""
toolbox_container_default=""
toolbox_container_old_v1=""
toolbox_container_old_v2=""
toolbox_container_prefix_default=""
toolbox_image=""
toolbox_runtime_directory="$XDG_RUNTIME_DIR"/toolbox
user_id_real=$(id -ru 2>&3)
verbose=false
LGC='\033[1;32m' # Light Green Color
LBC='\033[1;34m' # Light Blue Color
NC='\033[0m' # No Color
has_prefix()
(
str="$1"
prefix="$2"
ret_val=1
case "$str" in
"$prefix"* )
ret_val=0
;;
* )
ret_val=1
;;
esac
return $ret_val
)
has_substring()
(
haystack="$1"
needle="$2"
ret_val=1
case "$haystack" in
*"$needle"* )
ret_val=0
;;
* )
ret_val=1
;;
esac
return $ret_val
)
is_integer()
{
[ "$1" != "" ] && [ "$1" -eq "$1" ] 2>&3
return $?
}
save_positional_parameters()
{
for i; do
printf "%s\\n" "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" 2>&3
done
echo " "
}
spinner_start()
(
directory="$1"
message="$2"
if $verbose; then
rm --force --recursive "$directory" 2>&3
return 0
fi
if ! touch "$directory/spinner-start" 2>&3; then
echo "$base_toolbox_command: unable to start spinner: spinner start file couldn't be created" >&2
return 1
fi
printf "%s" "$message"
tput civis 2>&3
exec 4>"$directory/spinner-start"
if ! flock 4 2>&3; then
echo "$base_toolbox_command: unable to start spinner: spinner lock couldn't be acquired" >&2
return 1
fi
(
while [ -f "$directory/spinner-start" ]; do
echo "$spinner_animation" | sed "s/ /\n/g" 2>&3 | while read -r frame; do
if ! [ -f "$directory/spinner-start" ] 2>&3; then
break
fi
printf "%s" "$frame"
frame_len=${#frame}
i=0
while [ "$i" -lt "$frame_len" ]; do
printf "\b"
i=$((i + 1))
done
sleep 1
done
done
printf "\033[2K" # delete entire line regardless of cursor position
printf "\r"
tput cnorm 2>&3
) &
return 0
)
spinner_stop()
(
$verbose && return
directory="$1"
exec 4>"$directory/spinner-start"
if ! rm "$directory/spinner-start" 2>&3; then
echo "$base_toolbox_command: unable to stop spinner: spinner start file couldn't be removed" >&2
return
fi
if ! flock 4 2>&3; then
echo "$base_toolbox_command: unable to stop spinner: spinner lock couldn't be acquired" >&2
return
fi
rm --force --recursive "$directory" 2>&3
)
ask_for_confirmation()
(
default_response="$1"
prompt="$2"
ret_val=0
while :; do
printf "%s " "$prompt"
read -r user_response
if [ "$user_response" = "" ] 2>&3; then
user_response="$default_response"
else
user_response=$(echo "$user_response" | tr "[:upper:]" "[:lower:]" 2>&3)
fi
if [ "$user_response" = "no" ] 2>&3 || [ "$user_response" = "n" ] 2>&3; then
ret_val=1
break
elif [ "$user_response" = "yes" ] 2>&3 || [ "$user_response" = "y" ] 2>&3; then
ret_val=0
break
fi
done
return "$ret_val"
)
container_name_is_valid()
(
name="$1"
echo "$name" | grep "^$container_name_regexp$" >/dev/null 2>&3
return $?
)
copy_etc_profile_d_toolbox_to_container()
(
container="$1"
profile_d_lock="$toolbox_runtime_directory"/profile.d-toolbox.lock
# shellcheck disable=SC2174
if ! mkdir --mode 700 --parents "$toolbox_runtime_directory" 2>&3; then
echo "$base_toolbox_command: unable to copy $toolbox_runtime_directory/toolbox.sh: runtime directory not created" >&2
return 1
fi
exec 5>"$profile_d_lock"
if ! flock 5 2>&3; then
echo "$base_toolbox_command: unable to copy $toolbox_runtime_directory/toolbox.sh: copy lock not acquired" >&2
return 1
fi
if ! [ -f "$toolbox_runtime_directory"/toolbox.sh ] 2>&3; then
echo "$base_toolbox_command: $toolbox_runtime_directory/toolbox.sh not found" >&2
return 0
fi
echo "$base_toolbox_command: copying $toolbox_runtime_directory/toolbox.sh to container $container" >&3
if ! $prefix_sudo podman exec \
--user root:root \
"$container" \
sh -c "cp $toolbox_runtime_directory/toolbox.sh /etc/profile.d" sh 2>&3; then
echo "$base_toolbox_command: unable to copy $toolbox_runtime_directory/toolbox.sh to container $container" >&2
return 1
fi
return 0
)
copy_etc_profile_d_toolbox_to_runtime_directory()
(
profile_d_lock="$toolbox_runtime_directory"/profile.d-toolbox.lock
if ! [ -f /etc/profile.d/toolbox.sh ] 2>&3; then
echo "$base_toolbox_command: /etc/profile.d/toolbox.sh not found" >&2
return 0
fi
# shellcheck disable=SC2174
if ! mkdir --mode 700 --parents "$toolbox_runtime_directory" 2>&3; then
echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh: runtime directory not created" >&2
return 1
fi
exec 5>"$profile_d_lock"
if ! flock 5 2>&3; then
echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh: copy lock not acquired" >&2
return 1
fi
echo "$base_toolbox_command: copying /etc/profile.d/toolbox.sh to $toolbox_runtime_directory" >&3
if ! cp /etc/profile.d/toolbox.sh "$toolbox_runtime_directory" 2>&3; then
echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh to $toolbox_runtime_directory" >&2
return 1
fi
return 0
)
create_enter_command()
(
container="$1"
if [ "$container" = "$toolbox_container_default" ] 2>&3; then
echo "$base_toolbox_command enter"
elif [ "$container" = "$toolbox_container_prefix_default-$release" ] 2>&3; then
echo "$base_toolbox_command enter --release $release"
else
echo "$base_toolbox_command enter --container $container"
fi
)
create_environment_options()
(
columns=""
lines=""
if terminal_size=$(stty size 2>&3); then
columns=$(echo "$terminal_size" | cut --delimiter " " --fields 2 2>&3)
if ! is_integer "$columns"; then
echo "$base_toolbox_command: failed to parse the number of columns from the terminal size" >&3
columns=""
fi
lines=$(echo "$terminal_size" | cut --delimiter " " --fields 1 2>&3)
if ! is_integer "$lines"; then
echo "$base_toolbox_command: failed to parse the number of lines from the terminal size" >&3
lines=""
fi
else
echo "$base_toolbox_command: failed to read terminal size" >&3
fi
echo "$environment_variables" \
| sed "s/ \+/\n/g" 2>&3 \
| {
environment_options=""
echo "$base_toolbox_command: creating list of environment variables to forward" >&3
value=""
while read -r variable; do
if echo "$environment" | grep "^$variable" >/dev/null 2>&3; then
eval value="$""$variable"
echo "$base_toolbox_command: $variable=$value" >&3
environment_options="$environment_options --env=$variable=$value"
else
echo "$base_toolbox_command: $variable is unset" >&3
fi
done
if ! (echo "$environment_options" | grep COLUMNS >/dev/null 2>&3) && [ "$columns" != "" ] 2>&3; then
environment_options="$environment_options --env=COLUMNS=$columns"
fi
if ! (echo "$environment_options" | grep LINES >/dev/null 2>&3) && [ "$lines" != "" ] 2>&3; then
environment_options="$environment_options --env=LINES=$lines"
fi
environment_options=${environment_options#" "}
echo "$base_toolbox_command: created options for environment variables to forward" >&3
echo "$environment_options" >&3
echo "$environment_options"
}
)
create_toolbox_container_name()
(
image="$1"
basename=$(image_reference_get_basename "$image")
if [ "$basename" = "" ] 2>&3; then
return 100
fi
tag=$(image_reference_get_tag "$image")
if [ "$tag" = "" ] 2>&3; then
return 101
fi
echo "$basename-$tag"
return 0
)
create_toolbox_image_name()
(
# Based on the ResolveName function implemented in:
# https://github.com/containers/buildah/blob/master/util/util.go
if image_reference_can_be_id "$base_toolbox_image"; then
if base_toolbox_image_id=$($prefix_sudo podman inspect \
--format "{{.Id}}" \
--type image \
"$base_toolbox_image" 2>&3); then
if has_prefix "$base_toolbox_image_id" "$base_toolbox_image"; then
echo "$base_toolbox_image-$USER:latest"
return 0
fi
fi
fi
basename=$(image_reference_get_basename "$base_toolbox_image")
if [ "$basename" = "" ] 2>&3; then
return 100
fi
tag=$(image_reference_get_tag "$base_toolbox_image")
if [ "$tag" = "" ] 2>&3; then
echo "$basename-$USER:latest"
else
echo "$basename-$USER:$tag"
fi
return 0
)
enter_print_container_not_found()
(
container="$1"
echo "$base_toolbox_command: container $container not found" >&2
echo "Use the 'create' command to create a toolbox." >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
)
get_group_for_sudo()
(
group=""
if getent group sudo >/dev/null 2>&3; then
group="sudo"
elif getent group wheel >/dev/null 2>&3; then
group="wheel"
else
return 1
fi
echo "$group"
return 0
)
get_host_id()
(
# shellcheck disable=SC1091
. /usr/lib/os-release
echo "$ID"
)
get_host_variant_id()
(
# shellcheck disable=SC1091
. /usr/lib/os-release
echo "$VARIANT_ID"
)
get_host_version_id()
(
# shellcheck disable=SC1091
. /usr/lib/os-release
echo "$VERSION_ID"
)
image_reference_can_be_id()
(
image="$1"
echo "$image" | grep "^[a-f0-9]\{6,64\}$" >/dev/null 2>&3
return $?
)
image_reference_get_basename()
(
image="$1"
domain=$(image_reference_get_domain "$image")
remainder=${image#$domain}
path=${remainder%:*}
basename=${path##*/}
echo "$basename"
)
image_reference_get_domain()
(
image="$1"
image_reference_has_domain "$image" && domain=${image%%/*}
echo "$domain"
)
image_reference_get_tag()
(
image="$1"
domain=$(image_reference_get_domain "$image")
remainder=${image#$domain}
tag=""
if (echo "$remainder" | grep ":" >/dev/null 2>&3); then
tag=${remainder#*:}
fi
echo "$tag"
)
image_reference_has_domain()
(
# Based on the splitDockerDomain function implemented in:
# https://github.com/docker/distribution/blob/master/reference/normalize.go
image="$1"
if ! (echo "$image" | grep "/" >/dev/null 2>&3); then
return 1
fi
prefix=${image%%/*}
if ! (echo "$prefix" | grep "[.:]" >/dev/null 2>&3) && [ "$prefix" != "localhost" ] 2>&3; then
return 1
fi
return 0
)
images_get_details()
(
images="$1"
if ! echo "$images" | while read -r image; do
[ "$image" = "" ] 2>&3 && continue
if ! $prefix_sudo podman images \
--format "{{.ID}} {{.Repository}}:{{.Tag}} {{.Created}}" \
--noheading \
"$image" 2>&3; then
echo "$base_toolbox_command: failed to get details for image $image" >&2
return 1
fi
echo
done; then
return 1
fi
return 0
)
is_etc_profile_d_toolbox_a_bind_mount()
{
container="$1"
$prefix_sudo podman inspect --format "[{{range .Mounts}}{{.Dst}} {{end}}]" --type container "$container" 2>&3 \
| grep /etc/profile.d/toolbox.sh >/dev/null 2>/dev/null 2>&3
return "$?"
}
list_container_names()
(
if ! containers_old=$($prefix_sudo podman ps \
--all \
--filter "label=com.redhat.component=fedora-toolbox" \
--format "{{.Names}}" 2>&3); then
echo "$base_toolbox_command: failed to list containers with com.redhat.component=fedora-toolbox" >&2
return 1
fi
if ! containers=$($prefix_sudo podman ps \
--all \
--filter "label=com.github.debarshiray.toolbox=true" \
--format "{{.Names}}" 2>&3); then
echo "$base_toolbox_command: failed to list containers with com.github.debarshiray.toolbox=true" >&2
return 1
fi
printf "%s\n%s\n" "$containers_old" "$containers" | sort 2>&3 | uniq 2>&3
return 0
)
pull_base_toolbox_image()
(
domain=""
has_domain=false
prompt_for_download=true
pull_image=false
if image_reference_can_be_id "$base_toolbox_image"; then
echo "$base_toolbox_command: looking for image $base_toolbox_image" >&3
if $prefix_sudo podman image exists "$base_toolbox_image" >/dev/null 2>&3; then
return 0
fi
fi
image_reference_has_domain "$base_toolbox_image" && has_domain=true
if ! $has_domain; then
echo "$base_toolbox_command: looking for image localhost/$base_toolbox_image" >&3
if $prefix_sudo podman image exists localhost/$base_toolbox_image >/dev/null 2>&3; then
return 0
fi
fi
if $has_domain; then
base_toolbox_image_full="$base_toolbox_image"
else
base_toolbox_image_full="$registry/$fgc/$base_toolbox_image"
fi
echo "$base_toolbox_command: looking for image $base_toolbox_image_full" >&3
if $prefix_sudo podman image exists "$base_toolbox_image_full" >/dev/null 2>&3; then
return 0
fi
domain=$(image_reference_get_domain "$base_toolbox_image_full")
if $assume_yes || [ "$domain" = "localhost" ] 2>&3; then
prompt_for_download=false
pull_image=true
fi
if $prompt_for_download; then
echo "Image required to create toolbox container."
prompt=$(printf "Download %s (500MB)? [y/N]:" "$base_toolbox_image_full")
if ask_for_confirmation "n" "$prompt"; then
pull_image=true
else
pull_image=false
fi
fi
if ! $pull_image; then
return 1
fi
echo "$base_toolbox_command: pulling image $base_toolbox_image_full" >&3
if spinner_directory=$(mktemp --directory --tmpdir $spinner_template 2>&3); then
spinner_message="Pulling $base_toolbox_image_full: "
if ! spinner_start "$spinner_directory" "$spinner_message"; then
spinner_directory=""
fi
else
echo "$base_toolbox_command: unable to start spinner: spinner directory not created" >&2
spinner_directory=""
fi
$prefix_sudo podman pull $base_toolbox_image_full >/dev/null 2>&3
ret_val=$?
if [ "$spinner_directory" != "" ]; then
spinner_stop "$spinner_directory"
fi
if [ "$ret_val" -ne 0 ] 2>&3; then
echo "$base_toolbox_command: failed to pull base image $base_toolbox_image" >&2
fi
return $ret_val
)
create()
(
enter_command_skip="$1"
dbus_system_bus_address="unix:path=/var/run/dbus/system_bus_socket"
home_link=""
flatpak_system_directory_bind=""
kcm_socket=""
kcm_socket_bind=""
libvirt_system_directory_bind=""
run_media_path_bind=""
toolbox_profile_bind=""
ulimit_host=""
usr_mount_destination_flags="ro"
# shellcheck disable=SC2153
if [ "$DBUS_SYSTEM_BUS_ADDRESS" != "" ]; then
dbus_system_bus_address=$DBUS_SYSTEM_BUS_ADDRESS
fi
dbus_system_bus_path=$(echo "$dbus_system_bus_address" | cut --delimiter = --fields 2 2>&3)
dbus_system_bus_path=$(readlink --canonicalize "$dbus_system_bus_path" 2>&3)
if [ -d /var/lib/flatpak ] 2>&3; then
flatpak_system_directory_bind="--volume /var/lib/flatpak:/var/lib/flatpak:ro"
fi
# Note that 'systemctl show ...' doesn't terminate with a non-zero exit
# code when used with an unknown unit. eg.:
# $ systemctl show --value --property Listen foo
# $ echo $?
# 0
if ! kcm_socket_listen=$(systemctl show --value --property Listen sssd-kcm.socket 2>&3); then
echo "$base_toolbox_command: failed to use 'systemctl show'" >&3
kcm_socket_listen=""
elif [ "$kcm_socket_listen" = "" ] 2>&3; then
echo "$base_toolbox_command: failed to read property Listen from sssd-kcm.socket" >&3
else
echo "$base_toolbox_command: checking value $kcm_socket_listen of property Listen in sssd-kcm.socket" >&3
if ! (echo "$kcm_socket_listen" | grep " (Stream)$" >/dev/null 2>&3); then
echo "$base_toolbox_command: unknown socket in sssd-kcm.socket" >&2
echo "$base_toolbox_command: expected SOCK_STREAM" >&2
kcm_socket_listen=""
elif ! (echo "$kcm_socket_listen" | grep "^/" >/dev/null 2>&3); then
echo "$base_toolbox_command: unknown socket in sssd-kcm.socket" >&2
echo "$base_toolbox_command: expected file system socket in the AF_UNIX family" >&2
kcm_socket_listen=""
fi
fi
echo "$base_toolbox_command: parsing value $kcm_socket_listen of property Listen in sssd-kcm.socket" >&3
if [ "$kcm_socket_listen" != "" ] 2>&3; then
kcm_socket=${kcm_socket_listen%" (Stream)"}
kcm_socket_bind="--volume $kcm_socket:$kcm_socket"
fi
if [ -d /run/libvirt ] 2>&3; then
libvirt_system_directory_bind="--volume /run/libvirt:/run/libvirt"
fi
echo "$base_toolbox_command: checking if 'podman create' supports --ulimit host" >&3
if man podman-create 2>&3 | grep "You can pass host" >/dev/null 2>&3; then
echo "$base_toolbox_command: 'podman create' supports --ulimit host" >&3
ulimit_host="--ulimit host"
fi
if ! pull_base_toolbox_image; then
return 1
fi
if image_reference_has_domain "$base_toolbox_image"; then
base_toolbox_image_full="$base_toolbox_image"
else
if ! base_toolbox_image_full=$($prefix_sudo podman inspect \
--format "{{index .RepoTags 0}}" \
--type image \
"$base_toolbox_image" 2>&3); then
echo "$base_toolbox_command: failed to get RepoTag for base image $base_toolbox_image" >&2
return 1
fi
echo "$base_toolbox_command: base image $base_toolbox_image resolved to $base_toolbox_image_full" >&3
fi
echo "$base_toolbox_command: checking if container $toolbox_container already exists" >&3
enter_command=$(create_enter_command "$toolbox_container")
if $prefix_sudo podman container exists $toolbox_container >/dev/null 2>&3; then
echo "$base_toolbox_command: container $toolbox_container already exists" >&2
echo "Enter with: $enter_command" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
return 1
fi
if ! group_for_sudo=$(get_group_for_sudo); then
echo "$base_toolbox_command: failed to create container $toolbox_container: group for sudo not found" >&2
return 1
fi
if [ -f /etc/profile.d/toolbox.sh ] 2>&3; then
toolbox_profile_bind="--volume /etc/profile.d/toolbox.sh:/etc/profile.d/toolbox.sh:ro"
fi
if [ -d /run/media ] 2>&3; then
run_media_path_bind="--volume /run/media:/run/media:rslave"
fi
echo "$base_toolbox_command: checking if /usr is mounted read-only or read-write" >&3
if ! usr_mount_point=$(df --output=target /usr | tail --lines 1 2>&3); then
echo "$base_toolbox_command: failed to get the mount-point of /usr" >&2
else
echo "$base_toolbox_command: mount-point of /usr is $usr_mount_point" >&3
if ! usr_mount_source_flags=$(findmnt --noheadings --output OPTIONS "$usr_mount_point" 2>&3); then
echo "$base_toolbox_command: failed to get the mount options of $usr_mount_point" >&2
else
echo "$base_toolbox_command: mount flags of /usr on the host are $usr_mount_source_flags" >&3
if echo "$usr_mount_source_flags" | grep --invert-match "ro" >/dev/null 2>&3; then
usr_mount_destination_flags="rw"
fi
fi
fi
if ! home_canonical=$(readlink --canonicalize "$HOME" 2>&3); then
echo "$base_toolbox_command: failed to canonicalize $HOME" >&2
return 1
fi
echo "$base_toolbox_command: $HOME canonicalized to $home_canonical" >&3
echo "$base_toolbox_command: checking if /home is a symbolic link to /var/home" >&3
if [ "$(readlink /home)" = var/home ] 2>&3; then
echo "$base_toolbox_command: /home is a symbolic link to /var/home" >&3
home_link="--home-link"
fi
echo "$base_toolbox_command: calling org.freedesktop.Flatpak.SessionHelper.RequestSession" >&3
if ! gdbus call \
--session \
--dest org.freedesktop.Flatpak \
--object-path /org/freedesktop/Flatpak/SessionHelper \
--method org.freedesktop.Flatpak.SessionHelper.RequestSession >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to call org.freedesktop.Flatpak.SessionHelper.RequestSession" >&2
exit 1
fi
echo "$base_toolbox_command: creating container $toolbox_container" >&3
if spinner_directory=$(mktemp --directory --tmpdir $spinner_template 2>&3); then
spinner_message="Creating container $toolbox_container: "
if ! spinner_start "$spinner_directory" "$spinner_message"; then
spinner_directory=""
fi
else
echo "$base_toolbox_command: unable to start spinner: spinner directory not created" >&2
spinner_directory=""
fi
# shellcheck disable=SC2086
$prefix_sudo podman create \
--dns none \
--env TOOLBOX_PATH="$TOOLBOX_PATH" \
--group-add "$group_for_sudo" \
--hostname toolbox \
--ipc host \
--label "com.github.debarshiray.toolbox=true" \
--name $toolbox_container \
--network host \
--no-hosts \
--pid host \
--privileged \
--security-opt label=disable \
$ulimit_host \
--userns=keep-id \
--user root:root \
$flatpak_system_directory_bind \
$kcm_socket_bind \
$libvirt_system_directory_bind \
$run_media_path_bind \
$toolbox_profile_bind \
--volume "$TOOLBOX_PATH":/usr/bin/toolbox:ro \
--volume "$XDG_RUNTIME_DIR":"$XDG_RUNTIME_DIR" \
--volume "$XDG_RUNTIME_DIR"/.flatpak-helper/monitor:/run/host/monitor \
--volume "$dbus_system_bus_path":"$dbus_system_bus_path" \
--volume "$HOME":"$HOME":rslave \
--volume /etc:/run/host/etc \
--volume /dev:/dev:rslave \
--volume /media:/media:rslave \
--volume /mnt:/mnt:rslave \
--volume /run:/run/host/run:rslave \
--volume /tmp:/run/host/tmp:rslave \
--volume /usr:/run/host/usr:"$usr_mount_destination_flags",rslave \
--volume /var:/run/host/var:rslave \
"$base_toolbox_image_full" \
toolbox --verbose init-container \
--home "$HOME" \
$home_link \
--monitor-host \
--shell "$SHELL" \
--uid "$user_id_real" \
--user "$USER" >/dev/null 2>&3
ret_val=$?
if [ "$spinner_directory" != "" ]; then
spinner_stop "$spinner_directory"
fi
if [ $ret_val -ne 0 ]; then
echo "$base_toolbox_command: failed to create container $toolbox_container" >&2
return 1
fi
if ! $enter_command_skip; then
echo "Created container: $toolbox_container"
echo "Enter with: $enter_command"
fi
return 0
)
enter()
(
emit_escape_sequence=false
host_id=$(get_host_id)
host_variant_id=$(get_host_variant_id)
if [ "$host_id" = "fedora" ] 2>&3 \
&& { [ "$host_variant_id" = "silverblue" ] 2>&3 || [ "$host_variant_id" = "workstation" ] 2>&3; }; then
emit_escape_sequence=true
fi
run "$emit_escape_sequence" true false "$SHELL" -l
)
init_container()
{
init_container_home="$1"
init_container_home_link="$2"
init_container_monitor_host="$3"
init_container_shell="$4"
init_container_uid="$5"
init_container_user="$6"
echo "$base_toolbox_command: creating /run/.toolboxenv" >&3
if ! touch /run/.toolboxenv 2>&3; then
echo "$base_toolbox_command: failed to create /run/.toolboxenv" >&2
return 1
fi
if $init_container_monitor_host; then
working_directory="$PWD"
if [ -d /run/host/etc ] 2>&3; then
if ! readlink /etc/host.conf >/dev/null 2>&3; then
echo "$base_toolbox_command: redirecting /etc/host.conf to /run/host/etc/host.conf" >&3
if ! (cd /etc 2>&3 \
&& unlink host.conf 2>&3 \
&& ln --symbolic /run/host/etc/host.conf host.conf 2>&3); then
echo "$base_toolbox_command: failed to redirect /etc/host.conf to /run/host/etc/host.conf" >&2
return 1
fi
fi
if ! readlink /etc/hosts >/dev/null 2>&3; then
echo "$base_toolbox_command: redirecting /etc/hosts to /run/host/etc/hosts" >&3
if ! (cd /etc 2>&3 && unlink hosts 2>&3 && ln --symbolic /run/host/etc/hosts hosts 2>&3); then
echo "$base_toolbox_command: failed to redirect /etc/hosts to /run/host/etc/hosts" >&2
return 1
fi
fi
if ! readlink /etc/resolv.conf >/dev/null 2>&3; then
echo "$base_toolbox_command: redirecting /etc/resolv.conf to /run/host/etc/resolv.conf" >&3
if ! (cd /etc 2>&3 \
&& unlink resolv.conf 2>&3 \
&& ln --symbolic /run/host/etc/resolv.conf resolv.conf 2>&3); then
echo "$base_toolbox_command: failed to redirect /etc/resolv.conf to /run/host/etc/resolv.conf" \
>&2
return 1
fi
fi
fi
if [ -d /run/host/monitor ] 2>&3; then
if ! localtime_target=$(readlink /etc/localtime >/dev/null 2>&3) \
|| [ "$localtime_target" != "/run/host/monitor/localtime" ] 2>&3; then
echo "$base_toolbox_command: redirecting /etc/localtime to /run/host/monitor/localtime" >&3
if ! (cd /etc 2>&3 \
&& unlink localtime 2>&3 \
&& ln --symbolic /run/host/monitor/localtime localtime 2>&3); then
echo "$base_toolbox_command: failed to redirect /etc/localtime to /run/host/monitor/localtime" \
>&2
return 1
fi
fi
if ! readlink /etc/timezone >/dev/null 2>&3; then
echo "$base_toolbox_command: redirecting /etc/timezone to /run/host/monitor/timezone" >&3
if ! (cd /etc 2>&3 \
&& rm --force timezone 2>&3 \
&& ln --symbolic /run/host/monitor/timezone timezone 2>&3); then
echo "$base_toolbox_command: failed to redirect /etc/timezone to /run/host/monitor/timezone" >&2
return 1
fi
fi
fi
if ! cd "$working_directory" 2>&3; then
echo "$base_toolbox_command: failed to restore working directory" >&2
fi
fi
if ! id -u "$init_container_user" >/dev/null 2>&3; then
if $init_container_home_link ; then
echo "$base_toolbox_command: making /home a symlink" >&3
# shellcheck disable=SC2174
if ! (rmdir /home 2>&3 \
&& mkdir --mode 0755 --parents /var/home 2>&3 \
&& ln --symbolic var/home /home 2>&3); then
echo "$base_toolbox_command: failed to make /home a symlink" >&2
return 1
fi
fi
if ! groups=$(get_group_for_sudo); then
echo "$base_toolbox_command: failed to add user $init_container_user: group for sudo not found" >&2
return 1
fi
echo "$base_toolbox_command: adding user $init_container_user with UID $init_container_uid" >&3
if ! useradd \
--home-dir "$init_container_home" \
--no-create-home \
--shell "$init_container_shell" \
--uid "$init_container_uid" \
--groups "$groups" \
"$init_container_user" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to add user $init_container_user with UID $init_container_uid" >&2
return 1
fi
echo "$base_toolbox_command: removing password for user $init_container_user" >&3
if ! passwd --delete "$init_container_user" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to remove password for user $init_container_user" >&2
return 1
fi
echo "$base_toolbox_command: removing password for user root" >&3
if ! passwd --delete root >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to remove password for user root" >&2
return 1
fi
fi
if [ -d /etc/krb5.conf.d ] 2>&3 && ! [ -f /etc/krb5.conf.d/kcm_default_ccache ] 2>&3; then
echo "$base_toolbox_command: setting KCM as the default Kerberos credential cache" >&3
cat <<EOF >/etc/krb5.conf.d/kcm_default_ccache 2>&3
# Written by Toolbox
# https://github.com/debarshiray/toolbox
#
# # To disable the KCM credential cache, comment out the following lines.
[libdefaults]
default_ccache_name = KCM:
EOF
ret_val=$?
if [ "$ret_val" -ne 0 ] 2>&3; then
echo "$base_toolbox_command: failed to set KCM as the default Kerberos credential cache" >&2
return 1
fi
fi
echo "$base_toolbox_command: going to sleep" >&3
exec sleep +Inf
}
run()
(
emit_escape_sequence="$1"
fallback_to_bash="$2"
pedantic="$3"
program="$4"
shift 4
create_toolbox_container=false
prompt_for_create=true
echo "$base_toolbox_command: checking if container $toolbox_container exists" >&3
if ! $prefix_sudo podman container exists "$toolbox_container" 2>&3; then
echo "$base_toolbox_command: container $toolbox_container not found" >&3
if $prefix_sudo podman container exists "$toolbox_container_old_v1" 2>&3; then
echo "$base_toolbox_command: container $toolbox_container_old_v1 found" >&3
# shellcheck disable=SC2030
toolbox_container="$toolbox_container_old_v1"
elif $prefix_sudo podman container exists "$toolbox_container_old_v2" 2>&3; then
echo "$base_toolbox_command: container $toolbox_container_old_v2 found" >&3
# shellcheck disable=SC2030
toolbox_container="$toolbox_container_old_v2"
else
if $pedantic; then
enter_print_container_not_found "$toolbox_container"
exit 1
fi
if ! containers=$(list_container_names); then
enter_print_container_not_found "$toolbox_container"
exit 1
fi
containers_count=$(echo "$containers" | grep --count . 2>&3)
if ! is_integer "$containers_count"; then
enter_print_container_not_found "$toolbox_container"
exit 1
fi
echo "$base_toolbox_command: found $containers_count containers" >&3
if [ "$containers_count" -eq 0 ] 2>&3; then
if $assume_yes; then
create_toolbox_container=true
prompt_for_create=false
fi
if $prompt_for_create; then
prompt="No toolbox containers found. Create now? [y/N]"
if ask_for_confirmation "n" "$prompt"; then
create_toolbox_container=true
else
create_toolbox_container=false
fi
fi
if ! $create_toolbox_container; then
echo "A container can be created later with the 'create' command." >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
if ! update_container_and_image_names; then
exit 1
fi
if ! create true; then
exit 1
fi
elif [ "$containers_count" -eq 1 ] 2>&3 \
&& [ "$toolbox_container" = "$toolbox_container_default" ] 2>&3; then
echo "$base_toolbox_command: container $toolbox_container not found" >&2
toolbox_container=$(echo "$containers" | grep . 2>&3 | head --lines 1 2>&3)
echo "Entering container $toolbox_container instead." >&2
echo "Use the 'create' command to create a different toolbox." >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
else
echo "$base_toolbox_command: container $toolbox_container not found" >&2
echo "Use the '--container' option to select a toolbox." >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
fi
fi
echo "$base_toolbox_command: calling org.freedesktop.Flatpak.SessionHelper.RequestSession" >&3
if ! gdbus call \
--session \
--dest org.freedesktop.Flatpak \
--object-path /org/freedesktop/Flatpak/SessionHelper \
--method org.freedesktop.Flatpak.SessionHelper.RequestSession >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to call org.freedesktop.Flatpak.SessionHelper.RequestSession" >&2
exit 1
fi
echo "$base_toolbox_command: starting container $toolbox_container" >&3
if is_etc_profile_d_toolbox_a_bind_mount "$toolbox_container"; then
echo "$base_toolbox_command: /etc/profile.d/toolbox.sh already mounted in container $toolbox_container" >&3
if ! $prefix_sudo podman start "$toolbox_container" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to start container $toolbox_container" >&2
exit 1
fi
else
echo "$base_toolbox_command: /etc/profile.d/toolbox.sh not mounted in container $toolbox_container" >&3
if ! copy_etc_profile_d_toolbox_to_runtime_directory; then
exit 1
fi
if ! $prefix_sudo podman start "$toolbox_container" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to start container $toolbox_container" >&2
exit 1
fi
if ! copy_etc_profile_d_toolbox_to_container "$toolbox_container"; then
exit 1
fi
fi
if ! $prefix_sudo podman exec --user root:root "$toolbox_container" touch /run/.toolboxenv 2>&3; then
echo "$base_toolbox_command: failed to create /run/.toolboxenv in container $toolbox_container" >&2
exit 1
fi
set_environment=$(create_environment_options)
echo "$base_toolbox_command: looking for $program in container $toolbox_container" >&3
# shellcheck disable=SC2016
if ! $prefix_sudo podman exec \
--user "$USER" \
"$toolbox_container" \
sh -c 'command -v "$1"' sh "$program" >/dev/null 2>&3; then
if $fallback_to_bash; then
echo "$base_toolbox_command: $program not found in $toolbox_container; using /bin/bash instead" >&3
program=/bin/bash
else
echo "$base_toolbox_command: command '$program' not found in container $toolbox_container" >&2
exit 127
fi
fi
echo "$base_toolbox_command: running in container $toolbox_container:" >&3
echo "$base_toolbox_command: $program" >&3
for i in "$@"; do
echo "$base_toolbox_command: $i" >&3
done
$emit_escape_sequence && printf "\033]777;container;push;%s;toolbox\033\\" "$toolbox_container"
# shellcheck disable=SC2016
# for the command passed to capsh
# shellcheck disable=SC2086
$prefix_sudo podman exec \
--interactive \
--tty \
--user "$USER" \
--workdir "$PWD" \
$set_environment \
"$toolbox_container" \
capsh --caps="" -- -c 'exec "$@"' /bin/sh "$program" "$@" 2>&3
ret_val="$?"
$emit_escape_sequence && printf "\033]777;container;pop;;\033\\"
exit "$ret_val"
)
help()
(
to_help_command="$1"
if [ "$to_help_command" = "" ] 2>&3 || [ "$to_help_command" = "$base_toolbox_command" ] 2>&3; then
exec man toolbox 2>&1
fi
exec man toolbox-"$to_help_command" 2>&1
)
list_images()
(
output=""
if ! images_old=$($prefix_sudo podman images \
--filter "label=com.redhat.component=fedora-toolbox" \
--format "{{.Repository}}:{{.Tag}}" 2>&3); then
echo "$base_toolbox_command: failed to list images with com.redhat.component=fedora-toolbox" >&2
return 1
fi
if ! images=$($prefix_sudo podman images \
--filter "label=com.github.debarshiray.toolbox=true" \
--format "{{.Repository}}:{{.Tag}}" 2>&3); then
echo "$base_toolbox_command: failed to list images with com.github.debarshiray.toolbox=true" >&2
return 1
fi
images=$(printf "%s\n%s\n" "$images_old" "$images" | sort 2>&3 | uniq 2>&3)
if ! details=$(images_get_details "$images"); then
return 1
fi
if [ "$details" != "" ] 2>&3; then
table_data=$(printf "%s\t%s\t%s\n" "IMAGE ID" "IMAGE NAME" "CREATED"; echo "$details")
if ! output=$(echo "$table_data" | sed "s/ \{2,\}/\t/g" 2>&3 | column -s "$tab" -t 2>&3); then
echo "$base_toolbox_command: failed to parse list of images" >&2
return 1
fi
fi
if [ "$output" != "" ]; then
# shellcheck disable=SC2059
printf "${LBC}Images created by toolbox${NC}\n"
echo "$output"
fi
return 0
)
containers_get_details()
(
containers="$1"
if ! echo "$containers" | while read -r container; do
[ "$container" = "" ] 2>&3 && continue
if ! $prefix_sudo podman ps --all \
--filter "name=$container" \
--format "{{.ID}} {{.Names}} {{.Created}} {{.Status}} {{.Image}}" 2>&3; then
echo "$base_toolbox_command: failed to get details for container $container" >&2
return 1
fi
done; then
return 1
fi
return 0
)
list_containers()
(
output=""
if ! containers=$(list_container_names); then
return 1
fi
if ! details=$(containers_get_details "$containers"); then
return 1
fi
if [ "$details" != "" ] 2>&3; then
table_data=$(printf "%s\t%s\t%s\t%s\t%s\n" "CONTAINER ID" "CONTAINER NAME" "CREATED" "STATUS" "IMAGE NAME"
echo "$details")
if ! output=$(echo "$table_data" | sed "s/ \{2,\}/\t/g" 2>&3 | column -s "$tab" -t 2>&3); then
echo "$base_toolbox_command: failed to parse list of containers" >&2
return 1
fi
fi
if [ "$output" != "" ]; then
# shellcheck disable=SC2059
printf "${LBC}Containers created by toolbox${NC}\n"
echo "$output" | head --lines 1 2>&3
echo "$output" | tail --lines +2 2>&3 \
| (
while read -r container; do
id=$(echo "$container" | cut --delimiter " " --fields 1 2>&3)
is_running=$($prefix_sudo podman inspect "$id" --format "{{.State.Running}}" 2>&3)
if $is_running; then
# shellcheck disable=SC2059
printf "${LGC}$container${NC}\n"
else
echo "$container"
fi
done
)
fi
return 0
)
migrate()
(
configuration_directory="$HOME/.config/toolbox"
migrate_stamp="$configuration_directory/podman-system-migrate"
migrate_lock="$toolbox_runtime_directory"/migrate.lock
if ! version=$($prefix_sudo podman version --format "{{.Version}}" 2>&3); then
echo "$base_toolbox_command: unable to migrate containers: Podman version couldn't be read" >&2
return 1
fi
if ! mkdir --parents "$configuration_directory" 2>&3; then
echo "$base_toolbox_command: unable to migrate containers: configuration directory not created" >&2
return 1
fi
# shellcheck disable=SC2174
if ! mkdir --mode 700 --parents "$toolbox_runtime_directory" 2>&3; then
echo "$base_toolbox_command: unable to migrate containers: runtime directory not created" >&2
return 1
fi
exec 5>"$migrate_lock"
if ! flock 5 2>&3; then
echo "$base_toolbox_command: unable to migrate containers: migration lock not acquired" >&3
return 1
fi
if [ -f "$migrate_stamp" ] 2>&3; then
if grep "$version" "$migrate_stamp" >/dev/null 2>&3; then
echo "$base_toolbox_command: migration not needed: $version is unchanged" >&3
return 0
fi
if ! version_old=$(printf "%s\n" "$version" \
| cat "$migrate_stamp" - 2>&3 \
| sort --version-sort 2>&3 \
| head --lines 1 2>&3); then
echo "$base_toolbox_command: unable to migrate containers: Podman versions couldn't be sorted" >&2
return 1
fi
if [ "$version" = "$version_old" ] 2>&3; then
echo "$base_toolbox_command: migration not needed: $version is old" >&3
return 0
fi
fi
if ! $prefix_sudo podman system migrate >/dev/null 2>&3; then
echo "$base_toolbox_command: unable to migrate containers" >&2
return 1
fi
echo "$version" >"$migrate_stamp"
return 0
)
remove_containers()
(
ids=$1
all=$2
force=$3
ret_val=0
$force && force_option="--force"
if $all; then
if ! ids_old=$($prefix_sudo podman ps \
--all \
--filter "label=com.redhat.component=fedora-toolbox" \
--format "{{.ID}}" 2>&3); then
echo "$base_toolbox_command: failed to list containers with com.redhat.component=fedora-toolbox" >&2
return 1
fi
if ! ids=$($prefix_sudo podman ps \
--all \
--filter "label=com.github.debarshiray.toolbox=true" \
--format "{{.ID}}" 2>&3); then
echo "$base_toolbox_command: failed to list containers with com.github.debarshiray.toolbox=true" >&2
return 1
fi
ids=$(printf "%s\n%s\n" "$ids_old" "$ids" | sort 2>&3 | uniq 2>&3)
if [ "$ids" != "" ]; then
ret_val=$(echo "$ids" \
| (
while read -r id; do
if ! $prefix_sudo podman rm $force_option "$id" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to remove container $id" >&2
ret_val=1
fi
done
echo "$ret_val"
)
)
fi
else
ret_val=$(echo "$ids" \
| sed "s/ \+/\n/g" 2>&3 \
| (
while read -r id; do
if ! labels=$($prefix_sudo podman inspect \
--format "{{.Config.Labels}}" \
--type container \
"$id" 2>&3); then
echo "$base_toolbox_command: failed to inspect $id" >&2
ret_val=1
continue
fi
if ! has_substring "$labels" "com.github.debarshiray.toolbox" \
&& ! has_substring "$labels" "com.redhat.component:fedora-toolbox"; then
echo "$base_toolbox_command: $id is not a toolbox container" >&2
ret_val=1
continue
fi
if ! $prefix_sudo podman rm $force_option "$id" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to remove container $id" >&2
ret_val=1
fi
done
echo "$ret_val"
)
)
fi
return "$ret_val"
)
remove_images()
(
ids=$1
all=$2
force=$3
ret_val=0
$force && force_option="--force"
if $all; then
if ! ids_old=$($prefix_sudo podman images \
--filter "label=com.redhat.component=fedora-toolbox" \
--format "{{.ID}}" 2>&3); then
echo "$0: failed to list images with com.redhat.component=fedora-toolbox" >&2
return 1
fi
if ! ids=$($prefix_sudo podman images \
--all \
--filter "label=com.github.debarshiray.toolbox=true" \
--format "{{.ID}}" 2>&3); then
echo "$0: failed to list images with com.github.debarshiray.toolbox=true" >&2
return 1
fi
ids=$(printf "%s\n%s\n" "$ids_old" "$ids" | sort 2>&3 | uniq 2>&3)
if [ "$ids" != "" ]; then
ret_val=$(echo "$ids" \
| (
while read -r id; do
if ! $prefix_sudo podman rmi $force_option "$id" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to remove image $id" >&2
ret_val=1
fi
done
echo "$ret_val"
)
)
fi
else
ret_val=$(echo "$ids" \
| sed "s/ \+/\n/g" 2>&3 \
| (
while read -r id; do
if ! labels=$($prefix_sudo podman inspect \
--format "{{.Labels}}" \
--type image \
"$id" 2>&3); then
echo "$base_toolbox_command: failed to inspect $id" >&2
ret_val=1
continue
fi
if ! has_substring "$labels" "com.github.debarshiray.toolbox" \
&& ! has_substring "$labels" "com.redhat.component:fedora-toolbox"; then
echo "$base_toolbox_command: $id is not a toolbox image" >&2
ret_val=1
continue
fi
if ! $prefix_sudo podman rmi $force_option "$id" >/dev/null 2>&3; then
echo "$base_toolbox_command: failed to remove image $id" >&2
ret_val=1
fi
done
echo "$ret_val"
)
)
fi
return "$ret_val"
)
exit_if_extra_operand()
{
if [ "$1" != "" ]; then
echo "$base_toolbox_command: extra operand '$1'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
}
exit_if_missing_argument()
{
if [ "$2" = "" ]; then
echo "$base_toolbox_command: missing argument for '$1'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
}
exit_if_non_positive_argument()
{
if ! is_integer "$2"; then
echo "$base_toolbox_command: invalid argument for '$1'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
if [ "$2" -le 0 ] 2>&3; then
echo "$base_toolbox_command: invalid argument for '$1'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
}
exit_if_unrecognized_option()
{
echo "$base_toolbox_command: unrecognized option '$1'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
}
# shellcheck disable=SC2120
forward_to_host()
(
if ! command -v flatpak-spawn >/dev/null 2>&3; then
echo "$base_toolbox_command: flatpak-spawn not found" >&2
return 1
fi
eval "set -- $arguments"
set_environment=$(create_environment_options)
echo "$base_toolbox_command: forwarding to host:" >&3
echo "$base_toolbox_command: $TOOLBOX_PATH" >&3
for i in "$@"; do
echo "$base_toolbox_command: $i" >&3
done
# shellcheck disable=SC2086
flatpak-spawn $set_environment --host "$TOOLBOX_PATH" "$@" 2>&3
ret_val="$?"
return "$ret_val"
)
update_container_and_image_names()
{
[ "$release" = "" ] 2>&3 && release="$release_default"
if [ "$base_toolbox_image" = "" ] 2>&3; then
base_toolbox_image="fedora-toolbox:$release"
else
release=$(image_reference_get_tag "$base_toolbox_image")
[ "$release" = "" ] 2>&3 && release="$release_default"
fi
fgc="f$release"
echo "$base_toolbox_command: Fedora generational core is $fgc" >&3
echo "$base_toolbox_command: base image is $base_toolbox_image" >&3
toolbox_image=$(create_toolbox_image_name)
if ! (
ret_val=$?
if [ "$ret_val" -ne 0 ] 2>&3; then
if [ "$ret_val" -eq 100 ] 2>&3; then
echo "$base_toolbox_command: failed to get the basename of base image $base_toolbox_image" >&2
else
echo "$base_toolbox_command: failed to create an ID for the customized user-specific image" >&2
fi
exit 1
fi
exit 0
); then
return 1
fi
# shellcheck disable=SC2031
if [ "$toolbox_container" = "" ]; then
toolbox_container=$(create_toolbox_container_name "$base_toolbox_image")
if ! (
ret_val=$?
if [ "$ret_val" -ne 0 ] 2>&3; then
if [ "$ret_val" -eq 100 ] 2>&3; then
echo "$base_toolbox_command: failed to get the basename of image $base_toolbox_image" >&2
elif [ "$ret_val" -eq 101 ] 2>&3; then
echo "$base_toolbox_command: failed to get the tag of image $base_toolbox_image" >&2
else
echo "$base_toolbox_command: failed to create a name for the toolbox container" >&2
fi
exit 1
fi
exit 0
); then
return 1
fi
if ! container_name_is_valid "$toolbox_container"; then
echo "$base_toolbox_command: generated container name $toolbox_container is invalid" >&2
echo "Container names must match '$container_name_regexp'." >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
return 1
fi
toolbox_container_old_v1=$(create_toolbox_container_name "$toolbox_image")
if ! (
ret_val=$?
if [ "$ret_val" -ne 0 ] 2>&3; then
if [ "$ret_val" -eq 100 ] 2>&3; then
echo "$base_toolbox_command: failed to get the basename of image $toolbox_image" >&2
elif [ "$ret_val" -eq 101 ] 2>&3; then
echo "$base_toolbox_command: failed to get the tag of image $toolbox_image" >&2
else
echo "$base_toolbox_command: failed to create a name for the toolbox container" >&2
fi
exit 1
fi
exit 0
); then
return 1
fi
toolbox_container_old_v2="$toolbox_image"
fi
echo "$base_toolbox_command: container is $toolbox_container" >&3
return 0
}
arguments=$(save_positional_parameters "$@")
host_id=$(get_host_id)
if [ "$host_id" = "fedora" ] 2>&3; then
release_default=$(get_host_version_id)
else
release_default="30"
fi
toolbox_container_prefix_default="fedora-toolbox"
toolbox_container_default="$toolbox_container_prefix_default-$release_default"
while has_prefix "$1" -; do
case $1 in
--assumeyes | -y )
assume_yes=true
;;
-h | --help )
if [ -f /run/.containerenv ] 2>&3; then
if ! [ -f /run/.toolboxenv ] 2>&3; then
echo "$base_toolbox_command: this is not a toolbox container" >&2
exit 1
fi
# shellcheck disable=SC2119
forward_to_host
exit
fi
help "$2"
exit
;;
--sudo )
prefix_sudo="sudo"
;;
-v | --verbose )
exec 3>&2
verbose=true
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
echo "$base_toolbox_command: running as real user ID $user_id_real" >&3
if ! toolbox_command_path=$(realpath "$0" 2>&3); then
echo "$base_toolbox_command: failed to resolve absolute path to $0" >&2
exit 1
fi
echo "$base_toolbox_command: resolved absolute path for $0 to $toolbox_command_path" >&3
if [ -f /run/.containerenv ] 2>&3; then
if [ "$TOOLBOX_PATH" = "" ] 2>&3; then
echo "$base_toolbox_command: TOOLBOX_PATH not set" >&2
exit 1
fi
else
if [ "$user_id_real" -ne 0 ] 2>&3; then
echo "$base_toolbox_command: checking if /etc/subgid and /etc/subuid have entries for user $USER" >&3
if ! grep "^$USER:" /etc/subgid >/dev/null 2>&3 || ! grep "^$USER:" /etc/subuid >/dev/null 2>&3; then
echo "$base_toolbox_command: /etc/subgid and /etc/subuid don't have entries for user $USER" >&2
echo "See the podman(1), subgid(5), subuid(5) and usermod(8) manuals for more" >&2
echo "information." >&2
exit 1
fi
fi
if [ "$TOOLBOX_PATH" = "" ] 2>&3; then
TOOLBOX_PATH="$toolbox_command_path"
fi
fi
echo "$base_toolbox_command: TOOLBOX_PATH is $TOOLBOX_PATH" >&3
if [ "$1" = "" ]; then
echo "$base_toolbox_command: missing command" >&2
echo >&2
echo "These are some common commands:" >&2
echo "create Create a new toolbox container" >&2
echo "enter Enter an existing toolbox container" >&2
echo "list List all existing toolbox containers and images" >&2
echo >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
op=$1
shift
if [ -f /run/.containerenv ] 2>&3; then
case $op in
create | enter | list | rm | rmi | run | help )
if ! [ -f /run/.toolboxenv ] 2>&3; then
echo "$base_toolbox_command: this is not a toolbox container" >&2
exit 1
fi
# shellcheck disable=SC2119
forward_to_host
exit "$?"
;;
init-container )
init_container_home_link=false
init_container_monitor_host=false
while has_prefix "$1" -; do
case $1 in
-h | --help )
# shellcheck disable=SC2119
forward_to_host
exit
;;
--home )
shift
exit_if_missing_argument --home "$1"
init_container_home="$1"
;;
--home-link )
init_container_home_link=true
;;
--monitor-host )
init_container_monitor_host=true
;;
--shell )
shift
exit_if_missing_argument --shell "$1"
init_container_shell="$1"
;;
--uid )
shift
exit_if_missing_argument --uid "$1"
init_container_uid="$1"
;;
--user )
shift
exit_if_missing_argument --user "$1"
init_container_user="$1"
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
init_container \
"$init_container_home" \
"$init_container_home_link" \
"$init_container_monitor_host" \
"$init_container_shell" \
"$init_container_uid" \
"$init_container_user"
exit "$?"
;;
* )
echo "$base_toolbox_command: unrecognized command '$op'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
;;
esac
fi
if ! migrate; then
exit 1
fi
case $op in
create )
while has_prefix "$1" -; do
case $1 in
--candidate-registry )
registry=$registry_candidate
;;
-c | --container )
shift
exit_if_missing_argument --container "$1"
arg=$1
if ! container_name_is_valid "$arg"; then
echo "$base_toolbox_command: invalid argument for '--container'" >&2
echo "Container names must match '$container_name_regexp'." >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
fi
toolbox_container="$arg"
;;
-h | --help )
help "$op"
exit
;;
-i | --image )
shift
exit_if_missing_argument --image "$1"
base_toolbox_image=$1
;;
-r | --release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
exit_if_extra_operand "$1"
if ! update_container_and_image_names; then
exit 1
fi
if ! create false; then
exit 1
fi
exit
;;
enter )
while has_prefix "$1" -; do
case $1 in
-c | --container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
-h | --help )
help "$op"
exit
;;
-r | --release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
exit_if_extra_operand "$1"
if ! update_container_and_image_names; then
exit 1
fi
enter
exit
;;
help )
while has_prefix "$1" -; do
case $1 in
-h | --help )
help "$op"
exit
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
help "$1"
exit
;;
init-container )
while has_prefix "$1" -; do
case $1 in
-h | --help )
help "$op"
exit
esac
shift
done
echo "$base_toolbox_command: The 'init-container' command can only be used inside containers" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
;;
list )
ls_images=false
ls_containers=false
while has_prefix "$1" -; do
case $1 in
-c | --containers )
ls_containers=true
;;
-h | --help )
help "$op"
exit
;;
-i | --images )
ls_images=true
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
exit_if_extra_operand "$1"
if ! $ls_containers && ! $ls_images; then
ls_containers=true
ls_images=true
fi
if $ls_images; then
if ! images=$(list_images); then
exit 1
fi
fi
if $ls_containers; then
if ! containers=$(list_containers); then
exit 1
fi
fi
if $ls_images && [ "$images" != "" ] 2>&3; then
echo "$images"
fi
if $ls_containers && [ "$containers" != "" ] 2>&3; then
echo "$containers"
fi
exit
;;
rm | rmi )
rm_all=false
rm_force=false
while has_prefix "$1" -; do
case $1 in
-a | --all )
rm_all=true
;;
-f | --force )
rm_force=true
;;
-h | --help )
help "$op"
exit
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
rm_ids=""
if $rm_all; then
exit_if_extra_operand "$1"
else
exit_if_missing_argument "$op" "$1"
while [ "$1" != "" ]; do
rm_ids="$rm_ids $1"
shift
done
fi
rm_ids=$(echo "$rm_ids" | sed "s/^ \+//" 2>&3)
if [ "$op" = "rm" ]; then
remove_containers "$rm_ids" "$rm_all" "$rm_force"
else
remove_images "$rm_ids" "$rm_all" "$rm_force"
fi
exit
;;
run )
while has_prefix "$1" -; do
case $1 in
-c | --container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
-h | --help )
help "$op"
exit
;;
-r | --release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
if ! update_container_and_image_names; then
exit 1
fi
run false false true "$@"
exit
;;
* )
echo "$base_toolbox_command: unrecognized command '$op'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2
exit 1
esac