#include <sys/stat.h> // for umask
#include <dirent.h> // for opendir()
#include <signal.h> // for sigaction
+#include <errno.h> // for errno
#include "pnd_conf.h"
#include "pnd_container.h"
#include "pnd_utility.h"
#include "pnd_desktop.h"
#include "pnd_logger.h"
+#include "pnd_dbusnotify.h"
+#include "pnd_pndfiles.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..
char *menu_dotdesktoppath = NULL;
char *menu_iconpath = NULL;
char *menu_appspath = NULL;
+char *info_dotdesktoppath = NULL;
// pnd runscript
char *run_searchpath; // searchpath to find pnd_run.sh
char *run_script; // name of pnd_run.sh script from config
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;
+unsigned char g_info_p = 0; // spit out info .desktops
// constants
#define PNDNOTIFYD_LOGLEVEL "pndnotifyd.loglevel"
+#define PNDLOCKNAME "pndnotifyd-disco.lock"
// 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,
}
} else {
- printf ( "%s [-d] [##]\n", argv [ 0 ] );
+ printf ( "%s [-d] [-l] [##]\n", argv [ 0 ] );
printf ( "-d\tDaemon mode; detach from terminal, chdir to /tmp, suppress output. Optional.\n" );
printf ( "-n\tDo not scan on launch; default is to run a scan for apps when %s is invoked.\n", argv [ 0 ] );
printf ( "-l#\tLog-it; -l is 0-and-up (or all), and -l2 means 2-and-up (not all); l[0-3] for now. Log goes to /tmp/pndnotifyd.log\n" );
// umask
umask ( 022 ); // emitted files can be rwxr-xr-x
-
+
} // set up daemon
// wait for a user to be logged in - we should probably get hupped when a user logs in, so we can handle
pnd_log ( pndn_rem, "Apps searchpath is '%s'\n", menu_appspath );
pnd_log ( pndn_rem, ".desktop files emit to '%s'\n", menu_dotdesktoppath );
pnd_log ( pndn_rem, ".desktop icon files emit to '%s'\n", menu_iconpath );
+ pnd_log ( pndn_rem, ".desktop info files emit to '%s'\n", info_dotdesktoppath ? info_dotdesktoppath : "n/a" );
/* set up signal handler
*/
sigaction ( SIGHUP, &siggy, NULL );
+ siggy.sa_handler = sigint_handler;
+ sigaction ( SIGINT, &siggy, NULL );
+
/* set up notifies
*/
setup_notifications();
//}
+ dbh = pnd_dbusnotify_init();
+
/* daemon main loop
*/
+ unsigned char watch_inotify = 0, watch_dbus = 0;
+ unsigned char idle = 0;
while ( 1 ) {
+ int retcode;
+
+ // collect all events to avoid multiple PND rescans
+ do {
+ struct timeval timeout_1s = { 1, 0};
+ int fd_inotify = -1, fd_dbus = -1;
+ struct timeval *timeout = NULL;
+ fd_set rfds, efds;
+ int fd_max = -1;
+
+ if ( dbh )
+ fd_dbus = pnd_dbusnotify_fd ( dbh );
+ if ( nh )
+ fd_inotify = pnd_notify_fd ( nh );
+
+ FD_ZERO ( &rfds );
+ FD_ZERO ( &efds );
+
+ if ( fd_dbus != -1 ) {
+ FD_SET ( fd_dbus, &rfds );
+ FD_SET ( fd_dbus, &efds );
+ if ( fd_dbus > fd_max )
+ fd_max = fd_dbus;
+ }
- // need to rediscover?
- if ( scanonlaunch ||
- pnd_notify_rediscover_p ( nh ) )
- {
+ if ( fd_inotify != -1 ) {
+ FD_SET ( fd_inotify, &rfds );
+ FD_SET ( fd_inotify, &efds );
+ if ( fd_inotify > fd_max )
+ fd_max = fd_inotify;
+ }
- if ( time ( NULL ) - createtime <= 2 ) {
- pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
- sleep ( interval_secs );
- continue;
+ if ( fd_max == -1 ) {
+ pnd_log ( pndn_error, "ERROR: notify: nothing to watch\n" );
+ retcode = -1;
+ break;
}
- createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
+ // the idle timeout is needed for inotify as some file updates produce several events
+ // with a delay in between (length depends on things like file size and system load), like
+ // - IN_CREATE, IN_CLOSE_WRITE (cp, mv from other fs, etc)
+ // - IN_MOVED_TO, IN_CLOSE_WRITE (PNDManager)
+ // - multiple file copies, deletes, etc
+ timeout = idle ? NULL : &timeout_1s;
- // if this was a forced scan, lets not do that next iteration
- if ( scanonlaunch ) {
- scanonlaunch = 0;
+ retcode = select ( fd_max + 1, &rfds, NULL, &efds, timeout );
+
+ if ( retcode < 0 ) {
+ pnd_log ( pndn_error, "ERROR: notify: select failed: %d\n", errno );
+ if ( errno == EINTR )
+ retcode = 0;
+
+ break;
+ }
+ idle = ( retcode == 0 );
+
+ if ( dbh && FD_ISSET ( fd_dbus, &efds ) ) {
+ pnd_log ( pndn_error, "ERROR: notify: dbus fd error\n" );
+ pnd_dbusnotify_shutdown ( dbh );
+ dbh = NULL;
}
+ if ( nh && FD_ISSET ( fd_inotify, &efds ) ) {
+ pnd_log ( pndn_error, "ERROR: notify: inotify fd error\n" );
+ pnd_notify_shutdown ( nh );
+ nh = NULL;
+ }
+
+ if ( dbh && FD_ISSET ( fd_dbus, &rfds ) ) {
+ watch_dbus |= pnd_dbusnotify_rediscover_p ( dbh );
+ if ( watch_dbus && nh ) {
+ // will restart inotify (see below), drop all events
+ pnd_notify_shutdown ( nh );
+ nh = NULL;
+ }
+ }
+
+ if ( nh && FD_ISSET ( fd_inotify, &rfds ) ) {
+ watch_inotify |= pnd_notify_rediscover_p ( nh );
+ }
+ }
+ while ( !idle );
+
+ if ( retcode < 0 ) {
+ break;
+ }
+
+ // need to rediscover?
+ if ( scanonlaunch || watch_inotify || watch_dbus ) {
+
// 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" );
- pnd_log ( pndn_rem, "Changes within watched paths .. performing re-discover!\n" );
+
+ 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;
+ }
+
+ if ( watch_inotify ) {
+ pnd_log ( pndn_rem, "inotify detected an event\n" );
+ }
+
+ if ( watch_dbus ) {
+ pnd_log ( pndn_rem, "dbusnotify detected an event\n" );
+ }
+
+ if ( time ( NULL ) - createtime < interval_secs ) {
+ pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; delaying.\n" );
+ sleep ( interval_secs );
+ idle = 0;
+ continue;
+ }
+
+ pnd_log ( pndn_rem, "------------------------------------------------------\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" );
+ // do some 'locking'
+ pnd_log ( pndn_rem, "creating lockfile %s", PNDLOCKNAME );
+ if ( ! pnd_lock ( PNDLOCKNAME ) ) {
+ // problem .. well, too bad, we need to do this .. proceed!
+ }
+
+ // scan..
+ 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" );
}
}
+ // unlock
+ pnd_log ( pndn_rem, "clearing lockfile %s", PNDLOCKNAME );
+ pnd_unlock ( PNDLOCKNAME );
+
// if we've got a hup script located, lets invoke it
if ( pndhup ) {
pnd_log ( pndn_rem, "Invoking hup script '%s'.\n", pndhup );
// 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?
+ watch_inotify = watch_dbus = 0;
- // lets not eat up all the CPU
- // should use an alarm or select() or something -- I mean really, why aren't I putting interval_secs into
- // the select() call above in pnd_notify_whatsitcalled()? -- but lets not break this right before release shall we
- // NOTE: Oh right, I remember now -- inotify will spam when a card is inserted, and it will not be instantaneoous..
- // the events will dribble in over a second. So this sleep is a lame trick that generally works. I really should
- // do select(), and then when it returns just spin for a couple seconds slurping up events until no more and a thresh-hold
- // time is hit, but this will do for now. I suck.
- sleep ( interval_secs );
+ } // need to rediscover?
} // while
/* shutdown
*/
- pnd_notify_shutdown ( nh );
+ if ( nh ) {
+ pnd_notify_shutdown ( nh );
+ }
+ if ( dbh ) {
+ pnd_dbusnotify_shutdown ( dbh );
+ }
return ( 0 );
}
desktop_dotdesktoppath = pnd_conf_get_as_char ( desktoph, PND_DESKTOP_DOTDESKTOP_PATH_KEY );
desktop_iconpath = pnd_conf_get_as_char ( desktoph, PND_DESKTOP_ICONS_PATH_KEY );
desktop_appspath = pnd_conf_get_as_char ( desktoph, PND_DESKTOP_SEARCH_KEY );
+ info_dotdesktoppath = pnd_conf_get_as_char ( desktoph, "info.dotdesktoppath" );
}
if ( ! desktop_dotdesktoppath ) {
menu_appspath = pnd_conf_get_as_char ( desktoph, PND_MENU_SEARCH_KEY );
}
+ // info
+ if ( desktoph ) {
+ g_info_p = pnd_conf_get_as_int_d ( desktoph, "info.emit_info", 0 );
+ }
+
/* try to locate a runscript and optional hupscript
*/
mkdir ( desktop_dotdesktoppath, 0777 );
mkdir ( desktop_iconpath, 0777 );
+ if ( info_dotdesktoppath ) {
+ info_dotdesktoppath = pnd_expand_tilde ( strdup ( info_dotdesktoppath ) );
+ mkdir ( info_dotdesktoppath, 0777 );
+ }
+
if ( menu_dotdesktoppath ) {
menu_dotdesktoppath = pnd_expand_tilde ( strdup ( menu_dotdesktoppath ) );
mkdir ( menu_dotdesktoppath, 0777 );
return;
}
+void sigint_handler ( int n ) {
+
+ pnd_log ( pndn_rem, "---[ SIGINT received ]---\n" );
+
+ if ( dbh ) {
+ pnd_dbusnotify_shutdown ( dbh );
+ dbh = NULL;
+ }
+
+ if ( nh ) {
+ pnd_notify_shutdown ( nh );
+ nh = NULL;
+ }
+
+ 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..
// check if icon already exists (from a previous extraction say); if so, we needn't
// do it again
char existingpath [ FILENAME_MAX ];
- sprintf ( existingpath, "%s/%s.png", emiticonpath, d -> unique_id );
+ sprintf ( existingpath, "%s/%s.png", emiticonpath, d -> unique_id /*, d -> subapp_number */ );
struct stat dirs;
if ( stat ( existingpath, &dirs ) == 0 ) {
pnd_log ( pndn_debug, " Icon not already present, so trying to write it! %s\n", existingpath );
+ // handle same-path icon override for davec :)
+ char ovrfile [ PATH_MAX ];
+ char *fixpxml;
+ sprintf ( ovrfile, "%s/%s", d -> object_path, d -> object_filename );
+ fixpxml = strcasestr ( ovrfile, PND_PACKAGE_FILEEXT );
+ if ( fixpxml ) {
+ strcpy ( fixpxml, ".png" );
+ fixpxml = NULL;
+ struct stat statbuf;
+ if ( stat ( ovrfile, &statbuf ) == 0 ) {
+ d -> icon = strdup ( ovrfile );
+ fixpxml = ovrfile; // !NULL will be the trigger to skip emittinf desktop from .pnd
+ } // stat
+ } // ovr?
+
// attempt to create icon files; if successful, alter the disco struct to contain new
// path, otherwise leave it alone (since it could be a generic icon reference..)
- if ( pnd_emit_icon ( emiticonpath, d ) ) {
- // success; fix up icon path to new one..
- if ( d -> icon ) {
- free ( d -> icon );
+ if ( fixpxml == NULL ) {
+ // don't have an same-path override icon, so go fetch something from pnd file
+
+ if ( pnd_emit_icon ( emiticonpath, d ) ) {
+ // success; fix up icon path to new one..
+ if ( d -> icon ) {
+ free ( d -> icon );
+ }
+ d -> icon = strdup ( existingpath );
+ } else {
+ pnd_log ( pndn_debug, " WARN: Couldn't write out icon %s\n", existingpath );
}
- d -> icon = strdup ( existingpath );
- } else {
- pnd_log ( pndn_debug, " WARN: Couldn't write out icon %s\n", existingpath );
- }
+
+ } // got ovr icon already?
} // icon already exists?
pnd_log ( pndn_rem, "ERROR: Error creating .desktop file for app: %s\n", pnd_box_get_key ( d ) );
}
+ // info .desktop
+ if ( g_info_p && info_dotdesktoppath ) {
+ if ( ! pnd_emit_dotinfo ( info_dotdesktoppath, pndrun, d ) ) {
+ pnd_log ( pndn_rem, "ERROR: Error creating info .desktop file for app: %s\n", pnd_box_get_key ( d ) );
+ }
+ }
+
// does this object request any mkdir's?
if ( d -> mkdir_sp ) {