summaryrefslogtreecommitdiff
path: root/quickexec/johns/qinit_srv.c
Unidiff
Diffstat (limited to 'quickexec/johns/qinit_srv.c') (more/less context) (show whitespace changes)
-rw-r--r--quickexec/johns/qinit_srv.c242
1 files changed, 242 insertions, 0 deletions
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