summaryrefslogtreecommitdiffstats
path: root/core/modules/idleaction
diff options
context:
space:
mode:
authorSebastian2016-04-25 12:01:08 +0200
committerSebastian2016-04-25 12:01:08 +0200
commit5acda3eaeabae9045609539303a8c12c4ce401f1 (patch)
tree7e71975f8570b05aafe2ea6ec0e242a8912387bb /core/modules/idleaction
parentinitial commit (diff)
downloadmltk-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-idleaction7
-rwxr-xr-xcore/modules/idleaction/data/opt/openslx/scripts/idleaction-cron_script138
-rwxr-xr-xcore/modules/idleaction/data/opt/openslx/scripts/idleaction-scheduled_action77
-rw-r--r--core/modules/idleaction/module.build16
-rw-r--r--core/modules/idleaction/module.conf4
-rw-r--r--core/modules/idleaction/module.conf.centos6
-rw-r--r--core/modules/idleaction/module.conf.debian6
-rw-r--r--core/modules/idleaction/module.conf.fedora6
-rw-r--r--core/modules/idleaction/module.conf.opensuse6
-rw-r--r--core/modules/idleaction/module.conf.ubuntu6
-rw-r--r--core/modules/idleaction/xprintidle.c136
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;
+}