Skip to content

Commit

Permalink
Added a lame but working dbus watch ability..
Browse files Browse the repository at this point in the history
-- 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
  • Loading branch information
skeezix committed Feb 16, 2010
1 parent 28238a8 commit 51f7f6d
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 22 deletions.
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
86 changes: 68 additions & 18 deletions apps/pndnotifyd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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..
Expand Down Expand Up @@ -65,13 +66,15 @@ 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"

// 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,
Expand Down Expand Up @@ -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
*/

Expand All @@ -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" );
}
}

Expand All @@ -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?

Expand All @@ -318,6 +352,7 @@ int main ( int argc, char *argv[] ) {
/* shutdown
*/
pnd_notify_shutdown ( nh );
pnd_dbusnotify_shutdown ( dbh );

return ( 0 );
}
Expand Down Expand Up @@ -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..
Expand Down
2 changes: 1 addition & 1 deletion deployment/etc/pandora/conf/apps
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
39 changes: 39 additions & 0 deletions include/pnd_dbusnotify.h
Original file line number Diff line number Diff line change
@@ -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
140 changes: 140 additions & 0 deletions lib/pnd_dbusnotify.c
Original file line number Diff line number Diff line change
@@ -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 );
}
Loading

0 comments on commit 51f7f6d

Please sign in to comment.