diff options
-rw-r--r-- | Makefile.in | 11 | ||||
-rwxr-xr-x | configure | 16 | ||||
-rw-r--r-- | plugin_exec.c | 235 | ||||
-rw-r--r-- | qprintf.c | 41 | ||||
-rw-r--r-- | thread.c | 14 | ||||
-rw-r--r-- | thread.h | 11 |
6 files changed, 272 insertions, 56 deletions
diff --git a/Makefile.in b/Makefile.in index abbe2f5..f26474a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -91,7 +91,7 @@ lcd4linux_LDADD = @DRIVERS@ @DRVLIBS@ #remove next line for liblcd4linux lcd4linux_DEPENDENCIES = @DRIVERS@ -lcd4linux_SOURCES = lcd4linux.c cfg.c cfg.h debug.c debug.h drv.c drv.h evaluator.c evaluator.h hash.c hash.h layout.c layout.h lock.c lock.h pid.c pid.h timer.c timer.h thread.c thread.h udelay.c udelay.h qprintf.c qprintf.h widget.c widget.h widget_text.c widget_text.h widget_bar.c widget_bar.h widget_icon.c widget_icon.h plugin.c plugin.h plugin_math.c plugin_string.c plugin_cfg.c plugin_uname.c plugin_loadavg.c plugin_proc_stat.c plugin_cpuinfo.c plugin_meminfo.c plugin_netdev.c plugin_ppp.c plugin_dvb.c plugin_apm.c plugin_i2c_sensors.c plugin_imon.c plugin_exec.c plugin_xmms.c plugin_mysql.c plugin_seti.c +lcd4linux_SOURCES = lcd4linux.c cfg.c cfg.h debug.c debug.h drv.c drv.h evaluator.c evaluator.h hash.c hash.h layout.c layout.h lock.c lock.h pid.c pid.h timer.c timer.h thread.c thread.h udelay.c udelay.h qprintf.c qprintf.h widget.c widget.h widget_text.c widget_text.h widget_bar.c widget_bar.h widget_icon.c widget_icon.h plugin.c plugin.h plugin_math.c plugin_string.c plugin_cfg.c plugin_uname.c plugin_loadavg.c plugin_proc_stat.c plugin_cpuinfo.c plugin_meminfo.c plugin_netdev.c plugin_ppp.c plugin_dvb.c plugin_apm.c plugin_i2c_sensors.c plugin_imon.c plugin_exec.c plugin_xmms.c plugin_mysql.c plugin_wireless.c plugin_seti.c #liblcd4linux_la_DEPENDENCIES = @DRIVERS@ @@ -126,7 +126,8 @@ widget_text.o widget_bar.o widget_icon.o plugin.o plugin_math.o \ plugin_string.o plugin_cfg.o plugin_uname.o plugin_loadavg.o \ plugin_proc_stat.o plugin_cpuinfo.o plugin_meminfo.o plugin_netdev.o \ plugin_ppp.o plugin_dvb.o plugin_apm.o plugin_i2c_sensors.o \ -plugin_imon.o plugin_exec.o plugin_xmms.o plugin_mysql.o plugin_seti.o +plugin_imon.o plugin_exec.o plugin_xmms.o plugin_mysql.o \ +plugin_wireless.o plugin_seti.o CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -155,9 +156,9 @@ DEP_FILES = .deps/BeckmannEgle.P .deps/MilfordInstruments.P \ .deps/plugin_math.P .deps/plugin_meminfo.P .deps/plugin_mysql.P \ .deps/plugin_netdev.P .deps/plugin_ppp.P .deps/plugin_proc_stat.P \ .deps/plugin_seti.P .deps/plugin_string.P .deps/plugin_uname.P \ -.deps/plugin_xmms.P .deps/qprintf.P .deps/thread.P .deps/timer.P \ -.deps/udelay.P .deps/widget.P .deps/widget_bar.P .deps/widget_icon.P \ -.deps/widget_text.P +.deps/plugin_wireless.P .deps/plugin_xmms.P .deps/qprintf.P \ +.deps/thread.P .deps/timer.P .deps/udelay.P .deps/widget.P \ +.deps/widget_bar.P .deps/widget_icon.P .deps/widget_text.P SOURCES = $(lcd4linux_SOURCES) $(EXTRA_lcd4linux_SOURCES) OBJECTS = $(lcd4linux_OBJECTS) @@ -3966,9 +3966,12 @@ _ACEOF # Checks for X11 -echo "$as_me:$LINENO: checking for X" >&5 + +if test "x$ac_path_x_has_been_run" != xyes; then + echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6 +ac_path_x_has_been_run=yes # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -4061,7 +4064,7 @@ ac_x_header_dirs=' /usr/openwin/share/include' if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for Intrinsic.h. + # Guess where to find include files, by looking for a specified header file. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -4195,10 +4198,15 @@ else # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes \ ac_x_includes=$x_includes ac_x_libraries=$x_libraries" - echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 -echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 + # It might be that x_includes is empty (headers are found in the + # standard search path. Then output the corresponding message + ac_out_x_includes=$x_includes + test "x$x_includes" = x && ac_out_x_includes="in standard search path" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $ac_out_x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $ac_out_x_includes" >&6 fi +fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. diff --git a/plugin_exec.c b/plugin_exec.c index 59bfb89..565ace1 100644 --- a/plugin_exec.c +++ b/plugin_exec.c @@ -1,4 +1,4 @@ -/* $Id: plugin_exec.c,v 1.1 2004/03/20 11:49:40 reinelt Exp $ +/* $Id: plugin_exec.c,v 1.2 2004/04/08 10:48:25 reinelt Exp $ * * plugin for external processes * @@ -27,6 +27,11 @@ * * * $Log: plugin_exec.c,v $ + * Revision 1.2 2004/04/08 10:48:25 reinelt + * finished plugin_exec + * modified thread handling + * added '%x' format to qprintf (hexadecimal) + * * Revision 1.1 2004/03/20 11:49:40 reinelt * forgot to add plugin_exec.c ... * @@ -46,63 +51,215 @@ #include <stdlib.h> #include <stdio.h> #include <unistd.h> - -// #include <string.h> -// #include <ctype.h> -// #include <errno.h> - -#include <sys/ipc.h> -#include <sys/sem.h> -#include <sys/shm.h> +#include <string.h> +#include <errno.h> #include "debug.h" #include "plugin.h" #include "hash.h" #include "cfg.h" #include "thread.h" +#include "qprintf.h" + + +#define NUM_THREADS 16 +#define SHM_SIZE 256 + +typedef struct { + int delay; + int mutex; + pid_t pid; + int shmid; + char *cmd; + char *key; + char *ret; +} EXEC_THREAD; + +static EXEC_THREAD Thread[NUM_THREADS]; +static int max_thread = -1; static HASH EXEC = { 0, }; -static int fatal = 0; -static int do_exec (void) + +// x^0 + x^5 + x^12 +#define CRCPOLY 0x8408 + +static unsigned short CRC (unsigned char *s) +{ + int i; + unsigned short crc; + + // seed value + crc=0xffff; + + while (*s!='\0') { + crc ^= *s++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0); + } + return crc; +} + + +static void exec_thread (void *data) +{ + EXEC_THREAD *Thread = (EXEC_THREAD*)data; + FILE *pipe; + char buffer[SHM_SIZE]; + int len; + + // use a safe path + putenv ("PATH=/usr/local/bin:/usr/bin:/bin"); + + // forever... + while (1) { + pipe = popen(Thread->cmd, "r"); + if (pipe == NULL) { + error("exec error: could not run pipe '%s': %s", Thread->cmd, strerror(errno)); + len = 0; + } else { + len = fread(buffer, 1, SHM_SIZE-1, pipe); + if (len <= 0) { + error("exec error: could not read from pipe '%s': %s", Thread->cmd, strerror(errno)); + len = 0; + } + pclose(pipe); + } + + // force trailing zero + buffer[len] = '\0'; + + // remove trailing CR/LF + while (len>0 && (buffer[len-1]=='\n' || buffer[len-1]=='\r')) { + buffer[--len]='\0'; + } + + // lock shared memory + mutex_lock(Thread->mutex); + // write data + strncpy(Thread->ret, buffer, SHM_SIZE); + // unlock shared memory + mutex_unlock(Thread->mutex); + usleep (Thread->delay); + } +} + + +static void destroy_exec_thread (int n) +{ + if (Thread[n].mutex != 0) mutex_destroy(Thread[n].mutex); + if (Thread[n].cmd) free (Thread[n].cmd); + if (Thread[n].key) free (Thread[n].key); + if (Thread[n].ret) shm_destroy (Thread[n].shmid, Thread[n].ret); + + Thread[n].delay = 0; + Thread[n].mutex = 0; + Thread[n].pid = 0; + Thread[n].shmid = 0; + Thread[n].cmd = NULL; + Thread[n].key = NULL; + Thread[n].ret = NULL; +} + + +static int create_exec_thread (char *cmd, char *key, int delay) { - int age; + char name[10]; + + if (max_thread >= NUM_THREADS) { + error ("cannot create exec thread <%s>: thread buffer full!", cmd); + return -1; + } + + max_thread++; + Thread[max_thread].delay = delay; + Thread[max_thread].mutex = mutex_create(); + Thread[max_thread].pid = -1; + Thread[max_thread].cmd = strdup(cmd); + Thread[max_thread].key = strdup(key); + Thread[max_thread].ret = NULL; + + // create communication buffer + Thread[max_thread].shmid = shm_create ((void**)&Thread[max_thread].ret, SHM_SIZE); + + // catch error + if (Thread[max_thread].shmid < 0) { + error ("cannot create exec thread <%s>: shared memory allocation failed!", cmd); + destroy_exec_thread (max_thread--); + return -1; + } - // if a fatal error occured, do nothing - if (fatal != 0) return -1; + // create thread + qprintf(name, sizeof(name), "exec-%s", key); + Thread[max_thread].pid = thread_create (name, exec_thread, &Thread[max_thread]); + + // catch error + if (Thread[max_thread].pid < 0) { + error ("cannot create exec thread <%s>: fork failed?!", cmd); + destroy_exec_thread (max_thread--); + return -1; + } - // reread every 100 msec only - age=hash_age(&EXEC, NULL, NULL); - if (age>0 && age<=100) return 0; return 0; -} +} -static void my_junk (char *name) + +static int do_exec (char *cmd, char *key, int delay) { - int i; + int i, age; + + age = hash_age(&EXEC, key, NULL); - debug ("junk thread starting!"); + if (age < 0) { + hash_set (&EXEC, key, ""); + // first-time call: create thread + if (delay < 10) { + error ("exec(%s): delay %d is too short! using 10 msec", cmd, delay); + delay = 10; + } + if (create_exec_thread (cmd, key, 1000*delay)) { + return -1; + } + return 0; + } + + // reread every 10 msec only + if (age > 0 && age <= 10) return 0; - for (i=0; i<10; i++) { - debug ("junk look %d", i); - sleep (1); + // find thread + for (i = 0; i <= max_thread; i++) { + if (strcmp(key, Thread[i].key) == 0) { + // lock shared memory + mutex_lock(Thread[i].mutex); + // copy data + hash_set (&EXEC, key, Thread[i].ret); + // unlock shared memory + mutex_unlock(Thread[i].mutex); + return 0; + } } - debug ("junk thread done!"); + + error ("internal error: could not find thread exec-%s", key); + return -1; } - -static void my_exec (RESULT *result, int argc, RESULT *argv[]) +static void my_exec (RESULT *result, RESULT *arg1, RESULT *arg2) { - char *key, *val; + char *cmd, key[5], *val; + int delay; - if (do_exec()<0) { + cmd = R2S(arg1); + delay = (int)R2N(arg2); + + qprintf (key, sizeof(key), "%x", CRC(cmd)); + + if (do_exec(cmd, key, delay) < 0) { SetResult(&result, R_STRING, ""); return; } - // key=R2S(arg1); - val=hash_get(&EXEC, key); - if (val==NULL) val=""; + val = hash_get(&EXEC, key); + if (val == NULL) val = ""; SetResult(&result, R_STRING, val); } @@ -110,18 +267,18 @@ static void my_exec (RESULT *result, int argc, RESULT *argv[]) int plugin_init_exec (void) { - int junk; - - AddFunction ("exec", -1, my_exec); - - // junk=thread_create ("Junk", my_junk); - // debug ("junk=%d", junk); - + AddFunction ("exec", 2, my_exec); return 0; } void plugin_exit_exec(void) { + int i; + + for (i=0; i<=max_thread; i++) { + destroy_exec_thread(i); + } + hash_destroy(&EXEC); } @@ -1,4 +1,4 @@ -/* $Id: qprintf.c,v 1.1 2004/02/27 07:06:26 reinelt Exp $ +/* $Id: qprintf.c,v 1.2 2004/04/08 10:48:25 reinelt Exp $ * * simple but quick snprintf() replacement * @@ -26,6 +26,11 @@ * * * $Log: qprintf.c,v $ + * Revision 1.2 2004/04/08 10:48:25 reinelt + * finished plugin_exec + * modified thread handling + * added '%x' format to qprintf (hexadecimal) + * * Revision 1.1 2004/02/27 07:06:26 reinelt * new function 'qprintf()' (simple but quick snprintf() replacement) * @@ -79,6 +84,30 @@ static char *itoa(char* buffer, size_t size, int value) } +static char *itox(char* buffer, size_t size, unsigned int value) +{ + char *p; + int digit; + + // sanity checks + if (buffer==NULL || size<2) return (NULL); + + // p points to last char + p = buffer+size-1; + + // set terminating zero + *p='\0'; + + do { + digit = value%16; + value = value/16; + *--p = (digit < 10 ? '0' : 'a'-10) + digit; + } while (value!=0 && p>buffer); + + return p; +} + + int qprintf(char *str, size_t size, const char *format, ...) { va_list ap; @@ -100,6 +129,7 @@ int qprintf(char *str, size_t size, const char *format, ...) { if (*src=='%') { char buf[12], *s; int d; + unsigned int u; switch (*++src) { case 's': src++; @@ -118,6 +148,15 @@ int qprintf(char *str, size_t size, const char *format, ...) { *dst++ = *s++; } break; + case 'x': + src++; + u = va_arg(ap, unsigned int); + s = itox (buf, sizeof(buf), u); + while (len < size && *s != '\0') { + len++; + *dst++ = *s++; + } + break; default: len++; *dst++ = '%'; @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.2 2004/03/20 07:31:33 reinelt Exp $ +/* $Id: thread.c,v 1.3 2004/04/08 10:48:25 reinelt Exp $ * * thread handling (mutex, shmem, ...) * @@ -26,6 +26,11 @@ * * * $Log: thread.c,v $ + * Revision 1.3 2004/04/08 10:48:25 reinelt + * finished plugin_exec + * modified thread handling + * added '%x' format to qprintf (hexadecimal) + * * Revision 1.2 2004/03/20 07:31:33 reinelt * support for HD66712 (which has a different RAM layout) * further threading development @@ -140,13 +145,14 @@ int shm_create (void **buffer, int size) } -void shm_destroy (int shmid) +void shm_destroy (int shmid, void *buffer) { + shmdt (buffer); shmctl(shmid, IPC_RMID, NULL); } -int thread_create (char *name, void (*thread)(char *name)) +int thread_create (char *name, void (*thread)(void *data), void *data) { pid_t pid, ppid; @@ -158,7 +164,7 @@ int thread_create (char *name, void (*thread)(char *name)) return -1; case 0: info ("thread %s starting...", name); - thread(name); + thread(data); info ("thread %s ended.", name); exit (0); default: @@ -1,4 +1,4 @@ -/* $Id: thread.h,v 1.2 2004/03/20 07:31:33 reinelt Exp $ +/* $Id: thread.h,v 1.3 2004/04/08 10:48:25 reinelt Exp $ * * thread handling (mutex, shmem, ...) * @@ -26,6 +26,11 @@ * * * $Log: thread.h,v $ + * Revision 1.3 2004/04/08 10:48:25 reinelt + * finished plugin_exec + * modified thread handling + * added '%x' format to qprintf (hexadecimal) + * * Revision 1.2 2004/03/20 07:31:33 reinelt * support for HD66712 (which has a different RAM layout) * further threading development @@ -44,8 +49,8 @@ void mutex_unlock (int semid); void mutex_destroy (int semid); int shm_create (void **buffer, int size); -void shm_destroy (int shmid); +void shm_destroy (int shmid, void *buffer) ; -int thread_create (char *name, void (*thread)(char *name)); +int thread_create (char *name, void (*thread)(void *data), void *data); #endif |