]> rtime.felk.cvut.cz Git - novaboot.git/blob - server/novaboot-shell
0c476106ed6767fe9244081542d4acf89cf2aa45
[novaboot.git] / server / novaboot-shell
1 #!/bin/sh
2
3 set -e
4
5 die() {
6     echo >&2 "novaboot-shell: $*"
7     exit 1
8 }
9
10 print_help() {
11     cat <<EOF
12 Target commands:
13 - console
14 - reset
15 - on
16 - off
17 - rsync ...
18
19 Management commands:
20 - help
21 EOF
22
23     if [ "$NB_ADMIN" ]; then
24         cat <<EOF
25 - add-key
26 EOF
27     fi
28     exit 0
29 }
30
31 add_key() {
32     local user
33
34     user="$1"
35     die "Not implemented"
36 }
37
38 lock_queue() {
39     lslocks | awk '{ if ($9 == "'"$RUN_DIR"'") { print $2 } }'
40 }
41
42 print_queue() {
43     local queue
44
45     queue=$(
46         for pid in $(lock_queue); do
47             echo $pid $(sed --null-data -ne '/^NOVABOOT_ID=/ s///p' /proc/$pid/environ)
48         done | sort)
49     if [ "$queue" ]; then
50         echo "Target is occupied by:"
51         ( echo "PID USER LOGIN_TIME FROM"; echo "$queue" ) | column -t
52     fi
53 }
54
55 locked() {
56     print_queue
57     exec flock --no-fork "$RUN_DIR" "$@"
58 }
59
60 unlocked() {
61     exec "$@"
62 }
63
64 check_var() {
65     if eval [ "\"\$$1\"" ]; then
66         return 0
67     else
68         die "$1 variable not defined in $CFG"
69     fi
70 }
71
72 # run_subcommand should be called only after permission checks and/or locking
73 run_subcommand() {
74     case "$*" in
75         "console")
76             trap "rm -f $RUN_DIR/ppid" EXIT
77             echo $NOVABOOT_PPID > $RUN_DIR/ppid
78             echo 'novaboot-shell: Connected'
79             # TODO: $target_reset_begin
80             check_var target_console && eval exec $target_console;;
81         "reset")
82             check_var target_reset && eval exec $target_reset;;
83         "rsync --server "*" . .")
84             if ! [ $# -eq 5 -o \( $# -eq 6 -a "$4" = '--log-format=X' \) ]; then
85                 die "Unexpected rsync invocation: $*"
86             fi
87             mkdir -p "$HOME/tftproot"
88             cd "$HOME/tftproot"
89             exec "$@";;
90         "on")
91             check_var target_on && eval exec $target_on;;
92         "off")
93             check_var target_off && eval exec $target_off;;
94     esac
95 }
96
97 main() {
98     if [ "$1" = "-c" ]; then shift
99     else die "Permission denied"; fi
100
101     NB_ADMIN=
102     if [ "${1%% *}" = "user" ]; then
103         # Get user name encoded in ~/.ssh/authorized_keys
104         set -- $1
105         NB_USER="$2";
106         [ "$3" = "admin" ] && NB_ADMIN=1
107         set -- $SSH_ORIGINAL_COMMAND
108     fi
109
110     if [ $# -eq 0 ]; then print_help; fi
111
112     IP=${SSH_CONNECTION%% *}
113     HOST=$(getent hosts $IP) || HOST=$IP
114     REMOTE=${HOST##* }
115     DATE=$(LANG=C date +'%F_%T')
116     export NOVABOOT_ID="${NB_USER:-?} $DATE ${REMOTE}"
117     export NOVABOOT_PPID=$PPID
118
119     mkdir -p "$RUN_DIR"
120
121     case "$1" in
122         # Commands allowed at any time
123         "console") locked $0 console;;
124         "get-config") target_config; exit;;
125         "add-key") shift; add_key "$@"; exit;;
126         "help") print_help;;
127
128         # Commands allowed only when nobody or the same user is connected
129         # to the console. "The same user" means that we were executed by
130         # the same sshd process that has the lock. This is ensured by
131         # using SSH connection sharing on cline side.
132         reset | rsync | on | off)
133             ALLOWED_PPID=$(cat $RUN_DIR/ppid 2>/dev/null || :)
134             if [ "$PPID" -eq "${ALLOWED_PPID:-0}" ]; then run=unlocked; else run=locked; fi
135             $run $0 "$@";;
136         *)
137             echo >&2 "novaboot-shell: Command not allowed: $*"
138             logger -p error "novaboot-shell: Command not allowed: $*"
139             exit 1;;
140     esac
141 }
142
143 RUN_DIR="$XDG_RUNTIME_DIR/novaboot"
144
145 if [ "$NOVABOOT_SHELL_CONFIG" ]; then
146     CFG="$NOVABOOT_SHELL_CONFIG"
147 else
148     CFG="$HOME/.novaboot-shell"
149 fi
150
151 . "$CFG"
152
153 if [ -z "$NOVABOOT_ID" ]; then
154     main "$@"
155 else
156     run_subcommand "$@"
157 fi