-rw-r--r-- | quickexec/Makefile.in | 101 | ||||
-rw-r--r-- | quickexec/johns/README | 21 | ||||
-rw-r--r-- | quickexec/johns/library.lst | 2 | ||||
-rw-r--r-- | quickexec/johns/qinit_srv.c | 242 | ||||
-rw-r--r-- | quickexec/johns/so_stub.c | 23 | ||||
-rw-r--r-- | quickexec/qpe-quickexec.control | 11 | ||||
-rw-r--r-- | quickexec/quickexec.cpp | 98 | ||||
-rw-r--r-- | quickexec/quickexec.pro | 6 |
8 files changed, 504 insertions, 0 deletions
diff --git a/quickexec/Makefile.in b/quickexec/Makefile.in new file mode 100644 index 0000000..514e6cc --- a/dev/null +++ b/quickexec/Makefile.in | |||
@@ -0,0 +1,101 @@ | |||
1 | ############################################################################# | ||
2 | |||
3 | ####### Compiler, tools and options | ||
4 | |||
5 | CXX =$(SYSCONF_CXX) $(QT_CXX_MT) | ||
6 | CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) | ||
7 | CC =$(SYSCONF_CC) $(QT_C_MT) | ||
8 | CFLAGS =$(SYSCONF_CFLAGS) | ||
9 | INCPATH = | ||
10 | LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) | ||
11 | LIBS =$(SUBLIBS) -ldl -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) | ||
12 | MOC =$(SYSCONF_MOC) | ||
13 | UIC =$(SYSCONF_UIC) | ||
14 | |||
15 | ####### Target | ||
16 | |||
17 | DESTDIR = ../bin/ | ||
18 | VER_MAJ = 1 | ||
19 | VER_MIN = 0 | ||
20 | VER_PATCH = 0 | ||
21 | TARGET= quickexec | ||
22 | TARGET1 = lib$(TARGET).so.$(VER_MAJ) | ||
23 | |||
24 | ####### Files | ||
25 | |||
26 | HEADERS = | ||
27 | SOURCES =quickexec.cpp | ||
28 | OBJECTS =quickexec.o | ||
29 | INTERFACES = | ||
30 | UICDECLS = | ||
31 | UICIMPLS = | ||
32 | SRCMOC = | ||
33 | OBJMOC = | ||
34 | |||
35 | |||
36 | ####### Implicit rules | ||
37 | |||
38 | .SUFFIXES: .cpp .cxx .cc .C .c | ||
39 | |||
40 | .cpp.o: | ||
41 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
42 | |||
43 | .cxx.o: | ||
44 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
45 | |||
46 | .cc.o: | ||
47 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
48 | |||
49 | .C.o: | ||
50 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
51 | |||
52 | .c.o: | ||
53 | $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< | ||
54 | |||
55 | ####### Build rules | ||
56 | |||
57 | |||
58 | all: $(DESTDIR)$(TARGET) | ||
59 | |||
60 | $(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) | ||
61 | $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) | ||
62 | |||
63 | moc: $(SRCMOC) | ||
64 | |||
65 | tmake: | ||
66 | tmake quickexec.pro | ||
67 | |||
68 | clean: | ||
69 | -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) | ||
70 | -rm -f *~ core | ||
71 | -rm -f allmoc.cpp | ||
72 | |||
73 | ####### Extension Modules | ||
74 | |||
75 | listpromodules: | ||
76 | @echo | ||
77 | |||
78 | listallmodules: | ||
79 | @echo | ||
80 | |||
81 | listaddonpromodules: | ||
82 | @echo | ||
83 | |||
84 | listaddonentmodules: | ||
85 | @echo | ||
86 | |||
87 | |||
88 | REQUIRES= | ||
89 | |||
90 | ####### Sub-libraries | ||
91 | |||
92 | |||
93 | ###### Combined headers | ||
94 | |||
95 | |||
96 | |||
97 | ####### Compile | ||
98 | |||
99 | quickexec.o: quickexec.cpp | ||
100 | |||
101 | |||
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 | |||
2 | Compile qinit_srv.c to qinit_srv as usual | ||
3 | Compile your applications at shared libraries instead of as executables: | ||
4 | eg: gcc test.c -o test.so -shared | ||
5 | Make a symbolic link from qinit_srv to the name of the application: | ||
6 | eg: ln -s qinit_srv test | ||
7 | Now make sure 'test' (The symlink) and 'test.so' (the shared library version of the app) are together. | ||
8 | When you run ./test it will load test.so and run it just like you were running the application for real. | ||
9 | There will be a qinit_srv process created the first time you run a program this way. | ||
10 | |||
11 | How it works: | ||
12 | |||
13 | qinit_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. | ||
14 | If it's a server it loads all the libraries listed in the library.lst file. | ||
15 | It then waits for signals to be sent to it which tell it to fork itself and load shared libraries and run them. | ||
16 | If it decides it's not the server, it sends a signal to the server to run the given command. | ||
17 | The server then executes a shared object file of whatever name the original process is invoked as (argv[0], the symlink trick) | ||
18 | The 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 @@ | |||
1 | libqte.so | ||
2 | libqpe.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 | |||
13 | static int librariesFinishedLoading = 0; | ||
14 | static void **handles = NULL; | ||
15 | static int handleCount = 0; | ||
16 | |||
17 | |||
18 | static void savePid( void ); | ||
19 | static int loadPid( void ); | ||
20 | void saveRetVal( int retVal ); | ||
21 | int loadRetVal( void ); | ||
22 | static void saveCmd( int callingPid, int argc, char *argv[] ); | ||
23 | static int execCmd( void ); | ||
24 | static void loadLibraries( char *listFile ); | ||
25 | static void signalHandler( int signal ); | ||
26 | static void finishedHandler( int signal ); | ||
27 | static void cleanUpHandler( int signal ); | ||
28 | static void cleanUp( void ); | ||
29 | |||
30 | |||
31 | int 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 | |||
82 | void 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 | |||
95 | void 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 | |||
105 | int 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 | |||
116 | void 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 | |||
125 | int 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 | |||
136 | void 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 | |||
149 | int 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 | |||
189 | void finishedHandler( int signal ) { | ||
190 | // We have been notified of the completion of the task | ||
191 | exit( loadRetVal() ); | ||
192 | } | ||
193 | |||
194 | |||
195 | void cleanUpHandler( int signal ) { | ||
196 | // Cleanup and exit if we have been told to quit | ||
197 | cleanUp(); | ||
198 | exit(1); | ||
199 | } | ||
200 | |||
201 | |||
202 | void 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 | |||
225 | void 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 | |||
6 | int 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 | |||
diff --git a/quickexec/qpe-quickexec.control b/quickexec/qpe-quickexec.control new file mode 100644 index 0000000..e93b9b0 --- a/dev/null +++ b/quickexec/qpe-quickexec.control | |||
@@ -0,0 +1,11 @@ | |||
1 | Files: bin/quickexec | ||
2 | Priority: required | ||
3 | Section: qpe/applications | ||
4 | Maintainer: Warwick Allison <warwick@trolltech.com> | ||
5 | Architecture: arm | ||
6 | Arch: iPAQ | ||
7 | Version: $QPE_VERSION-3 | ||
8 | Depends: qpe-base ($QPE_VERSION) | ||
9 | Description: Calculator | ||
10 | A multi-function calculator for the Qtopia environment. | ||
11 | Includes units conversion. | ||
diff --git a/quickexec/quickexec.cpp b/quickexec/quickexec.cpp new file mode 100644 index 0000000..772ab4c --- a/dev/null +++ b/quickexec/quickexec.cpp | |||
@@ -0,0 +1,98 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <sys/types.h> | ||
3 | #include <sys/stat.h> | ||
4 | #include <unistd.h> | ||
5 | #include <fcntl.h> | ||
6 | #include <dlfcn.h> | ||
7 | |||
8 | #define QUICKEXEC "/tmp/.quickexec" | ||
9 | |||
10 | #include <signal.h> | ||
11 | #include <sys/wait.h> | ||
12 | |||
13 | void sigchildhandler(int) { | ||
14 | wait(0); | ||
15 | } | ||
16 | |||
17 | int exec( const char *lib, int argc, char** argv ) | ||
18 | { | ||
19 | setpgid(0,0); | ||
20 | // printf("loadlib %s, argc=%d\n", lib, argc ); | ||
21 | void *handle = dlopen ( lib, RTLD_LAZY); | ||
22 | if (!handle) { | ||
23 | fprintf( stderr, "%s\n", dlerror()); | ||
24 | exit(1); | ||
25 | } | ||
26 | typedef int (*Mainfunc)(int, char**); | ||
27 | Mainfunc mainfunc; | ||
28 | mainfunc = (Mainfunc) dlsym(handle, "main"); | ||
29 | char *error; | ||
30 | if ((error = dlerror()) != NULL) { | ||
31 | fprintf (stderr, "%s\n", error); | ||
32 | exit(1); | ||
33 | } | ||
34 | (*mainfunc)(argc,argv); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | #define BUFFER_SIZE 1024 | ||
39 | int main( int argc, char** argv ) | ||
40 | { | ||
41 | signal( SIGCHLD, sigchildhandler ); | ||
42 | (void) unlink( QUICKEXEC ); | ||
43 | if ( mkfifo( QUICKEXEC, S_IFIFO | S_IWUSR | S_IRUSR ) == -1 ) { | ||
44 | perror( QUICKEXEC ); | ||
45 | exit(1); | ||
46 | } | ||
47 | |||
48 | if ( argc > 1 && fork() == 0 ) | ||
49 | return exec( argv[1], argc-2, argc > 2 ? argv+2 : 0 ); | ||
50 | |||
51 | char buf[BUFFER_SIZE]; | ||
52 | int p = 0; | ||
53 | int r; | ||
54 | int fd = open( QUICKEXEC, O_RDONLY ); | ||
55 | if ( fd == -1 ) { | ||
56 | perror( QUICKEXEC ); | ||
57 | exit(1); | ||
58 | } | ||
59 | for ( ;; ) { | ||
60 | r = read( fd, buf+p, BUFFER_SIZE-p ); | ||
61 | p += r; | ||
62 | if ( r == 0 || p >= BUFFER_SIZE - 1 ) { | ||
63 | buf[p] = '\0'; | ||
64 | close ( fd ); | ||
65 | if ( fork() == 0 ) { | ||
66 | int argc = -1; | ||
67 | int i = 0; | ||
68 | int k = 0; | ||
69 | for ( i = 0; i <= p; i++ ) | ||
70 | if ( buf[i] == '\0' ) | ||
71 | argc++; | ||
72 | char** argv = new char*[argc]; | ||
73 | for ( i = 0; i < p; i++ ) { | ||
74 | if ( buf[i] == '\0' ) | ||
75 | argv[k++]=buf+i+1; | ||
76 | } | ||
77 | return exec( buf, argc, argv ); | ||
78 | } | ||
79 | p = 0; | ||
80 | fd = open( QUICKEXEC, O_RDONLY ); | ||
81 | } | ||
82 | } | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | |||
87 | |||
88 | |||
89 | |||
90 | |||
91 | |||
92 | |||
93 | |||
94 | |||
95 | |||
96 | |||
97 | |||
98 | |||
diff --git a/quickexec/quickexec.pro b/quickexec/quickexec.pro new file mode 100644 index 0000000..80fc945 --- a/dev/null +++ b/quickexec/quickexec.pro | |||
@@ -0,0 +1,6 @@ | |||
1 | TEMPLATE= app | ||
2 | CONFIG = qt warn_on release | ||
3 | DESTDIR = ../bin | ||
4 | HEADERS = | ||
5 | SOURCES = quickexec.cpp | ||
6 | LIBS += -ldl -lqpe | ||