diff options
Diffstat (limited to 'sysexec.c')
-rw-r--r-- | sysexec.c | 213 |
1 files changed, 176 insertions, 37 deletions
@@ -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; } |