summaryrefslogtreecommitdiff
path: root/quickexec/johns
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /quickexec/johns
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'quickexec/johns') (more/less context) (ignore whitespace changes)
-rw-r--r--quickexec/johns/README21
-rw-r--r--quickexec/johns/library.lst2
-rw-r--r--quickexec/johns/qinit_srv.c242
-rw-r--r--quickexec/johns/so_stub.c23
4 files changed, 288 insertions, 0 deletions
diff --git a/quickexec/johns/README b/quickexec/johns/README
new file mode 100644
index 0000000..1af84dc
--- a/dev/null
+++ b/quickexec/johns/README
@@ -0,0 +1,21 @@
1
2Compile qinit_srv.c to qinit_srv as usual
3Compile your applications at shared libraries instead of as executables:
4 eg: gcc test.c -o test.so -shared
5Make a symbolic link from qinit_srv to the name of the application:
6 eg: ln -s qinit_srv test
7Now make sure 'test' (The symlink) and 'test.so' (the shared library version of the app) are together.
8When you run ./test it will load test.so and run it just like you were running the application for real.
9There will be a qinit_srv process created the first time you run a program this way.
10
11How it works:
12
13qinit_srv checks to see if there is already a server, if not it starts as a server which runs in the background as a deamon.
14If it's a server it loads all the libraries listed in the library.lst file.
15It then waits for signals to be sent to it which tell it to fork itself and load shared libraries and run them.
16If it decides it's not the server, it sends a signal to the server to run the given command.
17The server then executes a shared object file of whatever name the original process is invoked as (argv[0], the symlink trick)
18The other process waits until the forked server finishes and signals the original process that it as finished and to return
19
20
21
diff --git a/quickexec/johns/library.lst b/quickexec/johns/library.lst
new file mode 100644
index 0000000..42f310b
--- a/dev/null
+++ b/quickexec/johns/library.lst
@@ -0,0 +1,2 @@
1libqte.so
2libqpe.so
diff --git a/quickexec/johns/qinit_srv.c b/quickexec/johns/qinit_srv.c
new file mode 100644
index 0000000..03c6cd3
--- a/dev/null
+++ b/quickexec/johns/qinit_srv.c
@@ -0,0 +1,242 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <signal.h>
4#include <unistd.h>
5#include <dlfcn.h>
6
7
8#define PID_FILE "/tmp/qinit1.pid"
9#define CMD_FILE "/tmp/qinit1.cmd"
10#define RET_FILE "/tmp/qinit1.ret"
11
12
13static int librariesFinishedLoading = 0;
14static void **handles = NULL;
15static int handleCount = 0;
16
17
18static void savePid( void );
19static int loadPid( void );
20void saveRetVal( int retVal );
21int loadRetVal( void );
22static void saveCmd( int callingPid, int argc, char *argv[] );
23static int execCmd( void );
24static void loadLibraries( char *listFile );
25static void signalHandler( int signal );
26static void finishedHandler( int signal );
27static void cleanUpHandler( int signal );
28static void cleanUp( void );
29
30
31int main( int argc, char *argv[] ) {
32 FILE *fh;
33
34 // See if there is already a server running
35 if ( ( fh = fopen( PID_FILE, "r" ) ) != NULL ) {
36 // There appears to already be a server running
37 fclose( fh );
38 // Install handler that tells us when the process created by the server has finished
39 signal( SIGUSR2, finishedHandler );
40 // Send our command to the server (saved to a file)
41 saveCmd( getpid(), argc, argv );
42 // Send a signal to the server to run our command
43 kill( loadPid(), SIGUSR1 );
44 // Wait for the process created by the server to terminate
45 for (;;)
46 sleep( 1 ); // Will eventually terminate when the SIGUSER2 signal is sent to us by the server
47 }
48
49 // Send the server to the background
50 daemon( 1, 1 );
51
52 // Save the process number of this process somewhere (in a file)
53 savePid();
54
55 // Wait for signal used to let us know when to fork to run commands
56 signal( SIGUSR1, signalHandler );
57 signal( SIGTERM, cleanUpHandler );
58 signal( SIGINT, cleanUpHandler );
59 signal( SIGABRT, cleanUpHandler );
60 signal( SIGQUIT, cleanUpHandler );
61
62 // Iterate library list file and dynamically load at runtime
63 // the library files from the list
64 if ( argc > 1 )
65 loadLibraries( argv[1] ); // Use a library list file specified from command line
66 else
67 loadLibraries( "library.lst" ); // Use the default library list file
68
69 // Run the given command
70 signalHandler( SIGUSR1 );
71
72 // Keep waiting for signals infinitely that tell us to fork
73 for (;;)
74 wait( NULL ); // Wait for child processes to die or signals to be sent to us
75
76 cleanUp();
77
78 return 0;
79}
80
81
82void cleanUp( void ) {
83 int i;
84
85 // Close the shared libraries we opened
86 for ( i = 0; i < handleCount; i++ )
87 dlclose( handles[ i ] );
88 free( handles );
89
90 // Unlink the PID_FILE file
91 remove( PID_FILE );
92}
93
94
95void savePid( void ) {
96 int pid = getpid();
97 FILE *fh = fopen( PID_FILE, "w");
98 if ( !fh )
99 fputs("error writing pid to file " PID_FILE, stderr), exit(1);
100 fprintf( fh, "%i", pid );
101 fclose( fh );
102}
103
104
105int loadPid( void ) {
106 int pid;
107 FILE *fh = fopen( PID_FILE, "r" );
108 if ( !fh )
109 fputs("error loading pid from file " PID_FILE, stderr), exit(1);
110 fscanf( fh, "%i", &pid );
111 fclose( fh );
112 return pid;
113}
114
115
116void saveRetVal( int retVal ) {
117 FILE *fh = fopen( RET_FILE, "w");
118 if ( !fh )
119 fputs("error writing retVal to file " RET_FILE, stderr), exit(1);
120 fprintf( fh, "%i", retVal );
121 fclose( fh );
122}
123
124
125int loadRetVal( void ) {
126 int retVal;
127 FILE *fh = fopen( RET_FILE, "r" );
128 if ( !fh )
129 fputs("error loading retVal from file " RET_FILE, stderr), exit(1);
130 fscanf( fh, "%i", &retVal );
131 fclose( fh );
132 return retVal;
133}
134
135
136void saveCmd( int callingPid, int argc, char *argv[] ) {
137 int i;
138 FILE *fh = fopen( CMD_FILE, "w" );
139 if ( !fh )
140 fputs("error saving arg list to file " CMD_FILE, stderr), exit(1);
141 fprintf( fh, "%i\n", callingPid );
142 fprintf( fh, "%s.so", argv[0] );
143 for ( i = 0; i < argc; i++ )
144 fprintf( fh, "\n%s", argv[i] );
145 fclose( fh );
146}
147
148
149int execCmd( void ) {
150 int callingPid;
151 char sharedObject[128];
152 int argc;
153 char argv[128][128];
154 int (*childMain)( int argc, char *argv[] );
155 char *error;
156 void *handle;
157 int retVal = 0;
158
159 // Get the name of the file to dlopen and the arguments to pass (from a file)
160 FILE *fh = fopen( CMD_FILE, "r" );
161 fscanf( fh, "%i\n", &callingPid );
162 fgets( sharedObject, 128, fh );
163 sharedObject[strlen( sharedObject ) - 1] = '\0';
164 for ( argc = 0; fgets( argv[argc], 128, fh ); argc++)
165 argv[argc][strlen( argv[argc] ) - 1] = '\0';
166 fclose( fh );
167
168 // Open the shared object of what we want to execute
169 handle = dlopen( sharedObject, RTLD_LAZY );
170 if ( !handle )
171 fputs( dlerror(), stderr ), kill( callingPid, SIGUSR2 ), exit( 1 );
172
173 // Find main symbol and jump to it
174 childMain = dlsym( handle, "main" );
175 if ( ( error = dlerror() ) != NULL )
176 fputs( error, stderr ), kill( callingPid, SIGUSR2 ), exit( 1 );
177 retVal = (*childMain)( argc, (char**)argv );
178
179 // Notify caller that we have finished
180 saveRetVal( retVal );
181 kill( callingPid, SIGUSR2 );
182
183 // When we are done, close the shared object
184 dlclose( handle );
185 return retVal;
186}
187
188
189void finishedHandler( int signal ) {
190 // We have been notified of the completion of the task
191 exit( loadRetVal() );
192}
193
194
195void cleanUpHandler( int signal ) {
196 // Cleanup and exit if we have been told to quit
197 cleanUp();
198 exit(1);
199}
200
201
202void signalHandler( int signal ) {
203 //printf("got a signal of %i\n", signal );
204
205 if ( fork() == 0 ) {
206 // We are the child process
207
208/*
209 while ( librariesFinishedLoading != 1 ) {
210 printf("waiting for libraries to load\n");
211 sleep(1);
212 }
213*/
214 // Close file handles and open others etc
215
216 // Execute the command and return when done
217 exit( execCmd() );
218 }
219
220 // Parent process, just continue
221 sleep( 1 ); // Need to yield to child process
222}
223
224
225void loadLibraries( char *listFile ) {
226 FILE *fh = fopen( listFile, "r" );
227 char line[1024];
228 if ( !fh )
229 fputs("error opening library list file", stderr), exit(1);
230 while ( fgets( line, 1024, fh ) ) {
231 line[strlen( line ) - 1] = '\0';
232 printf("loading library: --%s--\n", line);
233 handleCount++;
234 handles = realloc( handles, handleCount * sizeof( void * ) );
235 handles[ handleCount - 1 ] = dlopen( line, RTLD_NOW );
236 if ( !handles[ handleCount - 1 ] )
237 fputs( dlerror(), stderr ), exit( 1 );
238 }
239 fclose( fh );
240 librariesFinishedLoading = 1;
241}
242
diff --git a/quickexec/johns/so_stub.c b/quickexec/johns/so_stub.c
new file mode 100644
index 0000000..fe71f9c
--- a/dev/null
+++ b/quickexec/johns/so_stub.c
@@ -0,0 +1,23 @@
1#include <stdio.h>
2#include <string.h>
3#include <dlfcn.h>
4
5
6int main( int argc, char *argv[] ) {
7 char module[1024];
8 int (*loadedMain)( int argc, char *argv[] );
9 char *error;
10 int retVal = 0;
11 void *handle;
12 strcpy( module, argv[0] );
13 strcat( module, ".so" );
14 if ( !(handle = dlopen( module, RTLD_LAZY ) ) )
15 fputs( dlerror(), stderr ), exit( 1 );
16 loadedMain = dlsym( handle, "main" );
17 if ( ( error = dlerror() ) != NULL )
18 fputs( error, stderr ), exit( 1 );
19 retVal = (*loadedMain)( argc, argv );
20 dlclose( handle );
21 return retVal;
22}
23