author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /quickexec | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
-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 @@ +############################################################################# + +####### Compiler, tools and options + +CXX = $(SYSCONF_CXX) $(QT_CXX_MT) +CXXFLAGS= $(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) +CC = $(SYSCONF_CC) $(QT_C_MT) +CFLAGS = $(SYSCONF_CFLAGS) +INCPATH = +LFLAGS = $(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) +LIBS = $(SUBLIBS) -ldl -lqpe $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS) $(SYSCONF_LIBS_QTAPP) +MOC = $(SYSCONF_MOC) +UIC = $(SYSCONF_UIC) + +####### Target + +DESTDIR = ../bin/ +VER_MAJ = 1 +VER_MIN = 0 +VER_PATCH = 0 +TARGET = quickexec +TARGET1 = lib$(TARGET).so.$(VER_MAJ) + +####### Files + +HEADERS = +SOURCES = quickexec.cpp +OBJECTS = quickexec.o +INTERFACES = +UICDECLS = +UICIMPLS = +SRCMOC = +OBJMOC = + + +####### Implicit rules + +.SUFFIXES: .cpp .cxx .cc .C .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + + +all: $(DESTDIR)$(TARGET) + +$(DESTDIR)$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) + $(SYSCONF_LINK) $(LFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS) + +moc: $(SRCMOC) + +tmake: + tmake quickexec.pro + +clean: + -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) + -rm -f *~ core + -rm -f allmoc.cpp + +####### Extension Modules + +listpromodules: + @echo + +listallmodules: + @echo + +listaddonpromodules: + @echo + +listaddonentmodules: + @echo + + +REQUIRES= + +####### Sub-libraries + + +###### Combined headers + + + +####### Compile + +quickexec.o: quickexec.cpp + + 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 @@ + +Compile qinit_srv.c to qinit_srv as usual +Compile your applications at shared libraries instead of as executables: + eg: gcc test.c -o test.so -shared +Make a symbolic link from qinit_srv to the name of the application: + eg: ln -s qinit_srv test +Now make sure 'test' (The symlink) and 'test.so' (the shared library version of the app) are together. +When you run ./test it will load test.so and run it just like you were running the application for real. +There will be a qinit_srv process created the first time you run a program this way. + +How it works: + +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. +If it's a server it loads all the libraries listed in the library.lst file. +It then waits for signals to be sent to it which tell it to fork itself and load shared libraries and run them. +If it decides it's not the server, it sends a signal to the server to run the given command. +The server then executes a shared object file of whatever name the original process is invoked as (argv[0], the symlink trick) +The other process waits until the forked server finishes and signals the original process that it as finished and to return + + + 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 @@ +libqte.so +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 @@ +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <unistd.h> +#include <dlfcn.h> + + +#define PID_FILE "/tmp/qinit1.pid" +#define CMD_FILE "/tmp/qinit1.cmd" +#define RET_FILE "/tmp/qinit1.ret" + + +static int librariesFinishedLoading = 0; +static void **handles = NULL; +static int handleCount = 0; + + +static void savePid( void ); +static int loadPid( void ); +void saveRetVal( int retVal ); +int loadRetVal( void ); +static void saveCmd( int callingPid, int argc, char *argv[] ); +static int execCmd( void ); +static void loadLibraries( char *listFile ); +static void signalHandler( int signal ); +static void finishedHandler( int signal ); +static void cleanUpHandler( int signal ); +static void cleanUp( void ); + + +int main( int argc, char *argv[] ) { + FILE *fh; + + // See if there is already a server running + if ( ( fh = fopen( PID_FILE, "r" ) ) != NULL ) { + // There appears to already be a server running + fclose( fh ); + // Install handler that tells us when the process created by the server has finished + signal( SIGUSR2, finishedHandler ); + // Send our command to the server (saved to a file) + saveCmd( getpid(), argc, argv ); + // Send a signal to the server to run our command + kill( loadPid(), SIGUSR1 ); + // Wait for the process created by the server to terminate + for (;;) + sleep( 1 ); // Will eventually terminate when the SIGUSER2 signal is sent to us by the server + } + + // Send the server to the background + daemon( 1, 1 ); + + // Save the process number of this process somewhere (in a file) + savePid(); + + // Wait for signal used to let us know when to fork to run commands + signal( SIGUSR1, signalHandler ); + signal( SIGTERM, cleanUpHandler ); + signal( SIGINT, cleanUpHandler ); + signal( SIGABRT, cleanUpHandler ); + signal( SIGQUIT, cleanUpHandler ); + + // Iterate library list file and dynamically load at runtime + // the library files from the list + if ( argc > 1 ) + loadLibraries( argv[1] ); // Use a library list file specified from command line + else + loadLibraries( "library.lst" ); // Use the default library list file + + // Run the given command + signalHandler( SIGUSR1 ); + + // Keep waiting for signals infinitely that tell us to fork + for (;;) + wait( NULL ); // Wait for child processes to die or signals to be sent to us + + cleanUp(); + + return 0; +} + + +void cleanUp( void ) { + int i; + + // Close the shared libraries we opened + for ( i = 0; i < handleCount; i++ ) + dlclose( handles[ i ] ); + free( handles ); + + // Unlink the PID_FILE file + remove( PID_FILE ); +} + + +void savePid( void ) { + int pid = getpid(); + FILE *fh = fopen( PID_FILE, "w"); + if ( !fh ) + fputs("error writing pid to file " PID_FILE, stderr), exit(1); + fprintf( fh, "%i", pid ); + fclose( fh ); +} + + +int loadPid( void ) { + int pid; + FILE *fh = fopen( PID_FILE, "r" ); + if ( !fh ) + fputs("error loading pid from file " PID_FILE, stderr), exit(1); + fscanf( fh, "%i", &pid ); + fclose( fh ); + return pid; +} + + +void saveRetVal( int retVal ) { + FILE *fh = fopen( RET_FILE, "w"); + if ( !fh ) + fputs("error writing retVal to file " RET_FILE, stderr), exit(1); + fprintf( fh, "%i", retVal ); + fclose( fh ); +} + + +int loadRetVal( void ) { + int retVal; + FILE *fh = fopen( RET_FILE, "r" ); + if ( !fh ) + fputs("error loading retVal from file " RET_FILE, stderr), exit(1); + fscanf( fh, "%i", &retVal ); + fclose( fh ); + return retVal; +} + + +void saveCmd( int callingPid, int argc, char *argv[] ) { + int i; + FILE *fh = fopen( CMD_FILE, "w" ); + if ( !fh ) + fputs("error saving arg list to file " CMD_FILE, stderr), exit(1); + fprintf( fh, "%i\n", callingPid ); + fprintf( fh, "%s.so", argv[0] ); + for ( i = 0; i < argc; i++ ) + fprintf( fh, "\n%s", argv[i] ); + fclose( fh ); +} + + +int execCmd( void ) { + int callingPid; + char sharedObject[128]; + int argc; + char argv[128][128]; + int (*childMain)( int argc, char *argv[] ); + char *error; + void *handle; + int retVal = 0; + + // Get the name of the file to dlopen and the arguments to pass (from a file) + FILE *fh = fopen( CMD_FILE, "r" ); + fscanf( fh, "%i\n", &callingPid ); + fgets( sharedObject, 128, fh ); + sharedObject[strlen( sharedObject ) - 1] = '\0'; + for ( argc = 0; fgets( argv[argc], 128, fh ); argc++) + argv[argc][strlen( argv[argc] ) - 1] = '\0'; + fclose( fh ); + + // Open the shared object of what we want to execute + handle = dlopen( sharedObject, RTLD_LAZY ); + if ( !handle ) + fputs( dlerror(), stderr ), kill( callingPid, SIGUSR2 ), exit( 1 ); + + // Find main symbol and jump to it + childMain = dlsym( handle, "main" ); + if ( ( error = dlerror() ) != NULL ) + fputs( error, stderr ), kill( callingPid, SIGUSR2 ), exit( 1 ); + retVal = (*childMain)( argc, (char**)argv ); + + // Notify caller that we have finished + saveRetVal( retVal ); + kill( callingPid, SIGUSR2 ); + + // When we are done, close the shared object + dlclose( handle ); + return retVal; +} + + +void finishedHandler( int signal ) { + // We have been notified of the completion of the task + exit( loadRetVal() ); +} + + +void cleanUpHandler( int signal ) { + // Cleanup and exit if we have been told to quit + cleanUp(); + exit(1); +} + + +void signalHandler( int signal ) { + //printf("got a signal of %i\n", signal ); + + if ( fork() == 0 ) { + // We are the child process + +/* + while ( librariesFinishedLoading != 1 ) { + printf("waiting for libraries to load\n"); + sleep(1); + } +*/ + // Close file handles and open others etc + + // Execute the command and return when done + exit( execCmd() ); + } + + // Parent process, just continue + sleep( 1 ); // Need to yield to child process +} + + +void loadLibraries( char *listFile ) { + FILE *fh = fopen( listFile, "r" ); + char line[1024]; + if ( !fh ) + fputs("error opening library list file", stderr), exit(1); + while ( fgets( line, 1024, fh ) ) { + line[strlen( line ) - 1] = '\0'; + printf("loading library: --%s--\n", line); + handleCount++; + handles = realloc( handles, handleCount * sizeof( void * ) ); + handles[ handleCount - 1 ] = dlopen( line, RTLD_NOW ); + if ( !handles[ handleCount - 1 ] ) + fputs( dlerror(), stderr ), exit( 1 ); + } + fclose( fh ); + librariesFinishedLoading = 1; +} + 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 @@ +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> + + +int main( int argc, char *argv[] ) { + char module[1024]; + int (*loadedMain)( int argc, char *argv[] ); + char *error; + int retVal = 0; + void *handle; + strcpy( module, argv[0] ); + strcat( module, ".so" ); + if ( !(handle = dlopen( module, RTLD_LAZY ) ) ) + fputs( dlerror(), stderr ), exit( 1 ); + loadedMain = dlsym( handle, "main" ); + if ( ( error = dlerror() ) != NULL ) + fputs( error, stderr ), exit( 1 ); + retVal = (*loadedMain)( argc, argv ); + dlclose( handle ); + return retVal; +} + 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 @@ +Files: bin/quickexec +Priority: required +Section: qpe/applications +Maintainer: Warwick Allison <warwick@trolltech.com> +Architecture: arm +Arch: iPAQ +Version: $QPE_VERSION-3 +Depends: qpe-base ($QPE_VERSION) +Description: Calculator + A multi-function calculator for the Qtopia environment. + 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 @@ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <dlfcn.h> + +#define QUICKEXEC "/tmp/.quickexec" + +#include <signal.h> +#include <sys/wait.h> + +void sigchildhandler(int) { + wait(0); +} + +int exec( const char *lib, int argc, char** argv ) +{ + setpgid(0,0); +// printf("loadlib %s, argc=%d\n", lib, argc ); + void *handle = dlopen ( lib, RTLD_LAZY); + if (!handle) { + fprintf( stderr, "%s\n", dlerror()); + exit(1); + } + typedef int (*Mainfunc)(int, char**); + Mainfunc mainfunc; + mainfunc = (Mainfunc) dlsym(handle, "main"); + char *error; + if ((error = dlerror()) != NULL) { + fprintf (stderr, "%s\n", error); + exit(1); + } + (*mainfunc)(argc,argv); + return 0; +} + +#define BUFFER_SIZE 1024 +int main( int argc, char** argv ) +{ + signal( SIGCHLD, sigchildhandler ); + (void) unlink( QUICKEXEC ); + if ( mkfifo( QUICKEXEC, S_IFIFO | S_IWUSR | S_IRUSR ) == -1 ) { + perror( QUICKEXEC ); + exit(1); + } + + if ( argc > 1 && fork() == 0 ) + return exec( argv[1], argc-2, argc > 2 ? argv+2 : 0 ); + + char buf[BUFFER_SIZE]; + int p = 0; + int r; + int fd = open( QUICKEXEC, O_RDONLY ); + if ( fd == -1 ) { + perror( QUICKEXEC ); + exit(1); + } + for ( ;; ) { + r = read( fd, buf+p, BUFFER_SIZE-p ); + p += r; + if ( r == 0 || p >= BUFFER_SIZE - 1 ) { + buf[p] = '\0'; + close ( fd ); + if ( fork() == 0 ) { + int argc = -1; + int i = 0; + int k = 0; + for ( i = 0; i <= p; i++ ) + if ( buf[i] == '\0' ) + argc++; + char** argv = new char*[argc]; + for ( i = 0; i < p; i++ ) { + if ( buf[i] == '\0' ) + argv[k++]=buf+i+1; + } + return exec( buf, argc, argv ); + } + p = 0; + fd = open( QUICKEXEC, O_RDONLY ); + } + } + return 0; +} + + + + + + + + + + + + + + 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 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = ../bin +HEADERS = +SOURCES = quickexec.cpp +LIBS += -ldl -lqpe |