Added my own evdev handler for dpad/dpadbuttons/nubs, works fantastic
[pandora-libraries.git] / lib / pnd_apps.c
index daf3dda..73a78e3 100644 (file)
@@ -4,15 +4,47 @@
 #include <string.h> /* for memset */
 #include <unistd.h> /* for fork/exec */
 
+#include <sys/types.h> /* for wait */
+#include <sys/wait.h> /* for wait */
+
 #include "pnd_container.h"
 #include "pnd_pxml.h"
 #include "pnd_apps.h"
+#include "pnd_logger.h"
+
+static char apps_exec_runline [ 1024 ];
+
+char *pnd_apps_exec_runline ( void ) {
+  return ( apps_exec_runline );
+}
+
+unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
+                             char *rel_exec, char *rel_startdir,
+                             char *args,
+                             unsigned int clockspeed, unsigned int options )
+{
+  char *argv [ 60 ];
+  char s_clockspeed [ 100 ];
+  int f;
+
+  //printf ( "Entering pnd_apps_exec\n" );
+
+  if ( ! pndrun ) {
+    return ( 0 );
+  }
+
+  if ( ! fullpath ) {
+    return ( 0 );
+  }
 
-unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id, char *rel_exec, char *rel_startdir, unsigned int clockspeed ) {
-  char *argv [ 20 ];
-  int f, i;
+  if ( ! unique_id ) {
+    return ( 0 );
+  }
+
+  if ( ! rel_exec ) {
+    return ( 0 );
+  }
 
-  printf ( "Entering pnd_apps_exec\n" );
 #if 0
   printf ( "  runscript: %s\n", pndrun );
   printf ( "  path: %s\n", fullpath );
@@ -30,16 +62,79 @@ unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id, cha
   argv [ f++ ] = fullpath;
   argv [ f++ ] = "-e";
   argv [ f++ ] = rel_exec;
+  if ( rel_startdir ) {
+    argv [ f++ ] = "-s";
+    argv [ f++ ] = rel_startdir;
+  }
+  if ( args ) {
+    argv [ f++ ] = "-a";
+    argv [ f++ ] = args;
+  }
+  argv [ f++ ] = "-b";
+  argv [ f++ ] = unique_id;
+  if ( clockspeed ) {
+    argv [ f++ ] = "-c";
+    snprintf ( s_clockspeed, 100, "%u", clockspeed );
+    argv [ f++ ] = s_clockspeed;
+  }
+
   // skip -a (arguments) for now
 
-  //argv [ f++ ] = "-b";
-  //argv [ f++ ] = baename;
+  if ( options & PND_EXEC_OPTION_NOUNION ) {
+    argv [ f++ ] = "-n"; // no union for now
+  }
 
-  argv [ f++ ] = "-u"; // no union for now
+  if ( options & PND_EXEC_OPTION_NOX11 ) {
+    argv [ f++ ] = "-x"; // shut down X!
+  }
+
+  // finish
   argv [ f++ ] = NULL; // for execv
 
+  // stop here?
+  if ( options & PND_EXEC_OPTION_NORUN ) {
+    unsigned char i;
+    bzero ( apps_exec_runline, 1024 );
+    //pnd_log ( PND_LOG_DEFAULT, "Norun %u\n", f );
+    unsigned char quotenext = 0;
+    for ( i = 0; i < ( f - 1 ); i++ ) {
+      //pnd_log ( PND_LOG_DEFAULT, "Norun %u: %s\n", i, argv [ i ] );
+
+      // add spacing between args
+      if ( i > 0 ) {
+       strncat ( apps_exec_runline, " ", 1000 );
+      }
+
+      // quoting
+      if ( quotenext ) {
+       strncat ( apps_exec_runline, "\"", 1000 );
+      }
+
+      // arg
+      strncat ( apps_exec_runline, argv [ i ], 1000 );
+
+      // unquoting
+      if ( quotenext ) {
+       strncat ( apps_exec_runline, "\"", 1000 );
+      }
+
+      // clear quoting
+      if ( quotenext ) {
+       quotenext = 0;
+      } else {
+       // if this is for -a, we need to wrap with quotes
+       if ( strcmp ( argv [ i ], "-a" ) == 0 ) {
+         quotenext = 1;
+       }
+      }
+
+    } // for
+    return ( 1 );
+  }
+
   // debug
 #if 0
+  int i;
   for ( i = 0; i < f; i++ ) {
     printf ( "exec's argv %u [ %s ]\n", i, argv [ i ] );
   }
@@ -56,7 +151,74 @@ unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id, cha
     execv ( pndrun, argv );
   } 
 
-  printf ( "Exiting pnd_apps_exec\n" );
+  // by definition, either error occurred or we are the original application.
+
+  // do we wish to wait until the child process completes? (we don't
+  // care if it crashed, was killed, was suspended, whatever.)
+  if ( options & PND_EXEC_OPTION_BLOCK ) {
+    int status = 0;
+    waitpid ( f, &status, 0 /* no options */ );
+    //wait ( &status );
+  }
+
+  // printf ( "Exiting pnd_apps_exec\n" );
+
+  return ( 1 );
+}
+
+void pnd_get_ro_mountpoint ( char *fullpath, char *unique_id, char *r_mountpoint, unsigned int mountpoint_len ) {
+
+  if ( ! r_mountpoint ) {
+    return; // sillyness
+  }
+
+  snprintf ( r_mountpoint, mountpoint_len, "%s/%s/", PND_MOUNT_PATH, unique_id );
+
+  return;
+}
+
+unsigned char pnd_get_appdata_path ( char *fullpath, char *unique_id, char *r_path, unsigned int path_len ) {
+  // you know, determining the 'mount point' used is sort of a pain in the rear
+  // use df <file>, skip header line, grab first token. Cheap and should work.
+  // (Rather than just assume first two path chunks in path, say, which would be pretty darned
+  // accurate, but whose to say they're not using NFS or crazy mountpoints?)
+  FILE *df;
+  char cmdbuf [ 1024 ];
+
+  snprintf ( cmdbuf, 1023, "/bin/df %s", fullpath );
+
+  df = popen ( cmdbuf, "r" );
+
+  if ( ! df ) {
+    return ( 0 ); // tunefs: you can tune a filesystem but you can't tune a fish
+  }
+
+  // fetch and discard header
+  if ( ! fgets ( cmdbuf, 1023, df ) ) {
+    pclose ( df );
+    return ( 0 );
+  }
+
+  // grab df result line
+  if ( ! fgets ( cmdbuf, 1023, df ) ) {
+    pclose ( df );
+    return ( 0 );
+  }
+
+  pclose ( df );
+
+  // parse
+  char *ws = strchr ( cmdbuf, ' ' );
+
+  if ( ! ws ) {
+    return ( 0 );
+  }
+
+  *ws = '\0';
+
+  if ( r_path && path_len ) {
+    snprintf ( r_path, path_len, "%s/appdata/%s/", cmdbuf, unique_id );
+  }
 
   return ( 1 );
 }