+
+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..
+void process_discoveries ( pnd_box_handle applist, char *emitdesktoppath, char *emiticonpath ) {
+ pnd_disco_t *d = pnd_box_get_head ( applist );
+
+ while ( d ) {
+
+ pnd_log ( pndn_rem, "Found app: %s\n", pnd_box_get_key ( d ) );
+
+ // 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 /*, d -> subapp_number */ );
+
+ struct stat dirs;
+ if ( stat ( existingpath, &dirs ) == 0 ) {
+ // icon seems to exist, so just crib the location into the .desktop
+
+ pnd_log ( pndn_rem, " Found icon already existed, so reusing it! %s\n", existingpath );
+
+ if ( d -> icon ) {
+ free ( d -> icon );
+ }
+ d -> icon = strdup ( existingpath );
+
+ } else {
+ // icon seems unreadable or does not exist; lets try to create it..
+
+ 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 ( 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 );
+ }
+
+ } // got ovr icon already?
+
+ } // icon already exists?
+
+ // create the .desktop file
+ if ( pnd_emit_dotdesktop ( emitdesktoppath, pndrun, d ) ) {
+ // add a watch onto the newly created .desktop?
+#if 0
+ char buffer [ FILENAME_MAX ];
+ sprintf ( buffer, "%s/%s", emitdesktoppath, d -> unique_id );
+ pnd_notify_watch_path ( nh, buffer, PND_NOTIFY_RECURSE );
+#endif
+ } else {
+ 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 ) ) {
+ // nada
+ } else {
+ 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 ) {
+
+ // it would appear it does! but we have to carefully validate these suckers
+ pnd_log ( pndn_rem, " App %s requests mkdir: %s\n", d -> object_path, d -> mkdir_sp );
+
+ // for each mkdir requested path, do it...
+ char *searchpath = d -> mkdir_sp;
+
+ SEARCHCHUNK_PRE
+ {
+ /* "buffer" now holds each chunk of the searchpath, expanded */
+
+ // WARN: This whole concept could be flawed; what if they represent '..' in some other obscure way (unicode?)
+ // and we end up allowing mkdir's all over the place? The risk really is limited -- once the pnd is here,
+ // if the user _runs it_, it can go nuts, so creating a few dirs isn't all that dangerous...
+ // HMRF :/
+ // Perhaps I should have a config setting for pndnotifyd to suppress this whole mkdir behaviour?
+
+ // if not containing ".." we allow it
+ if ( strstr ( buffer, ".." ) == NULL ) {
+
+ // determine mountpoint for the file
+ // - we could deduce this from the path (somewhat risky if we assume leading /media/mmcblk1p1 type notation .. could
+ // be other distributions entirely
+ // - better to scan through mount-list and figure it out.. *sucks*
+ char mountpoint [ PATH_MAX ];
+ if ( pnd_determine_mountpoint ( d -> object_path, mountpoint, PATH_MAX - strlen ( buffer ) - 1 ) == 1 ) {
+
+ strcat ( mountpoint, "/" );
+ strcat ( mountpoint, buffer );
+
+ struct stat t;
+ if ( stat ( mountpoint, &t ) == 0 ) {
+ pnd_log ( pndn_rem, " Skipping existing mkdir: %s\n", mountpoint );
+ } else {
+ pnd_log ( pndn_rem, " Attempting create of non-existant path: %s\n", mountpoint );
+ mkdir ( mountpoint, 0777 );
+ }
+
+ } // if figured out the mountpoint
+
+ } // if valid path
+
+ }
+ SEARCHCHUNK_POST
+
+ } // mkdir request
+
+ // next!
+ d = pnd_box_get_next ( d );
+
+ } // while applist
+
+ return;
+}
+
+// returns true if any applications were found
+unsigned char perform_discoveries ( char *appspath, char *overridespath, // args to do discovery
+ char *emitdesktoppath, char *emiticonpath ) // args to do emitting
+{
+ pnd_box_handle applist;
+
+ pnd_log ( pndn_rem, "perform discovery - apps: %s, overrides: %s\n", appspath, overridespath );
+ pnd_log ( pndn_rem, " - emit desktop: %s, icons: %s\n", emitdesktoppath, emiticonpath );
+
+ // attempt to auto-discover applications in the given path
+ applist = pnd_disco_search ( appspath, overridespath );
+
+ if ( applist ) {
+ process_discoveries ( applist, emitdesktoppath, emiticonpath );
+ }
+
+ // run a clean up, to remove any dotdesktop files that we didn't
+ // just now create (that seem to have been created by pndnotifyd
+ // previously.) This allows SD eject (or .pnd remove) to remove
+ // an app from the launcher
+ // NOTE: Could opendir and iterate across all .desktop files,
+ // removing any that have Source= something else, and that the
+ // app name is not in the list found in applist box above. But
+ // a cheesy simple way right now is to just remove .desktop files
+ // that have a last mod time prior to the time we stored above.
+ {
+ DIR *dir;
+
+ if ( ( dir = opendir ( emitdesktoppath ) ) ) {
+ struct dirent *dirent;
+ struct stat dirs;
+ char buffer [ FILENAME_MAX ];
+
+ while ( ( dirent = readdir ( dir ) ) ) {
+
+ // file is a .desktop?
+ if ( strstr ( dirent -> d_name, ".desktop" ) == NULL ) {
+ continue;
+ }
+
+ // figure out full path
+ sprintf ( buffer, "%s/%s", emitdesktoppath, dirent -> d_name );
+
+ // file was previously created by libpnd; check Source= line
+ // logic: default to 'yes' (in case we can't open the file for some reason)
+ // if we can open the file, default to no and look for the source flag we added; if
+ // that matches then we know its libpnd created, otherwise assume not.
+ unsigned char source_libpnd = 1;
+ {
+ char line [ 256 ];
+ FILE *grep = fopen ( buffer, "r" );
+ if ( grep ) {
+ source_libpnd = 0;
+ while ( fgets ( line, 255, grep ) ) {
+ if ( strcasestr ( line, PND_DOTDESKTOP_SOURCE ) ) {
+ source_libpnd = 2;
+ }
+ } // while
+ fclose ( grep );
+ }
+ }
+ if ( source_libpnd ) {
+#if 1
+ pnd_log ( pndn_debug,
+ "File '%s' appears to have been created by libpnd so candidate for delete: %u\n", buffer, source_libpnd );
+#endif
+ } else {
+#if 0
+ pnd_log ( pndn_debug, "File '%s' appears NOT to have been created by libpnd, so leave it alone\n", buffer );
+#endif
+ continue; // skip deleting it
+ }
+
+ // file is 'new'?
+ if ( stat ( buffer, &dirs ) == 0 ) {
+ if ( dirs.st_mtime >= createtime ) {
+#if 1
+ pnd_log ( pndn_debug, "File '%s' seems 'new', so leave it alone.\n", buffer );
+#endif
+ continue; // skip deleting it
+ }
+ }
+
+ // by this point, the .desktop file must be 'old' and created by pndnotifyd
+ // previously, so can remove it
+ pnd_log ( pndn_rem, "File '%s' seems nolonger relevent; removing it.\n", dirent -> d_name );
+ unlink ( buffer );
+
+ } // while getting filenames from dir
+
+ closedir ( dir );
+ }
+
+ } // purge old .desktop files
+
+ //WARN: MEMORY LEAK HERE
+ pnd_log ( pndn_debug, "pndnotifyd - memory leak here - perform_discoveries()\n" );
+ if ( applist ) {
+ pnd_box_delete ( applist ); // does not free the disco_t contents!
+ }
+
+ return ( 1 );
+}