pndevmapperd: add f-keys
[pandora-libraries.git] / lib / pnd_apps.c
index 4a2cf94..92a4b7a 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h> /* for malloc */
 #include <string.h> /* for memset */
 #include <unistd.h> /* for fork/exec */
+#include <limits.h>
 
 #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"
 
-unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
-                             char *rel_exec, char *rel_startdir,
-                             unsigned int clockspeed, unsigned int options )
+static char apps_exec_runline [ 1024 ];
+
+char *pnd_apps_exec_runline ( void ) {
+  return ( apps_exec_runline );
+}
+
+unsigned char pnd_apps_exec_disco ( char *pndrun, pnd_disco_t *app,
+                                   unsigned int options, void *reserved )
 {
-  char *argv [ 20 ];
+  char *argv [ 60 ];
+  char fullpath [ PATH_MAX ] = "";
   int f;
 
   //printf ( "Entering pnd_apps_exec\n" );
@@ -24,27 +32,23 @@ unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
     return ( 0 );
   }
 
-  if ( ! fullpath ) {
+  if ( ! app -> unique_id ) {
     return ( 0 );
   }
 
-  if ( ! unique_id ) {
+  if ( ! app -> exec ) {
     return ( 0 );
   }
 
-  if ( ! rel_exec ) {
+  if ( options & PND_EXEC_OPTION_INFO && ! reserved ) {
     return ( 0 );
   }
 
-#if 0
-  printf ( "  runscript: %s\n", pndrun );
-  printf ( "  path: %s\n", fullpath );
-  printf ( "  id: %s\n", unique_id );
-  printf ( "  exec: %s\n", rel_exec );
-  printf ( "  cwd: %s\n", rel_startdir );
-  printf ( "  clock: %u\n", clockspeed );
-#endif
+  // determine path to pnd-file
+  sprintf ( fullpath, "%s/%s", app -> object_path, app -> object_filename );
 
+  // nail down argv for the app
+  //
   memset ( argv, '\0', sizeof(char*) * 20 );
 
   f = 0;
@@ -52,23 +56,114 @@ unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
   argv [ f++ ] = "-p";
   argv [ f++ ] = fullpath;
   argv [ f++ ] = "-e";
-  argv [ f++ ] = rel_exec;
-  if ( rel_startdir ) {
+  if ( options & PND_EXEC_OPTION_INFO ) {
+    argv [ f++ ] = ((pnd_apps_exec_info_t*)reserved) -> viewer;
+  } else {
+    argv [ f++ ] = app -> exec;
+  }
+  if ( app -> startdir ) {
     argv [ f++ ] = "-s";
-    argv [ f++ ] = rel_startdir;
+    argv [ f++ ] = app -> startdir;
+  }
+  if ( options & PND_EXEC_OPTION_INFO ) {
+    if ( ((pnd_apps_exec_info_t*)reserved) -> args ) {
+      argv [ f++ ] = "-a";
+      argv [ f++ ] = ((pnd_apps_exec_info_t*)reserved) -> args;
+    }
+  } else {
+    if ( app -> execargs ) {
+      argv [ f++ ] = "-a";
+      argv [ f++ ] = app -> execargs;
+    }
+  }
+  if ( app -> appdata_dirname ) {
+    argv [ f++ ] = "-b";
+    argv [ f++ ] = app -> appdata_dirname;
+  } else {
+    argv [ f++ ] = "-b";
+    argv [ f++ ] = app -> unique_id;
   }
-  // skip -a (arguments) for now
 
-  //argv [ f++ ] = "-b";
-  //argv [ f++ ] = baename;
+  if ( options & PND_EXEC_OPTION_INFO ) {
+    // we don't need to overclock for showing info :) do we? crazy active .js pages maybe?
+  } else {
+    if ( app -> clockspeed ) {
+      argv [ f++ ] = "-c";
+      argv [ f++ ] = app -> clockspeed;
+    }
+  }
+
+  // skip -a (arguments) for now
 
   if ( options & PND_EXEC_OPTION_NOUNION ) {
     argv [ f++ ] = "-n"; // 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 {
+       // deprecated; need to handle spaces in some additional args
+       //   if ( strcmp ( argv [ i ], "-a" ) == 0 ) {
+       // if this is for -a, we need to wrap with quotes
+       // ivanovic:
+       // to allow spaces in filenames we have to add quotes around most terms!
+       // terms with quotes:
+       // -a additional arguments
+       // -p fullpath to pnd
+       // -e name of execuatable inside the pnd
+       // -s startdir
+       // -b name for the appdir
+
+       if ( ( strcmp ( argv [ i ], "-a" ) == 0 ) ||
+            ( strcmp ( argv [ i ], "-p" ) == 0 ) ||
+            ( strcmp ( argv [ i ], "-e" ) == 0 ) ||
+            ( strcmp ( argv [ i ], "-s" ) == 0 ) ||
+            ( strcmp ( argv [ i ], "-b" ) == 0 ) )
+       {
+         quotenext = 1;
+       }
+
+      }
+
+    } // for
+    return ( 1 );
+  }
+
   // debug
 #if 0
   int i;
@@ -86,7 +181,7 @@ unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
   } else {
     // child, do it
     execv ( pndrun, argv );
-  } 
+  }
 
   // by definition, either error occurred or we are the original application.
 
@@ -94,11 +189,104 @@ unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
   // 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 );
+    waitpid ( f, &status, 0 /* no options */ );
+    //wait ( &status );
   }
 
   // printf ( "Exiting pnd_apps_exec\n" );
 
   return ( 1 );
 }
+
+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 )
+{
+  pnd_disco_t d;
+  bzero ( &d, sizeof(pnd_disco_t) );
+
+  char cpuspeed [ 10 ];
+  sprintf ( cpuspeed, "%u", clockspeed );
+
+  char hackpath [ PATH_MAX ];
+  strncpy ( hackpath, fullpath, PATH_MAX );
+  char *c = strrchr ( hackpath, '/' );
+  if ( c ) {
+    *c = '\0';
+    d.object_path = hackpath;
+    d.object_filename = c + 1;
+  } else {
+    d.object_path = fullpath;
+  }
+
+  d.unique_id = unique_id;
+  d.exec = rel_exec;
+  d.startdir = rel_startdir;
+  d.execargs = args;
+  if ( clockspeed ) {
+    d.clockspeed = cpuspeed;
+  } else {
+    d.clockspeed = NULL;
+  }
+
+  return ( pnd_apps_exec_disco ( pndrun, &d, options, NULL ) );
+}
+
+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/pandora/appdata/%s/", cmdbuf, unique_id );
+  }
+
+  return ( 1 );
+}
+