You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
5.7 KiB
Bash

#!/bin/bash
#
# CDM: The Console Display Manager
#
# Copyright (C) 2009-2011, Daniel J Griffiths <ghost1227@archlinux.us>
# Thanks to:
#
# Andrwe beta-testing and submitting the fix for the all
# important X incrementation function
# brisbin33 code cleanup
# tigrmesh finding a critical issue with the gnome-session handler
# Profjim several incredibly useful patches
# lambchops468 consolekit and hibernation patches
# CasperVector Massive rearchitecturing and code sanitation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
name=$(basename "$0")
longname='Console Display Manager'
ver='0.6'
trap '' SIGINT SIGTSTP
# Helper functions.
warn() { (printf ' \033[01;33m*\033[00m '; echo "$name: $*") > /dev/stderr; }
error() { (printf ' \033[01;31m*\033[00m '; echo "$name: $*") > /dev/stderr; }
exitnormal() { exit 0; }
exiterror() { sleep 1; exit 1; }
yesno()
{
[ -z "$1" ] && return 1
eval value=\$${1}
case "$value" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
*) warn "Invalid value for \`$1'; falling back to \`no' for now.";;
esac
}
# Source cdm configurations.
if [[ -n "$1" ]]; then
if [[ -f "$1" ]]
then
source "$1"
else
error "config file \`$1' does not exist."
exiterror
fi
elif [[ -f "$HOME/.cdmrc" ]]; then
source "$HOME/.cdmrc"
elif [[ -f /etc/cdmrc ]]; then
source /etc/cdmrc
fi
# Default options.
binlist=${binlist:-()}
namelist=${namelist:-()}
flaglist=${flaglist:-()}
dialogrc=${dialogrc:-}
countfrom=${countfrom:-0}
display=${display:-0}
xtty=${xtty:-7}
locktty=${locktty:-no}
serverargs=${serverargs:-'-nolisten tcp'}
consolekit=${consolekit:-yes}
cktimeout=${cktimeout:-30}
# Offer all available sessions in /etc/X11/Sessions,
# if binlist if not explicitly set in cdmrc.
if [[ "$binlist" == "()" ]]; then
binlist=($(ls /etc/X11/Sessions))
flaglist=($(sed 's/[[:digit:]]\+/X/g' <<< ${!flaglist[*]}))
namelist=(${binlist[@]^})
fi
# Generate the main menu.
menu=()
for ((count = 0; count < ${#namelist[@]}; count++)); do
menu=("${menu[@]}" "$((count+countfrom))" "${namelist[${count}]}")
done
# Override dialog display if only one option is available.
if [[ "$count" == 1 ]]; then
binindex=0
else
# Display selection dialog.
binindex=$(
DIALOGRC="$dialogrc" dialog --colors --stdout \
--backtitle "${longname} v${ver}" \
--ok-label ' Select ' --cancel-label ' Exit ' \
--menu 'Select session' 0 0 0 "${menu[@]}"
)
if [[ $? != 0 ]]; then
clear
exitnormal
fi
fi
# Run $bin according to its flag.
let binindex-=countfrom
bin="${binlist[${binindex}]}"
case ${flaglist[$binindex]} in
# *C*onsole programs.
[Cc])
clear
# If $bin is a login shell, it might `exec' cdm again, causing an endless
# loop. To solve this problem, export $CDM_SPAWN when `exec'ing $bin and
# only let the shell automatically `exec' cdm when $CDM_SPAWN is not set.
# See also the example shell profile file shipped with the cdm package.
# Also untrap SIGINT and SIGTSTP before spawning process: If this is not
# done, *ANY* child process of *ANY* child (bash) shell will completely
# ignore SIGINT, which is rather confusing, and cannot be undone.
trap - SIGINT SIGTSTP
CDM_SPAWN=$$ exec $bin
;;
# *X* programs.
[Xx])
clear
# If X is already running and locktty=yes, activate it
if $(yesno locktty); then
if xdpyinfo -display ":$display.0" &> /dev/null; then
chvt "$((display+xtty))"
exitnormal
fi
fi
# Get the first empty display.
display=0
while ((display < 7)); do
if dpyinfo=$(xdpyinfo -display ":$display.0" 2>&1 1>/dev/null) ||
# Display is in use by another user.
[[ "$dpyinfo" == 'No protocol specified'* ]] ||
# Invalid MIT cookie.
[[ "$dpyinfo" == 'Invalid MIT'* ]]
then
let display+=1
else
break
fi
done
# run X in current tty
if [[ $xtty == "keep" ]]; then
vt=$(tty)
vt=${vt#/dev/}
if [[ $vt != tty* ]]; then
error "error: invalid TTY"
exiterror
fi
vt=${vt#tty}
else
vt=$((xtty+display))
fi
serverargs=":${display} $serverargs vt$vt"
$(yesno consolekit) && launchflags="-c -t $cktimeout"
if ! eval cdm-xlaunch $launchflags -- $bin -- $serverargs; then
warn "\`cdm-xlaunch' exited unsuccessfully."
exiterror
else
exitnormal
fi
;;
*)
error "unknown flag: \`${flaglist[$binindex]}'."
exiterror
;;
esac
# vim:set ts=4 sw=4 et: