#define _BSD_SOURCE #include #include #include #include #include #include #include #include #include "monitor.h" #include "so.h" #include "me.h" struct mon_process_entry { void *(*callback)(void *); void *args; int flags; char *name; struct mon_process_entry *next; struct mon_process_entry *prev; }; struct process { char *name; struct process *next; struct process *prev; }; static void *mon_process_run(void *args); static void mon_process_dump(void); static int process_add(struct process **l, char *name); static void process_free(struct process **l); static int process_find(struct process *l, char *name); static pthread_t t; static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; static struct mon_process_entry *list = NULL; static int running = 0; static void *mon_process_run(void *args) { struct mon_process_entry *p, *e; struct process *current = NULL; FILE *fp; char buf[256], *name; int i; glob_t g; pthread_t ct; while(1) { pthread_mutex_lock(&m); if(!list) { running = 0; pthread_mutex_unlock(&m); return NULL; } process_free(¤t); memset(&g, 0x00, sizeof(g)); glob(SO"/proc/[0-9]*/cmdline", 0, NULL, &g); for(i = 0; i < g.gl_pathc; i++) { if(!(fp = fopen(g.gl_pathv[i], "r"))) continue; if(fgets(buf, sizeof(buf), fp)) { if(!(name = strrchr(buf, '/'))) name = buf; if(name[0] == '/') name++; process_add(¤t, name); } fclose(fp); } globfree(&g); p = list; while(p) { if((!(p->flags & MON_FLAG_NEG) && process_find(current, p->name)) || ((p->flags & MON_FLAG_NEG) && !process_find(current, p->name))) { pthread_create(&ct, NULL, p->callback, p->args); pthread_detach(ct); if(p == list) list = p->next; if(p->next) p->next->prev = p->prev; if(p->prev) p->prev->next = p->next; e = p; p = p->next; if(e->name) free(e->name); free(e); } else { p = p->next; } } mon_process_dump(); pthread_mutex_unlock(&m); sleep(1); } } void mon_process_start(void *args) { pthread_mutex_lock(&m); if(!running) if(!pthread_create(&t, NULL, mon_process_run, NULL)) running = 1; pthread_mutex_unlock(&m); } void *mon_process_addwatch(void *(*callback)(void *), void *args, int flags, ...) { struct mon_process_entry *p = NULL; va_list va; pthread_mutex_lock(&m); do { if(!list) { if(!(list = malloc(sizeof(struct mon_process_entry)))) break; list->prev = NULL; p = list; } else { for(p = list; p->next; p = p->next); if(!(p->next = malloc(sizeof(struct mon_process_entry)))) break; p->next->prev = p; p = p->next; } p->next = NULL; p->callback = callback; p->args = args; p->flags = flags; va_start(va, flags); p->name = strdup(va_arg(va, char *)); va_end(va); if(!running) if(!pthread_create(&t, NULL, mon_process_run, NULL)) running = 1; } while(0); mon_process_dump(); pthread_mutex_unlock(&m); return p; } void mon_process_delwatch(void *entry) { struct mon_process_entry *p = NULL, *e = (struct mon_process_entry *)entry; if(!list || !e) return; pthread_mutex_lock(&m); for(p = list; p && (p != e); p = p->next); if(p) { if(p == list) list = p->next; if(p->next) p->next->prev = p->prev; if(p->prev) p->prev->next = p->next; if(p->name) free(p->name); free(p); } pthread_mutex_unlock(&m); return; } void mon_process_dump(void) { #if 0 struct mon_process_entry *p = NULL; debugme("\n--- PROCESS MONITOR LIST ---\n"); for(p = list; p; p = p->next) debugme("- %s (at %p)\n", p->name, (void *)p); debugme("\n"); #endif return; } static int process_add(struct process **l, char *name) { struct process *p; if(!*l) { if(!(*l = malloc(sizeof(struct process)))) return -1; (*l)->prev = NULL; p = *l; } else { for(p = *l; p->next; p = p->next) if(!strcasecmp(p->name, name)) return 0; if(!strcasecmp(p->name, name)) return 0; if(!(p->next = malloc(sizeof(struct process)))) return -1; p->next->prev = p; p = p->next; } p->next = NULL; p->name = strdup(name); return 1; } static void process_free(struct process **l) { struct process *p; while(*l) { p = (*l)->next; if((*l)->name) free((*l)->name); free(*l); *l = p; } return; } static int process_find(struct process *l, char *name) { for(; l; l = l->next) { if(!fnmatch(name, l->name, FNM_PERIOD|FNM_CASEFOLD)) return 1; } return 0; } .