Added pnd_run binary app for invoking a pndfile by path; the app will figure out...
[pandora-libraries.git] / apps / pnd_run.c
1
2 #include <stdio.h> /* for printf, NULL */
3 #include <stdlib.h> /* for free */
4 #include <string.h> /* for strdup */
5
6 #include "pnd_conf.h"
7 #include "pnd_container.h"
8 #include "pnd_apps.h"
9 #include "pnd_discovery.h"
10 #include "pnd_locate.h"
11 #include "pnd_pndfiles.h"
12 #include "pnd_pxml.h"
13
14 static void usage ( char *argv[] ) {
15   printf ( "%s [-r runscript] [-n] path-to-pndfile\n", argv [ 0 ] );
16   printf ( "-r\tOptional. If not specified, will attempt to suss from configs.\n" );
17   printf ( "-n\tOptional. If present, instruct runscript to kill/restart X11 around app.\n" );
18   printf ( "pndfile\tRequired. Full path to the pnd-file to execute.\n" );
19   return;
20 }
21
22 int main ( int argc, char *argv[] ) {
23   char *pnd_run = NULL;
24   char *pndfile = NULL;
25   unsigned char no_x11 = 0;
26   unsigned char i;
27
28   for ( i = 1; i < argc; i++ ) {
29
30     if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'r' ) {
31       pnd_run = argv [ i + 1 ];
32       i++;
33       if ( ! pnd_run ) {
34         printf ( "-r specified, but no argument provided.\n" );
35         exit ( 0 );
36       }
37     } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'n' ) {
38       no_x11 = 1;
39     } else {
40
41       if ( argv [ i ][ 0 ] == '-' ) {
42         usage ( argv );
43         exit ( 0 );
44       } else if ( pndfile ) {
45         printf ( "Only one pndfile may be specified.\n" );
46       } else {
47         pndfile = argv [ i ];
48       }
49
50     }
51
52   } // for args
53
54   // if runscript was not specified on cmdline, attempt to pick it up from config
55   // ---> cribbed right out of discotest :/ copypaste ftw!
56   if ( ! pnd_run ) {
57     char *configpath;
58     char *appspath;
59     char *overridespath;
60
61     // attempt to fetch a sensible default searchpath for configs
62     configpath = pnd_conf_query_searchpath();
63
64     // attempt to fetch the apps config. since it finds us the runscript
65     pnd_conf_handle apph;
66
67     apph = pnd_conf_fetch_by_id ( pnd_conf_apps, configpath );
68
69     if ( apph ) {
70       appspath = pnd_conf_get_as_char ( apph, PND_APPS_KEY );
71
72       if ( ! appspath ) {
73         appspath = PND_APPS_SEARCHPATH;
74       }
75
76       overridespath = pnd_conf_get_as_char ( apph, PND_PXML_OVERRIDE_KEY );
77
78       if ( ! overridespath ) {
79         overridespath = PND_PXML_OVERRIDE_SEARCHPATH;
80       }
81
82     } else {
83       // couldn't find a useful app search path so use the default
84       appspath = PND_APPS_SEARCHPATH;
85       overridespath = PND_PXML_OVERRIDE_SEARCHPATH;
86     }
87
88     // given app-config, try to locate a runscript
89     char *run_searchpath;
90     char *run_script;
91     char *pndrun;
92
93     if ( apph ) {
94       run_searchpath = pnd_conf_get_as_char ( apph, PND_PNDRUN_SEARCHPATH_KEY );
95       run_script = pnd_conf_get_as_char ( apph, PND_PNDRUN_KEY );
96       pndrun = NULL;
97
98       if ( ! run_searchpath ) {
99         run_searchpath = PND_APPS_SEARCHPATH;
100         run_script = PND_PNDRUN_FILENAME;
101       }
102
103     } else {
104       run_searchpath = NULL;
105       run_script = NULL;
106       pndrun = PND_PNDRUN_DEFAULT;
107     }
108
109     if ( ! pndrun ) {
110       pndrun = pnd_locate_filename ( run_searchpath, run_script );
111     }
112
113     // hand back to main proggy
114     pnd_run = pndrun; // lame, fix this
115
116   } // try to locate runscript
117
118   if ( ! pnd_run ) {
119     printf ( "Runscript could not be determined. Fail.\n" );
120     exit ( 0 );
121   }
122
123   if ( ! pndfile ) {
124     usage ( argv );
125     exit ( 0 );
126   }
127
128   // summary
129   printf ( "Runscript\t%s\n", pnd_run );
130   printf ( "Pndfile\t%s\n", pndfile );
131   printf ( "Kill X11\t%s\n", no_x11 ? "true" : "false" );
132
133   // sadly, to launch a pnd-file we need to know what the executable is in there
134   unsigned int pxmlbuflen = 96 * 1024; // lame, need to calculate it
135   char *pxmlbuf = malloc ( pxmlbuflen );
136   if ( ! pxmlbuf ) {
137     printf ( "ERROR: RAM exhausted!\n" );
138     exit ( 0 );
139   }
140   memset ( pxmlbuf, '\0', pxmlbuflen );
141
142   FILE *f = fopen ( pndfile, "r" );
143   if ( ! f ) {
144     printf ( "ERROR: Couldn't open pndfile %s!\n", pndfile );
145     exit ( 0 );
146   }
147
148   pnd_pxml_handle h = NULL;
149   if ( pnd_pnd_seek_pxml ( f ) ) {
150     if ( pnd_pnd_accrue_pxml ( f, pxmlbuf, pxmlbuflen ) ) {
151       h = pnd_pxml_fetch_buffer ( "pnd_run", pxmlbuf );
152     }
153   }
154
155   fclose ( f );
156
157   if ( ! h ) {
158     printf ( "ERROR: Couldn't pull PXML.xml from the pndfile.\n" );
159     exit ( 0 );
160   }
161
162   // attempt to invoke
163   unsigned int options = 0;
164   if ( no_x11 ) {
165     options |= PND_EXEC_OPTION_NOX11;
166   }
167
168   unsigned int clock = 200;
169   if ( pnd_pxml_get_clockspeed ( h ) ) {
170     clock = atoi ( pnd_pxml_get_clockspeed ( h ) );
171   }
172
173   pnd_apps_exec ( pnd_run, pndfile,
174                   pnd_pxml_get_unique_id ( h ),
175                   pnd_pxml_get_exec ( h ),
176                   pnd_pxml_get_startdir ( h ),
177                   clock,
178                   options );
179
180   return ( 0 );
181 } // main