Comment 11 for bug 306584

Revision history for this message
Alex S (alex-shillington) wrote :

First, thanks to the timekpr team - this is extremely useful. Here is my solution to the 'screen locked/user switched time keeps counting' problem - I hope this will help out someone else. I found the code for an executable named idle at http://coderrr.wordpress.com/2008/04/20/getting-idle-time-in-unix/ - I modified it somewhat to just return the number of seconds of idle time for that display. Here's the C code:

#include <X11/extensions/scrnsaver.h>
#include <stdio.h>

main() {
  XScreenSaverInfo *info = XScreenSaverAllocInfo();
  Display *display = XOpenDisplay(NULL);

  if (display != NULL) {
    XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
    printf("%lu", info->idle/1000);
  } else {
    puts ("error");
  }
}

I compiled that with the command "gcc -o idle idle.c -lXss" and put the resulting binary in /usr/local/sbin/idle. You call that by first exporting the display that you want to query idle time for as $DISPLAY, then you run idle. For example, say that you have users logged in to displays :5 and :6, then you can run the following commands (as root):

export DISPLAY=:5.0;/usr/local/sbin/idle
and
export DISPLAY=:6.0;/usr/local/sbin/idle

to find the number of seconds that those users have been idle (no keyboard/mouse activity.) For timekpr, what we really need to find are the users that are active (the normal users command returns all users that are logged in, active or not.) For this, I wrote a shell script and put that in /usr/local/sbin/active_users.sh - here's the code for that:

#!/bin/bash

if [ "$(id -u)" != "0" ]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

for i in `w | grep tty | awk '{print $2 $3 ":" $1}' | sed 's/^tty[0-9]*\://g'`; do
    display=`echo $i | awk -F ':' '{print $1}'`
    display=:${display}.0
    user=`echo $i | awk -F ':' '{print $2}'`
    idletime=`export DISPLAY=$display;/usr/local/sbin/idle`
    case "$1" in
        debug)
      echo "$user is on display $display with idletime $idletime"
         ;;
        *)
            if [ $idletime -lt 10 ]; then
      echo -n "$user "
            fi
         ;;
     esac
done
echo

As root, when you run /usr/local/sbin/active_users.sh, you will get only a listing of users that are currently active (in a gnome session only - this doesn't help you are trying to limit time for ssh users...)

Almost done!!!

Now, we have to edit /usr/share/python-support/timekpr/timekpr.py to use /usr/local/sbin/active_users.sh instead of the built in users command. Simply change the line that reads:

u = getcmdoutput('users')
to
u = getcmdoutput('/usr/local/sbin/active_users.sh')

(it's in the getusers function.) Now, just restart the timekpr daemon (/etc/init.d/timekpr restart) and it is ready to go.

I admit, this is a huge hack, but it works for my use case and hopefully can be easily adapted to work for you. There are some problems with this approach - for example, if a time limited user is watching a movie via an app that won't lock the screen, then that user will get extra time. In my case, though, it's all interactive activity so I don't have that problem.

I hope this is useful, and hope even more so that someone improves upon it. Thanks!