Merge branch 'master' of git://git.openpandora.org/pandora-libraries
authorvimacs <vimacs@pndtest>
Sun, 15 Nov 2009 00:02:53 +0000 (01:02 +0100)
committervimacs <vimacs@pndtest>
Sun, 15 Nov 2009 00:02:53 +0000 (01:02 +0100)
13 files changed:
Makefile
apps/pnd_run.c [new file with mode: 0644]
apps/pndnotifyd.c
deployment/etc/pandora/conf/apps
include/pnd_apps.h
include/pnd_conf.h
include/pnd_device.h
include/pnd_logger.h [new file with mode: 0644]
lib/pnd_conf.c
lib/pnd_device.c
lib/pnd_logger.c [new file with mode: 0644]
test/loggertest.c [new file with mode: 0644]
testdata/conf/apps

index 4bfd9cf..e17b2a1 100644 (file)
--- 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
+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
+all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest pnd_run
 
 clean:
-       ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o
+       ${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/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o
        ${RM} -rf deployment/media
        find . -name "*~*" -exec rm {} \; -print
 
@@ -51,6 +51,9 @@ pndnotifyd:   pndnotifyd.o ${SOLIB1}
 pndvalidator:  pndvalidator.o ${SOLIB1}
        ${CC} -lstdc++ -o bin/pndvalidator pndvalidator.o ${SOLIB1}
 
+pnd_run:       pnd_run.o ${SOLIB1}
+       ${CC} -lstdc++ -o bin/pnd_run pnd_run.o ${SOLIB1}
+
 # deployment and assembly components
 #
 
@@ -75,6 +78,7 @@ deploy:
        # copy in goodies
        cp libpnd* deployment/usr/lib
        cp bin/pndnotifyd deployment/usr/bin
+       cp bin/pnd_run deployment/usr/bin
        cp testdata/scripts/* deployment/usr/pandora/scripts
        # copy in freebee .pnd apps to /usr/pandora/apps
        # add pndnotify to etc/rc/startup-whatever
@@ -98,3 +102,6 @@ locatetest:  locatetest.o ${SOLIB1}
 
 rawpxmltest:    rawpxmltest.o ${LIB}
        ${CC} -lstdc++ -o bin/rawpxmltest rawpxmltest.o ${LIB}
+
+loggertest:    loggertest.o ${LIB}
+       ${CC} -lstdc++ -o bin/loggertest loggertest.o libpnd.a
diff --git a/apps/pnd_run.c b/apps/pnd_run.c
new file mode 100644 (file)
index 0000000..98b9bc7
--- /dev/null
@@ -0,0 +1,185 @@
+
+#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 [-r runscript] [-n] path-to-pndfile\n", argv [ 0 ] );
+  printf ( "-r\tOptional. If not specified, will attempt to suss from configs.\n" );
+  printf ( "-n\tOptional. If present, instruct runscript to kill/restart X11 around app.\n" );
+  printf ( "pndfile\tRequired. Full path to the pnd-file to execute.\n" );
+  return;
+}
+
+int main ( int argc, char *argv[] ) {
+  char *pnd_run = NULL;
+  char *pndfile = NULL;
+  unsigned char no_x11 = 0;
+  unsigned char i;
+
+  for ( i = 1; i < argc; i++ ) {
+
+    if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'r' ) {
+      pnd_run = argv [ i + 1 ];
+      i++;
+      if ( ! pnd_run ) {
+       printf ( "-r specified, but no argument provided.\n" );
+       exit ( 0 );
+      }
+    } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'n' ) {
+      no_x11 = 1;
+    } else {
+
+      if ( argv [ i ][ 0 ] == '-' ) {
+       usage ( argv );
+       exit ( 0 );
+      } else if ( pndfile ) {
+       printf ( "Only one pndfile may be specified.\n" );
+      } else {
+       pndfile = argv [ i ];
+      }
+
+    }
+
+  } // for args
+
+  // if runscript was not specified on cmdline, attempt to pick it up from config
+  // ---> cribbed right out of discotest :/ copypaste ftw!
+  if ( ! pnd_run ) {
+    char *configpath;
+    char *appspath;
+    char *overridespath;
+
+    // attempt to fetch a sensible default searchpath for configs
+    configpath = pnd_conf_query_searchpath();
+
+    // attempt to fetch the apps config. since it finds us the runscript
+    pnd_conf_handle apph;
+
+    apph = pnd_conf_fetch_by_id ( pnd_conf_apps, configpath );
+
+    if ( apph ) {
+      appspath = pnd_conf_get_as_char ( apph, PND_APPS_KEY );
+
+      if ( ! appspath ) {
+       appspath = PND_APPS_SEARCHPATH;
+      }
+
+      overridespath = pnd_conf_get_as_char ( apph, PND_PXML_OVERRIDE_KEY );
+
+      if ( ! overridespath ) {
+       overridespath = PND_PXML_OVERRIDE_SEARCHPATH;
+      }
+
+    } else {
+      // couldn't find a useful app search path so use the default
+      appspath = PND_APPS_SEARCHPATH;
+      overridespath = PND_PXML_OVERRIDE_SEARCHPATH;
+    }
+
+    // given app-config, try to locate a runscript
+    char *run_searchpath;
+    char *run_script;
+    char *pndrun;
+
+    if ( apph ) {
+      run_searchpath = pnd_conf_get_as_char ( apph, PND_PNDRUN_SEARCHPATH_KEY );
+      run_script = pnd_conf_get_as_char ( apph, PND_PNDRUN_KEY );
+      pndrun = NULL;
+
+      if ( ! run_searchpath ) {
+       run_searchpath = PND_APPS_SEARCHPATH;
+       run_script = PND_PNDRUN_FILENAME;
+      }
+
+    } else {
+      run_searchpath = NULL;
+      run_script = NULL;
+      pndrun = PND_PNDRUN_DEFAULT;
+    }
+
+    if ( ! pndrun ) {
+      pndrun = pnd_locate_filename ( run_searchpath, run_script );
+    }
+
+    // hand back to main proggy
+    pnd_run = pndrun; // lame, fix this
+
+  } // try to locate runscript
+
+  if ( ! pnd_run ) {
+    printf ( "Runscript could not be determined. Fail.\n" );
+    exit ( 0 );
+  }
+
+  if ( ! pndfile ) {
+    usage ( argv );
+    exit ( 0 );
+  }
+
+  // summary
+  printf ( "Runscript\t%s\n", pnd_run );
+  printf ( "Pndfile\t%s\n", pndfile );
+  printf ( "Kill X11\t%s\n", no_x11 ? "true" : "false" );
+
+  // sadly, to launch a pnd-file we need to know what the executable is in there
+  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 );
+  }
+
+  // attempt to invoke
+  unsigned int options = 0;
+  if ( no_x11 ) {
+    options |= PND_EXEC_OPTION_NOX11;
+  }
+
+  unsigned int clock = 200;
+  if ( pnd_pxml_get_clockspeed ( h ) ) {
+    clock = atoi ( pnd_pxml_get_clockspeed ( h ) );
+  }
+
+  if ( ! pnd_apps_exec ( pnd_run, pndfile,
+                        pnd_pxml_get_unique_id ( h ),
+                        pnd_pxml_get_exec ( h ),
+                        pnd_pxml_get_startdir ( h ),
+                        clock,
+                        options )
+       )
+  {
+    printf ( "ERROR: PXML.xml data is bad\n" );
+  }
+
+  return ( 0 );
+} // main
index 70ab5ac..822c8f9 100644 (file)
@@ -30,6 +30,7 @@
 #include "pnd_pxml.h"
 #include "pnd_utility.h"
 #include "pnd_desktop.h"
+#include "pnd_logger.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..
 // op mode; emitting stdout or no?
 static unsigned char g_daemon_mode = 0;
 
+typedef enum {
+  pndn_debug = 0,
+  pndn_rem,          // will set default log level to here, so 'debug' is omitted
+  pndn_warning,
+  pndn_error,
+  pndn_none
+} pndnotify_loglevels_e;
+
 // like discotest
 char *configpath;
 char *appspath;
@@ -54,6 +63,9 @@ char *pndhup = NULL;  // full path to located pnd_hup.sh
 // notifier handle
 pnd_notify_handle nh = 0;
 
+// constants
+#define PNDNOTIFYD_LOGLEVEL "pndnotifyd.loglevel"
+
 // decl's
 void consume_configuration ( void );
 void setup_notifications ( void );
@@ -87,12 +99,21 @@ int main ( int argc, char *argv[] ) {
       exit ( 0 );
     }
 
-  }
+  } // for
 
-  if ( ! g_daemon_mode ) {
-    printf ( "Interval between checks is %u seconds\n", interval_secs );
+  /* enable logging?
+   */
+  if ( g_daemon_mode ) {
+    // nada
+  } else {
+    pnd_log_set_filter ( pndn_rem );
+    pnd_log_set_pretext ( "pndnotifyd" );
+    pnd_log_to_stdout();
+    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 );
+
   // basic daemon set up
   if ( g_daemon_mode ) {
 
@@ -103,7 +124,7 @@ int main ( int argc, char *argv[] ) {
 
     // detach from terminal
     if ( ( i = fork() ) < 0 ) {
-      printf ( "ERROR: Couldn't fork()\n" );
+      pnd_log ( pndn_error, "ERROR: Couldn't fork()\n" );
       exit ( i );
     }
     if ( i ) {
@@ -124,13 +145,11 @@ int main ( int argc, char *argv[] ) {
   /* startup
    */
 
-  if ( ! g_daemon_mode ) {
-    printf ( "Apps searchpath is '%s'\n", appspath );
-    printf ( "PXML overrides searchpath is '%s'\n", overridespath );
-    printf ( ".desktop files emit to '%s'\n", dotdesktoppath );
-    printf ( ".desktop icon files emit to '%s'\n", iconpath );
-    printf ( "Notify searchpath is '%s'\n", notifypath );
-  }
+  pnd_log ( pndn_rem, "Apps searchpath is '%s'\n", appspath );
+  pnd_log ( pndn_rem, "PXML overrides searchpath is '%s'\n", overridespath );
+  pnd_log ( pndn_rem, ".desktop files emit to '%s'\n", dotdesktoppath );
+  pnd_log ( pndn_rem, ".desktop icon files emit to '%s'\n", iconpath );
+  pnd_log ( pndn_rem, "Notify searchpath is '%s'\n", notifypath );
 
   /* set up signal handler
    */
@@ -172,10 +191,8 @@ int main ( int argc, char *argv[] ) {
       // 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 ( ! g_daemon_mode ) {
-       printf ( "------------------------------------------------------\n" );
-       printf ( "Changes within watched paths .. performing re-discover!\n" );
-      }
+      pnd_log ( pndn_rem, "------------------------------------------------------\n" );
+      pnd_log ( pndn_rem, "Changes within watched paths .. performing re-discover!\n" );
 
       // run the discovery
       applist = pnd_disco_search ( appspath, overridespath );
@@ -186,9 +203,7 @@ int main ( int argc, char *argv[] ) {
 
        while ( d ) {
 
-         if ( ! g_daemon_mode ) {
-           printf ( "Found app: %s\n", pnd_box_get_key ( 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
@@ -199,9 +214,7 @@ int main ( int argc, char *argv[] ) {
          if ( stat ( existingpath, &dirs ) == 0 ) {
            // icon seems to exist, so just crib the location into the .desktop
 
-           if ( ! g_daemon_mode ) {
-             printf ( "  Found icon already existed, so reusing it! %s\n", existingpath );
-           }
+           pnd_log ( pndn_rem, "  Found icon already existed, so reusing it! %s\n", existingpath );
 
            if ( d -> icon ) {
              free ( d -> icon );
@@ -211,9 +224,7 @@ int main ( int argc, char *argv[] ) {
          } else {
            // icon seems unreadable or does not exist; lets try to create it..
 
-           if ( ! g_daemon_mode ) {
-             printf ( "  Icon not already present, so trying to write it! %s\n", existingpath );
-           }
+           pnd_log ( pndn_rem, "  Icon not already present, so trying to write it! %s\n", existingpath );
 
            // 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..)
@@ -224,9 +235,7 @@ int main ( int argc, char *argv[] ) {
              }
              d -> icon = strdup ( existingpath );
            } else {
-             if ( ! g_daemon_mode ) {
-               printf ( "  WARN: Couldn't write out icon %s\n", existingpath );
-             }
+             pnd_log ( pndn_rem, "  WARN: Couldn't write out icon %s\n", existingpath );
            }
 
          } // icon already exists?
@@ -240,9 +249,7 @@ int main ( int argc, char *argv[] ) {
            pnd_notify_watch_path ( nh, buffer, PND_NOTIFY_RECURSE );
 #endif
          } else {
-           if ( ! g_daemon_mode ) {
-             printf ( "ERROR: Error creating .desktop file for app: %s\n", pnd_box_get_key ( d ) );
-           }
+           pnd_log ( pndn_rem, "ERROR: Error creating .desktop file for app: %s\n", pnd_box_get_key ( d ) );
          }
 
          // next!
@@ -252,9 +259,7 @@ int main ( int argc, char *argv[] ) {
 
       } else {
 
-       if ( ! g_daemon_mode ) {
-         printf ( "No applications found in search path\n" );
-       }
+       pnd_log ( pndn_rem, "No applications found in search path\n" );
 
       } // got apps?
 
@@ -305,15 +310,12 @@ int main ( int argc, char *argv[] ) {
            }
            if ( source_libpnd ) {
 #if 0
-             if ( ! g_daemon_mode ) {
-               printf ( "File '%s' appears to have been created by libpnd so candidate for delete: %u\n", buffer, source_libpnd );
-             }
+             pnd_log ( pndn_rem,
+                       "File '%s' appears to have been created by libpnd so candidate for delete: %u\n", buffer, source_libpnd );
 #endif
            } else {
 #if 0
-             if ( ! g_daemon_mode ) {
-               printf ( "File '%s' appears NOT to have been created by libpnd, so leave it alone\n", buffer );
-             }
+             pnd_log ( pndn_rem, "File '%s' appears NOT to have been created by libpnd, so leave it alone\n", buffer );
 #endif
              continue; // skip deleting it
            }
@@ -322,9 +324,7 @@ int main ( int argc, char *argv[] ) {
            if ( stat ( buffer, &dirs ) == 0 ) {
              if ( dirs.st_mtime >= createtime ) {
 #if 0
-               if ( ! g_daemon_mode ) {
-                 printf ( "File '%s' seems 'new', so leave it alone.\n", buffer );
-               }
+               pnd_log ( pndn_rem, "File '%s' seems 'new', so leave it alone.\n", buffer );
 #endif
                continue; // skip deleting it
              }
@@ -332,9 +332,7 @@ int main ( int argc, char *argv[] ) {
 
            // by this point, the .desktop file must be 'old' and created by pndnotifyd
            // previously, so can remove it
-           if ( ! g_daemon_mode ) {
-             printf ( "File '%s' seems nolonger relevent; removing it.\n", dirent -> d_name );
-           }
+           pnd_log ( pndn_rem, "File '%s' seems nolonger relevent; removing it.\n", dirent -> d_name );
            unlink ( buffer );
 
          } // while getting filenames from dir
@@ -346,9 +344,7 @@ int main ( int argc, char *argv[] ) {
 
       // if we've got a hup script located, lets invoke it
       if ( pndhup ) {
-       if ( ! g_daemon_mode ) {
-         printf ( "Invoking hup script '%s'.\n", pndhup );
-       }
+       pnd_log ( pndn_rem, "Invoking hup script '%s'.\n", pndhup );
        pnd_exec_no_wait_1 ( pndhup, NULL );
       }
 
@@ -443,6 +439,11 @@ void consume_configuration ( void ) {
       run_script = PND_PNDRUN_FILENAME;
     }
 
+    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() );
+    }
+
   } else {
     run_searchpath = NULL;
     run_script = NULL;
@@ -479,15 +480,13 @@ void consume_configuration ( void ) {
   }
 
   // debug
-  if ( ! g_daemon_mode ) {
-    if ( run_searchpath ) printf ( "Locating pnd run in %s\n", run_searchpath );
-    if ( run_script ) printf ( "Locating pnd runscript as %s\n", run_script );
-    if ( pndrun ) printf ( "pndrun is %s\n", pndrun );
-    if ( pndhup ) {
-      printf ( "pndhup is %s\n", pndhup );
-    } else {
-      printf ( "No pndhup found (which is fine.)\n" );
-    }
+  if ( run_searchpath ) pnd_log ( pndn_rem, "Locating pnd run in %s\n", run_searchpath );
+  if ( run_script ) pnd_log ( pndn_rem, "Locating pnd runscript as %s\n", run_script );
+  if ( pndrun ) pnd_log ( pndn_rem, "pndrun is %s\n", pndrun );
+  if ( pndhup ) {
+    pnd_log ( pndn_rem, "pndhup is %s\n", pndhup );
+  } else {
+    pnd_log ( pndn_rem, "No pndhup found (which is fine.)\n" );
   }
 
   /* handle globbing or variable substitution
@@ -523,25 +522,18 @@ void setup_notifications ( void ) {
   }
 
   if ( ! nh ) {
-    if ( ! g_daemon_mode ) {
-      printf ( "INOTIFY failed to init.\n" );
-    }
+    pnd_log ( pndn_rem, "INOTIFY failed to init.\n" );
     exit ( -1 );
   }
 
 #if 0
-  if ( ! g_daemon_mode ) {
-    printf ( "INOTIFY is up.\n" );
-  }
+  pnd_log ( pndn_rem, "INOTIFY is up.\n" );
 #endif
 
   SEARCHPATH_PRE
   {
 
-    if ( ! g_daemon_mode ) {
-      printf ( "Watching path '%s' and its descendents.\n", buffer );
-    }
-
+    pnd_log ( pndn_rem, "Watching path '%s' and its descendents.\n", buffer );
     pnd_notify_watch_path ( nh, buffer, PND_NOTIFY_RECURSE );
 
   }
@@ -552,9 +544,7 @@ void setup_notifications ( void ) {
 
 void sighup_handler ( int n ) {
 
-  if ( ! g_daemon_mode ) {
-    printf ( "---[ SIGHUP received ]---\n" );
-  }
+  pnd_log ( pndn_rem, "---[ SIGHUP received ]---\n" );
 
   // reparse config files
   consume_configuration();
index 340814c..9040efe 100644 (file)
@@ -18,3 +18,8 @@ searchpath    ~/pxml-overrides
 [pnd]
 searchpath     /media/*/pandora/scripts:/usr/pandora/scripts
 runscript      pnd_run.sh
+
+# [pndnotifyd] sets some extra pndnotifyd specific items
+[pndnotifyd]
+# logging level 0 means to include debug; level 1 (regular), 2 (warnings), 3 (errors)
+#loglevel      0
index 719622a..51939f9 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * NOTE: if specified, clock speed will be set prior to invoking the script, and set back on exit
  * NOTE: No values can be except clockspeed; a 0 clockspeed means 'leave alone'. Set startdoir to "." instead of NULL.
  * fork() is implied; calling this function does not kill this process :)
- * NOTE: PAss in the full path to the awesomeapp.pnd or to the directory containing PXML.xml (not the PXML.xml itself.)
+ * NOTE: Pass in the full path to the awesomeapp.pnd or to the directory containing PXML.xml (not the PXML.xml itself.)
  * Options is a set of boolean flags, derived from the #define's below; OR them together.
  *   option-block, when set, suggests the launch should wait until the invoked application exits (disregarding why app exits)
  *   example: options = PND_EXEC_OPTION_BLOCK | PND_EXEC_OPTION_2;
index 6cd18f5..9af6eee 100644 (file)
@@ -120,6 +120,8 @@ pnd_conf_handle pnd_conf_fetch_by_path ( char *fullpath );
  * Returns NULL on error, otherwise a READ ONLY char* reference to the value.
  */
 char *pnd_conf_get_as_char ( pnd_conf_handle c, char *key );
+#define PND_CONF_BADNUM (-31337) /* really lame hack, I know */
+int pnd_conf_get_as_int ( pnd_conf_handle c, char *key );
 
 #ifdef __cplusplus
 } /* "C" */
index b1f021a..706b783 100644 (file)
@@ -20,7 +20,7 @@ extern "C" {
 #define PND_DEVICE_SYS_BACKLIGHT_BRIGHTNESS "/sys/class/backlight/gpio-backlight/brightness"
 #define PND_DEVICE_FRAMEBUFFER "/dev/fb0"
 #define PND_DEVICE_NUB1 "/dev/input/js1"
-#define PND_DEVICE_NUB1 "/dev/input/js2"
+#define PND_DEVICE_NUB2 "/dev/input/js2"
 
 /* utility
  */
diff --git a/include/pnd_logger.h b/include/pnd_logger.h
new file mode 100644 (file)
index 0000000..d9fcc19
--- /dev/null
@@ -0,0 +1,46 @@
+
+#ifndef h_pnd_logger_h
+#define h_pnd_logger_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+
+/* rudimentary logger; note that this is meant to be a no-brainer to use, so no setup is needed.
+ */
+#define PND_LOG_FORCE (0xFF) /* use this log level to require it be emitted, no skipping */
+
+// defaults will have no filtering, so any message will be emitted to all targets
+// default target is nothing, however, so logger is silent unless activated
+unsigned char pnd_log ( unsigned char level, char *format, ... );           // returns true if emitted; \n is implied!
+unsigned char pnd_log_to_stdout ( void );                                   // same as pnd_log_to_stream ( stdout );
+unsigned char pnd_log_to_stderr ( void );                                   // same as pnd_log_to_stream ( stderr );
+
+/* the below is all optional, for when you need more control
+ */
+
+// logging is additive; you can log to multiple targets at once. Returns 'true' if accepted, false if could not set up.
+void pnd_log_to_nil ( void );                                               // stop logging to anywhere; does not close streams/etc
+unsigned char pnd_log_to_stream ( FILE * );                                 // 'stdout', 'stderr', or your own FILE* are good values
+unsigned char pnd_log_to_syslog ( char *facility );                         // NYI
+typedef void (*pnd_log_callback_f)( char *text, void *userdata );
+unsigned char pnd_log_to_callback ( pnd_log_callback_f f, void *userdata ); // NYI
+
+// pass NULL to free any pre-text, otherwise it'll be kept. Passed in string is duplicated, so you may free yours if you like.
+void pnd_log_set_pretext ( char * );                                        // example: your app-name, or app+function-names, say.
+
+// set a 'filter level'; any log message of higher-or-equal level than current filter-level will be emitted. Thus, to remove filters
+// just set to level 0. Returns existing setting.
+unsigned char pnd_log_set_filter ( unsigned char newlevel );                // ex: app-specific enum/#defines for your levels
+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 );
+
+#ifdef __cplusplus
+} /* "C" */
+#endif
+
+#endif
index e3077c2..636625e 100644 (file)
@@ -239,3 +239,15 @@ pnd_conf_handle pnd_conf_fetch_by_path ( char *fullpath ) {
 char *pnd_conf_get_as_char ( pnd_conf_handle c, char *key ) {
   return ( pnd_box_find_by_key ( c, key ) );
 }
+
+int pnd_conf_get_as_int ( pnd_conf_handle c, char *key ) {
+  char *t = pnd_box_find_by_key ( c, key );
+
+  if ( ! t ) {
+    return ( PND_CONF_BADNUM ); // non-existant
+  }
+
+  int i = atoi ( t );
+
+  return ( i );
+}
index f853ffc..42a17ca 100644 (file)
@@ -71,7 +71,7 @@ unsigned char pnd_device_set_backlight ( unsigned int c ) {
   return ( pnd_device_open_write_close ( PND_DEVICE_SYS_BACKLIGHT_BRIGHTNESS, buffer ) );
 }
 
-unsigned int pnd_device_get_clock ( void ) {
+unsigned int pnd_device_get_backlight ( void ) {
   char buffer [ 100 ];
 
   if ( pnd_device_open_read_close ( PND_DEVICE_SYS_BACKLIGHT_BRIGHTNESS, buffer, 100 ) ) {
diff --git a/lib/pnd_logger.c b/lib/pnd_logger.c
new file mode 100644 (file)
index 0000000..ebfd230
--- /dev/null
@@ -0,0 +1,190 @@
+
+#include <stdarg.h> // va-args
+#include <stdlib.h> // malloc/free
+#include <string.h> // strdup
+#include "pnd_logger.h"
+
+char *log_pretext = NULL;
+unsigned char log_filterlevel = 0;
+
+typedef enum {
+  pndl_nil = 0,
+  pndl_stream,
+  pndl_syslog,
+  pndl_callback
+} pnd_logger_e;
+
+typedef struct {
+  pnd_logger_e type;
+  union {
+    FILE *stream;
+    pnd_log_callback_f callback;
+  };
+} pnd_log_target_t;
+
+#define PND_LOG_MAX 5
+static pnd_log_target_t log_targets [ PND_LOG_MAX ]; // implicitly nil
+
+static int pnd_log_empty_slot ( void ) {
+  unsigned char i;
+
+  for ( i = 0; i < PND_LOG_MAX; i++ ) {
+    if ( log_targets [ i ].type == pndl_nil ) {
+      return ( i );
+    }
+  }
+
+  return ( -1 );
+}
+
+unsigned char pnd_log_set_filter ( unsigned char newlevel ) {
+  unsigned char foo = log_filterlevel;
+  log_filterlevel = newlevel;
+  return ( foo );
+}
+
+unsigned char pnd_log_get_filter ( void ) {
+  return ( log_filterlevel );
+}
+
+void pnd_log_set_pretext ( char *pre ) {
+
+  if ( log_pretext ) {
+    free ( log_pretext );
+    log_pretext = NULL;
+  }
+
+  if ( pre ) {
+    log_pretext = strdup ( pre );
+  }
+
+  return;
+}
+
+void pnd_log_to_nil ( void ) {
+  memset ( log_targets, '\0', sizeof(pnd_log_target_t) * PND_LOG_MAX );
+  return;
+}
+
+unsigned char pnd_log_to_stream ( FILE *f ) {
+  int i = pnd_log_empty_slot();
+
+  if ( i < 0 ) {
+    return ( 0 ); // fail!
+  }
+
+  log_targets [ i ].type = pndl_stream;
+  log_targets [ i ].stream = f;
+
+  return ( 1 );
+}
+
+unsigned char pnd_log_to_syslog ( char *facility ) {
+  return ( 0 ); // NYI
+}
+
+unsigned char pnd_log_to_callback ( pnd_log_callback_f f, void *userdata ) {
+  return ( 0 ); // NYI
+}
+
+unsigned char pnd_log_to_stdout ( void ) {
+  return ( pnd_log_to_stream ( stdout ) );
+}
+
+unsigned char pnd_log_to_stderr ( void ) {
+  return ( pnd_log_to_stream ( stderr ) );
+}
+
+unsigned char pnd_log_max_targets ( void ) {
+  return ( PND_LOG_MAX );
+}
+
+void pnd_log_emit ( char *message ) {
+  unsigned char i;
+
+  // iterate across targets and attempt to emit
+  for ( i = 0; i < PND_LOG_MAX; i++ ) {
+
+    switch ( log_targets [ i ].type ) {
+
+    case pndl_nil:
+      // nop
+      break;
+
+    case pndl_stream:
+      if ( log_pretext ) {
+       fprintf ( log_targets [ i ].stream, "%s\t", log_pretext );
+      }
+      if ( message ) {
+       fprintf ( log_targets [ i ].stream, "%s", message );
+       if ( strchr ( message, '\n' ) == NULL ) {
+         fprintf ( log_targets [ i ].stream, "\n" );
+       }
+      }
+      break;
+
+    case pndl_syslog:
+      // NYI
+      break;
+
+    case pndl_callback:
+      // NYI
+      break;
+
+    } // switch
+
+  } // for
+
+  return;
+}
+
+unsigned char pnd_log ( unsigned char level, char *fmt, ... ) {
+
+  if ( level == PND_LOG_FORCE ) {
+    // always proceed
+  } else if ( level < log_filterlevel ) {
+    return ( 0 ); // too low level
+  }
+
+  // format the actual log string
+  int n, size = 100;
+  char *p, *np;
+  va_list ap;
+
+  if ( ( p = malloc ( size ) ) == NULL ) {
+    return ( 0 ); // fail!
+  }
+
+  while  ( 1 ) {
+
+    /* Try to print in the allocated space. */
+    va_start ( ap, fmt );
+    n = vsnprintf ( p, size, fmt, ap );
+    va_end ( ap );
+
+    /* If that worked, return the string. */
+    if ( n > -1 && n < size ) {
+      pnd_log_emit ( p );
+      break;
+    }
+
+    /* Else try again with more space. */
+    if ( n > -1 )   /* glibc 2.1 */
+      size = n + 1; /* precisely what is needed */
+    else           /* glibc 2.0 */
+      size *= 2;  /* twice the old size */
+    if ( ( np = realloc ( p, size ) ) == NULL ) {
+      free(p);
+      return ( 0 ); // fail!
+    } else {
+      p = np;
+    }
+
+  } // while
+
+  if ( p ) {
+    free ( p );
+  }
+
+  return ( 1 );
+}
diff --git a/test/loggertest.c b/test/loggertest.c
new file mode 100644 (file)
index 0000000..f9255cf
--- /dev/null
@@ -0,0 +1,39 @@
+
+#include "pnd_logger.h"
+
+// arbitrary warning level
+#define PLOG_LOW    0
+#define PLOG_MEDIUM 1
+#define PLOG_HIGH   2
+
+int main ( void ) {
+
+  pnd_log ( PLOG_LOW, "low message, should be ignored" );
+
+  /* normal operation -------------- */
+  pnd_log_to_stdout();
+  pnd_log ( PLOG_LOW, "low message, should go stdout once" );
+  /* ------------------------------- */
+
+  /* extra testing vvvvvvvvvvvvvvvvv
+   */
+
+  pnd_log_to_stdout();
+  pnd_log ( PLOG_LOW, "low message, should go stdout twice" );
+
+  pnd_log_to_nil();
+  pnd_log_to_stdout();
+
+  pnd_log_set_pretext ( "loggertest" );
+  pnd_log ( PLOG_LOW, "low message, emit once, with pretext" );
+
+  pnd_log_set_filter ( PLOG_MEDIUM );
+  pnd_log ( PLOG_LOW, "low message, emit once, filter is medium+" );
+  pnd_log ( PLOG_MEDIUM, "medium message, emit once, filter is medium+" );
+  pnd_log ( PLOG_HIGH, "high message, emit once, filter is medium+" );
+
+  pnd_log_set_filter ( PLOG_LOW );
+  pnd_log ( PLOG_LOW, "low message, emit once, filter is low+ again" );
+
+  return ( 0 );
+}
index 46884ee..f7ab2c2 100644 (file)
@@ -14,3 +14,8 @@ searchpath    ~/pxml-overrides:./testdata/apps-override
 [pnd]
 searchpath     /mnt/sd?/pandora/scripts:./testdata/scripts
 runscript      pnd_run.sh
+
+# [pndnotifyd] sets some extra pndnotifyd specific items
+[pndnotifyd]
+# logging level 0 means to include debug; level 1 (regular), 2 (warnings), 3 (errors)
+loglevel       0