diff options
-rw-r--r-- | rhdropbox.c | 21 | ||||
-rw-r--r-- | string_list.c | 4 | ||||
-rw-r--r-- | sysexec.c | 179 | ||||
-rw-r--r-- | sysexec.h | 54 | ||||
-rw-r--r-- | watch_list.c | 4 |
5 files changed, 199 insertions, 63 deletions
diff --git a/rhdropbox.c b/rhdropbox.c index 5c3ca2d..1049fd1 100644 --- a/rhdropbox.c +++ b/rhdropbox.c @@ -59,7 +59,7 @@ int send_response(int fd, const char* response) return ret; } -int process_watch(int inotify_fd, read_buffer_t* buffer, watch_list_t* watch_lst, options_t* opt, client_t* client_lst) +int process_watch(int inotify_fd, read_buffer_t* buffer, watch_list_t* watch_lst, options_t* opt, client_t* client_lst, child_list_t* child_lst) { log_printf(DEBUG, "something changed on watch descriptor '%d'", inotify_fd); @@ -96,7 +96,7 @@ int process_watch(int inotify_fd, read_buffer_t* buffer, watch_list_t* watch_lst else { char* const argv[] = { opt->script_, path, event->len > 0 ? event->name : "", NULL }; char* const evp[] = { NULL }; - uanytun_exec(opt->script_, argv, evp); + rh_exec(opt->script_, argv, evp, child_lst); char buf[100]; snprintf(buf, 100, "new file in '%s', name='%s'", path, event->len > 0 ? event->name : ""); @@ -328,24 +328,34 @@ int main_loop(int cmd_listen_fd, int inotify_fd, options_t* opt) watch_list_t watch_lst; watch_list_init(&watch_lst); + child_list_t child_lst; + child_list_init(&child_lst); + int sig_fd = signal_init(); if(sig_fd < 0) return -1; FD_SET(sig_fd, &readfds); max_fd = (max_fd < sig_fd) ? sig_fd : max_fd; + struct timeval timeout; int return_value = 0; while(!return_value) { memcpy(&tmpfds, &readfds, sizeof(tmpfds)); - int ret = select(max_fd+1, &tmpfds, NULL, NULL, NULL); + timeout.tv_sec = 0; + timeout.tv_usec = 200000; + int ret = select(max_fd+1, &tmpfds, NULL, NULL, &timeout); if(ret == -1 && errno != EINTR) { log_printf(ERROR, "select returned with error: %s", strerror(errno)); return_value = -1; break; } - if(ret == -1 || !ret) + if(ret == -1) + continue; + if(!ret) { + rh_waitpid(&child_lst); continue; + } if(FD_ISSET(sig_fd, &tmpfds)) { if(signal_handle()) { @@ -355,7 +365,7 @@ int main_loop(int cmd_listen_fd, int inotify_fd, options_t* opt) } if(FD_ISSET(inotify_fd, &tmpfds)) { - return_value = process_watch(inotify_fd, &event_buffer, &watch_lst, opt, client_lst); + return_value = process_watch(inotify_fd, &event_buffer, &watch_lst, opt, client_lst, &child_lst); if(return_value) break; } @@ -395,6 +405,7 @@ int main_loop(int cmd_listen_fd, int inotify_fd, options_t* opt) } } + child_list_clear(&child_lst); watch_list_clear(&watch_lst); client_clear(&client_lst); signal_stop(); diff --git a/string_list.c b/string_list.c index e5e8a62..a4f4ab8 100644 --- a/string_list.c +++ b/string_list.c @@ -92,8 +92,8 @@ int string_list_add(string_list_t* list, const char* string) tmp->next_->next_ = 0; tmp->next_->string_ = strdup(string); if(!tmp->next_->string_) { - free(list->first_); - list->first_ = NULL; + free(tmp->next_); + tmp->next_ = NULL; return -2; } } @@ -1,36 +1,22 @@ /* - * uAnytun + * rhdropbox * - * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full - * featured implementation uAnytun has no support for multiple connections - * or synchronisation. It is a small single threaded implementation intended - * to act as a client on small platforms. - * The secure anycast tunneling protocol (satp) defines a protocol used - * for communication between any combination of unicast and anycast - * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel - * mode and allows tunneling of every ETHER TYPE protocol (e.g. - * ethernet, ip, arp ...). satp directly includes cryptography and - * message authentication based on the methodes used by SRTP. It is - * intended to deliver a generic, scaleable and secure solution for - * tunneling and relaying of packets of any protocol. - * + * Copyright (C) 2009 Christian Pointner <equinox@helsinki.at> * - * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org> + * This file is part of rhdropbox. * - * This file is part of uAnytun. - * - * uAnytun is free software: you can redistribute it and/or modify + * rhdropbox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * - * uAnytun is distributed in the hope that it will be useful, + * rhdropbox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with uAnytun. If not, see <http://www.gnu.org/licenses/>. + * along with rhdropbox. If not, see <http://www.gnu.org/licenses/>. */ #include "datatypes.h" @@ -47,7 +33,119 @@ #include "sysexec.h" #include "log.h" -int uanytun_exec(const char* script, char* const argv[], char* const evp[]) +void child_list_init(child_list_t* list) +{ + if(!list) + return; + + list->first_ = NULL; +} + +void child_list_clear(child_list_t* list) +{ + if(!list) + return; + + while(list->first_) { + child_list_element_t* tmp; + tmp = list->first_; + list->first_ = tmp->next_; + if(tmp->script_) + free(tmp->script_); + free(tmp); + } +} + +int child_list_add(child_list_t* list, pid_t pid, const char* script, int err_fd) +{ + if(!list) + return -1; + + 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; + } + } + 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; + } + } + return 0; +} + +void child_list_rm(child_list_t* list, pid_t pid) +{ + if(!list) + return; + + child_list_element_t* tmp = NULL; + if(list->first_->pid_ == pid) { + tmp = list->first_; + list->first_ = list->first_->next_; + + if(tmp->script_) + free(tmp->script_); + free(tmp); + return; + } + + child_list_element_t* prev = list->first_; + tmp = list->first_->next_; + while(tmp) { + if(tmp->pid_ == pid) { + prev->next_ = tmp->next_; + + if(tmp->script_) + free(tmp->script_); + free(tmp); + return; + } + prev = tmp; + tmp = tmp->next_; + } +} + +child_list_element_t* child_list_find(child_list_t* list, pid_t pid) +{ + if(!list) + return NULL; + + child_list_element_t* tmp = list->first_; + while(tmp) { + if(tmp->pid_ == pid) + return tmp; + tmp = tmp->next_; + } + + return NULL; +} + +int rh_exec(const char* script, char* const argv[], char* const evp[], child_list_t* child_lst) { if(!script) return -1; @@ -88,28 +186,47 @@ int uanytun_exec(const char* script, char* const argv[], char* const evp[]) } close(pipefd[1]); + log_printf(NOTICE, "called script '%s' with pid %d", script, pid); + return child_list_add(child_lst, pid, script, pipefd[0]); +} + +int rh_waitpid(child_list_t* child_lst) +{ int status = 0; - waitpid(pid, &status, 0); + pid_t pid = waitpid(-1, &status, WNOHANG); + if(!pid || (pid < 0 && errno == ECHILD)) + return 0; + if(pid < 0) { + log_printf(ERROR, "waitpid returned with error: %s", strerror(errno)); + return pid; + } + + child_list_element_t* child = child_list_find(child_lst, pid); + if(!child) { + log_printf(ERROR, "waitpid returned unknown child pid (%d)", pid); + return 0; + } fd_set rfds; FD_ZERO(&rfds); - FD_SET(pipefd[0], &rfds); + FD_SET(child->err_fd_, &rfds); struct timeval tv = { 0 , 0 }; - if(select(pipefd[0]+1, &rfds, NULL, NULL, &tv) == 1) { + if(select(child->err_fd_+1, &rfds, NULL, NULL, &tv) == 1) { int err = 0; - if(read(pipefd[0], (void*)(&err), sizeof(err)) >= sizeof(err)) { - log_printf(NOTICE, "script '%s' exec() error: %s", script, strerror(err)); - close(pipefd[0]); + if(read(child->err_fd_, (void*)(&err), sizeof(err)) >= sizeof(err)) { + log_printf(NOTICE, "script '%s' exec() error: %s", child->script_, strerror(err)); + close(child->script_); return -1; } } if(WIFEXITED(status)) - log_printf(NOTICE, "script '%s' returned %d", script, WEXITSTATUS(status)); + log_printf(NOTICE, "script '%s' (pid %d) returned %d", child->script_, child->pid_, WEXITSTATUS(status)); else if(WIFSIGNALED(status)) - log_printf(NOTICE, "script '%s' terminated after signal %d", script, WTERMSIG(status)); + log_printf(NOTICE, "script '%s' (pid %d) terminated after signal %d", child->script_, child->pid_, WTERMSIG(status)); else - log_printf(ERROR, "executing script '%s': unkown error", script); + log_printf(ERROR, "executing script '%s' (pid %d): unkown error", child->script_, child->pid_); - close(pipefd[0]); + close(child->err_fd_); return status; } + @@ -1,41 +1,49 @@ /* - * uAnytun + * rhdropbox * - * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full - * featured implementation uAnytun has no support for multiple connections - * or synchronisation. It is a small single threaded implementation intended - * to act as a client on small platforms. - * The secure anycast tunneling protocol (satp) defines a protocol used - * for communication between any combination of unicast and anycast - * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel - * mode and allows tunneling of every ETHER TYPE protocol (e.g. - * ethernet, ip, arp ...). satp directly includes cryptography and - * message authentication based on the methodes used by SRTP. It is - * intended to deliver a generic, scaleable and secure solution for - * tunneling and relaying of packets of any protocol. - * + * Copyright (C) 2009 Christian Pointner <equinox@helsinki.at> * - * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org> + * This file is part of rhdropbox. * - * This file is part of uAnytun. - * - * uAnytun is free software: you can redistribute it and/or modify + * rhdropbox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * - * uAnytun is distributed in the hope that it will be useful, + * rhdropbox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with uAnytun. If not, see <http://www.gnu.org/licenses/>. + * along with rhdropbox. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef UANYTUN_sysexec_h_INCLUDED -#define UANYTUN_sysexec_h_INCLUDED +#ifndef RHDROPBOX_sysexec_h_INCLUDED +#define RHDROPBOX_sysexec_h_INCLUDED + +#include <sys/types.h> + +struct child_list_element_struct { + pid_t pid_; + char* script_; + int err_fd_; + struct child_list_element_struct* next_; +}; +typedef struct child_list_element_struct child_list_element_t; + +struct child_list_struct { + child_list_element_t* first_; +}; +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_find(child_list_t* list, pid_t pid); -int uanytun_exec(const char* script, char* const argv[], char* const evp[]); +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); #endif diff --git a/watch_list.c b/watch_list.c index 7e23b93..39c61f2 100644 --- a/watch_list.c +++ b/watch_list.c @@ -80,8 +80,8 @@ int watch_list_add(watch_list_t* list, int watch_fd, const char* string) tmp->next_->watch_fd_ = watch_fd; tmp->next_->path_ = strdup(string); if(!tmp->next_->path_) { - free(list->first_); - list->first_ = NULL; + free(tmp->next_); + tmp->next_ = NULL; return -2; } } |