#!/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. # source /etc/os-release release=$VERSION_ID prefix_sudo="" registry="registry.fedoraproject.org" registry_candidate="candidate-registry.fedoraproject.org" toolbox_prompt="🔹[\u@\h \W]\\$ " is_integer() { [ "$1" != "" ] && [ $1 -eq $1 2>&42 ] return $? } create() ( dbus_system_bus_address="unix:path=/var/run/dbus/system_bus_socket" tmpfs_size=$((64 * 1024 * 1024)) # 64 MiB working_container_name="fedora-toolbox-working-container-$(uuidgen --time)" 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>&42) dbus_system_bus_path=$(readlink --canonicalize $dbus_system_bus_path 2>&42) echo "$0: checking if image $toolbox_image already exists" >&42 if ! $prefix_sudo buildah inspect --type image $toolbox_image >/dev/null 2>&42; then echo "$0: trying to create working container $working_container_name" >&42 echo "$0: looking for image localhost/$base_toolbox_image" >&42 if ! $prefix_sudo buildah from \ --name $working_container_name \ localhost/$base_toolbox_image >/dev/null 2>&42; then echo "$0: looking for image $registry/$fgc/$base_toolbox_image" >&42 if ! $prefix_sudo buildah from \ --name $working_container_name \ $registry/$fgc/$base_toolbox_image >/dev/null 2>&42; then echo "$0: failed to create working container" exit 1 fi fi echo "$0: trying to configure working container $working_container_name" >&42 if ! $prefix_sudo buildah run $working_container_name -- useradd \ --no-create-home \ --shell $SHELL \ --uid $UID \ --groups wheel \ $USER \ >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to create user $USER with UID $UID" exit 1 fi if ! $prefix_sudo buildah run $working_container_name -- passwd -d $USER >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to remove password for user $USER" exit 1 fi if ! $prefix_sudo buildah run $working_container_name -- passwd -d root >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to remove password for user root" exit 1 fi if ! $prefix_sudo buildah config --volume $HOME $working_container_name >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to configure volume for $HOME" exit 1 fi if ! $prefix_sudo buildah config --volume $XDG_RUNTIME_DIR $working_container_name >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to configure volume for $XDG_RUNTIME_DIR" exit 1 fi if ! $prefix_sudo buildah config \ --volume $dbus_system_bus_path \ $working_container_name >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to configure volume for $dbus_system_bus_path" exit 1 fi if ! $prefix_sudo buildah config --volume /dev/dri $working_container_name >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to configure volume for /dev/dri" exit 1 fi if ! $prefix_sudo buildah config --user $USER $working_container_name >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to configure the default user as $USER" exit 1 fi if ! $prefix_sudo buildah config --workingdir $HOME $working_container_name >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to configure the initial working directory to $HOME" exit 1 fi echo "$0: trying to create image $toolbox_image" >&42 if ! $prefix_sudo buildah commit --rm $working_container_name $toolbox_image >/dev/null 2>&42; then $prefix_sudo buildah rm $working_container_name >/dev/null 2>&42 echo "$0: failed to create image $toolbox_image" exit 1 fi echo "$0: created image $toolbox_image" >&42 fi echo "$0: checking if container $toolbox_container already exists" >&42 if $prefix_sudo podman inspect --type container $toolbox_container >/dev/null 2>&42; then echo "$0: container $toolbox_container already exists" exit 1 fi total_ram=$(awk '( $1 == "MemTotal:" ) { print $2 }' /proc/meminfo 2>&42) # kibibytes if is_integer $total_ram; then tmpfs_size=$((total_ram*1024/2)) # bytes fi max_uid_count=65536 max_minus_uid=$((max_uid_count-UID)) uid_plus_one=$((UID+1)) echo "$0: trying to create container $toolbox_container" >&42 if ! $prefix_sudo podman create \ --group-add wheel \ --hostname toolbox \ --interactive \ --name $toolbox_container \ --network host \ --privileged \ --security-opt label=disable \ --tmpfs /dev/shm:size=$tmpfs_size \ --tty \ --uidmap $UID:0:1 \ --uidmap 0:1:$UID \ --uidmap $uid_plus_one:$uid_plus_one:$max_minus_uid \ --volume $HOME:$HOME \ --volume $XDG_RUNTIME_DIR:$XDG_RUNTIME_DIR \ --volume $dbus_system_bus_path:$dbus_system_bus_path \ --volume /dev/dri:/dev/dri \ $toolbox_image \ /bin/sh >/dev/null 2>&42; then echo "$0: failed to create container $toolbox_container" exit 1 fi echo "$0: created container $toolbox_container" >&42 ) enter() ( shell_to_exec=/bin/bash echo "$0: trying to start container $toolbox_container" >&42 if ! $prefix_sudo podman start $toolbox_container >/dev/null 2>&42; then echo "$0: failed to start container $toolbox_container" exit 1 fi if [ "$DBUS_SYSTEM_BUS_ADDRESS" != "" ]; then set_dbus_system_bus_address="--env DBUS_SYSTEM_BUS_ADDRESS=$DBUS_SYSTEM_BUS_ADDRESS" fi echo "$0: looking for $SHELL in container $toolbox_container" >&42 if $prefix_sudo podman exec $toolbox_container test -f $SHELL 2>&42; then shell_to_exec=$SHELL else echo "$0: $SHELL not found in $toolbox_container; using $shell_to_exec instead" >&42 fi echo "$0: trying to exec $shell_to_exec in container $toolbox_container" >&42 $prefix_sudo podman exec \ --env COLORTERM=$COLORTERM \ --env DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \ $set_dbus_system_bus_address \ --env DESKTOP_SESSION=$DESKTOP_SESSION \ --env DISPLAY=$DISPLAY \ --env LANG=$LANG \ --env SHELL=$SHELL \ --env SSH_AUTH_SOCK=$SSH_AUTH_SOCK \ --env TERM=$TERM \ --env VTE_VERSION=$VTE_VERSION \ --env XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP \ --env XDG_DATA_DIRS=$XDG_DATA_DIRS \ --env XDG_MENU_PREFIX=$XDG_MENU_PREFIX \ --env XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \ --env XDG_SEAT=$XDG_SEAT \ --env XDG_SESSION_DESKTOP=$XDG_SESSION_DESKTOP \ --env XDG_SESSION_ID=$XDG_SESSION_ID \ --env XDG_SESSION_TYPE=$XDG_SESSION_TYPE \ --env XDG_VTNR=$XDG_VTNR \ --interactive \ --tty \ $toolbox_container \ /bin/sh -c 'cd "$1"; export PS1="$2"; shift 2; exec "$@"' \ /bin/sh \ "$PWD" \ "$toolbox_prompt" \ $shell_to_exec -l 2>&42 ) exit_if_extra_operand() { if [ "$1" != "" ]; then echo "$0: extra operand '$1'" echo "Try '$0 --help' for more information." exit 1 fi } exit_if_unrecognized_option() { echo "$0: unrecognized option '$1'" echo "Try '$0 --help' for more information." exit 1 } usage() { echo "Usage: fedora-toolbox [--container ]" echo " [--release ]" echo " [-v | --verbose]" echo " create [--candidate-registry]" echo " [--image ]" echo " or: fedora-toolbox [--container ]" echo " [--release ]" echo " [-v | --verbose]" echo " enter" echo " or: fedora-toolbox --help" } exec 42>/dev/null while [[ "$1" = -* ]]; do case $1 in --container ) shift if [ "$1" = "" ]; then echo "$0: missing argument for '--container'" echo "Try '$0 --help' for more information." exit 1 fi toolbox_container=$1 ;; -h | --help ) usage exit ;; --release ) shift if [ "$1" = "" ]; then echo "$0: missing argument for '--release'" echo "Try '$0 --help' for more information." exit 1 fi arg=$(echo $1 | sed 's/^F\|^f//' 2>&42) if ! is_integer $arg; then echo "$0: invalid argument for '--release'" echo "Try '$0 --help' for more information." exit 1 fi if [ $arg -le 0 2>&42 ]; then echo "$0: invalid argument for '--release'" echo "Try '$0 --help' for more information." exit 1 fi release=$arg ;; --sudo ) prefix_sudo="sudo" ;; -v | --verbose ) exec 42>&2 ;; * ) exit_if_unrecognized_option $1 esac shift done fgc="f$release" [ "$toolbox_container" = "" ] && toolbox_container="fedora-toolbox-$USER:$release" base_toolbox_image="fedora-toolbox:$release" toolbox_image="fedora-toolbox-$USER:$release" if [ "$1" = "" ]; then echo "$0: missing command" echo "Try '$0 --help' for more information." exit 1 fi op=$1 shift case $op in create ) while [[ "$1" = -* ]]; do case $1 in --candidate-registry ) registry=$registry_candidate ;; --image ) shift if [ "$1" = "" ]; then echo "$0: missing argument for '--image'" echo "Try '$0 --help' for more information." exit 1 fi toolbox_image=$1 ;; * ) exit_if_unrecognized_option $1 esac shift done exit_if_extra_operand $1 create exit ;; enter ) while [[ "$1" = -* ]]; do case $1 in * ) exit_if_unrecognized_option $1 esac shift done exit_if_extra_operand $1 enter exit ;; * ) echo "$0: unrecognized command '$op'" echo "Try '$0 --help' for more information." exit 1 esac