print_help() {
cat <<EOF
Target commands:
-- console
+- console (default command)
- reset
- on
- off
- rsync ...
+- get-config
Management commands:
- help
if [ "$NB_ADMIN" ]; then
cat <<EOF
- add-key
+- shell (use with ssh -t)
EOF
fi
exit 0
add_key() {
local user
+ [ "$NB_ADMIN" ] || return 1
+ case $# in
+ 0) die "Usage: ssh ... add-key USERNAME < id_rsa.pub";;
+ 1) break;;
+ *) die "User name must not contain spaces: $*";;
+ esac
user="$1"
- die "Not implemented"
+ key=$(cat)
+
+ tmp=$(mktemp ~/.ssh/authorized_keys.XXXXXXXX)
+ {
+ cat ~/.ssh/authorized_keys
+ echo "command=\"user $user\" $key"
+ } | sort -u > $tmp
+
+ mv $tmp ~/.ssh/authorized_keys
+}
+
+exec_shell() {
+ [ "$NB_ADMIN" ] || die "Permission denied"
+ if ! tty > /dev/null; then
+ echo "novaboot-shell: Consider starting the shell with 'ssh -t'"
+ fi
+ exec /usr/bin/env bash || exec /bin/sh
}
lock_queue() {
exec "$@"
}
-check_var() {
- if eval [ "\"\$$1\"" ]; then
- return 0
+read_config() {
+ . "${NOVABOOT_SHELL_CONFIG:-$HOME/.novaboot-shell}"
+}
+
+power() {
+ local cmd
+ case "$1" in
+ "on") cmd="${on_cmd:?}";;
+ "off") cmd="${off_cmd:?}";;
+ *) die "Unexpected power parameter";;
+ esac
+
+ if [ "$PPID" -ne 1 ] && systemctl --user is-enabled --quiet novaboot-delayed-power-off.service; then
+ case "$1" in
+ "on") systemctl --user start novaboot-delayed-power-off.service;;
+ "off") sudo novaboot-power off;;
+ esac
else
- die "$1 variable not defined in $CFG"
+ eval "$cmd"
fi
}
+run_console() {
+ trap "rm -f $RUN_DIR/ppid" EXIT
+ echo $NOVABOOT_PPID > $RUN_DIR/ppid
+ echo 'novaboot-shell: Connected'
+ # TODO: $reset_begin_cmd
+ [ -n "${on_cmd}" ] && power on
+ eval "$1"
+}
+
+# Run novaboot with the same configuration as specified in
+# ~/.novaboot-shell, but allow the caller to extend of override them
+# via parameters of this function.
+run_novaboot() {
+ nbscript=$1
+ shift
+ OLD_IFS=$IFS
+ # Split $target_config below by newlines, not by words
+ IFS="
+"
+ novaboot "$nbscript" $target_config --server="$HOME/tftproot" --reset-cmd="${reset_cmd:?}" --remote-cmd="${console_cmd:?}" "$@"
+ IFS=$OLD_IFS
+}
+
# run_subcommand should be called only after permission checks and/or locking
run_subcommand() {
+ read_config
case "$*" in
+ "default")
+ run_console "${default_cmd:-${console_cmd:?}}";;
"console")
- trap "rm -f $RUN_DIR/ppid" EXIT
- echo $NOVABOOT_PPID > $RUN_DIR/ppid
- echo 'novaboot-shell: Connected'
- # TODO: $target_reset_begin
- check_var target_console && eval exec $target_console;;
+ run_console "${console_cmd:?}";;
"reset")
- check_var target_reset && eval exec $target_reset;;
+ eval "${reset_cmd:?}";;
"rsync --server "*" . .")
- if [ $# -ne 5 ]; then die "Unexpected rsync invocation: $*"; fi
+ if ! [ $# -eq 5 -o \( $# -eq 6 -a "$4" = '--log-format=X' \) ]; then
+ die "Unexpected rsync invocation: $*"
+ fi
mkdir -p "$HOME/tftproot"
cd "$HOME/tftproot"
- exec rsync --server $3 . . ;;
+ exec "$@";;
"on")
- check_var target_on && eval exec $target_on;;
+ power on
+ exit;;
"off")
- check_var target_off && eval exec $target_off;;
+ power off
+ exit;;
+ *)
+ die "Unknown command: $*";;
esac
}
main() {
- if [ "$1" = "-c" ]; then shift
- else die "Permission denied"; fi
+ if [ "$1" = "-c" ]; then
+ set -- $2
+ elif [ $# -gt 0 ]; then
+ die "Permission denied"
+ fi
NB_ADMIN=
- if [ "${1%% *}" = "user" ]; then
+ if [ "$1" = "user" ]; then
# Get user name encoded in ~/.ssh/authorized_keys
- set -- $1
- NB_USER="$2";
+ export NB_USER="$2";
[ "$3" = "admin" ] && NB_ADMIN=1
set -- $SSH_ORIGINAL_COMMAND
fi
- if [ $# -eq 0 ]; then print_help; fi
-
IP=${SSH_CONNECTION%% *}
- HOST=$(getent hosts $IP) || HOST=$IP
+ if [ "$IP" ]; then
+ HOST=$(getent hosts $IP) || HOST=$IP
+ else
+ HOST=localhost
+ fi
REMOTE=${HOST##* }
DATE=$(LANG=C date +'%F_%T')
export NOVABOOT_ID="${NB_USER:-?} $DATE ${REMOTE}"
case "$1" in
# Commands allowed at any time
+ "") locked $0 default;;
"console") locked $0 console;;
- "add-key") shift; add_key "$@"; exit $?;;
+ "get-config") read_config && echo -n "${target_config}"; exit;;
+ "add-key") shift; add_key "$@"; exit;;
+ "shell") exec_shell; exit;;
"help") print_help;;
# Commands allowed only when nobody or the same user is connected
# to the console. "The same user" means that we were executed by
# the same sshd process that has the lock. This is ensured by
- # using SSH connection sharing on cline side.
- console | reset | rsync | on | off)
+ # using SSH connection sharing on client side.
+ reset | rsync | on | off)
ALLOWED_PPID=$(cat $RUN_DIR/ppid 2>/dev/null || :)
if [ "$PPID" -eq "${ALLOWED_PPID:-0}" ]; then run=unlocked; else run=locked; fi
$run $0 "$@";;
esac
}
-RUN_DIR="$XDG_RUNTIME_DIR/novaboot"
+if [ -d "$HOME" ]; then
+ RUN_DIR="$HOME"
+else
+ RUN_DIR="/tmp/novaboot-shell@$USER"
+ mkdir -p "$RUN_DIR"
+fi
-if [ -z "$NOVABOOT_ID" ]; then
+if [ -z "$NOVABOOT_ID" ] && [ "$PPID" -ne 1 ]; then
main "$@"
else
- if [ "$NOVABOOT_SHELL_CONFIG" ]; then
- CFG="$NOVABOOT_SHELL_CONFIG"
- else
- CFG="$HOME/.novaboot-shell"
- fi
-
- . "$CFG"
-
run_subcommand "$@"
fi