summaryrefslogtreecommitdiff
path: root/quickexec
Side-by-side diff
Diffstat (limited to 'quickexec') (more/less context) (show whitespace changes)
-rw-r--r--quickexec/Makefile.in101
-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
-rw-r--r--quickexec/qpe-quickexec.control11
-rw-r--r--quickexec/quickexec.cpp98
-rw-r--r--quickexec/quickexec.pro6
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