diff --git a/README.md b/README.md index 22a6c08..62c45ad 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,15 @@ Invocation ---------- To run cdm, use - $ cdm [RCFILE] + + $ cdm [RCFILE] cdm tries to source configuration files in this order, and uses the first existing one: - [RCFILE specified on command line] - $HOME/.cdmrc - /etc/cdmrc + + [RCFILE specified on command line] + $HOME/.cdmrc + /etc/cdmrc To autostart cdm when you log in your account, copy the content of /usr/share/doc/cdm/profile.sh to the tail of your shell profile (~/.profile, @@ -37,7 +39,7 @@ Thanks to: 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 sanisation + CasperVector Massive rearchitecturing and code sanitation Licensed under GPLv2+ diff --git a/src/cdm b/src/cdm index 3663685..6c0b529 100755 --- a/src/cdm +++ b/src/cdm @@ -48,7 +48,7 @@ yesno() 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.";; + *) warn "invalid value for \`$1'; falling back to \`no' for now.";; esac } @@ -70,27 +70,25 @@ 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} +[[ -z "${binlist[*]}" ]] && binlist=() +[[ -z "${namelist[*]}" ]] && namelist=() +[[ -z "${flaglist[*]}" ]] && flaglist=() +[[ -z "${serverargs[*]}" ]] && serverargs=(-nolisten tcp) # Offer all available sessions in /etc/X11/Sessions, -# if binlist if not explicitly set in cdmrc. +# if $binlist if not explicitly set in cdmrc. -if [[ "$binlist" == "()" ]]; then +if [[ "${#binlist[@]}" == 0 ]]; then binlist=($(find /etc/X11/Sessions -maxdepth 1 -type f)) - for ((i=0; i<${#binlist[@]}; i++)); do - declare flaglist[$i]="X" - declare namelist[$i]=$(basename ${binlist[$i]}) - done + flaglist=($(sed 's/[[:digit:]]\+/X/g' <<< ${!binlist[@]})) + namelist=(${binlist[@]##*/}) fi # Generate the main menu. @@ -106,7 +104,7 @@ else # Display selection dialog. binindex=$( DIALOGRC="$dialogrc" dialog --colors --stdout \ - --backtitle "${longname} v${ver}" \ + --backtitle "$longname v$ver" \ --ok-label ' Select ' --cancel-label ' Exit ' \ --menu 'Select session' 0 0 0 "${menu[@]}" ) @@ -118,34 +116,33 @@ fi # Run $bin according to its flag. let binindex-=countfrom -bin="${binlist[${binindex}]}" +bin=($(eval echo "${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 + # 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 + 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 + # If X is already running and locktty=yes, activate it. + if $(yesno locktty) && xdpyinfo -display ":$display.0" &> /dev/null; then + chvt "$((display+xtty))" + exitnormal fi # Get the first empty display. @@ -163,27 +160,27 @@ case ${flaglist[$binindex]} in fi done - # run X in current tty - if [[ $xtty == "keep" ]]; then - vt=$(tty) - vt=${vt#/dev/} - if [[ $vt != tty* ]]; then - error "error: invalid TTY" + # Support for running X in current tty. + if [[ $xtty == 'keep' ]]; then + vt="$(tty)" + if [[ "$vt" != '/dev/tty'* ]]; then + error 'invalid TTY.' exiterror fi - vt=${vt#tty} + vt="${vt#/dev/tty}" else - vt=$((xtty+display)) + vt="$((xtty+display))" fi - serverargs=":${display} $serverargs vt$vt" + serverargs=(":${display}" "${serverargs[@]}" "vt$vt") - $(yesno consolekit) && launchflags="-c -t $cktimeout" - if ! eval cdm-xlaunch $launchflags -- $bin -- $serverargs; then + $(yesno consolekit) && launchflags=(-c -t "$cktimeout") + if cdm-xlaunch "${launchflags[@]}" -- "${bin[@]}" -- "${serverargs[@]}" + then + exitnormal + else warn "\`cdm-xlaunch' exited unsuccessfully." exiterror - else - exitnormal fi ;; @@ -193,4 +190,4 @@ case ${flaglist[$binindex]} in ;; esac -# vim:set ts=4 sw=4 et: +# vim:ts=4:sw=4:et diff --git a/src/cdm-xlaunch b/src/cdm-xlaunch index e6b4986..5535ec7 100755 --- a/src/cdm-xlaunch +++ b/src/cdm-xlaunch @@ -56,7 +56,7 @@ done # Do first to avoid race conditions. if $consolekit; then - info "waiting for ConsoleKit to register X session." + info 'waiting for ConsoleKit to register X session.' sleep "$cktimeout" & clockpid=$! dbuspidfifo=$(mktemp --dry-run --tmpdir $name.XXXXXXXX) if ! mkfifo "$dbuspidfifo"; then @@ -77,7 +77,7 @@ if $consolekit; then fi # Conform to POSIX and do not use `>&' here. -setsid startx $* > /dev/null 2>&1 & +setsid startx "$@" > /dev/null 2>&1 & # If wait(1) returns with a value >128, it was interrupted by kill(1), # so registration was sucessful. @@ -86,14 +86,14 @@ if $consolekit; then if wait "$clockpid" >& /dev/null then kill "$dbuspid" - error "ConsoleKit registration timed out." + error 'ConsoleKit registration timed out.' exit 1 else kill "$dbuspid" - info "ConsoleKit registration succeeded." + info 'ConsoleKit registration succeeded.' exit 0 fi fi fi -# vim:set ts=4 sw=4 et: +# vim:ts=4:sw=4:et diff --git a/src/cdmrc b/src/cdmrc index 1d0525c..07ef72f 100644 --- a/src/cdmrc +++ b/src/cdmrc @@ -8,17 +8,17 @@ # # (An example:) # binlist=( -# "~/.xsession" # Launch your X session, -# "/bin/bash --login" # or just execute your shell, -# "/usr/bin/fbterm" # or start a frame buffer console, -# "/usr/bin/cdm ~/.submenu.cdmrc" # or go to a submenu :) +# '~/.xsession' # Launch your X session, +# '/bin/bash --login' # or just execute your shell, +# '/usr/bin/fbterm' # or start a frame buffer console, +# '/usr/bin/cdm ~/.submenu.cdmrc' # or go to a submenu :) # ) # List all program display names, one-by-one matched with $binlist. # Names with whitespaces should be quoted or escaped. # # (Continued example:) -# namelist=("X session" Console FBTerm "Sub menu") +# namelist=('X session' Console FBTerm 'Sub menu') # Type of the programs, one-by-one matched with $binlist. # `C' for *C*onsole programs, which would be `exec'ed. @@ -39,19 +39,20 @@ countfrom=0 display=0 # Where should the first X tty be spawned? -# special value 'keep' causes to run X in current tty +# special value `keep' causes to run X in current tty. xtty=7 # Should cdm(1) stick to the specified display? locktty=no -# Additional arguments to pass to X server, which is usually called as: -# /usr/bin/X :$display $serverargs vt$((xtty+display)) -serverargs='-nolisten tcp' - # Use ConsoleKit for X session? consolekit=yes # Timeout for waiting for X session to register with ConsoleKit. cktimeout=30 +# Additional arguments to pass to X server, which is usually called as: +# /usr/bin/X :$display "${serverargs[@]}" vt$((xtty+display)) +# Arguments with whitespaces should be quoted or escaped. +serverargs=(-nolisten tcp) + diff --git a/src/profile.sh b/src/profile.sh index c5eae0a..3dbdeac 100644 --- a/src/profile.sh +++ b/src/profile.sh @@ -1,5 +1,8 @@ -if [[ "$(tty)" == /dev/tty* ]]; then +# To avoid potential situation where cdm(1) crashes on every TTY, here we +# default to execute cdm(1) on tty1 only, and leave other TTYs untouched. +if [[ "$(tty)" == '/dev/tty1' ]]; then [[ -n "$CDM_SPAWN" ]] && return - [[ -z "$DISPLAY$SSH_TTY" ]] && exec cdm + # Avoid executing cdm(1) when X11 has already been started. + [[ -z "$DISPLAY$SSH_TTY$(pgrep xinit)" ]] && exec cdm fi