From: skeezix Date: Tue, 16 Feb 2010 17:51:57 +0000 (-0500) Subject: Added a lame but working dbus watch ability.. X-Git-Tag: Release-2010-05/1~115^2 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=commitdiff_plain;h=51f7f6de18d222ac36d8e6f8f01b5a1c0203e85f Added a lame but working dbus watch ability.. -- 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 --- diff --git a/Makefile b/Makefile index beac4d7..887fa3f 100644 --- 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 diff --git a/apps/pndnotifyd.c b/apps/pndnotifyd.c index 13bfa93..b9b350e 100644 --- a/apps/pndnotifyd.c +++ b/apps/pndnotifyd.c @@ -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.. diff --git a/deployment/etc/pandora/conf/apps b/deployment/etc/pandora/conf/apps index 1444505..a93080d 100644 --- a/deployment/etc/pandora/conf/apps +++ b/deployment/etc/pandora/conf/apps @@ -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 index 0000000..00f8581 --- /dev/null +++ b/include/pnd_dbusnotify.h @@ -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 index 0000000..dfa200c --- /dev/null +++ b/lib/pnd_dbusnotify.c @@ -0,0 +1,140 @@ + +#include // for stdio, NULL +#include // for malloc, etc +#include // for close +#include // for time() +#include // for kill +#include // for kill signal +#include // for bzero +#include // 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 index 0000000..0c253a4 --- /dev/null +++ b/test/dbusnotifytest.c @@ -0,0 +1,32 @@ + +#include // for stdio +#include // for exit() +#include // for exit() +#include // 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 ); +}