source: trunk/cereal/src/common @ 1173

Last change on this file since 1173 was 1173, checked in by jrollins, 10 years ago

new packaging system, like debirf.

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