diff options
author | Sebastian | 2016-04-25 12:01:08 +0200 |
---|---|---|
committer | Sebastian | 2016-04-25 12:01:08 +0200 |
commit | 5acda3eaeabae9045609539303a8c12c4ce401f1 (patch) | |
tree | 7e71975f8570b05aafe2ea6ec0e242a8912387bb /core/modules/idleaction | |
parent | initial commit (diff) | |
download | mltk-5acda3eaeabae9045609539303a8c12c4ce401f1.tar.gz mltk-5acda3eaeabae9045609539303a8c12c4ce401f1.tar.xz mltk-5acda3eaeabae9045609539303a8c12c4ce401f1.zip |
merge with latest dev version
Diffstat (limited to 'core/modules/idleaction')
-rw-r--r-- | core/modules/idleaction/data/etc/cron.d/openslx-idleaction | 7 | ||||
-rwxr-xr-x | core/modules/idleaction/data/opt/openslx/scripts/idleaction-cron_script | 138 | ||||
-rwxr-xr-x | core/modules/idleaction/data/opt/openslx/scripts/idleaction-scheduled_action | 77 | ||||
-rw-r--r-- | core/modules/idleaction/module.build | 16 | ||||
-rw-r--r-- | core/modules/idleaction/module.conf | 4 | ||||
-rw-r--r-- | core/modules/idleaction/module.conf.centos | 6 | ||||
-rw-r--r-- | core/modules/idleaction/module.conf.debian | 6 | ||||
-rw-r--r-- | core/modules/idleaction/module.conf.fedora | 6 | ||||
-rw-r--r-- | core/modules/idleaction/module.conf.opensuse | 6 | ||||
-rw-r--r-- | core/modules/idleaction/module.conf.ubuntu | 6 | ||||
-rw-r--r-- | core/modules/idleaction/xprintidle.c | 136 |
11 files changed, 408 insertions, 0 deletions
diff --git a/core/modules/idleaction/data/etc/cron.d/openslx-idleaction b/core/modules/idleaction/data/etc/cron.d/openslx-idleaction new file mode 100644 index 00000000..3dd07ccb --- /dev/null +++ b/core/modules/idleaction/data/etc/cron.d/openslx-idleaction @@ -0,0 +1,7 @@ +# Trigger scripts that checks idle status of machine and triggers actions + +SHELL=/bin/ash +PATH=/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin + +*/5 * * * * root /opt/openslx/scripts/idleaction-cron_script + diff --git a/core/modules/idleaction/data/opt/openslx/scripts/idleaction-cron_script b/core/modules/idleaction/data/opt/openslx/scripts/idleaction-cron_script new file mode 100755 index 00000000..b7617940 --- /dev/null +++ b/core/modules/idleaction/data/opt/openslx/scripts/idleaction-cron_script @@ -0,0 +1,138 @@ +#!/bin/ash + +. /opt/openslx/config || exit 1 + +# If existent, no session is open. Will contain timestamp of last activity. +# If not existent, at least one user is logged in +CRONFILE="/etc/cron.d/idleaction-shutdown_schedule" +IDLEHINT="/dev/shm/idlehint" +NOW=$(date +%s) + +# +# 1) Check for idle timeout +# +if [ -n "${SLX_LOGOUT_TIMEOUT}" ] && [ "${SLX_LOGOUT_TIMEOUT}" -gt 0 ]; then + # Logout timeout is set, see which users we should kick + IS_IDLE=yes + # get all sessions + SESSIONS=$(loginctl | awk '{print $1}') + if [ -n "$SESSIONS" ]; then + TMP="/dev/shm/idlecheck.tmp" + # Iterate over sessions + for ses in $SESSIONS; do + # Get information + loginctl show-session "$ses" > "$TMP" + NAME=$(grep '^Name=' "$TMP" | cut -c 6-) + [ -z "$NAME" ] && continue # No name - should not happen + export DISPLAY=$(grep '^Display=' "$TMP" | cut -c 9-) + # X11 + if [ -n "$DISPLAY" ]; then + # Seems to be x11 + IDLE= + export XAUTHORITY=$(ps a | grep " $DISPLAY " | grep -o -- '-auth.*$' | grep -m1 -v grep | awk '{print $2}') + [ -n "$XAUTHORITY" ] && [ -f "$XAUTHORITY" ] && IDLE=$(xprintidle) + # Now that we have DISPLAY and XAUTHORITY set, xprintidle should work + if [ -z "$IDLE" ]; then + # Try user's xauth + USRHOME=$(/usr/bin/getent passwd "$NAME" | awk -F ':' '{print $6}') + export XAUTHORITY="$USRHOME/.Xauthority" + [ -f "$XAUTHORITY" ] && IDLE=$(xprintidle) + fi + if [ -n "$IDLE" ]; then + IDLE=$(( $IDLE / 1000 )) + if [ -z "$IDLE" ] || [ "$IDLE" -lt "$SLX_LOGOUT_TIMEOUT" ]; then + IS_IDLE=no + else + loginctl terminate-session "$ses" + fi + else # xprintidle did not work + IS_IDLE=no + fi + continue # Done with this session, skip normal tty/ssh checks + fi + # end X11 + # other sessions + IDLE=$(grep '^IdleSinceHint=' "$TMP" | cut -c 15-) + if [ "${#IDLE}" -lt 7 ]; then # wah wah waaaah + IS_IDLE=no + continue + fi + # divide by 1000000 by chopping of last 6 chars - number might be too large for $(( )) + IDLE=$(echo "$IDLE" | cut -c "-$(( ${#IDLE} - 6 ))") + [ "$IDLE" -gt "$NOW" ] && IDLE="$NOW" + IDLE=$(( $NOW - $IDLE )) + if [ "$IDLE" -lt "$SLX_LOGOUT_TIMEOUT" ]; then + IS_IDLE=no + else + loginctl terminate-session "$ses" + fi + # end other sessions + done + rm -f -- "$TMP" + fi + if [ "$IS_IDLE" = "yes" ]; then + [ ! -e "$IDLEHINT" ] && echo "$NOW" > "$IDLEHINT" + else + rm -f -- "$IDLEHINT" + fi +else + # No logout timeout is set, take shortcut for shutdown timeout (if set) + if [ -n "$SLX_SHUTDOWN_TIMEOUT" ]; then + SESSIONS=$(loginctl | wc -l) + if [ "$SESSIONS" = "0" ]; then + [ ! -e "$IDLEHINT" ] && echo "$NOW" > "$IDLEHINT" + else + rm -f -- "$IDLEHINT" + fi + fi +fi + +# +# 2) Check for no-session-shutdown timeout +# +if [ -n "${SLX_SHUTDOWN_TIMEOUT}" ] && [ "${SLX_SHUTDOWN_TIMEOUT}" -gt 0 ] && [ -e "$IDLEHINT" ]; then + IDLE=$(cat "$IDLEHINT") + [ "$IDLE" -gt "$NOW" ] && IDLE="$NOW" + IDLE=$(( $NOW - $IDLE )) + if [ "$IDLE" -gt "$SLX_SHUTDOWN_TIMEOUT" ]; then + poweroff + fi +fi + +# +# 3) Check for hard scheduled shutdown +# +# A cron file is created dynamically here so there's everything +# in one module and you don't need to repack config.tgz + +invalid_time () +{ + slxlog "idleaction-schedule" "Invalid shutdown time: '$time'. Expected HH:MM format." + return 0 +} + +if [ -n "$SLX_SHUTDOWN_SCHEDULE" -o -n "$SLX_REBOOT_SCHEDULE" ] && [ ! -e "$CRONFILE" ]; then + echo "# OpenSLX: Trigger poweroff at certain time of day" > "$CRONFILE" + echo "SHELL=/bin/ash" >> "$CRONFILE" + echo "PATH=/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin" >> "$CRONFILE" + echo "" >> "$CRONFILE" + for time in $SLX_SHUTDOWN_SCHEDULE; do + HOUR=${time%%:*} + MINUTE=${time##*:} + [ -z "$HOUR$MINUTE" ] && invalid_time && continue + [ "$HOUR" -lt 0 -o "$HOUR" -gt 23 ] && invalid_time && continue + [ "$MINUTE" -lt 0 -o "$MINUTE" -gt 59 ] && invalid_time && continue + echo "$MINUTE $HOUR * * * root /opt/openslx/scripts/idleaction-scheduled_action poweroff" >> "$CRONFILE" + done + # do it again for SLX_REBOOT_SCHEDULE + for time in $SLX_REBOOT_SCHEDULE; do + HOUR=${time%%:*} + MINUTE=${time##*:} + [ -z "$HOUR$MINUTE" ] && invalid_time && continue + [ "$HOUR" -lt 0 -o "$HOUR" -gt 23 ] && invalid_time && continue + [ "$MINUTE" -lt 0 -o "$MINUTE" -gt 59 ] && invalid_time && continue + echo "$MINUTE $HOUR * * * root /opt/openslx/scripts/idleaction-scheduled_action reboot" >> "$CRONFILE" + done + touch "/etc/cron.d" # Aufs bug where it won't update dir mtime when creating the file within +fi + diff --git a/core/modules/idleaction/data/opt/openslx/scripts/idleaction-scheduled_action b/core/modules/idleaction/data/opt/openslx/scripts/idleaction-scheduled_action new file mode 100755 index 00000000..6ef6969c --- /dev/null +++ b/core/modules/idleaction/data/opt/openslx/scripts/idleaction-scheduled_action @@ -0,0 +1,77 @@ +#!/bin/ash + +if [ "$(whoami)" != "root" ]; then + echo "Only root can call this" + exit 1 +fi + +if [ $# -ne 1 ]; then + echo "$0 <reboot|poweroff>" + exit 1 +fi + +MODE=$1 + +if [ "$MODE" != "reboot" ] && [ "$MODE" != "poweroff" ]; then + slxlog "idleaction-failed-call" "Invalid call to idleaction-scheduled_action. Mode '$MODE' unknown." + exit 1 +fi + +NUM=$(who | wc -l) +[ "$NUM" = "0" ] && $MODE # Easy way out - machine is idle + +# Someone logged in +for MINUTES in 5 X X X X X X X 3 X X X 2 X X X 1 X X X; do + NUM=$(who | wc -l) + [ "$NUM" = "0" ] && break + if [ "$MINUTES" != "X" ]; then + USERS=0 + if [ "$MODE" = "reboot" ]; then + MESSAGE="Das System wird in $MINUTES Minute(n) neugestartet, bitte beenden Sie Ihre Sitzung. +The system will reboot in $MINUTES minute(s). Please save your work and end the session." + else + MESSAGE="Dieser Rechner wird in $MINUTES Minute(n) abgeschaltet, bitte beenden Sie Ihre Sitzung. +The system will power off in $MINUTES minute(s). Please save your work and end the session." + fi + for d in $(who | awk '{print $2}' | sort -u); do + if [ "${d:0:1}" = ":" ]; then + # X11 + export DISPLAY=$d + export XAUTHORITY=$(ps a | grep " $DISPLAY " | grep -o -- '-auth.*$' | grep -m1 -v grep | awk '{print $2}') + # TODO: Don't look... We need to pick a proper util for this + /opt/openslx/cups/printergui --error "$MESSAGE" & + unset DISPLAY XAUTHORITY + USERS=$(( $USERS + 1 )) + elif [ "${d:0:3}" = "tty" ]; then + # Regular tty + cat > "/dev/$d" <<-EOF + * + *************************** + $MESSAGE + *************************** + * + EOF + USERS=$(( $USERS + 1 )) + elif [ "${d:0:3}" = "pts" ]; then + # pts - xterm or ssh session + cat > "/dev/pts/${d:3}" <<-EOF + * + *************************** + $MESSAGE + *************************** + * + EOF + USERS=$(( $USERS + 1 )) + fi + done + FILE=$(mktemp) + who > "$FILE" + slxlog "idleaction-busy" "Postponed $MODE ($MINUTES minutes max.) - $USERS user(s) still active" + sleep 1 + rm -- "$FILE" + fi + sleep 15 +done + +$MODE + diff --git a/core/modules/idleaction/module.build b/core/modules/idleaction/module.build new file mode 100644 index 00000000..1b740aa1 --- /dev/null +++ b/core/modules/idleaction/module.build @@ -0,0 +1,16 @@ +fetch_source() { + : +} + +build() { + # We ship xprintidle's source as suse doesn't have it in one of the default repos + # and its just too tiny to do anything fancy like fetching source from somewhere + mkdir -p "$MODULE_BUILD_DIR/opt/openslx/bin" + gcc -o "$MODULE_BUILD_DIR/opt/openslx/bin/xprintidle" "$MODULE_DIR/xprintidle.c" -lX11 -lXss -lXext \ + || perror "Compilation of xprintidle failed!" +} + +post_copy() { + : +} + diff --git a/core/modules/idleaction/module.conf b/core/modules/idleaction/module.conf new file mode 100644 index 00000000..1661735b --- /dev/null +++ b/core/modules/idleaction/module.conf @@ -0,0 +1,4 @@ +REQUIRED_BINARIES=" + xprintidle +" + diff --git a/core/modules/idleaction/module.conf.centos b/core/modules/idleaction/module.conf.centos new file mode 100644 index 00000000..d368cbd8 --- /dev/null +++ b/core/modules/idleaction/module.conf.centos @@ -0,0 +1,6 @@ +REQUIRED_INSTALLED_PACKAGES=" + libX11-devel + libXScrnSaver-devel + xorg-x11-proto-devel +" + diff --git a/core/modules/idleaction/module.conf.debian b/core/modules/idleaction/module.conf.debian new file mode 100644 index 00000000..0dad2e48 --- /dev/null +++ b/core/modules/idleaction/module.conf.debian @@ -0,0 +1,6 @@ +REQUIRED_INSTALLED_PACKAGES=" + libx11-dev + libxss-dev + x11proto-scrnsaver-dev +" + diff --git a/core/modules/idleaction/module.conf.fedora b/core/modules/idleaction/module.conf.fedora new file mode 100644 index 00000000..d368cbd8 --- /dev/null +++ b/core/modules/idleaction/module.conf.fedora @@ -0,0 +1,6 @@ +REQUIRED_INSTALLED_PACKAGES=" + libX11-devel + libXScrnSaver-devel + xorg-x11-proto-devel +" + diff --git a/core/modules/idleaction/module.conf.opensuse b/core/modules/idleaction/module.conf.opensuse new file mode 100644 index 00000000..d368cbd8 --- /dev/null +++ b/core/modules/idleaction/module.conf.opensuse @@ -0,0 +1,6 @@ +REQUIRED_INSTALLED_PACKAGES=" + libX11-devel + libXScrnSaver-devel + xorg-x11-proto-devel +" + diff --git a/core/modules/idleaction/module.conf.ubuntu b/core/modules/idleaction/module.conf.ubuntu new file mode 100644 index 00000000..0dad2e48 --- /dev/null +++ b/core/modules/idleaction/module.conf.ubuntu @@ -0,0 +1,6 @@ +REQUIRED_INSTALLED_PACKAGES=" + libx11-dev + libxss-dev + x11proto-scrnsaver-dev +" + diff --git a/core/modules/idleaction/xprintidle.c b/core/modules/idleaction/xprintidle.c new file mode 100644 index 00000000..7fc62486 --- /dev/null +++ b/core/modules/idleaction/xprintidle.c @@ -0,0 +1,136 @@ +/* + +This program prints the "idle time" of the user to stdout. The "idle +time" is the number of milliseconds since input was received on any +input device. If unsuccessful, the program prints a message to stderr +and exits with a non-zero exit code. + +Copyright (c) 2005, 2008 Magnus Henoch <henoch@dtek.chalmers.se> +Copyright (c) 2006, 2007 by Danny Kukawka + <dkukawka@suse.de>, <danny.kukawka@web.de> +Copyright (c) 2008 Eivind Magnus Hvidevold <hvidevold@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License +as published by the Free Software Foundation. + +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. + +The function workaroundCreepyXServer was adapted from kpowersave-0.7.3 by +Eivind Magnus Hvidevold <hvidevold@gmail.com>. kpowersave is licensed under +the GNU GPL, version 2 _only_. + +*/ + +#include <X11/Xlib.h> +#include <X11/extensions/dpms.h> +#include <X11/extensions/scrnsaver.h> +#include <stdio.h> + +void usage(char *name); +unsigned long workaroundCreepyXServer(Display *dpy, unsigned long _idleTime ); + +int main(int argc, char *argv[]) +{ + XScreenSaverInfo ssi; + Display *dpy; + int event_basep, error_basep; + + if (argc != 1) { + usage(argv[0]); + return 1; + } + + dpy = XOpenDisplay(NULL); + if (dpy == NULL) { + fprintf(stderr, "couldn't open display\n"); + return 1; + } + + if (!XScreenSaverQueryExtension(dpy, &event_basep, &error_basep)) { + fprintf(stderr, "screen saver extension not supported\n"); + return 1; + } + + if (!XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), &ssi)) { + fprintf(stderr, "couldn't query screen saver info\n"); + return 1; + } + + printf("%lu\n", workaroundCreepyXServer(dpy, ssi.idle)); + + XCloseDisplay(dpy); + return 0; +} + +void usage(char *name) +{ + fprintf(stderr, + "Usage:\n" + "%s\n" + "That is, no command line arguments. The user's idle time\n" + "in milliseconds is printed on stdout.\n", + name); +} + +/*! + * This function works around an XServer idleTime bug in the + * XScreenSaverExtension if dpms is running. In this case the current + * dpms-state time is always subtracted from the current idletime. + * This means: XScreenSaverInfo->idle is not the time since the last + * user activity, as descriped in the header file of the extension. + * This result in SUSE bug # and sf.net bug #. The bug in the XServer itself + * is reported at https://bugs.freedesktop.org/buglist.cgi?quicksearch=6439. + * + * Workaround: Check if if XServer is in a dpms state, check the + * current timeout for this state and add this value to + * the current idle time and return. + * + * \param _idleTime a unsigned long value with the current idletime from + * XScreenSaverInfo->idle + * \return a unsigned long with the corrected idletime + */ +unsigned long workaroundCreepyXServer(Display *dpy, unsigned long _idleTime ){ + int dummy; + CARD16 standby, suspend, off; + CARD16 state; + BOOL onoff; + + if (DPMSQueryExtension(dpy, &dummy, &dummy)) { + if (DPMSCapable(dpy)) { + DPMSGetTimeouts(dpy, &standby, &suspend, &off); + DPMSInfo(dpy, &state, &onoff); + + if (onoff) { + switch (state) { + case DPMSModeStandby: + /* this check is a littlebit paranoid, but be sure */ + if (_idleTime < (unsigned) (standby * 1000)) + _idleTime += (standby * 1000); + break; + case DPMSModeSuspend: + if (_idleTime < (unsigned) ((suspend + standby) * 1000)) + _idleTime += ((suspend + standby) * 1000); + break; + case DPMSModeOff: + if (_idleTime < (unsigned) ((off + suspend + standby) * 1000)) + _idleTime += ((off + suspend + standby) * 1000); + break; + case DPMSModeOn: + default: + break; + } + } + } + } + + return _idleTime; +} |