#!/bin/sh -efu
#
# Copyright (C) 2019  Paul Wolneykien <manowar@altlinux.org>
#
# This file 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
  
. shell-config

PROG="${0##*/}"
PROG_VERSION=1.0.1

WAKEFIX_CONFIG="${WAKEFIX_CONFIG:-/etc/sysconfig/wakefix.conf}"

show_help()
{
	cat <<EOF
Usage: $PROG [options]

$PROG is a tool to read and modify (fix) the ACPI wakeup event table
(/proc/acpi/wakeup). It is intended to be installed as a system startup
service to make such modifications at boot.

$PROG uses $WAKEFIX_CONFIG configuration file.

Options:
  -l, --list                print out the contents of the kernel ACPI
                            wakeup table (the default action);

  -e NAMEs, --enable=NAMEs  enable wakeup by events from devices
                            which name contains one of the listed NAMEs;

  -d NAMEs, --disable=NAMEs disable wakeup by events from devices
                            which name contains one of the listed NAMEs;

  -f, --fix      make modifications in accordance with the configuration
                 file $WAKEFIX_CONFIG;

  -n,--dry-run   just print out which devices would be enabled or
                 disabled without actual state changes;

  -v,--verbose   print information about the actual changes;

  -V,--version        print program version and exit;
  -h,--help           show this text and exit.


With no options given $PROG prints out the contents of the kernel ACPI
wakeup table (as with -l).

Report bugs to http://bugs.altlinux.ru/

EOF
}

print_version()
{
	cat <<EOF
$PROG version $PROG_VERSION
Written by Paul Wolneykien <manowar@altlinux.org>

Copyright (C) 2019 Paul Wolneykien <manowar@altlinux.org>
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.
EOF
}

show_usage()
{
	cat <<EOF
Usage: $PROG [options]

Run $PROG -h to see the help page.
EOF
}

dry_run=0
verbose=0
toggle_wakeup()
{
    local state="$1"; shift
    local regexp="$(echo "$*" | sed -e 's/[^0-9A-Za-z_-]\+/ /g' -e 's/^[[:space:]]\+//' -e 's/[[:space:]]\+$//' -e 's/[[:space:]]\+/\\|/g')"

    [ -n "$regexp" ] || return

    for dev in $(cat /proc/acpi/wakeup | grep "$state" | cut -f1 | grep -e "^\\($regexp\\)"); do
        if [ $dry_run -ne 0 ]; then
            echo "Would toggle '$dev' (currently $state)"
        else
            if [ $verbose -ne 0 ]; then
                echo "Toggle '$dev' (currently $state)" >&2
            fi
            echo "$dev" > /proc/acpi/wakeup
        fi
    done
}

list_wakeups()
{
    cat /proc/acpi/wakeup
}

OPTS=`getopt -n $PROG -o l,e:,d:,f,n,v,V,h \
             -l list,enable:,disable:,fix,dry-run,verbose,version,help -- "$@"` ||
	show_usage
eval set -- "$OPTS"


enable_list=
disable_list=
fix_enable_list=
fix_disable_list=

while :; do
	case "$1" in
		-l|--list)
            list_wakeups
            exit 0
            ;;
		-e|--enable)
            shift
            enable_list="$1"
            ;;
		-d|--disable)
            shift
            disable_list="$1"
            ;;
        -f|--fix)
            fix_disable_list="$(shell_config_get "$WAKEFIX_CONFIG" 'DISABLE' '[[:space:]]*=[[:space:]]*')"
            fix_enable_list="$(shell_config_get "$WAKEFIX_CONFIG" 'ENABLE' '[[:space:]]*=[[:space:]]*')"
            if [ -z "$fix_disable_list$fix_enable_list" ]; then
                echo "WARNING: Configuration is empty --- nothing to do!" >&2
            fi
            ;;
        -n|--dry_run)
            dry_run=1
            ;;
        -v|--verbose)
            verbose=1
            ;;
		-V|--version)
            print_version
            exit 0
            ;;
		-h|--help)
            show_help
            exit 0
            ;;
        --)
            shift
            break
            ;;
		*)
            echo "Unrecognized option: $1" >&2
            exit 1
            ;;
	esac
	shift
done

action=0
if [ -n "$enable_list" ]; then
    toggle_wakeup 'disabled' "$enable_list"
    action=1
fi

if [ -n "$disable_list" ]; then
    toggle_wakeup 'enabled' "$disable_list"
    action=1
fi

if [ -n "$fix_disable_list$fix_enable_list" ]; then
    toggle_wakeup 'disabled' "$fix_enable_list"
    toggle_wakeup 'enabled' "$fix_disable_list"
    action=1
fi

if [ $action -eq 0 ]; then
    list_wakeups
fi
