Merge branch 'master' of git://git.openpandora.org/pandora-libraries
authorvimacs <vimacs@pndtest>
Mon, 15 Feb 2010 18:52:03 +0000 (19:52 +0100)
committervimacs <vimacs@pndtest>
Mon, 15 Feb 2010 18:52:03 +0000 (19:52 +0100)
19 files changed:
Makefile
apps/pnd_info.c [new file with mode: 0644]
apps/pndevmapperd.c
apps/pndnotifyd.c
include/pnd_discovery.h
include/pnd_logger.h
include/pnd_pxml.h
include/pnd_pxml_names.h
include/pnd_utility.h
lib/pnd_conf.c
lib/pnd_discovery.c
lib/pnd_logger.c
lib/pnd_notify.c
lib/pnd_pathiter.h
lib/pnd_pxml.c
lib/pnd_tinyxml.cpp
lib/pnd_utility.c
test/discotest.c
testdata/apps/sampleapp1/PXML.xml

index 356756d..beac4d7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -23,10 +23,10 @@ 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
 
-all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest pnd_run pndevmapperd
+all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest 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 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/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 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
 
@@ -54,6 +54,9 @@ pndvalidator: pndvalidator.o ${SOLIB1}
 pnd_run:       pnd_run.o ${SOLIB1}
        ${CC} -lstdc++ -o bin/pnd_run pnd_run.o ${SOLIB1}
 
+pnd_info:      pnd_info.o ${SOLIB1}
+       ${CC} -lstdc++ -o bin/pnd_info pnd_info.o ${SOLIB1}
+
 pndevmapperd:  pndevmapperd.o ${SOLIB1}
        ${CC} -lstdc++ -o bin/pndevmapperd pndevmapperd.o ${SOLIB1}
 
@@ -82,6 +85,7 @@ deploy:
        cp libpnd* deployment/usr/lib
        cp bin/pndnotifyd deployment/usr/bin
        cp bin/pnd_run deployment/usr/bin
+       cp bin/pnd_info deployment/usr/bin
        cp testdata/scripts/* deployment/usr/pandora/scripts
        cp bin/pndevmapperd deployment/usr/bin
        # copy in freebee .pnd apps to /usr/pandora/apps
diff --git a/apps/pnd_info.c b/apps/pnd_info.c
new file mode 100644 (file)
index 0000000..a2acb4b
--- /dev/null
@@ -0,0 +1,113 @@
+
+#include <stdio.h> /* for printf, NULL */
+#include <stdlib.h> /* for free */
+#include <string.h> /* for strdup */
+
+#include "pnd_conf.h"
+#include "pnd_container.h"
+#include "pnd_apps.h"
+#include "pnd_discovery.h"
+#include "pnd_locate.h"
+#include "pnd_pndfiles.h"
+#include "pnd_pxml.h"
+
+static void usage ( char *argv[] ) {
+  printf ( "%s\tObtain a description, install guide or other info about a pnd-file\n", argv [ 0 ] );
+  printf ( "\n" );
+  printf ( "%s path-to-pndfile [section] [section-2...]\n", argv [ 0 ] );
+  printf ( "\n" );
+  printf ( "section\tOptional. If not specified, general description is shown. (Section 'description')\n" );
+  printf ( "\tIf present, show the named section of the PXML -- such as to obtain install instructions etc.\n" );
+  printf ( "pndfile\tRequired. Full path to the pnd-file to execute.\n" );
+  return;
+}
+
+#define SECTIONMAX 100
+
+int main ( int argc, char *argv[] ) {
+  char *pndfile = NULL;
+  char *section [ SECTIONMAX ];
+  unsigned char sections = 0;
+  int i;
+
+  for ( i = 1; i < argc; i++ ) {
+
+    if ( ! pndfile ) {
+      pndfile = argv [ i ];
+      continue;
+    }
+
+    section [ sections++ ] = argv [ i ];
+
+    if ( sections == SECTIONMAX ) {
+      break;
+    }
+
+  } // for args
+
+  if ( ! pndfile ) {
+    usage ( argv );
+    exit ( 0 );
+  }
+
+  if ( ! sections ) {
+    section [ sections++ ] = "description";
+  }
+
+  // summary
+  printf ( "Pndfile\t%s\n", pndfile );
+  printf ( "Sections to include:\n" );
+  for ( i = 0; i < sections; i++ ) {
+    printf ( "- %s\n", section [ i ] );
+  } // for
+  printf ( "\n" );
+
+  // pull PXML
+  unsigned int pxmlbuflen = 96 * 1024; // lame, need to calculate it
+  char *pxmlbuf = malloc ( pxmlbuflen );
+  if ( ! pxmlbuf ) {
+    printf ( "ERROR: RAM exhausted!\n" );
+    exit ( 0 );
+  }
+  memset ( pxmlbuf, '\0', pxmlbuflen );
+
+  FILE *f = fopen ( pndfile, "r" );
+  if ( ! f ) {
+    printf ( "ERROR: Couldn't open pndfile %s!\n", pndfile );
+    exit ( 0 );
+  }
+
+  pnd_pxml_handle h = NULL;
+  if ( pnd_pnd_seek_pxml ( f ) ) {
+    if ( pnd_pnd_accrue_pxml ( f, pxmlbuf, pxmlbuflen ) ) {
+      h = pnd_pxml_fetch_buffer ( "pnd_run", pxmlbuf );
+    }
+  }
+
+  fclose ( f );
+
+  if ( ! h ) {
+    printf ( "ERROR: Couldn't pull PXML.xml from the pndfile.\n" );
+    exit ( 0 );
+  }
+
+  // display sections
+  for ( i = 0; i < sections; i++ ) {
+    char *t;
+
+    if ( strcasecmp ( section [ i ], "description" ) == 0 ) {
+
+      printf ( "Section: %s\n", section [ i ] );
+
+      if ( ( t = pnd_pxml_get_description_en ( h ) ) ) {
+       printf ( "%s\n", t );
+      } else {
+       printf ( "Not supplied by PXML.xml in the pnd-file\n" );
+      }
+
+    }
+
+  } // for
+
+  return ( 0 );
+} // main
index afed8d9..8a49d6d 100644 (file)
@@ -17,6 +17,7 @@
 #include <fcntl.h> // for open(2)
 #include <errno.h> // for errno
 #include <time.h> // for time(2)
+#include <ctype.h> // for isdigit
 
 #include <linux/input.h> // for keys
 //#include "../../kernel-rip/input.h" // for keys
@@ -29,6 +30,8 @@
 #include "pnd_pndfiles.h"
 #include "pnd_pxml.h"
 #include "pnd_logger.h"
+#include "pnd_utility.h"
+#include "pnd_notify.h"
 
 // daemon and logging
 //
@@ -100,18 +103,32 @@ void dispatch_event ( int code, int val );
 static void usage ( char *argv[] ) {
   printf ( "%s [-d]\n", argv [ 0 ] );
   printf ( "-d\tDaemon mode; detach from terminal, chdir to /tmp, suppress output. Optional.\n" );
+  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/pndevmapperd.log\n" );
   printf ( "Signal: HUP the process to force reload of configuration and reset the notifier watch paths\n" );
   return;
 }
 
 int main ( int argc, char *argv[] ) {
   int i;
+  int logall = -1; // -1 means normal logging rules; >=0 means log all!
 
   for ( i = 1; i < argc; i++ ) {
 
     if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'd' ) {
       //printf ( "Going daemon mode. Silent running.\n" );
       g_daemon_mode = 1;
+    } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'l' ) {
+
+      if ( isdigit ( argv [ i ][ 2 ] ) ) {
+       unsigned char x = atoi ( argv [ i ] + 2 );
+       if ( x >= 0 &&
+            x < pndn_none )
+       {
+         logall = x;
+       }
+      } else {
+       logall = 0;
+      }
     } else {
       usage ( argv );
       exit ( 0 );
@@ -121,14 +138,40 @@ int main ( int argc, char *argv[] ) {
 
   /* enable logging?
    */
-  if ( g_daemon_mode ) {
-    // nada
+  pnd_log_set_pretext ( "pndevmapperd" );
+  pnd_log_set_flush ( 1 );
+
+  if ( logall == -1 ) {
+    // standard logging; non-daemon versus daemon
+
+    if ( g_daemon_mode ) {
+      // nada
+    } else {
+      pnd_log_set_filter ( pndn_rem );
+      pnd_log_to_stdout();
+    }
+
   } else {
-    pnd_log_set_filter ( pndn_rem );
-    pnd_log_set_pretext ( "pndevmapperd" );
-    pnd_log_to_stdout();
-    pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
-  }
+    FILE *f;
+
+    f = fopen ( "/tmp/pndevmapperd.log", "w" );
+
+    if ( f ) {
+      pnd_log_set_filter ( logall );
+      pnd_log_to_stream ( f );
+      pnd_log ( pndn_rem, "logall mode - logging to /tmp/pndevmapperd.log\n" );
+    }
+
+    if ( logall == pndn_debug ) {
+      pnd_log_set_buried_logging ( 1 ); // log the shit out of it
+      pnd_log ( pndn_rem, "logall mode 0 - turned on buried logging\n" );
+    }
+
+  } // logall
+
+  pnd_log ( pndn_rem, "%s built %s %s", argv [ 0 ], __DATE__, __TIME__ );
+
+  pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
 
   // basic daemon set up
   if ( g_daemon_mode ) {
@@ -151,6 +194,45 @@ int main ( int argc, char *argv[] ) {
     
   } // set up daemon
 
+  /* hmm, seems to not like working right after boot.. do we depend on another daemon or
+   * on giving kernel time to init something, or ... wtf?
+   * -- lets give the system some time to wake up
+   */
+  { // delay
+
+    // this one works for pndnotifyd, which actually needs INOTIFYH..
+    //
+
+    // check if inotify is awake yet; if not, try waiting for awhile to see if it does
+    pnd_log ( pndn_rem, "Starting INOTIFY test; should be instant, but may take awhile...\n" );
+
+    if ( ! pnd_notify_wait_until_ready ( 120 /* seconds */ ) ) {
+      pnd_log ( pndn_error, "ERROR: INOTIFY refuses to be useful and quite awhile has passed. Bailing out.\n" );
+      return ( -1 );
+    }
+
+    pnd_log ( pndn_rem, "INOTIFY seems to be useful, whew.\n" );
+
+    // pndnotifyd also waits for user to log in .. pretty excessive, especially since
+    // what if user wants to close the lid while at the log in screen? for now play the
+    // odds as thats pretty unliekly usage scenariom but is clearly not acceptible :/
+    //
+
+    // wait for a user to be logged in - we should probably get hupped when a user logs in, so we can handle
+    // log-out and back in again, with SDs popping in and out between..
+    pnd_log ( pndn_rem, "Checking to see if a user is logged in\n" );
+    char tmp_username [ 128 ];
+    while ( 1 ) {
+      if ( pnd_check_login ( tmp_username, 127 ) ) {
+       break;
+      }
+      pnd_log ( pndn_debug, "  No one logged in yet .. spinning.\n" );
+      sleep ( 2 );
+    } // spin
+    pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", tmp_username );
+
+  } // delay
+
   /* inhale config or die trying
    */
   char *configpath;
index bf0b47d..d31395b 100644 (file)
@@ -61,6 +61,8 @@ char *run_searchpath; // searchpath to find pnd_run.sh
 char *run_script;     // name of pnd_run.sh script from config
 char *pndrun;         // full path to located pnd_run.sh
 char *pndhup = NULL;  // full path to located pnd_hup.sh
+// default username
+char g_username [ 128 ]; // since we have to wait for login (!!), store username here
 // notifier handle
 pnd_notify_handle nh = 0;
 
@@ -79,6 +81,7 @@ int main ( int argc, char *argv[] ) {
   // behaviour
   unsigned char scanonlaunch = 1;
   unsigned int interval_secs = 5;
+  int logall = -1; // -1 means normal logging rules; >=0 means log all!
   // misc
   int i;
 
@@ -93,10 +96,24 @@ int main ( int argc, char *argv[] ) {
       interval_secs = atoi ( argv [ i ] );
     } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'n' ) {
       scanonlaunch = 0;
+    } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'l' ) {
+
+      if ( isdigit ( argv [ i ][ 2 ] ) ) {
+       unsigned char x = atoi ( argv [ i ] + 2 );
+       if ( x >= 0 &&
+            x < pndn_none )
+       {
+         logall = x;
+       }
+      } else {
+       logall = 0;
+      }
+
     } else {
       printf ( "%s [-d] [##]\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" );
       printf ( "##\tA numeric value is interpreted as number of seconds between checking for filesystem changes. Default %u.\n",
               interval_secs );
       printf ( "Signal: HUP the process to force reload of configuration and reset the notifier watch paths\n" );
@@ -107,15 +124,40 @@ int main ( int argc, char *argv[] ) {
 
   /* enable logging?
    */
-  if ( g_daemon_mode ) {
-    // nada
+  pnd_log_set_pretext ( "pndnotifyd" );
+  pnd_log_set_flush ( 1 );
+
+  if ( logall == -1 ) {
+    // standard logging; non-daemon versus daemon
+
+    if ( g_daemon_mode ) {
+      // nada
+    } else {
+      pnd_log_set_filter ( pndn_rem );
+      pnd_log_to_stdout();
+    }
+
   } else {
-    pnd_log_set_filter ( pndn_rem );
-    pnd_log_set_pretext ( "pndnotifyd" );
-    pnd_log_to_stdout();
-    pnd_log_set_flush ( 1 );
-    pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
-  }
+    FILE *f;
+
+    f = fopen ( "/tmp/pndnotifyd.log", "w" );
+
+    if ( f ) {
+      pnd_log_set_filter ( logall );
+      pnd_log_to_stream ( f );
+      pnd_log ( pndn_rem, "logall mode - logging to /tmp/pndnotifyd.log\n" );
+    }
+
+    if ( logall == pndn_debug ) {
+      pnd_log_set_buried_logging ( 1 ); // log the shit out of it
+      pnd_log ( pndn_rem, "logall mode 0 - turned on buried logging\n" );
+    }
+
+  } // logall
+
+  pnd_log ( pndn_rem, "%s built %s %s", argv [ 0 ], __DATE__, __TIME__ );
+
+  pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
 
   pnd_log ( pndn_rem, "Interval between checks is %u seconds\n", interval_secs );
 
@@ -155,15 +197,14 @@ int main ( int argc, char *argv[] ) {
   // wait for a user to be logged in - we should probably get hupped when a user logs in, so we can handle
   // log-out and back in again, with SDs popping in and out between..
   pnd_log ( pndn_rem, "Checking to see if a user is logged in\n" );
-  char tmp_username [ 128 ];
   while ( 1 ) {
-    if ( pnd_check_login ( tmp_username, 127 ) ) {
+    if ( pnd_check_login ( g_username, 127 ) ) {
       break;
     }
     pnd_log ( pndn_debug, "  No one logged in yet .. spinning.\n" );
     sleep ( 2 );
   } // spin
-  pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", tmp_username );
+  pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", g_username );
 
   /* parse configs
    */
@@ -215,6 +256,13 @@ int main ( int argc, char *argv[] ) {
     if ( scanonlaunch ||
         pnd_notify_rediscover_p ( nh ) )
     {
+
+      if ( time ( NULL ) - createtime <= 2 ) {
+       pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
+       sleep ( interval_secs );
+       continue;
+      }
+
       createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
 
       // if this was a forced scan, lets not do that next iteration
@@ -353,8 +401,12 @@ void consume_configuration ( void ) {
     }
 
     if ( pnd_conf_get_as_int ( apph, PNDNOTIFYD_LOGLEVEL ) != PND_CONF_BADNUM ) {
-      pnd_log_set_filter ( pnd_conf_get_as_int ( apph, PNDNOTIFYD_LOGLEVEL ) );
-      pnd_log ( pndn_rem, "config file causes loglevel to change to %u", pnd_log_get_filter() );
+      if ( pnd_log_do_buried_logging() == 0 ) {
+       pnd_log_set_filter ( pnd_conf_get_as_int ( apph, PNDNOTIFYD_LOGLEVEL ) );
+       pnd_log ( pndn_rem, "config file causes loglevel to change to %u", pnd_log_get_filter() );
+      } else {
+       pnd_log ( pndn_rem, "-l command line suppresses log level change in config file\n" );
+      }
     }
 
   } else {
@@ -406,14 +458,41 @@ void consume_configuration ( void ) {
    * the user is formally logged in
    */
   pnd_log ( pndn_rem, "Setting a default $HOME to non-root user\n" );
-  {
+
+  // first, try to see if known-username maps to a homedir; if so, just use that!
+  // otherwise, pick first non-root homedir and assume .. or we start blaring .desktops
+  // out to all users like idiots
+  unsigned char got_user_homedir = 0;
+
+  if ( g_username [ 0 ] ) {
+    struct stat homedir;
+    char path [ PATH_MAX ];
+
+    sprintf ( path, "/home/%s", g_username );
+
+    // does this made up path exist?
+    if ( stat ( path, &homedir ) == 0 ) {
+
+      // and its a dir?
+      if ( S_ISDIR(homedir.st_mode) ) {
+       pnd_log ( pndn_rem, "  User [%s] matches path [%s], going with '%s'\n", g_username, path, path );
+       setenv ( "HOME", path, 1 /* overwrite */ );
+       got_user_homedir = 1;
+      } // and its a dir?
+
+    } // guessing a homedirname..
+
+  } // got a username?
+
+  // if guessing a path was no good, just try finding one
+  if ( got_user_homedir == 0 ) {
     DIR *dir;
 
     if ( ( dir = opendir ( "/home" ) ) ) {
       struct dirent *dirent;
 
       while ( ( dirent = readdir ( dir ) ) ) {
-       pnd_log ( pndn_rem, "  Found user homedir '%s'\n", dirent -> d_name );
+       pnd_log ( pndn_rem, "  Scanning user homedir '%s'\n", dirent -> d_name );
 
        // file is a .desktop?
        if ( dirent -> d_name [ 0 ] == '.' ) {
@@ -565,6 +644,55 @@ void process_discoveries ( pnd_box_handle applist, char *emitdesktoppath, char *
       pnd_log ( pndn_rem, "ERROR: Error creating .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 );
 
@@ -579,6 +707,9 @@ unsigned char perform_discoveries ( char *appspath, char *overridespath,
 {
   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 );
 
@@ -632,13 +763,13 @@ unsigned char perform_discoveries ( char *appspath, char *overridespath,
          }
        }
        if ( source_libpnd ) {
-#if 0
-         pnd_log ( pndn_rem,
+#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_rem, "File '%s' appears NOT to have been created by libpnd, so leave it alone\n", buffer );
+         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
        }
@@ -646,8 +777,8 @@ unsigned char perform_discoveries ( char *appspath, char *overridespath,
        // file is 'new'?
        if ( stat ( buffer, &dirs ) == 0 ) {
          if ( dirs.st_mtime >= createtime ) {
-#if 0
-           pnd_log ( pndn_rem, "File '%s' seems 'new', so leave it alone.\n", buffer );
+#if 1
+           pnd_log ( pndn_debug, "File '%s' seems 'new', so leave it alone.\n", buffer );
 #endif
            continue; // skip deleting it
          }
index 707e1e1..e4b11b4 100644 (file)
@@ -66,6 +66,7 @@ typedef struct {
   char *alt_category2;
   char *preview_pic1;
   char *preview_pic2;
+  char *mkdir_sp;
 } pnd_disco_t;
 
 void pnd_disco_destroy ( pnd_disco_t *p ); // a function name that simply could not be avoided
index 6db1aed..349593e 100644 (file)
@@ -41,6 +41,12 @@ unsigned char pnd_log_get_filter ( void );
 // how many targets can be opened, entirely? this is a compile time limit, for sanity.
 unsigned char pnd_log_max_targets ( void );
 
+// tell buried lib functions to do some logging here; ie: since not all API's have a 'options' type flag where we could
+// add a hint to begin logging, they can just ask the logger if they need to do it
+#define PND_LOG_DEFAULT 0 // level 0 is by default the 'debug' level, with anything higher non-debug; only used for buried logging
+void pnd_log_set_buried_logging ( unsigned char yesno ); // set 1 for 'yes', 0 for 'no'
+unsigned char pnd_log_do_buried_logging ( void ); // return 1 for 'yes'
+
 #ifdef __cplusplus
 } /* "C" */
 #endif
index e8853c2..a9733fd 100644 (file)
@@ -83,6 +83,7 @@ char *pnd_pxml_get_associationitem3_parameter ( pnd_pxml_handle h );
 char *pnd_pxml_get_clockspeed ( pnd_pxml_handle h );
 char *pnd_pxml_get_background ( pnd_pxml_handle h );
 char *pnd_pxml_get_startdir ( pnd_pxml_handle h );
+char *pnd_pxml_get_mkdir ( pnd_pxml_handle h );
 
 // for 'set' functions, pass NULL value to delete existing value without setting new one
 void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v );
@@ -142,6 +143,7 @@ typedef struct
        char *exec_no_x11;
        char *package_name;
        char *package_release_date;
+        char *mkdir_sp; // a colon separated list of paths to be mkdir'd (silently fail) when pnd is autodiscovered. path is always relative to the root of the hosting device.
 
 }  pnd_pxml_t;
 
index 15540eb..39f72d2 100644 (file)
@@ -87,6 +87,14 @@ extern "C" {
 #define PND_PXML_ATTRNAME_PACKAGE_NAME "name"
 #define PND_PXML_ATTRNAME_PACKAGE_DATE "released"
 
+/* <mkdir>
+ *   <dir path="..." />
+ * </mkdir>
+ */
+#define PND_PXML_NODENAME_MKDIR "mkdir"
+#define PND_PXML_ENAME_MKDIR "dir"
+#define PND_PXML_ATTRNAME_MKDIRPATH "path"
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 62af5af..f9dce27 100644 (file)
@@ -25,6 +25,11 @@ void pnd_exec_no_wait_1 ( char *fullpath, char *arg1 );
 //   NOTE: Does _NOT_ automatically pick up PXML-overrides; you can call that function if you want
 pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath );
 
+// determine_mountpoint() will examine a path, and return the mountpoint that this path
+// is sitting on; returns 1 on success, meaning the target was populated.
+// consider for a similar effect: df /home -> look at "Mounted on"
+unsigned char pnd_determine_mountpoint ( char *fullpath, char *r_mountpoint, unsigned char mountpoint_len );
+
 #ifdef __cplusplus
 } /* "C" */
 #endif
index 64c9ade..aece00d 100644 (file)
@@ -35,7 +35,7 @@ char *pnd_conf_query_searchpath ( void ) {
 
   temp = pnd_conf_get_as_char ( ch, PND_CONF_KEY );
 
-  if ( searchpath ) {
+  if ( temp ) {
     searchpath = strdup ( temp );
   } else {
     searchpath = strdup ( PND_CONF_SEARCHPATH );
index b29f733..594a03e 100644 (file)
@@ -16,6 +16,7 @@
 #include "pnd_pathiter.h"
 #include "pnd_apps.h"
 #include "pnd_pndfiles.h"
+#include "pnd_logger.h"
 
 // need these 'globals' due to the way nftw and ftw work :/
 static pnd_box_handle disco_box;
@@ -36,6 +37,7 @@ void pnd_disco_destroy ( pnd_disco_t *p ) {
   if ( p -> alt_category ) {   free ( p -> alt_category );   }
   if ( p -> alt_category1 ) {  free ( p -> alt_category1 );  }
   if ( p -> alt_category2 ) {  free ( p -> alt_category2 );  }
+  if ( p -> mkdir_sp )      {  free ( p -> mkdir_sp );       }
 
   return;
 }
@@ -46,12 +48,17 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
   unsigned char valid = pnd_object_type_unknown;
   pnd_pxml_handle pxmlh = 0;
   unsigned int pxml_close_pos = 0;
+  unsigned char logit = pnd_log_do_buried_logging();
 
-  //printf ( "disco root callback encountered '%s'\n", fpath );
+  if ( logit ) {
+    pnd_log ( PND_LOG_DEFAULT, "disco callback encountered '%s'\n", fpath );
+  }
 
   // PXML.xml is a possible application candidate (and not a dir named PXML.xml :)
   if ( typeflag & FTW_D ) {
-    //printf ( " .. is dir, skipping\n" );
+    if ( logit ) {
+      pnd_log ( PND_LOG_DEFAULT, " .. is dir, skipping\n" );
+    }
     return ( 0 ); // skip directories and other non-regular files
   }
 
@@ -65,7 +72,9 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
 
   // if not a file of interest, just keep looking until we run out
   if ( ! valid ) {
-    //printf ( " .. bad filename, skipping\n" );
+    if ( logit ) {
+      pnd_log ( PND_LOG_DEFAULT, " .. bad filename, skipping\n" );
+    }
     return ( 0 );
   }
 
@@ -213,6 +222,10 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb,
       if ( ( z = pnd_pxml_get_previewpic2 ( pxmlh ) ) ) {
        p -> preview_pic2 = strdup ( z );
       }
+      // mkdirs
+      if ( pnd_pxml_get_mkdir ( pxmlh ) ) {
+       p -> mkdir_sp = strdup ( pnd_pxml_get_mkdir ( pxmlh ) );
+      }
 
     } else {
       //printf ( "Invalid PXML; skipping.\n" );
index 96b3e3f..79b8558 100644 (file)
@@ -2,11 +2,13 @@
 #include <stdarg.h> // va-args
 #include <stdlib.h> // malloc/free
 #include <string.h> // strdup
+#include <time.h>
 #include "pnd_logger.h"
 
-char *log_pretext = NULL;
-unsigned char log_filterlevel = 0;
-unsigned char log_flushafter = 0;
+static char *log_pretext = NULL;
+static unsigned char log_filterlevel = 0;
+static unsigned char log_flushafter = 0;
+static time_t log_first = 0;
 
 typedef enum {
   pndl_nil = 0,
@@ -105,7 +107,7 @@ unsigned char pnd_log_max_targets ( void ) {
   return ( PND_LOG_MAX );
 }
 
-void pnd_log_emit ( char *message ) {
+static void pnd_log_emit ( unsigned char level, char *message ) {
   unsigned char i;
 
   // iterate across targets and attempt to emit
@@ -118,9 +120,13 @@ void pnd_log_emit ( char *message ) {
       break;
 
     case pndl_stream:
+      // pretext
       if ( log_pretext ) {
-       fprintf ( log_targets [ i ].stream, "%s\t", log_pretext );
+       fprintf ( log_targets [ i ].stream, "%s ", log_pretext );
       }
+      // log level
+      fprintf ( log_targets [ i ].stream, "%u %u\t", level, (unsigned int) (time ( NULL ) - log_first) );
+      // message
       if ( message ) {
        fprintf ( log_targets [ i ].stream, "%s", message );
        if ( strchr ( message, '\n' ) == NULL ) {
@@ -149,6 +155,10 @@ void pnd_log_emit ( char *message ) {
 
 unsigned char pnd_log ( unsigned char level, char *fmt, ... ) {
 
+  if ( log_first == 0 ) {
+    log_first = time ( NULL );
+  }
+
   if ( level == PND_LOG_FORCE ) {
     // always proceed
   } else if ( level < log_filterlevel ) {
@@ -173,7 +183,7 @@ unsigned char pnd_log ( unsigned char level, char *fmt, ... ) {
 
     /* If that worked, return the string. */
     if ( n > -1 && n < size ) {
-      pnd_log_emit ( p );
+      pnd_log_emit ( level, p );
       break;
     }
 
@@ -197,3 +207,17 @@ unsigned char pnd_log ( unsigned char level, char *fmt, ... ) {
 
   return ( 1 );
 }
+
+
+static unsigned char _do_buried_logging = 0;
+void pnd_log_set_buried_logging ( unsigned char yesno ) {
+  _do_buried_logging = yesno;
+  return;
+}
+
+unsigned char pnd_log_do_buried_logging ( void ) {
+  if ( _do_buried_logging == 1 ) {
+    return ( 1 );
+  }
+  return ( 0 );
+}
index 7dd135b..55127b8 100644 (file)
@@ -153,7 +153,7 @@ unsigned char pnd_notify_rediscover_p ( pnd_notify_handle h ) {
     return ( 0 ); // nothing, or overflow, or .. whatever.
   }
 
-  unsigned int i;
+  unsigned int i = 0;
   struct inotify_event *e;
 
   while ( i < actuallen ) {
index e91a408..5e13aa8 100644 (file)
@@ -22,6 +22,9 @@
 
 #if 1 // globbing is performed
 
+// only iterates actual existing paths; if you want to return
+// non-matching paths, see below
+
 #define SEARCHPATH_PRE                            \
   char *end, *colon;                              \
   char *head = searchpath;                        \
                                                   \
   } // while
 
+
+// the following will return even non-matching chunks, but is not doing wordexp() expansion on it
+
+#define SEARCHCHUNK_PRE                           \
+  char *end, *colon;                              \
+  char *head = searchpath;                        \
+  char chunk [ FILENAME_MAX ];                    \
+                                                  \
+  /*fprintf ( stderr, "sp %s\n", searchpath );*/  \
+                                                  \
+  while ( 1 ) {                                   \
+    colon = strchr ( head, ':' );                 \
+    end = strchr ( head, '\0' );                  \
+                                                  \
+    if ( colon && colon < end ) {                 \
+      memset ( chunk, '\0', FILENAME_MAX );       \
+      strncpy ( chunk, head, colon - head );      \
+    } else {                                      \
+      strncpy ( chunk, head, FILENAME_MAX - 1 );  \
+    }                                             \
+                                                  \
+    /*fprintf ( stderr, "-> %s\n", chunk ); */    \
+                                                  \
+    char buffer [ FILENAME_MAX ];                 \
+                                                  \
+    strcpy ( buffer, chunk );                            \
+    /*fprintf ( stderr, "glob %s\n", buffer );*/  \
+    { /* user code */
+
+#define SEARCHCHUNK_POST                          \
+    } /* user code */                            \
+    /* next search path */                       \
+    if ( colon && colon < end ) {                 \
+      head = colon + 1;                           \
+    } else {                                      \
+      break; /* done! */                          \
+    }                                             \
+                                                  \
+  } // while
+
+
 #endif // globbing is done
 
 
index 6ad67c3..02d0841 100644 (file)
@@ -497,3 +497,8 @@ char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) {
   pnd_pxml_t *p = (pnd_pxml_t*) h;
   return ( p -> startdir );
 }
+
+char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) {
+  pnd_pxml_t *p = (pnd_pxml_t*) h;
+  return ( p -> mkdir_sp );
+}
index 6a7e2e3..b11d450 100644 (file)
@@ -315,6 +315,43 @@ unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int
          app -> package_release_date = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_DATE );
        }
 
+       // mkdir request
+       if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_MKDIR).Element()) ) {
+
+         // seek <dir>
+         if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_MKDIR)) ) {
+           char *t;
+
+           if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) {
+             // first <dir>, so just replace it wholesale; we use strdup so we can free() easily later, consistently. Mmm, leak seems imminent.
+             app -> mkdir_sp = strdup ( t );
+           }
+
+           while ( ( pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_MKDIR ) ) ) {
+             
+             if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) {
+               char *foo = (char*) malloc ( strlen ( app -> mkdir_sp ) + strlen ( t ) + 1 /*:*/ + 1 /*\0*/ );
+
+               if ( foo ) {
+                 sprintf ( foo, "%s:%s", app -> mkdir_sp, t );
+                 free ( app -> mkdir_sp );
+                 app -> mkdir_sp = foo;
+               } // assuming we got ram, lets cat it all together
+
+             } // got another elem?
+
+           } // while
+
+         } // found a <dir>
+
+#if 0
+         if ( app -> mkdir_sp ) {
+           printf ( "mkdir: %s\n", app -> mkdir_sp );
+         }
+#endif
+
+       } // mkdir
+
        return (1);
 }
 
index 3733ad0..5009b51 100644 (file)
@@ -8,6 +8,8 @@
 #include <utmp.h> /* for expand-tilde below; see commentary for this about-turn */
 #include <sys/types.h> /* ditto */
 #include <pwd.h> /* ditto */
+#include <sys/stat.h> /* for fstat */
+#include <dirent.h> /* for opendir */
 
 #include "pnd_pxml.h"
 #include "pnd_container.h"
@@ -65,8 +67,8 @@ char *pnd_expand_tilde ( char *freeable_buffer ) {
   char *s = freeable_buffer;
   char *home = getenv ( "HOME" );
 
-  printf ( "DEBUG: expand tilde IN: '%s'\n", freeable_buffer );
-  printf ( "DEBUG:  $HOME was %s\n", home );
+  //printf ( "DEBUG: expand tilde IN: '%s'\n", freeable_buffer );
+  //printf ( "DEBUG:  $HOME was %s\n", home );
 
   // well, as pndnotifyd (etc) may be running as _root_, while the user is logged in
   // as 'pandora' or god knows what, this could be problematic. Other parts of the lib
@@ -104,7 +106,7 @@ char *pnd_expand_tilde ( char *freeable_buffer ) {
              florp = strdup ( pw -> pw_dir );
 
              home = florp;
-             printf ( "  DEBUG: home (for %s) is %s (from %u)\n", b.ut_user, home, b.ut_type );
+             //printf ( "  DEBUG: home (for %s) is %s (from %u)\n", b.ut_user, home, b.ut_type );
 
            } // passwd entry matches the utmp entry
 
@@ -124,10 +126,10 @@ char *pnd_expand_tilde ( char *freeable_buffer ) {
     return ( s ); // can't succeed
   }
 
-  printf ( "DEBUG: entering while (%s) with home (%s)\n", s, home );
+  //printf ( "DEBUG: entering while (%s) with home (%s)\n", s, home );
 
   while ( ( p = strchr ( s, '~' ) ) ) {
-    printf ( "DEBUG: within while (%s)\n", s );
+    //printf ( "DEBUG: within while (%s)\n", s );
     char *temp = malloc ( strlen ( s ) + strlen ( home ) + 1 );
     memset ( temp, '\0', strlen ( s ) + strlen ( home ) + 1 );
     // copy in stuff prior to ~
@@ -141,7 +143,7 @@ char *pnd_expand_tilde ( char *freeable_buffer ) {
     s = temp;
   } // while finding matches
 
-  printf ( "DEBUG: expand tilde OUT: '%s'\n", s );
+  //printf ( "DEBUG: expand tilde OUT: '%s'\n", s );
 
   return ( s );
 }
@@ -223,3 +225,81 @@ pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath ) {
 
   return ( pxmlh );
 }
+
+unsigned char pnd_determine_mountpoint ( char *fullpath, char *r_mountpoint, unsigned char mountpoint_len ) {
+
+  // just cheap it, and call df like an idiot.
+
+  // Filesystem           1K-blocks      Used Available Use% Mounted on
+
+  char cmd [ PATH_MAX ];
+  FILE *p;
+  char inbuf [ PATH_MAX ];
+
+  sprintf ( cmd, "/bin/df %s 2>/dev/null", fullpath );
+
+  if ( ( p = popen ( cmd, "r" ) ) ) {
+
+    // ignore title line; we really shoudl analyze it to figure out which column, but we make assumptions..
+    fgets ( inbuf, PATH_MAX, p );
+
+    if ( ! fgets ( inbuf, PATH_MAX, p ) ) {
+      pclose ( p );
+      return ( 0 );
+    }
+
+    pclose ( p );
+
+    // by now, good
+    char crap [ PATH_MAX ];
+    char mount [ PATH_MAX ];
+    if ( sscanf ( inbuf, "%s %s %s %s %s %s", crap, crap, crap, crap, crap, mount ) != 6 ) {
+      return ( 0 );
+    }
+
+    if ( strlen ( mount ) < mountpoint_len ) {
+      strcpy ( r_mountpoint, mount );
+      return ( 1 );
+    }
+
+  } // if popen
+
+  return ( 0 );
+
+#if 0
+  struct stat fooby;
+
+  // can we even stat this file?
+  if ( stat ( fullpath, &fooby ) == 0 ) {
+    //dev_t     st_dev;     /* ID of device containing file */
+    //dev_t     st_rdev;    /* device ID (if special file) */
+
+    dev_t mount = fooby.st_dev;
+
+    DIR *d = opendir ( "/dev" );
+
+    if ( d ) {
+      struct dirent *de;
+      char path [ FILENAME_MAX ];
+
+      while ( de = readdir ( d ) ) {
+       sprintf ( path, "/dev/%s", de -> d_name );
+
+       if ( stat ( path, &fooby ) == 0 ) {
+
+         // finally, if we find the same major/minor pair in /dev, as we found for the target file, it means we found the right device
+         if ( fooby.st_rdev == mount ) {
+           printf ( "Device: %s\n", path );
+         }
+
+       } // if
+
+      } // while
+
+    } // opened /dev?
+
+  } // stat
+#endif
+
+  return ( 0 );
+}
index 95465bf..cbe1040 100644 (file)
@@ -157,6 +157,9 @@ int main ( int argc, char *argv[] ) {
       if ( d -> preview_pic2 ) {
        printf ( "  Preview Pic 2: %s\n", d -> preview_pic2 );
       }
+      if ( d -> mkdir_sp ) {
+       printf ( "  mkdir requests: %s\n", d -> mkdir_sp );
+      }
 
       if ( do_icon ) {
        if ( pnd_emit_icon ( "./testdata/dotdesktop", d ) ) {
index e761151..88f1962 100644 (file)
@@ -16,6 +16,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.1" xsi:noN
 
   <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
 
+  <mkdir>
+    <dir path="common/mydir1"/>
+    <dir path="common/mydir2"/>
+  </mkdir>
+
   <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
   <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->