2 #include <stdio.h> /* for FILE etc */
3 #include <stdlib.h> /* for malloc */
4 #include <string.h> /* for memset */
5 #include <unistd.h> /* for fork/exec */
8 #include <sys/types.h> /* for wait */
9 #include <sys/wait.h> /* for wait */
11 #include "pnd_container.h"
14 #include "pnd_logger.h"
16 static char apps_exec_runline [ 1024 ];
18 char *pnd_apps_exec_runline ( void ) {
19 return ( apps_exec_runline );
22 unsigned char pnd_apps_exec_disco ( char *pndrun, pnd_disco_t *app,
23 unsigned int options, void *reserved )
26 char fullpath [ PATH_MAX ] = "";
29 //printf ( "Entering pnd_apps_exec\n" );
35 if ( ! app -> unique_id ) {
39 if ( ! app -> exec ) {
43 if ( options & PND_EXEC_OPTION_INFO && ! reserved ) {
47 // determine path to pnd-file
48 sprintf ( fullpath, "%s/%s", app -> object_path, app -> object_filename );
50 // nail down argv for the app
52 memset ( argv, '\0', sizeof(char*) * 20 );
55 argv [ f++ ] = pndrun;
57 argv [ f++ ] = fullpath;
59 if ( options & PND_EXEC_OPTION_INFO ) {
60 argv [ f++ ] = ((pnd_apps_exec_info_t*)reserved) -> viewer;
62 argv [ f++ ] = app -> exec;
64 if ( app -> startdir ) {
66 argv [ f++ ] = app -> startdir;
68 if ( options & PND_EXEC_OPTION_INFO ) {
69 if ( ((pnd_apps_exec_info_t*)reserved) -> args ) {
71 argv [ f++ ] = ((pnd_apps_exec_info_t*)reserved) -> args;
74 if ( app -> execargs ) {
76 argv [ f++ ] = app -> execargs;
79 if ( app -> appdata_dirname ) {
81 argv [ f++ ] = app -> appdata_dirname;
84 argv [ f++ ] = app -> unique_id;
87 if ( options & PND_EXEC_OPTION_INFO ) {
88 // we don't need to overclock for showing info :) do we? crazy active .js pages maybe?
90 if ( app -> clockspeed ) {
92 argv [ f++ ] = app -> clockspeed;
96 // skip -a (arguments) for now
98 if ( options & PND_EXEC_OPTION_NOUNION ) {
99 argv [ f++ ] = "-n"; // no union for now
102 if ( options & PND_EXEC_OPTION_NOX11 ) {
103 argv [ f++ ] = "-x"; // shut down X!
107 argv [ f++ ] = NULL; // for execv
110 if ( options & PND_EXEC_OPTION_NORUN ) {
112 bzero ( apps_exec_runline, 1024 );
113 //pnd_log ( PND_LOG_DEFAULT, "Norun %u\n", f );
114 unsigned char quotenext = 0;
115 for ( i = 0; i < ( f - 1 ); i++ ) {
116 //pnd_log ( PND_LOG_DEFAULT, "Norun %u: %s\n", i, argv [ i ] );
118 // add spacing between args
120 strncat ( apps_exec_runline, " ", 1000 );
125 strncat ( apps_exec_runline, "\"", 1000 );
129 strncat ( apps_exec_runline, argv [ i ], 1000 );
133 strncat ( apps_exec_runline, "\"", 1000 );
140 // deprecated; need to handle spaces in some additional args
141 // if ( strcmp ( argv [ i ], "-a" ) == 0 ) {
142 // if this is for -a, we need to wrap with quotes
144 // to allow spaces in filenames we have to add quotes around most terms!
145 // terms with quotes:
146 // -a additional arguments
147 // -p fullpath to pnd
148 // -e name of execuatable inside the pnd
150 // -b name for the appdir
152 if ( ( strcmp ( argv [ i ], "-a" ) == 0 ) ||
153 ( strcmp ( argv [ i ], "-p" ) == 0 ) ||
154 ( strcmp ( argv [ i ], "-e" ) == 0 ) ||
155 ( strcmp ( argv [ i ], "-s" ) == 0 ) ||
156 ( strcmp ( argv [ i ], "-b" ) == 0 ) )
170 for ( i = 0; i < f; i++ ) {
171 printf ( "exec's argv %u [ %s ]\n", i, argv [ i ] );
177 if ( ( f = fork() ) < 0 ) {
179 } else if ( f > 0 ) {
183 execv ( pndrun, argv );
186 // by definition, either error occurred or we are the original application.
188 // do we wish to wait until the child process completes? (we don't
189 // care if it crashed, was killed, was suspended, whatever.)
190 if ( options & PND_EXEC_OPTION_BLOCK ) {
192 waitpid ( f, &status, 0 /* no options */ );
196 // printf ( "Exiting pnd_apps_exec\n" );
201 unsigned char pnd_apps_exec ( char *pndrun, char *fullpath, char *unique_id,
202 char *rel_exec, char *rel_startdir,
204 unsigned int clockspeed, unsigned int options )
207 bzero ( &d, sizeof(pnd_disco_t) );
209 char cpuspeed [ 10 ];
210 sprintf ( cpuspeed, "%u", clockspeed );
212 char hackpath [ PATH_MAX ];
213 strncpy ( hackpath, fullpath, PATH_MAX );
214 char *c = strrchr ( hackpath, '/' );
217 d.object_path = hackpath;
218 d.object_filename = c + 1;
220 d.object_path = fullpath;
223 d.unique_id = unique_id;
225 d.startdir = rel_startdir;
228 d.clockspeed = cpuspeed;
233 return ( pnd_apps_exec_disco ( pndrun, &d, options, NULL ) );
236 void pnd_get_ro_mountpoint ( char *fullpath, char *unique_id, char *r_mountpoint, unsigned int mountpoint_len ) {
238 if ( ! r_mountpoint ) {
242 snprintf ( r_mountpoint, mountpoint_len, "%s/%s/", PND_MOUNT_PATH, unique_id );
247 unsigned char pnd_get_appdata_path ( char *fullpath, char *unique_id, char *r_path, unsigned int path_len ) {
248 // you know, determining the 'mount point' used is sort of a pain in the rear
249 // use df <file>, skip header line, grab first token. Cheap and should work.
250 // (Rather than just assume first two path chunks in path, say, which would be pretty darned
251 // accurate, but whose to say they're not using NFS or crazy mountpoints?)
253 char cmdbuf [ 1024 ];
255 snprintf ( cmdbuf, 1023, "/bin/df %s", fullpath );
257 df = popen ( cmdbuf, "r" );
260 return ( 0 ); // tunefs: you can tune a filesystem but you can't tune a fish
263 // fetch and discard header
264 if ( ! fgets ( cmdbuf, 1023, df ) ) {
269 // grab df result line
270 if ( ! fgets ( cmdbuf, 1023, df ) ) {
278 char *ws = strchr ( cmdbuf, ' ' );
286 if ( r_path && path_len ) {
287 snprintf ( r_path, path_len, "%s/pandora/appdata/%s/", cmdbuf, unique_id );