From a90fe72dc74613b75b61ee64ac288c71359b3572 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Tue, 16 Feb 2010 14:58:35 +0000 Subject: adding directories from -d|--dir argument to watch list at startup max-client argument works now --- rhdropbox.c | 22 +++++-- sysexec.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++----------- sysexec.h | 16 +++-- 3 files changed, 204 insertions(+), 47 deletions(-) diff --git a/rhdropbox.c b/rhdropbox.c index 90694f7..234d24d 100644 --- a/rhdropbox.c +++ b/rhdropbox.c @@ -111,10 +111,10 @@ int process_watch(int inotify_fd, read_buffer_t* buffer, watch_list_t* watch_lst char* const argv[] = { opt->script_, path, event->len > 0 ? event->name : "", buf, NULL }; char* const evp[] = { NULL }; - rh_exec(opt->script_, argv, evp, child_lst); + rh_exec(opt->script_, argv, evp, child_lst, opt); snprintf(buf, 100, "new file in '%s', name='%s'", path, event->len > 0 ? event->name : ""); - log_printf(NOTICE, "%s, executed script %s", buf, opt->script_); + log_printf(NOTICE, "%s, executing script %s", buf, opt->script_); client_t* client; int listener_cnt = 0; for(client = client_lst; client; client = client->next) @@ -142,6 +142,9 @@ int process_watch(int inotify_fd, read_buffer_t* buffer, watch_list_t* watch_lst void send_status_watch_list(int fd, watch_list_t* watch_lst, client_t* client_lst) { + if(fd <= 0 && !client_lst) + return; + if(!watch_lst || !watch_lst->first_) { if(fd > 0) send_response(fd, "currently no paths in watch list"); @@ -191,7 +194,8 @@ void process_cmd_add_remove(cmd_id_t cmd_id, const char* path, int fd, int inoti wd = inotify_rm_watch(inotify_fd, tmp_fd); else { log_printf(ERROR, "cmd_add_remove path not found in watch list"); - send_response(fd, "Error: path not found in watch list"); + if(fd > 0) + send_response(fd, "Error: path not found in watch list"); return; } } @@ -201,7 +205,8 @@ void process_cmd_add_remove(cmd_id_t cmd_id, const char* path, int fd, int inoti } if(wd < 0) { log_printf(ERROR, "inotify %s '%s' failed: %s", cmd_id == ADD ? "adding" : "removing", path, strerror(errno)); - send_response(fd, "Error: add/remove failed"); + if(fd > 0) + send_response(fd, "Error: add/remove failed"); return; } @@ -210,7 +215,8 @@ void process_cmd_add_remove(cmd_id_t cmd_id, const char* path, int fd, int inoti ret = watch_list_add(watch_lst, wd, path); if(ret) { log_printf(ERROR, "can't add path to watch list"); - send_response(fd, "Error: can't add path to watch list"); + if(fd > 0) + send_response(fd, "Error: can't add path to watch list"); } } else { @@ -350,6 +356,10 @@ int main_loop(int cmd_listen_fd, int inotify_fd, options_t* opt) FD_SET(sig_fd, &readfds); max_fd = (max_fd < sig_fd) ? sig_fd : max_fd; + string_list_element_t* dir = opt->dirs_.first_; + for(;dir;dir=dir->next_) + process_cmd_add_remove(ADD, dir->string_, -1, inotify_fd, &watch_lst, client_lst); + struct timeval timeout; int return_value = 0; while(!return_value) { @@ -366,7 +376,7 @@ int main_loop(int cmd_listen_fd, int inotify_fd, options_t* opt) if(ret == -1) continue; if(!ret) { - rh_waitpid(&child_lst); + rh_waitpid(&child_lst, opt); continue; } diff --git a/sysexec.c b/sysexec.c index d8722f4..79f4e74 100644 --- a/sysexec.c +++ b/sysexec.c @@ -33,6 +33,50 @@ #include "sysexec.h" #include "log.h" +char** dup_ptrptr(char* const ptrptr[]) +{ + if(!ptrptr) + return NULL; + + int n = 0; + while(ptrptr[n]) + n++; + + char** my_ptrptr; + my_ptrptr = malloc((n+1)*sizeof(char*)); + if(!my_ptrptr) + return NULL; + + int i; + for(i = 0; i < n; ++i) { + my_ptrptr[i] = strdup(ptrptr[i]); + if(!my_ptrptr[i]) { + i--; + for(; i >= 0; --i) + free(my_ptrptr[i]); + + free(my_ptrptr); + return NULL; + } + } + + my_ptrptr[n] = NULL; + + return my_ptrptr; +} + +void free_ptrptr(char** ptrptr) +{ + if(!ptrptr) + return; + + int i; + for(i = 0; ptrptr[i]; ++i) + free(ptrptr[i]); + + free(ptrptr); +} + void child_list_init(child_list_t* list) { if(!list) @@ -56,49 +100,93 @@ void child_list_clear(child_list_t* list) } } -int child_list_add(child_list_t* list, pid_t pid, const char* script, int err_fd) +child_list_element_t* child_list_new(const char* script, char* const argv[], char* const evp[]) +{ + child_list_element_t* new_child; + + new_child = malloc(sizeof(child_list_element_t)); + if(!new_child) + return NULL; + + new_child->next_ = 0; + new_child->pid_ = -1; + new_child->err_fd_ = -1; + new_child->running_ = 0; + new_child->script_ = strdup(script); + if(!new_child->script_) { + free(new_child); + return NULL; + } + + new_child->argv_ = dup_ptrptr(argv); + if(!new_child->argv_) { + free(new_child->script_); + free(new_child); + return NULL; + + } + + new_child->evp_ = dup_ptrptr(evp); + if(!new_child->evp_) { + free_ptrptr(new_child->argv_); + free(new_child->script_); + free(new_child); + return NULL; + } + return new_child; +} + +child_list_element_t* child_list_add(child_list_t* list, const char* script, char* const argv[], char* const evp[]) { if(!list) - return -1; + return NULL; if(!list->first_) { - list->first_ = malloc(sizeof(child_list_element_t)); - if(!list->first_) - return -2; - - list->first_->next_ = 0; - list->first_->pid_ = pid; - list->first_->err_fd_ = err_fd; - list->first_->script_ = strdup(script); - if(!list->first_->script_) { - free(list->first_); - list->first_ = NULL; - return -2; - } + list->first_ = child_list_new(script, argv, evp); + return list->first_; } else { child_list_element_t* tmp = list->first_; while(tmp->next_) tmp = tmp->next_; - tmp->next_ = malloc(sizeof(child_list_element_t)); - if(!tmp->next_) - return -2; - - tmp->next_->next_ = 0; - tmp->next_->pid_ = pid; - tmp->next_->err_fd_ = err_fd; - tmp->next_->script_ = strdup(script); - if(!tmp->next_->script_) { - free(tmp->next_); - tmp->next_ = NULL; - return -2; + tmp->next_ = child_list_new(script, argv, evp); + return tmp->next_; + } +} + +void child_list_rm(child_list_t* list, child_list_element_t* child) +{ + if(!list || !child) + return; + + if(child == list->first_) { + list->first_ = list->first_->next_; + free_ptrptr(child->argv_); + free_ptrptr(child->evp_); + if(child->script_) + free(child->script_); + free(child); + return; + } + else { + child_list_element_t* tmp = list->first_; + while(tmp) { + if(tmp->next_ == child) { + tmp->next_ = tmp->next_->next_; + free_ptrptr(child->argv_); + free_ptrptr(child->evp_); + if(child->script_) + free(child->script_); + free(child); + return; + } + tmp = tmp->next_; } } - return 0; } -void child_list_rm(child_list_t* list, pid_t pid) +void child_list_rm_pid(child_list_t* list, pid_t pid) { if(!list) return; @@ -108,6 +196,8 @@ void child_list_rm(child_list_t* list, pid_t pid) tmp = list->first_; list->first_ = list->first_->next_; + free_ptrptr(tmp->argv_); + free_ptrptr(tmp->evp_); if(tmp->script_) free(tmp->script_); free(tmp); @@ -120,6 +210,8 @@ void child_list_rm(child_list_t* list, pid_t pid) if(tmp->pid_ == pid) { prev->next_ = tmp->next_; + free_ptrptr(tmp->argv_); + free_ptrptr(tmp->evp_); if(tmp->script_) free(tmp->script_); free(tmp); @@ -145,21 +237,56 @@ child_list_element_t* child_list_find(child_list_t* list, pid_t pid) return NULL; } -int rh_exec(const char* script, char* const argv[], char* const evp[], child_list_t* child_lst) +int child_list_num_running(child_list_t* list) +{ + int num = 0; + + if(!list) + return 0; + + child_list_element_t* tmp = list->first_; + for(;tmp;tmp=tmp->next_) + if(tmp->running_) num++; + + return num; +} + +int rh_exec(const char* script, char* const argv[], char* const evp[], child_list_t* child_lst, options_t* opt) { if(!script) return -1; + child_list_element_t* child = child_list_add(child_lst, script, argv, evp); + if(!child) + return -2; + + if(child_list_num_running(child_lst) >= opt->max_children_) { + log_printf(INFO, "deferring script execution '%s'", script); + return 0; + } + + int ret = rh_exec_child(child); + if(ret) + child_list_rm(child_lst, child); + + return ret; +} + +int rh_exec_child(child_list_element_t* child) +{ + if(!child || child->pid_ != -1) + return -1; + int pipefd[2]; if(pipe(pipefd) == -1) { - log_printf(ERROR, "executing script '%s' pipe() error: %s", script, strerror(errno)); + log_printf(ERROR, "executing script '%s' failed: pipe() error: %s", child->script_, strerror(errno)); return -1; } pid_t pid; pid = fork(); if(pid == -1) { - log_printf(ERROR, "executing script '%s' fork() error: %s", script, strerror(errno)); + log_printf(ERROR, "executing script '%s' failed: fork() error: %s", child->script_, strerror(errno)); return -1; } @@ -177,7 +304,7 @@ int rh_exec(const char* script, char* const argv[], char* const evp[], child_lis if(dup(fd) == -1) // stderr log_printf(WARNING, "can't open stderr"); } - execve(script, argv, evp); + execve(child->script_, child->argv_, child->evp_); // if execve returns, an error occurred, but logging doesn't work // because we closed all file descriptors, so just write errno to // pipe and call exit @@ -186,11 +313,16 @@ int rh_exec(const char* script, char* const argv[], char* const evp[], child_lis } close(pipefd[1]); - log_printf(INFO, "called script '%s' with pid %d", script, pid); - return child_list_add(child_lst, pid, script, pipefd[0]); + child->pid_ = pid; + child->err_fd_ = pipefd[0]; + child->running_ = 1; + + log_printf(INFO, "called script '%s' with pid %d", child->script_, child->pid_); + + return 0; } -int rh_waitpid(child_list_t* child_lst) +int rh_waitpid(child_list_t* child_lst, options_t* opt) { int status = 0; pid_t pid = waitpid(-1, &status, WNOHANG); @@ -215,7 +347,8 @@ int rh_waitpid(child_list_t* child_lst) int err = 0; if(read(child->err_fd_, (void*)(&err), sizeof(err)) >= sizeof(err)) { log_printf(INFO, "script '%s' exec() error: %s", child->script_, strerror(err)); - close(child->script_); + close(child->err_fd_); + child_list_rm_pid(child_lst, pid); return -1; } } @@ -227,6 +360,12 @@ int rh_waitpid(child_list_t* child_lst) log_printf(INFO, "executing script '%s' (pid %d): unkown error", child->script_, child->pid_); close(child->err_fd_); + + child_list_rm_pid(child_lst, pid); + + if(child_list_num_running(child_lst) < opt->max_children_) + rh_exec_child(child_list_find(child_lst, -1)); + return status; } diff --git a/sysexec.h b/sysexec.h index 119405c..8954622 100644 --- a/sysexec.h +++ b/sysexec.h @@ -23,11 +23,15 @@ #define RHDROPBOX_sysexec_h_INCLUDED #include +#include "options.h" struct child_list_element_struct { pid_t pid_; char* script_; int err_fd_; + int running_; + char** argv_; + char** evp_; struct child_list_element_struct* next_; }; typedef struct child_list_element_struct child_list_element_t; @@ -39,11 +43,15 @@ typedef struct child_list_struct child_list_t; void child_list_init(child_list_t* list); void child_list_clear(child_list_t* list); -int child_list_add(child_list_t* list, pid_t pid, const char* script, int err_fd); -void child_list_rm(child_list_t* list, pid_t pid); +child_list_element_t* child_list_new(const char* script, char* const argv[], char* const evp[]); +child_list_element_t* child_list_add(child_list_t* list, const char* script, char* const argv[], char* const evp[]); +void child_list_rm(child_list_t* list, child_list_element_t* child); +void child_list_rm_pid(child_list_t* list, pid_t pid); child_list_element_t* child_list_find(child_list_t* list, pid_t pid); +int child_list_num_running(child_list_t* list); -int rh_exec(const char* script, char* const argv[], char* const evp[], child_list_t* child_lst); -int rh_waitpid(child_list_t* child_lst); +int rh_exec(const char* script, char* const argv[], char* const evp[], child_list_t* child_lst, options_t* opt); +int rh_exec_child(child_list_element_t* child); +int rh_waitpid(child_list_t* child_lst, options_t* opt); #endif -- cgit v1.2.3