#!/bin/sh
#
# primitive configurator for powerd.
#
# can be used from the commandline to activate a profile,
# otherwise, will bring up a series of dialog-based config
# screens to let you select and edit a profile.
#
#
# Copyright (C) 2009, Paul G Fox
#
# 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., 675 Mass Ave, Cambridge, MA 02139,
# USA.
#


INHIBITDIR=/var/run/powerd-inhibit-suspend
INHIBIT_BY_TOUCH=$INHIBITDIR/.fake_activity
CONFIGDIR=/etc/powerd
CONFIGFILE=$CONFIGDIR/powerd.conf
TMPCONFIG=$CONFIGFILE.tmp
NEWCONFIG=$TMPCONFIG.new
EVENTFIFO=/var/run/powerevents

TMP=/tmp/powerdconfig.$$


#exec 2>pc.log
#set -x

me=${0##*/}

usage()
{
    cat <<EOF >&2
usage: $me [ -a | =<eventname> | configname ]"
    -a         Will cause pseudo-activity, to keep the laptop awake"
    =foo       Will send event 'foo' to powerd"
    configname If $CONFIGFILE is a symlink,"
               specifying the name of a file in $CONFIGDIR will"
               repoint the symlink and cause powerd to reconfigure itself."
    Otherwise, giving no arguments will bring up a configuration"
    editor on the current $CONFIGFILE"

EOF
    exit 1
}


trap "rm -f $TMP $TMPCONFIG $NEWCONFIG" 0

backtitle="powerd configuration"


yes_no()
{
    case $1 in
    1|[yYtT]*)  echo yes  ;;
    *)          echo no   ;;
    esac
}

setvar()
{
    varname=$1
    val=$2

    grep -v "^$varname=" $TMPCONFIG >$NEWCONFIG
    echo $varname="\"$val\"" >>$NEWCONFIG
    mv $NEWCONFIG $TMPCONFIG
}

edit_config()
{

    cfg=$1

    ro=;
    test "$readonly" && ro=2

    # suck in the config
    . $cfg

    bat_dim=${config_BATTERY_TIME_DIM:-120}
    bat_sleep=${config_BATTERY_TIME_SLEEP:-240}
    bat_blank=${config_BATTERY_TIME_BLANK:-480}

    # force numeric, and reasonable defaults
    test "$bat_dim" -eq "$bat_dim" || bat_dim=120
    test "$bat_sleep" -eq "$bat_sleep" || bat_sleep=$(( bat_dim + 120 ))
    test "$bat_blank" -eq "$bat_blank" || bat_blank=$(( bat_dim + 240 ))


    ebook_dim=${config_EBOOK_TIME_DIM:-120}
    ebook_sleep=${config_EBOOK_TIME_SLEEP:-240}
    ebook_blank=${config_EBOOK_TIME_BLANK:-480}

    # force numeric, and reasonable defaults
    test "$ebook_dim" -eq "$ebook_dim" || ebook_dim=120
    test "$ebook_sleep" -eq "$ebook_sleep" || ebook_sleep=$(( ebook_dim + 120 ))
    test "$ebook_blank" -eq "$ebook_blank" || ebook_blank=$(( ebook_dim + 240 ))

    plug_dim=${config_PLUGGED_TIME_DIM:-120}
    plug_sleep=${config_PLUGGED_TIME_SLEEP:-240}
    plug_blank=${config_PLUGGED_TIME_BLANK:-480}

    # force numeric, and reasonable defaults
    test "$plug_dim" -eq "$plug_dim" || plug_dim=120
    test "$plug_sleep" -eq "$plug_sleep" || plug_sleep=$(( plug_dim + 120 ))
    test "$plug_blank" -eq "$plug_blank" || plug_blank=$(( plug_dim + 240 ))

    idledim=${config_IDLE_DIM_LEVEL:-5}
    test "$idledim" -eq "$idledim" || idledim=5

    wlanpower=${config_MESH_DURING_SUSPEND:-no}
    wlanwake=${config_WAKE_ON_WLAN:-yes}
    maxsleep=${config_MAX_SLEEP_BEFORE_SHUTDOWN:-3600}
    test "$maxsleep" -eq "$maxsleep" || maxsleep=5
    allowshut=${config_ALLOW_SHUTDOWN_WHEN_PLUGGED:-yes}
    lidsleep=${config_SLEEP_WHEN_LID_CLOSED:-yes}

    splashdelay=${config_CONFIRM_SECONDS:-8}


    # Careful!  adding fields means adjusting numbers in many places
    #  below the new field (at least two per line), and _also_ means
    #  the results need to be assigned differently after return.  see below.
    row=1
    if ! dialog \
          --backtitle "$backtitle" --mixedform \
            "${editing:-}Dim, Sleep and Blank may be scheduled in any order." \
            22 67 16 \
      \
      "Battery:    Dim"         1 1      "$bat_dim"     1  17 9 9 "$ro" \
                  "Sleep"       1 28     "$bat_sleep"   1  34 9 9 "$ro" \
                  "Blank"       1 45     "$bat_blank"   1  51 9 9 "$ro" \
      \
      "Ebook:      Dim"         2 1      "$ebook_dim"   2  17 9 9 "$ro" \
                  "Sleep"       2 28     "$ebook_sleep" 2  34 9 9 "$ro" \
                  "Blank"       2 45     "$ebook_blank" 2  51 9 9 "$ro" \
      \
      "Plugged:    Dim"         3 1      "$plug_dim"    3  17 9 9 "$ro" \
                  "Sleep"       3 28     "$plug_sleep"  3  34 9 9 "$ro" \
                  "Blank"       3 45     "$plug_blank"  3  51 9 9 "$ro" \
      \
      "Screen brightness (0-15) when dimmed:"    5 1      "$idledim"   5  43 3 3 "$ro" \
      \
      "Keep wlan powered in suspend? (XO-1)"    7 1      "$wlanpower"   7  41 5 5 "$ro" \
      "Wake on wireless activity?"    8 1      "$wlanwake"   8  41 5 5 "$ro" \
      \
      "Max blanked sleep before shutdown:"    10 1      "$maxsleep"   10  37 9 9 "$ro" \
      "Allow shutdown when plugged in?"    11 1      "$allowshut"   11  41 5 5 "$ro" \
      "Always sleep when lid closed?"    12 1      "$lidsleep"   12  41 5 5 "$ro" \
      \
      "Power button splash screen timeout:"   14 1 "$splashdelay"  14  43 3 3 "$ro" \
        2>$TMP
    then
        return 1
    fi

    if [ ! "$readonly" ]
    then
	# assign results to to the right variables here:
        set -- $(cat $TMP)
        bat_dim=$1
        bat_sleep=$2
        bat_blank=$3
        ebook_dim=$4
        ebook_sleep=$5
        ebook_blank=$6
        plug_dim=$7
        plug_sleep=$8
        plug_blank=$9
        idledim=${10}
        wlanpower=${11}
        wlanwake=${12}
        maxsleep=${13}
        allowshut=${14}
        lidsleep=${15}
        splashdelay=${16}

        setvar config_BATTERY_TIME_DIM $bat_dim
        setvar config_BATTERY_TIME_SLEEP $bat_sleep
        setvar config_BATTERY_TIME_BLANK $bat_blank
        setvar config_EBOOK_TIME_DIM $ebook_dim
        setvar config_EBOOK_TIME_SLEEP $ebook_sleep
        setvar config_EBOOK_TIME_BLANK $ebook_blank
        setvar config_PLUGGED_TIME_DIM $plug_dim
        setvar config_PLUGGED_TIME_SLEEP $plug_sleep
        setvar config_PLUGGED_TIME_BLANK $plug_blank

        setvar config_IDLE_DIM_LEVEL $idledim
        setvar config_MESH_DURING_SUSPEND $(yes_no $wlanpower)
        setvar config_WAKE_ON_WLAN $(yes_no $wlanwake)
        setvar config_MAX_SLEEP_BEFORE_SHUTDOWN $maxsleep
        setvar config_ALLOW_SHUTDOWN_WHEN_PLUGGED $(yes_no $allowshut)
        setvar config_SLEEP_WHEN_LID_CLOSED $(yes_no $lidsleep)
        setvar config_CONFIRM_SECONDS $splashdelay
    fi

    return 0

}

activate_config()
{
    echo reconfig >$EVENTFIFO
}

newconfig()
{
    new="$1"

    if [ ! -L $CONFIGFILE ]
    then
        echo "$me: $CONFIGFILE isn't a symlink." >&2
        echo " configuration switching unavailable." >&2
        exit 1
    fi

    # make sure it points to a file in $CONFIGDIR, otherwise this
    # program can't restore it.  maybe overkill.
    l=$(readlink $CONFIGFILE)
    case $l in
    */*)
        echo "$me: $CONFIGFILE must be a local symlink." >&2
        echo "  (currently points to '$l')" >&2
        exit 1
        ;;
    esac

    if [ ! -s $CONFIGDIR/$new ]
    then
        echo "$me: $CONFIGDIR/$new doesn't exist or is empty." >&2
        exit 1
    fi

    ln -sf $new $CONFIGFILE && activate_config
}

o_check_root()
{
    if [ "$(whoami)" != root ]
    then
        dialog \
            --backtitle "$backtitle" \
            --msgbox \
            "You must be root to run this configuration program" 0 0
        exit 1
    fi
}

check_root()
{
    am_root=;
    test "$(whoami)" = root && am_root=yes
}

main()
{

    set -u

    arg1="${1:-}"

    case $arg1 in
    -a) # force pseudo-activity by touching the magic file
        if [ -d $INHIBITDIR ]
        then
            touch $INHIBIT_BY_TOUCH
        else
            echo "$me: no powerd running?" >&2
        fi
        exit
        ;;
    -*) # we have no other -options
        usage
        ;;
    esac

    check_root

    if [ "$arg1" -a ! "$am_root" ]
    then
        echo "You must be root to control powerd" >&2
        exit 1
    fi

    case $arg1 in
    "")
        ;;
    =*) # =foo is just a direct event to the daemon,
        #  with the '=' removed.
        if [ ! -p $EVENTFIFO ]
        then
            echo $me: problem with $EVENTFIFO >&2
            exit 1
        fi
        echo ${arg1#=} >$EVENTFIFO
        exit
        ;;
    *)
        newconfig $1
        exit
        ;;
    esac

    if ! type dialog >/dev/null 2>&1
    then
        (
        echo "${0##*/}: the 'dialog' program isn't available, quitting."
        echo "  Use a text editor to edit profiles under $CONFIGDIR,"
        echo "  and (re)activate them with: '${0##*/} profilename'"
        echo "  (Or use 'sudo yum install dialog' to install the package.)"
        ) >&2
        exit 1
    fi

    descr=;
    if [ -L $CONFIGFILE ]
    then
        cfg_file=$(readlink -e $CONFIGFILE 2>/dev/null)
        test -r "$cfg_file"
        r=$?
        descr=" linked profile"
    elif [ -s $CONFIGFILE ]
    then
        cfg_file=$CONFIGFILE
        r=0
    else # no config file -- (try to) create one
        > $CONFIGFILE
        cfg_file=$CONFIGFILE
        descr=" new"
        r=$?
    fi

    if [ $r != 0 ]
    then
        echo $me: problem with config file >&2
        exit 1
    fi

    readonly=;
    if [ ! "$am_root" ]
    then
        test -w "$cfg_file" || readonly=yes
        test -w $(dirname "$cfg_file") || readonly=yes
    fi

    if [ $readonly ]
    then
        editing="Showing read-only contents of$descr '$cfg_file'.\n"
        edit_config $CONFIGFILE
    else
        editing="Editing$descr '$cfg_file'.\n"
        cp "$cfg_file" $TMPCONFIG
        if edit_config $TMPCONFIG
        then
            cp $CONFIGFILE $CONFIGFILE.bak
            # don't disturb possible symlink
            cat $TMPCONFIG >$CONFIGFILE
            activate_config
        else
            rm $TMPCONFIG
            echo No changes made.
        fi
    fi
}


main "$@"
