The work around was to install xscreensaver, which authenticates using a PAM module when the screen is locked. However, the 'hook' which tells the system to 'lock' after a determined idle time is disabled to prevent gnome from locking out the user.
So, I created my own C application which runs in the background and monitors for user mouse movement or keystrokes. There are 4 threads:
- Timer Thread (Track user idle time, locks screen if threshold is reached.)
- Screen Watch Thread (Start timer if screen is ever Unlocked)
- Mouse Thread (Restart timer if mouse is moved)
- Keyboard Thread (Restart timer if keystroke is made)
I used several sources and although this is not the most elegant solution it does work. I would appreciate any feed back, as this is the first C application I have ever written, except for "Hello world."
#include
#include
#include
#include
#include
#include
typedef struct Timer
{
double elapsed;
struct timespec start,finish;
}Timer;
//Predefine global vars.
double timeLimit = 300.0; //seconds
int verboseClock = 0; //1-True,0-False
int verboseMouse = 0; //1-True,0-False
int verboseKeyboard = 0; //1-True,0-False
//do not modify these
volatile int movement = 0;
volatile int screenlocked = 0;
pthread_t threads[4];
int rc_one;
int rc_two;
int rc_three;
int rc_four;
void *MouseWatch(void *threadid) {
//This threa will watch the mouse and ensure the timer is reset if event fired.
FILE *fp;
char buffer[3];
/* Open the command for reading from xinput. */
fp = popen("xinput --test 9", "r");
if (fp == NULL) {
printf("Failed to watch mouse\n");
exit;
}
printf("Watching Mouse...\n");
/* Read the output a line at a time - output it. */
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
if(verboseMouse) {
printf("%c", buffer[0]);
}
if(buffer[0]=='m') {
//motion detected.
movement = 1;
}
}
pclose(fp);
}
void *LockTimer(void *threadid) {
//This thread acts as a timer until Locked, provided mousemove==0 the whole time.
Timer stopwatch;
//start timer.
clock_gettime(CLOCK_MONOTONIC, &stopwatch.start);
//while time < timeLimit seconds.
while(stopwatch.elapsed < timeLimit ) {
if(movement == 1) {
movement = 0;
//mouse moved, restart the clock
clock_gettime(CLOCK_MONOTONIC, &stopwatch.start);
}
//get elapsed time. if clock has exceeded threshold, lock screen.
sleep(1);
clock_gettime(CLOCK_MONOTONIC, &stopwatch.finish);
stopwatch.elapsed = (stopwatch.finish.tv_sec - stopwatch.start.tv_sec);
stopwatch.elapsed += (stopwatch.finish.tv_nsec - stopwatch.start.tv_nsec) / 1000000000.0;
if(verboseClock) {
printf("elapsed time: %f\n",stopwatch.elapsed);
}
if(screenlocked) { break; }
}
system("xscreensaver-command -lock");
screenlocked = 1;
while(screenlocked) {
sleep(2);
}
printf("restarting the timer\n");
rc_two = pthread_create(&threads[2], NULL, LockTimer, (void *)2);
if(rc_two) {
printf("ERROR; return code from pthread_create() is %d\n", rc_two);
exit(-1);
}
pthread_exit(NULL);
}
void *KeyboardWatch(void *threadid) {
//This threa will watch the keyboard and ensure the timer is reset if key is pressed.
FILE *fp;
char buffer[3];
/* Open the command for reading from xinput. */
fp = popen("xinput --test 10", "r");
if (fp == NULL) {
printf("Failed to watch keyboard\n");
exit;
}
printf("Watching Keyboard...\n");
/* Read the output a line at a time - output it. */
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
if(verboseKeyboard) { printf("%s", buffer); }
if(buffer[0]=='k') {
//key press detected.
movement = 1;
}
}
pclose(fp);
}
void *ScreenWatch(void *threadid) {
//This thread will watch the screen and ensure timer is started when screen is 'U'nlocked.
FILE *fp;
char buffer[50];
/* Open the command for reading. */
fp = popen("xscreensaver-command -watch", "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit;
}
printf("Watching Screen...\n");
/* Read the output a line at a time - output it. */
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
printf("%s", buffer);
if(buffer[0]=='U') {
screenlocked=0;
}
if(buffer[0]=='L') {
screenlocked=1;
}
}
}
int main()
{
printf("In main: creating threads. \n");
//start mouse watch thread
rc_one = pthread_create(&threads[1], NULL, MouseWatch, (void *)1);
if(rc_one) {
printf("ERROR; return code from mouse thread is %d\n", rc_one);
exit(-1);
}
//start timer thread
rc_two = pthread_create(&threads[2], NULL, LockTimer, (void *)2);
if(rc_two) {
printf("ERROR; return code from timer thread is %d\n", rc_two);
exit(-1);
}
//start Screen watch thread
rc_three = pthread_create(&threads[3], NULL, ScreenWatch, (void *)3);
if(rc_three) {
printf("ERROR; return code from screen watch thread is %d\n", rc_one);
exit(-1);
}
//start keyboard watch thread
rc_four = pthread_create(&threads[4], NULL, KeyboardWatch, (void *)4);
if(rc_four) {
printf("ERROR; return code from keyboard thread is %d\n", rc_four);
exit(-1);
}
//LOOP Forever until user Kills main thread. (Ctrl+C)
while(1) {
sleep(10);
}
}
#include
#include
#include
#include
#include
#include
typedef struct Timer
{
double elapsed;
struct timespec start,finish;
}Timer;
//Predefine global vars.
double timeLimit = 300.0; //seconds
int verboseClock = 0; //1-True,0-False
int verboseMouse = 0; //1-True,0-False
int verboseKeyboard = 0; //1-True,0-False
//do not modify these
volatile int movement = 0;
volatile int screenlocked = 0;
pthread_t threads[4];
int rc_one;
int rc_two;
int rc_three;
int rc_four;
void *MouseWatch(void *threadid) {
//This threa will watch the mouse and ensure the timer is reset if event fired.
FILE *fp;
char buffer[3];
/* Open the command for reading from xinput. */
fp = popen("xinput --test 9", "r");
if (fp == NULL) {
printf("Failed to watch mouse\n");
exit;
}
printf("Watching Mouse...\n");
/* Read the output a line at a time - output it. */
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
if(verboseMouse) {
printf("%c", buffer[0]);
}
if(buffer[0]=='m') {
//motion detected.
movement = 1;
}
}
pclose(fp);
}
void *LockTimer(void *threadid) {
//This thread acts as a timer until Locked, provided mousemove==0 the whole time.
Timer stopwatch;
//start timer.
clock_gettime(CLOCK_MONOTONIC, &stopwatch.start);
//while time < timeLimit seconds.
while(stopwatch.elapsed < timeLimit ) {
if(movement == 1) {
movement = 0;
//mouse moved, restart the clock
clock_gettime(CLOCK_MONOTONIC, &stopwatch.start);
}
//get elapsed time. if clock has exceeded threshold, lock screen.
sleep(1);
clock_gettime(CLOCK_MONOTONIC, &stopwatch.finish);
stopwatch.elapsed = (stopwatch.finish.tv_sec - stopwatch.start.tv_sec);
stopwatch.elapsed += (stopwatch.finish.tv_nsec - stopwatch.start.tv_nsec) / 1000000000.0;
if(verboseClock) {
printf("elapsed time: %f\n",stopwatch.elapsed);
}
if(screenlocked) { break; }
}
system("xscreensaver-command -lock");
screenlocked = 1;
while(screenlocked) {
sleep(2);
}
printf("restarting the timer\n");
rc_two = pthread_create(&threads[2], NULL, LockTimer, (void *)2);
if(rc_two) {
printf("ERROR; return code from pthread_create() is %d\n", rc_two);
exit(-1);
}
pthread_exit(NULL);
}
void *KeyboardWatch(void *threadid) {
//This threa will watch the keyboard and ensure the timer is reset if key is pressed.
FILE *fp;
char buffer[3];
/* Open the command for reading from xinput. */
fp = popen("xinput --test 10", "r");
if (fp == NULL) {
printf("Failed to watch keyboard\n");
exit;
}
printf("Watching Keyboard...\n");
/* Read the output a line at a time - output it. */
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
if(verboseKeyboard) { printf("%s", buffer); }
if(buffer[0]=='k') {
//key press detected.
movement = 1;
}
}
pclose(fp);
}
void *ScreenWatch(void *threadid) {
//This thread will watch the screen and ensure timer is started when screen is 'U'nlocked.
FILE *fp;
char buffer[50];
/* Open the command for reading. */
fp = popen("xscreensaver-command -watch", "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit;
}
printf("Watching Screen...\n");
/* Read the output a line at a time - output it. */
while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
printf("%s", buffer);
if(buffer[0]=='U') {
screenlocked=0;
}
if(buffer[0]=='L') {
screenlocked=1;
}
}
}
int main()
{
printf("In main: creating threads. \n");
//start mouse watch thread
rc_one = pthread_create(&threads[1], NULL, MouseWatch, (void *)1);
if(rc_one) {
printf("ERROR; return code from mouse thread is %d\n", rc_one);
exit(-1);
}
//start timer thread
rc_two = pthread_create(&threads[2], NULL, LockTimer, (void *)2);
if(rc_two) {
printf("ERROR; return code from timer thread is %d\n", rc_two);
exit(-1);
}
//start Screen watch thread
rc_three = pthread_create(&threads[3], NULL, ScreenWatch, (void *)3);
if(rc_three) {
printf("ERROR; return code from screen watch thread is %d\n", rc_one);
exit(-1);
}
//start keyboard watch thread
rc_four = pthread_create(&threads[4], NULL, KeyboardWatch, (void *)4);
if(rc_four) {
printf("ERROR; return code from keyboard thread is %d\n", rc_four);
exit(-1);
}
//LOOP Forever until user Kills main thread. (Ctrl+C)
while(1) {
sleep(10);
}
}