1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
|
# -*-shell-script-*-
# Shared bash functions for cereal
#
# The cereal scripts were written by
# Jameson Graef Rollins <jrollins@finestructure.net>
# and
# Daniel Kahn Gillmor <dkg@fifthhorseman.net>.
#
# They are Copyright 2007, and are all released under the GPL, version 3
# or later.
##################################################
# managed directories
ETC="/etc/cereal"
export ETC
SESSIONDIR="/var/lib/cereal/sessions"
export SESSIONDIR
ERR=0
export ERR
##################################################
error() {
echo "$1" >&2
ERR=${2:-'1'}
}
failure() {
echo "$1" >&2
exit ${2:-'2'}
}
# check if TTY is valid tty
# check_is_tty TTY
check_tty() {
[ -c "$1" ] || failure "'$1' is not a valid tty."
}
# check is tty is already being used in another session
# check_is_session_tty TTY
check_session_tty() {
local SESSION
local TTY
TTY="$1"
for SESSION in $(ls "$SESSIONDIR") ; do
if grep -q "^$TTY$" "$SESSIONDIR/$SESSION/env/TTY" ; then
failure "TTY '$TTY' is already being monitored by session '$SESSION'."
fi
done
}
# check if USER is valid
# check_user USER
check_user() {
getent passwd "$1" > /dev/null || failure "'$1' is not a valid user."
}
# check if GROUP is valid
# check_group GROUP
check_group() {
getent group "$1" > /dev/null || failure "'$1' is not a valid group."
}
# check if the user can read/write to a TTY
is_tty_rw() {
chpst -u "$1:$2" bash -c "test -r $3 && test -w $3"
}
# check_tty_rw USER GROUP TTY
check_tty_rw() {
is_tty_rw "$@" || failure "User '$1' does not have read/write access to tty '$3', tty is not g+rw, or you do not have permission to change user."
}
# start_check
# this is called with "chpst -e" with a session environment
start_check() {
is_tty_rw "$USER" "$GROUP" "$TTY"
}
# check if session exists
# is_session SESSION
is_session() {
test -d "$SESSIONDIR/$1"
}
# is_running SESSION
is_running() {
local SESSION
SESSION="$1"
STAT_FILE="$SESSIONDIR/$SESSION/supervise/stat"
if [ -r "$SESSIONDIR/$SESSION/supervise" ] ; then
if [ -e "$STAT_FILE" ] ; then
if [ $(cat "$STAT_FILE") = 'run' ] ; then
# return 0 if the service is running
return 0
else
# return 1 if the service is *not* running
return 1
fi
else
# if the stat file doesn't exist, assume it's not running
return 1
fi
else
# return 2 if we can't read the stat file and don't know the status
return 2
fi
}
# check if sessions tty is locked
# is_locked SESSION
is_locked() {
local TTY
TTY=$(cat "$SESSIONDIR/$1/env/TTY")
test -e /var/lock/LCK..${TTY##/dev/}
}
# can_attach SESSION [USER]
can_attach() {
local USER
USER=${2:-"$USER"}
[ "$USER" = $(cat "$SESSIONDIR/$1/env/USER") ]
}
# in_group USER GROUP
in_group() {
groups "$1" | cut -d ':' -f 2 | tr ' ' '\n' | grep -q "^$2$"
}
# can_follow SESSION [USER]
can_follow() {
local LOGUSER
local LOGGROUP
local USER
LOGUSER=$(cat "$SESSIONDIR/$1/env/LOGUSER")
LOGGROUP=$(cat "$SESSIONDIR/$1/env/LOGGROUP")
USER=${2:-"$USER"}
[ "$USER" = "$LOGUSER" ] || in_group "$USER" "$LOGGROUP" || [ $(id -u "$USER") = '0' ]
}
# write to the log of a session
#log_write SESSION STATEMENT
log_write() {
printf "\ncereal: %s\n" "$2" >> "$SESSIONDIR/$1/socket"
}
# display_session SESSION [USER]
display_session() {
local SESSION
local SFLAG
local AFLAG
local FFLAG
SESSION="$1"
USER=${2:-"$USER"}
# set state flag
# last flag works only for users that can read supervise/stat
is_running "$SESSION"
case $? in
0)
SFLAG='+' # running
;;
1)
SFLAG='-' # stopped
;;
2)
SFLAG='?' # unknown
;;
esac
# set attach flag
if can_attach "$SESSION" "$USER" ; then
AFLAG='a'
else
AFLAG='-'
fi
# set follow flag
if can_follow "$SESSION" "$USER" ; then
FFLAG='f'
else
FFLAG='-'
fi
cd "$SESSIONDIR/$SESSION/env"
echo "${SFLAG}${AFLAG}${FFLAG} $SESSION $(cat TTY) $(cat BAUD) $(cat USER) $(cat LOGGROUP)"
}
# list [-n] SESSION [SESSION...]
list() {
local SESSION
local SESSIONS
local DISP
DISP=0
# flag to just output session names (otherwise display full info)
if [ "$1" = '--names' -o "$1" = '-n' ] ; then
unset DISP
shift 1
fi
# list of session to display
if [ "$1" ] ; then
SESSIONS="$@"
else
SESSIONS=$(ls -1 "$SESSIONDIR" 2> /dev/null)
[ "$SESSIONS" ] || return 1
fi
for SESSION in $SESSIONS ; do
if ! is_session "$SESSION" ; then
error "Session '$SESSION' not found." 1
elif [ "$DISP" ] ; then
display_session "$SESSION"
else
echo "$SESSION"
fi
done
}
# function called by the session service run script to actually start screen
# takes no arguments, since it is called with a "chpst -e"
mainrun() {
check_tty "$TTY"
check_user "$USER"
check_group "$GROUP"
check_group "$LOGGROUP"
check_tty_rw "$USER" "$GROUP" "$TTY"
chown "$USER:$LOGGROUP" ./socket || failure "Can not properly set ownership of socket."
chmod 0640 ./socket || failure "Can not properly set permissions on socket."
echo "starting screen session..."
LOCKFILE=/var/lock/LCK..${TTY##/dev/}
lockfile -r0 "$LOCKFILE"
LOCK_EXIT_CODE=$?
if [ "$LOCK_EXIT_CODE" != 0 ] ; then
exit "$LOCK_EXIT_CODE"
fi
chmod u+w "$LOCKFILE"
printf '%9s\n' $$ >> "$LOCKFILE"
exec chpst -u "$USER:$GROUP" /usr/bin/screen -D -m -L -c "$SCREENRC" -s /bin/false -S "cereal:$SESSION" -t "$SESSION" "$TTY" "$BAUD"
}
# function called by the session service finish script to remove the
# serial device lockfile
# takes no arguments, since it is called with a "chpst -e"
remove_lock() {
LOCKFILE=/var/lock/LCK..${TTY##/dev/}
rm -r "$LOCKFILE"
}
|