#!/bin/bash # # CDM: The Console Display Manager # # Copyright (C) 2009-2011, Daniel J Griffiths # 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: