Added a lame but working dbus watch ability..
authorskeezix <skeezix@flotsam-vm.(none)>
Tue, 16 Feb 2010 17:51:57 +0000 (12:51 -0500)
committerskeezix <skeezix@flotsam-vm.(none)>
Tue, 16 Feb 2010 17:51:57 +0000 (12:51 -0500)
-- dbus can watch insert/eject
-- inotify can watch file moves
-- etc/pandora/conf/apps notify list removed /media (was catching the OS, since fw mounted to /media/mmcblk0p1 when boot off SD!)
-- dbusnotifytest seems to work on desktop and panda
Working much better, catches every insert/eject just fine, without spamming

Makefile
apps/pndnotifyd.c
deployment/etc/pandora/conf/apps
include/pnd_dbusnotify.h [new file with mode: 0644]
lib/pnd_dbusnotify.c [new file with mode: 0644]
test/dbusnotifytest.c [new file with mode: 0644]

index beac4d7..887fa3f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,12 +21,12 @@ LIB = libpnd.a
 SOLIB = libpnd.so.1         # canonicle name
 SOLIB1 = libpnd.so.1.0.1    # versioned name
 XMLOBJ = lib/tinyxml/tinystr.o lib/tinyxml/tinyxml.o lib/tinyxml/tinyxmlerror.o lib/tinyxml/tinyxmlparser.o
-ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o
+ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o pnd_dbusnotify.o
 
-all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest pnd_run pndevmapperd pnd_info
+all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest dbusnotifytest pnd_run pndevmapperd pnd_info
 
 clean:
-       ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/*
+       ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest dbusnotifytest.o bin/dbusnotifytest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/*
        ${RM} -rf deployment/media
        find . -name "*~*" -exec rm {} \; -print
 
@@ -113,3 +113,6 @@ rawpxmltest:    rawpxmltest.o ${LIB}
 
 loggertest:    loggertest.o ${LIB}
        ${CC} -lstdc++ -o bin/loggertest loggertest.o libpnd.a
+
+dbusnotifytest:        dbusnotifytest.o ${LIB}
+       ${CC} -lstdc++ -o bin/dbusnotifytest dbusnotifytest.o libpnd.a
index 13bfa93..b9b350e 100644 (file)
@@ -27,6 +27,7 @@
 #include "pnd_utility.h"
 #include "pnd_desktop.h"
 #include "pnd_logger.h"
+#include "pnd_dbusnotify.h"
 
 // this piece of code was simpler once; but need to grow it a bit and in a rush
 // moving all these to globals rather than refactor the code a bit; tsk tsk..
@@ -65,6 +66,7 @@ char *pndhup = NULL;  // full path to located pnd_hup.sh
 char g_username [ 128 ]; // since we have to wait for login (!!), store username here
 // notifier handle
 pnd_notify_handle nh = 0;
+pnd_dbusnotify_handle dbh = 0;
 
 // constants
 #define PNDNOTIFYD_LOGLEVEL "pndnotifyd.loglevel"
@@ -72,6 +74,7 @@ pnd_notify_handle nh = 0;
 // decl's
 void consume_configuration ( void );
 void setup_notifications ( void );
+void sigint_handler ( int n );
 void sighup_handler ( int n );
 void process_discoveries ( pnd_box_handle applist, char *emitdesktoppath, char *emiticonpath );
 unsigned char perform_discoveries ( char *appspath, char *overridespath,
@@ -239,6 +242,9 @@ int main ( int argc, char *argv[] ) {
 
   sigaction ( SIGHUP, &siggy, NULL );
 
+  siggy.sa_handler = sigint_handler;
+  sigaction ( SIGINT, &siggy, NULL );
+
   /* set up notifies
    */
 
@@ -248,46 +254,72 @@ int main ( int argc, char *argv[] ) {
   setup_notifications();
   //}
 
+  dbh = pnd_dbusnotify_init();
+
   /* daemon main loop
    */
+  unsigned char watch_inotify, watch_dbus;
   while ( 1 ) {
 
+    watch_dbus = 0;
+    watch_inotify = 0;
+
+    if ( dbh ) {
+      watch_dbus = pnd_dbusnotify_rediscover_p ( dbh );
+    }
+
+    if ( ! watch_dbus && nh ) {
+      watch_inotify = pnd_notify_rediscover_p ( nh );
+    }
+
     // need to rediscover?
-    if ( scanonlaunch ||
-        pnd_notify_rediscover_p ( nh ) )
-    {
+    if ( scanonlaunch || watch_inotify || watch_dbus ) {
 
-      if ( time ( NULL ) - createtime <= 2 ) {
-       pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
-       sleep ( interval_secs );
-       continue;
-      }
+      // by this point, the watched directories have notified us that something of relevent
+      // has occurred; we should be clever, but we're not, so just re-brute force the
+      // discovery and spit out .desktop files..
+      pnd_log ( pndn_rem, "------------------------------------------------------\n" );
 
-      createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
+      pnd_log ( pndn_rem, "System changes detected in dbus or watched paths .. performing re-discover!\n" );
 
       // if this was a forced scan, lets not do that next iteration
       if ( scanonlaunch ) {
+       pnd_log ( pndn_rem, "scan-on-first-launch detected an event\n" );
        scanonlaunch = 0;
       }
 
-      // by this point, the watched directories have notified us that something of relevent
-      // has occurred; we should be clever, but we're not, so just re-brute force the
-      // discovery and spit out .desktop files..
+      if ( watch_inotify ) {
+       pnd_log ( pndn_rem, "inotify detected an event\n" );
+      }
+
+      if ( watch_dbus ) {
+       pnd_log ( pndn_rem, "dbusnotify detected an event\n" );
+       pnd_notify_shutdown ( nh );
+       nh = 0;
+      }
+
+      if ( time ( NULL ) - createtime <= 2 ) {
+       pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
+       sleep ( interval_secs );
+       continue;
+      }
+
       pnd_log ( pndn_rem, "------------------------------------------------------\n" );
-      pnd_log ( pndn_rem, "Changes within watched paths .. performing re-discover!\n" );
+
+      createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
 
       /* run the discovery
        */
 
-      pnd_log ( pndn_rem, "Scanning desktop paths----------------------------\n" );
+      pnd_log ( pndn_rem, "  Scanning desktop paths----------------------------\n" );
       if ( ! perform_discoveries ( desktop_appspath, overridespath, desktop_dotdesktoppath, desktop_iconpath ) ) {
-       pnd_log ( pndn_rem, "No applications found in desktop search path\n" );
+       pnd_log ( pndn_rem, "    No applications found in desktop search path\n" );
       }
 
       if ( menu_appspath && menu_dotdesktoppath && menu_iconpath ) {
-       pnd_log ( pndn_rem, "Scanning menu paths----------------------------\n" );
+       pnd_log ( pndn_rem, "  Scanning menu paths----------------------------\n" );
        if ( ! perform_discoveries ( menu_appspath, overridespath, menu_dotdesktoppath, menu_iconpath ) ) {
-         pnd_log ( pndn_rem, "No applications found in menu search path\n" );
+         pnd_log ( pndn_rem, "    No applications found in menu search path\n" );
        }
       }
 
@@ -300,7 +332,9 @@ int main ( int argc, char *argv[] ) {
       // since its entirely likely new directories have been found (ie: SD with a directory structure was inserted)
       // we should re-apply watches to catch all these new directories; ie: user might use on-device browser to
       // drop in new applications, or use the shell to juggle them around, or any number of activities.
-      //setup_notifications();
+      if ( watch_dbus ) {
+       setup_notifications();
+      }
 
     } // need to rediscover?
 
@@ -318,6 +352,7 @@ int main ( int argc, char *argv[] ) {
   /* shutdown
    */
   pnd_notify_shutdown ( nh );
+  pnd_dbusnotify_shutdown ( dbh );
 
   return ( 0 );
 }
@@ -598,6 +633,21 @@ void sighup_handler ( int n ) {
   return;
 }
 
+void sigint_handler ( int n ) {
+
+  pnd_log ( pndn_rem, "---[ SIGINT received ]---\n" );
+
+  if ( dbh ) {
+    pnd_dbusnotify_shutdown ( dbh );
+  }
+
+  if ( nh ) {
+    pnd_notify_shutdown ( nh );
+  }
+
+  return;
+}
+
 // This very recently was inline code; just slight refactor to functionize it so that it can be
 // reused in a couple of places. Simple code with simple design quickly became too large for
 // its simple design; should revisit a lot of these little things..
index 1444505..a93080d 100644 (file)
@@ -7,7 +7,7 @@
 searchpath     /media/*/pandora/apps:/media/*/pandora/desktop:/media/*/pandora/menu:/usr/pandora/apps
 # notifypath is a list of paths to monitor; if anything in those paths changes, the searchpath is rescanned
 # note that for each path chunk, all current subdirs of that path are also watched)
-notifypath     /media:/media/*/pandora/apps:/media/*/pandora/desktop:/media/*/pandora/menu:/usr/pandora/apps
+notifypath     /media/*/pandora/apps:/media/*/pandora/desktop:/media/*/pandora/menu:/usr/pandora/apps
 
 # PXMLs may be overridden .. ie: overrides are a subset of PXML, where the values are copied over the full PXML
 [overrides]
diff --git a/include/pnd_dbusnotify.h b/include/pnd_dbusnotify.h
new file mode 100644 (file)
index 0000000..00f8581
--- /dev/null
@@ -0,0 +1,39 @@
+
+#ifndef h_dbusnotify_h
+#define h_dbusnotify_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* pnd_dbusnotify_handle;
+
+/* An option is to use dbus for a lot of things, or even specific things such as
+ * watching for media to be inserted or ejected; one could supplement such info
+ * with inotify for file-moves.
+ * Really, we need a serious model for watching and receiving system state changes
+ * but I started simple, so going to try to keep it simple. For now.
+ */
+
+/* must invoke this to obtain a handle; other notify functions require it of course.
+ * Returns NULL on failure.
+ */
+pnd_dbusnotify_handle pnd_dbusnotify_init ( void );
+
+/* shutdown..
+ */
+void pnd_dbusnotify_shutdown ( pnd_dbusnotify_handle h );
+
+/* HACK HACK HACK
+ * I'd like to have a real dbus-listener here using libdbus/whatever, but for now
+ * I'm going to implement a lame little hack to use dbus-monitor, as time is tight!
+ * HACK HACK HACK
+ *
+ */
+unsigned char pnd_dbusnotify_rediscover_p ( pnd_dbusnotify_handle h );
+
+#ifdef __cplusplus
+} /* "C" */
+#endif
+
+#endif
diff --git a/lib/pnd_dbusnotify.c b/lib/pnd_dbusnotify.c
new file mode 100644 (file)
index 0000000..dfa200c
--- /dev/null
@@ -0,0 +1,140 @@
+
+#include <stdio.h>          // for stdio, NULL
+#include <stdlib.h>         // for malloc, etc
+#include <unistd.h>         // for close
+#include <time.h>           // for time()
+#include <sys/types.h>      // for kill
+#include <signal.h>         // for kill signal
+#include <string.h>         // for bzero
+#include <poll.h>           // for poll()
+
+#include "pnd_dbusnotify.h"
+#include "pnd_logger.h"
+
+/* HACK HACK HACK
+ * Not yet doing a real libdbus implementation.
+ * First cut is using dbus-monitor; I'll work on a real dbus listener soon.
+ * HACK HACK HACK
+ */
+
+typedef struct {
+  pid_t child_pid;         // pid for dbus-monitor
+  int fd [ 2 ];            // pipe fd pair
+} pnd_dbusnotify_t;
+
+#define MONITOR "/usr/bin/dbus-monitor"
+#define MONARG1 "--system"
+#define MONARG2 "interface=org.freedesktop.Hal.Device"
+#define MONGREP "volume.is_mounted"
+
+pnd_dbusnotify_handle pnd_dbusnotify_init ( void ) {
+  pnd_dbusnotify_t *p;
+
+  // get thee a handle
+  // and I will brandish it for Zo Kath Ra
+
+  p = malloc ( sizeof(pnd_dbusnotify_t) );
+
+  if ( ! p ) {
+    return ( NULL ); // uhh..
+  }
+
+  bzero ( p, sizeof(pnd_dbusnotify_t) );
+
+  // can we make a pipe?
+  if ( pipe ( p -> fd ) == -1 ) {
+    free ( p );
+    return ( NULL );
+  }
+
+  // spawn child process
+  p -> child_pid = fork();
+
+  if ( p -> child_pid == -1 ) {
+    free ( p );
+    return ( NULL ); // borked
+
+  } else if ( p -> child_pid == 0 ) {
+    // child
+
+    close ( p -> fd [ 0 ] ); // ditch stdin on child
+    dup2 ( p -> fd [ 1 ], 1 ); // assign write-end of pipe to stdout
+    close ( p -> fd [ 1 ] ); // we don't need this anymore anyway
+    execlp ( MONITOR, MONITOR, MONARG1, MONARG2, NULL );
+
+    exit ( 1 ); // damnit
+
+  } else {
+    // parent
+
+    close ( p -> fd [ 1 ] ); // ditch write end, we're a grepper
+
+  } // child or parent?
+
+  return ( p );
+}
+
+void pnd_dbusnotify_shutdown ( pnd_dbusnotify_handle h ) {
+  pnd_dbusnotify_t *p = (pnd_dbusnotify_t*) h;
+
+  // free up
+  close ( p -> fd [ 0 ] ); // kill reader end of pipe
+
+  // destroy child process
+  kill ( p -> child_pid, SIGKILL );
+
+  free ( p );
+
+  return;
+}
+
+unsigned char pnd_dbusnotify_rediscover_p ( pnd_dbusnotify_handle h ) {
+  pnd_dbusnotify_t *p = (pnd_dbusnotify_t*) h;
+  int r;
+  struct pollfd fds [ 1 ];
+
+  fds [ 0 ].fd = p -> fd [ 0 ]; // read side of pipe
+  fds [ 0 ].events = POLLIN | POLLPRI /* | POLLRDHUP */;
+  fds [ 0 ].revents = 0;
+
+  r = poll ( fds, 1, 0 /* timeout*/ );
+
+  if ( r < 0 ) {
+    // error
+    // should rebuild a new child process
+    return ( 0 );
+
+  } else if ( r == 0 ) {
+    // no input on the pipe
+    return ( 0 );
+
+  } // activity
+
+  // something on the pipe, lets check it
+
+  if ( fds [ 0 ].revents & ( POLLERR|POLLHUP/*|POLLRDHUP*/ ) ) {
+    // bad
+    // should rebuild a new child process
+    return ( 0 );
+  }
+
+  // something useful on the pipe
+  char buf [ 4096 ];
+  int readcount;
+
+  readcount = read ( fds [ 0 ].fd, buf, 4000 );
+
+  if ( readcount < 0 ) {
+    // error
+    return ( 0 );
+  }
+
+  // terminate the string
+  *( buf + readcount + 1 ) = '\0';
+
+  if ( strstr ( buf, MONGREP ) != NULL ) {
+    return ( 1 );
+  }
+
+  return ( 0 );
+}
diff --git a/test/dbusnotifytest.c b/test/dbusnotifytest.c
new file mode 100644 (file)
index 0000000..0c253a4
--- /dev/null
@@ -0,0 +1,32 @@
+
+#include <stdio.h> // for stdio
+#include <unistd.h> // for exit()
+#include <stdlib.h> // for exit()
+#include <time.h> // for time
+
+#include "pnd_conf.h"
+#include "pnd_dbusnotify.h"
+
+int main ( int argc, char *argv[] ) {
+  pnd_dbusnotify_handle h;
+
+  h = pnd_dbusnotify_init();
+
+  time_t start = time ( NULL );
+
+  while ( time ( NULL ) - start < 20 ) {
+    printf ( "Tick %u\n", (unsigned int) ( time ( NULL ) - start ) );
+
+    if ( pnd_dbusnotify_rediscover_p ( h ) ) {
+      printf ( "Event!\n" );
+    }
+
+    fflush ( stdout );
+    sleep ( 1 );
+
+  } // while
+
+  pnd_dbusnotify_shutdown ( h );
+
+  return ( 0 );
+}