From 8ca893076f298a01d536a0614fad14c4b5b43d54 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sun, 24 Apr 2011 21:06:04 +0000 Subject: fixed file header added sysexec code diff --git a/src/Makefile b/src/Makefile index 3efcf5e..9651ce6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,10 +1,7 @@ ## ## rharchive ## -## rharchive is a simple tcp connection proxy which combines the -## features of rinetd and 6tunnel. rharchive supports IPv4 and -## IPv6 and also supports connections from IPv6 to IPv4 -## endpoints and vice versa. +## The Radio Helsinki Archive Daemon ## ## ## Copyright (C) 2010-2011 Christian Pointner diff --git a/src/configure b/src/configure index ce0ec7f..56a0112 100755 --- a/src/configure +++ b/src/configure @@ -2,10 +2,7 @@ # # rharchive # -# rharchive is a simple tcp connection proxy which combines the -# features of rinetd and 6tunnel. rharchive supports IPv4 and -# IPv6 and also supports connections from IPv6 to IPv4 -# endpoints and vice versa. +# The Radio Helsinki Archive Daemon # # # Copyright (C) 2010-2011 Christian Pointner diff --git a/src/daemon.h b/src/daemon.h index 75e61bc..7a287fe 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/datatypes.h b/src/datatypes.h index 3387d69..9a9b04e 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/file_list.c b/src/file_list.c index b71a863..00b8b12 100644 --- a/src/file_list.c +++ b/src/file_list.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/file_list.h b/src/file_list.h index daed7ad..92bfbf0 100644 --- a/src/file_list.h +++ b/src/file_list.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/log.c b/src/log.c index 073f216..ef8e989 100644 --- a/src/log.c +++ b/src/log.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/log.h b/src/log.h index 29f9fa1..c0f210c 100644 --- a/src/log.h +++ b/src/log.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/log_targets.h b/src/log_targets.h index 5436021..7f4346c 100644 --- a/src/log_targets.h +++ b/src/log_targets.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/options.c b/src/options.c index 823703e..00e52bf 100644 --- a/src/options.c +++ b/src/options.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/options.h b/src/options.h index 3cd2abd..7b08c55 100644 --- a/src/options.h +++ b/src/options.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/rharchive.c b/src/rharchive.c index 82f7dda..32dee31 100644 --- a/src/rharchive.c +++ b/src/rharchive.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/sig_handler.c b/src/sig_handler.c index 02150fa..ce793b2 100644 --- a/src/sig_handler.c +++ b/src/sig_handler.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/sig_handler.h b/src/sig_handler.h index dee9589..b8f7bd8 100644 --- a/src/sig_handler.h +++ b/src/sig_handler.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/slist.c b/src/slist.c index c96c576..262f243 100644 --- a/src/slist.c +++ b/src/slist.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/slist.h b/src/slist.h index c16ee23..077ae92 100644 --- a/src/slist.h +++ b/src/slist.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/string_list.c b/src/string_list.c index 96fe84e..ffea526 100644 --- a/src/string_list.c +++ b/src/string_list.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/string_list.h b/src/string_list.h index e028e17..7179b8d 100644 --- a/src/string_list.h +++ b/src/string_list.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/sysexec.c b/src/sysexec.c new file mode 100644 index 0000000..9a66e90 --- /dev/null +++ b/src/sysexec.c @@ -0,0 +1,374 @@ +/* + * rharchive + * + * The Radio Helsinki Archive Daemon + * + * + * Copyright (C) 2010-2011 Christian Pointner + * + * This file is part of rharchive. + * + * rharchive 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. + * + * rharchive 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 rharchive. If not, see . + */ + +#include "datatypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#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) + 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); + } +} + +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 NULL; + + if(!list->first_) { + 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_ = 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_; + } + } +} + +void child_list_rm_pid(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_; + + free_ptrptr(tmp->argv_); + free_ptrptr(tmp->evp_); + 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_; + + free_ptrptr(tmp->argv_); + free_ptrptr(tmp->evp_); + 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 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' failed: pipe() error: %s", child->script_, strerror(errno)); + return -1; + } + + pid_t pid; + pid = fork(); + if(pid == -1) { + log_printf(ERROR, "executing script '%s' failed: fork() error: %s", child->script_, strerror(errno)); + return -1; + } + + if(!pid) { + int fd; + for (fd=getdtablesize();fd>=0;--fd) // close all file descriptors + if(fd != pipefd[1]) close(fd); + + fd = open("/dev/null",O_RDWR); // stdin + if(fd == -1) + log_printf(WARNING, "can't open stdin"); + else { + if(dup(fd) == -1) // stdout + log_printf(WARNING, "can't open stdout"); + if(dup(fd) == -1) // stderr + log_printf(WARNING, "can't open stderr"); + } + 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 + write(pipefd[1], (void*)(&errno), sizeof(errno)); + exit(-1); + } + close(pipefd[1]); + + 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, options_t* opt) +{ + int 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(child->err_fd_, &rfds); + struct timeval tv = { 0 , 0 }; + if(select(child->err_fd_+1, &rfds, NULL, NULL, &tv) == 1) { + 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->err_fd_); + child_list_rm_pid(child_lst, pid); + return -1; + } + } + if(WIFEXITED(status)) + log_printf(INFO, "script '%s' (pid %d) returned %d", child->script_, child->pid_, WEXITSTATUS(status)); + else if(WIFSIGNALED(status)) + log_printf(INFO, "script '%s' (pid %d) terminated after signal %d", child->script_, child->pid_, WTERMSIG(status)); + else + 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/src/sysexec.h b/src/sysexec.h new file mode 100644 index 0000000..481bc9d --- /dev/null +++ b/src/sysexec.h @@ -0,0 +1,60 @@ +/* + * rharchive + * + * The Radio Helsinki Archive Daemon + * + * + * Copyright (C) 2010-2011 Christian Pointner + * + * This file is part of rharchive. + * + * rharchive 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. + * + * rharchive 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 rharchive. If not, see . + */ + +#ifndef RHARCHIVE_sysexec_h_INCLUDED +#define RHARCHIVE_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; + +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); +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, options_t* opt); +int rh_exec_child(child_list_element_t* child); +int rh_waitpid(child_list_t* child_lst, options_t* opt); + +#endif diff --git a/src/writer.c b/src/writer.c index c8b18fc..0459b19 100644 --- a/src/writer.c +++ b/src/writer.c @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner diff --git a/src/writer.h b/src/writer.h index 7e10e82..e9d6b71 100644 --- a/src/writer.h +++ b/src/writer.h @@ -1,10 +1,7 @@ /* * rharchive * - * rharchive is a simple tcp connection proxy which combines the - * features of rinetd and 6tunnel. rharchive supports IPv4 and - * IPv6 and also supports connections from IPv6 to IPv4 - * endpoints and vice versa. + * The Radio Helsinki Archive Daemon * * * Copyright (C) 2010-2011 Christian Pointner -- cgit v0.10.2