diff options
author | Christian Pointner <equinox@helsinki.at> | 2016-03-23 23:52:05 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2016-03-23 23:52:05 (GMT) |
commit | 04a3a6beeaa199dc1a80a711f26de3a41d98ff74 (patch) | |
tree | cceaa0a23b051007fd8b69194c9dd9243dc01084 /src | |
parent | a077e3014dadfcfa958351415253f081633ce070 (diff) |
started rewrite in go
Diffstat (limited to 'src')
38 files changed, 103 insertions, 6253 deletions
diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 2751eb7..0000000 --- a/src/Makefile +++ /dev/null @@ -1,122 +0,0 @@ -## -## rhctl -## -## Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> -## -## This file is part of rhctl. -## -## rhctl 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. -## -## rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. -## - -ifneq ($(MAKECMDGOALS),distclean) -include include.mk -endif - -EXE_SWITCHCTL := switchctl -EXE_SERIALCLIENT := serialclient -EXE_STDIOCLIENT := stdioclient -EXE_HEARTBEATCLIENT := heartbeatclient -EXE_LUACLIENT := luaclient - -COMMONOBJ := log.o \ - sig_handler.o \ - string_list.o \ - key_value_storage.o \ - utils.o - -SWITCHCTLOBJ := command_queue.o \ - client_list.o \ - opt-switchctl.o \ - switchctl.o - -SERIALCLIENTOBJ := opt-serialclient.o \ - serialclient.o - -STDIOCLIENTOBJ := opt-stdioclient.o \ - stdioclient.o - -HEARTBEATCLIENTOBJ := opt-heartbeatclient.o \ - heartbeatclient.o - -LUACLIENTOBJ := opt-luaclient.o \ - l_log.o \ - l_sig_handler.o \ - l_cmd.o \ - luaclient.o - - -SRC := $(COMMONOBJ:%.o=%.c) $(SWITCHCTLOBJ:%.o=%.c) $(SERIALCLIENTOBJ:%.o=%.c) $(STDIOCLIENTOBJ:%.o=%.c) $(HEARTBEATCLIENTOBJ:%.o=%.c) $(LUACLIENTOBJ:%.o=%.c) options.c - -.PHONY: clean distclean - -all: $(EXE_SWITCHCTL) $(EXE_SERIALCLIENT) $(EXE_STDIOCLIENT) $(EXE_HEARTBEATCLIENT) $(EXE_LUACLIENT) - -%.d: %.c - @set -e; rm -f $@; \ - $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ - rm -f $@.$$$$; echo '(re)building $@' - -ifneq ($(MAKECMDGOALS),distclean) --include $(SRC:%.c=%.d) -endif - -$(EXE_SWITCHCTL): $(COMMONOBJ) $(SWITCHCTLOBJ) - $(CC) $(COMMONOBJ) $(SWITCHCTLOBJ) -o $@ $(LDFLAGS) - -$(EXE_SERIALCLIENT): $(COMMONOBJ) $(SERIALCLIENTOBJ) - $(CC) $(COMMONOBJ) $(SERIALCLIENTOBJ) -o $@ $(LDFLAGS) - -$(EXE_STDIOCLIENT): $(COMMONOBJ) $(STDIOCLIENTOBJ) - $(CC) $(COMMONOBJ) $(STDIOCLIENTOBJ) -o $@ $(LDFLAGS) - -$(EXE_HEARTBEATCLIENT): $(COMMONOBJ) $(HEARTBEATCLIENTOBJ) - $(CC) $(COMMONOBJ) $(HEARTBEATCLIENTOBJ) -o $@ $(LDFLAGS) - -$(EXE_LUACLIENT): $(COMMONOBJ) $(LUACLIENTOBJ) - $(CC) $(COMMONOBJ) $(LUACLIENTOBJ) -o $@ $(LDFLAGS) $(LUA_LDFLAGS) - -opt-switchctl.o: options.c - $(CC) $(CFLAGS) -DOPT_SWITCHCTL -o $@ -c $< - -opt-serialclient.o: options.c - $(CC) $(CFLAGS) -DOPT_SERIALCLIENT -o $@ -c $< - -opt-stdioclient.o: options.c - $(CC) $(CFLAGS) -DOPT_STDIOCLIENT -o $@ -c $< - -opt-heartbeatclient.o: options.c - $(CC) $(CFLAGS) -DOPT_HEARTBEATCLIENT -o $@ -c $< - -opt-luaclient.o: options.c - $(CC) $(CFLAGS) -DOPT_LUACLIENT -o $@ -c $< - -%.o: %.c - $(CC) $(CFLAGS) -c $< - - -distclean: clean - find . -name *.o -exec rm -f {} \; - find . -name "*.\~*" -exec rm -rf {} \; - rm -f include.mk - -clean: - rm -f *.o - rm -f *.d - rm -f *.d.* - rm -f $(EXE_SWITCHCTL) - rm -f $(EXE_SERIALCLIENT) - rm -f $(EXE_STDIOCLIENT) - rm -f $(EXE_HEARTBEATCLIENT) - rm -f $(EXE_LUACLIENT) diff --git a/src/client_list.c b/src/client_list.c deleted file mode 100644 index f21aea3..0000000 --- a/src/client_list.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <unistd.h> - -#include "client_list.h" -#include "datatypes.h" - -char* client_type_tostring(client_type_t type) -{ - switch(type) - { - case MASTER: return "master"; - case STANDBY: return "standby"; - case HB_MASTER: return "hb_master"; - case HB_STANDBY: return "hb_standby"; - case DEFAULT: return "unspecified"; - } - return "<invalid>"; -} - -client_t* client_get_last(client_t* first) -{ - if(!first) - return NULL; - - while(first->next) { - first = first->next; - } - - return first; -} - -int client_add(client_t** first, int fd) -{ - if(!first) - return -1; - - client_t* new_client = malloc(sizeof(client_t)); - if(!new_client) - return -2; - - new_client->fd = fd; - new_client->type = DEFAULT; - new_client->request_listener = 0; - new_client->mode_listener = 0; - new_client->status_listener = 0; - new_client->gpi_listener = 0; - new_client->oc_listener = 0; - new_client->relay_listener = 0; - new_client->silence_listener = 0; - new_client->health_listener = 0; - new_client->next = NULL; - new_client->buffer.offset = 0; - - if(!(*first)) { - *first = new_client; - return 0; - } - - client_get_last(*first)->next = new_client; - - return 0; -} - -void client_remove(client_t** first, int fd) -{ - if(!first || !(*first)) - return; - - client_t* deletee = *first; - if((*first)->fd == fd) { - *first = (*first)->next; - close(deletee->fd); - free(deletee); - return; - } - - client_t* prev = deletee; - deletee = deletee->next; - while(deletee) { - if(deletee->fd == fd) { - prev->next = deletee->next; - close(deletee->fd); - free(deletee); - return; - } - prev = deletee; - deletee = deletee->next; - } -} - -client_t* client_find(client_t* first, int fd) -{ - if(!first) - return NULL; - - while(first) { - if(first->fd == fd) - return first; - - first = first->next; - } - return NULL; -} - -void client_clear(client_t** first) -{ - if(!first || !(*first)) - return; - - while(*first) { - client_t* deletee = *first; - *first = (*first)->next; - close(deletee->fd); - free(deletee); - } -} diff --git a/src/client_list.h b/src/client_list.h deleted file mode 100644 index d0b6d3e..0000000 --- a/src/client_list.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_client_list_h_INCLUDED -#define RHCTL_client_list_h_INCLUDED - -#include "datatypes.h" - -enum client_type_enum { DEFAULT, MASTER, STANDBY, HB_MASTER, HB_STANDBY }; -typedef enum client_type_enum client_type_t; -char* client_type_tostring(client_type_t); - -struct client_struct { - int fd; - client_type_t type; - int request_listener; - int mode_listener; - int status_listener; - int gpi_listener; - int oc_listener; - int relay_listener; - int silence_listener; - int health_listener; - struct client_struct* next; - read_buffer_t buffer; -}; -typedef struct client_struct client_t; - -int client_add(client_t** first, int fd); -void client_remove(client_t** first, int fd); -client_t* client_find(client_t* first, int fd); -void client_clear(client_t** first); - -#endif diff --git a/src/command_queue.c b/src/command_queue.c deleted file mode 100644 index d59f7ef..0000000 --- a/src/command_queue.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <string.h> - -#include "command_queue.h" -#include "datatypes.h" - -cmd_t* cmd_get_last(cmd_t* first) -{ - if(!first) - return NULL; - - while(first->next) { - first = first->next; - } - - return first; -} - -int cmd_push(cmd_t** first, int fd, cmd_id_t cmd, const char* param) -{ - if(!first) - return -1; - - cmd_t* new_cmd = malloc(sizeof(cmd_t)); - if(!new_cmd) - return -2; - - new_cmd->fd = fd; - new_cmd->cmd = cmd; - if(param) { - new_cmd->param = strdup(param); - if(!new_cmd->param) { - free(new_cmd); - return -2; - } - } - else - new_cmd->param = NULL; - new_cmd->sent = 0; - new_cmd->tv_start.tv_sec = 0; - new_cmd->tv_start.tv_usec = 0; - new_cmd->next = NULL; - - if(!(*first)) { - *first = new_cmd; - return 0; - } - - cmd_get_last(*first)->next = new_cmd; - - return 0; -} - -void cmd_sent(cmd_t* cmd) -{ - if(!cmd) - return; - - cmd->sent = 1; - gettimeofday(&cmd->tv_start, NULL); -} - -int cmd_has_expired(cmd_t cmd) -{ - struct timeval now; - timerclear(&now); - gettimeofday(&now, NULL); - cmd.tv_start.tv_sec++; - - return timercmp(&cmd.tv_start, &now, <); -} - -void cmd_pop(cmd_t** first) -{ - if(!first || !(*first)) - return; - - cmd_t* deletee = *first; - *first = (*first)->next; - if(deletee->param) - free(deletee->param); - free(deletee); -} - -void cmd_clear(cmd_t** first) -{ - if(!first || !(*first)) - return; - - while(*first) { - cmd_t* deletee = *first; - *first = (*first)->next; - if(deletee->param) - free(deletee->param); - free(deletee); - } -} diff --git a/src/command_queue.h b/src/command_queue.h deleted file mode 100644 index 3e5cdb2..0000000 --- a/src/command_queue.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_command_queue_h_INCLUDED -#define RHCTL_command_queue_h_INCLUDED - -#include <sys/time.h> - -enum cmd_id_enum { SWITCH, CHANNEL, TYPE, MODE, HEARTBEAT, STATUS, HEALTH, LOG, LISTEN }; -typedef enum cmd_id_enum cmd_id_t; - -struct cmd_struct { - int fd; - cmd_id_t cmd; - char* param; - int sent; - struct timeval tv_start; - struct cmd_struct* next; -}; -typedef struct cmd_struct cmd_t; - -int cmd_push(cmd_t** first, int fd, cmd_id_t cmd, const char* param); -void cmd_sent(cmd_t* cmd); -int cmd_has_expired(cmd_t cmd); -void cmd_pop(cmd_t** first); -void cmd_clear(cmd_t** first); - -#endif diff --git a/src/configure b/src/configure deleted file mode 100755 index 6b8bdf6..0000000 --- a/src/configure +++ /dev/null @@ -1,194 +0,0 @@ -#!/bin/sh -# -# rhctl -# -# Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> -# -# This file is part of rhctl. -# -# rhctl 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. -# -# rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. -# - -TARGET=`uname -s` - -USE_CLANG=0 - -LUA_LDFLAGS='-lm' -LUA_DIR='' -LUA='' -LUA_VER='' - - -print_usage() { - echo "configure --help print this" - echo " --target=<TARGET> build target i.e. Linux (default: autodetect)" - echo " --with-lua=<DIR> use this lua tree instead of system default" - echo " --lua-version=nnn set fixed Lua version for automatic detection (501 -> 5.1, 502 -> 5.2)" - echo " --use-clang use clang/llvm as compiler/linker" -} - -for arg -do - case $arg in - --target=*) - TARGET=${arg#--target=} - ;; - --use-clang) - USE_CLANG=1 - ;; - --with-lua=*) - LUA_DIR=${arg#--with-lua=} - ;; - --lua-version=*) - LUA_VER=${arg#--lua-version=} - ;; - --help) - print_usage - exit 0 - ;; - *) - echo "Unknown argument: $arg" - print_usage - exit 1 - ;; - esac -done - -if [ $USE_CLANG -eq 0 ]; then - CFLAGS='-g -Wall -O2' - LDFLAGS='-g -Wall -O2' - COMPILER='gcc' -else - CFLAGS='-g -O2' - LDFLAGS='-g -O2' - COMPILER='clang' -fi - -rm -f include.mk -case $TARGET in - Linux) - echo "Linux specific build options" - LUA_LDFLAGS=$LUA_LDFLAGS' -ldl' - ;; - OpenBSD|FreeBSD|NetBSD) - echo "BSD specific build options" - CFLAGS=$CFLAGS' -I/usr/local/include' - LDFLAGS=$LDFLAGS' -L/usr/local/lib' - ;; - *) - echo "Plattform not supported" - exit 1; - ;; -esac - -test_lua_version() -{ - LUA_VERSION_MAJ=`cat $1 | grep "#define LUA_VERSION_MAJOR[ ]" | cut -f2- | tr -d '"'` - LUA_VERSION_MIN=`cat $1 | grep "#define LUA_VERSION_MINOR[ ]" | cut -f2- | tr -d '"'` - LUA_VERSION_REL=`cat $1 | grep "#define LUA_VERSION_RELEASE[ ]" | cut -f2- | tr -d '"'` - - LUA_VERSION="$LUA_VERSION_MAJ.$LUA_VERSION_MIN" - LUA_RELEASE="$LUA_VERSION_MAJ.$LUA_VERSION_MIN.$LUA_VERSION_REL" - - if [ -z "$LUA_VERSION_MAJ" ]; then - LUA_VERSION=`cat $1 | grep "#define LUA_VERSION[ ]" | cut -f2- | tr -d '"' | sed -e 's/Lua \([0-9][0-9.]*\)/\1/'` - LUA_RELEASE=`cat $1 | grep "#define LUA_RELEASE[ ]" | cut -f2- | tr -d '"' | sed -e 's/Lua //'` - fi - - LUA_VERSION_NUM=`cat $1 | grep "#define LUA_VERSION_NUM" | awk '{ print $3 }'` - - if [ -n "$LUA_VER" ]; then - if [ "$LUA_VER" -eq $LUA_VERSION_NUM ]; then - return 1 - else - return 0 - fi - else - if [ $LUA_VERSION_NUM -ge 501 ]; then - return 1 - else - return 0 - fi - fi -} - -if [ -z "$LUA_DIR" ]; then - for prefix in /usr /usr/local; do - if [ -e $prefix/include/lua.h ]; then - test_lua_version $prefix/include/lua.h - if [ $? -eq 1 ]; then - echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $prefix/include" - CFLAGS="$CFLAGS -I'$prefix/include'" - LUA_LDFLAGS="$LUA_LDFLAGS -L'$prefix/lib' -llua" - LUA=$prefix/lua - LUAC=$prefix/luac - break - fi - else - for dir in `ls -r -d $prefix/include/lua* 2> /dev/null`; do - if [ -e $dir/lua.h ]; then - test_lua_version $dir/lua.h - if [ $? -eq 1 ]; then - echo "using Lua $LUA_VERSION ($LUA_RELEASE) found at $dir" - CFLAGS="$CFLAGS -I$dir" - if [ -x "$prefix/bin/lua$LUA_VERSION" ]; then - LUA_LDFLAGS="$LUA_LDFLAGS -L'$prefix/lib' -llua$LUA_VERSION" - LUA=$prefix/bin/lua$LUA_VERSION - LUAC=$prefix/bin/luac$LUA_VERSION - elif [ -x "$prefix/bin/lua-$LUA_VERSION" ]; then - LUA_LDFLAGS="$LUA_LDFLAGS -L'$prefix/lib' -llua-$LUA_VERSION" - LUA=$prefix/bin/lua-$LUA_VERSION - LUAC=$prefix/bin/luac-$LUA_VERSION - else - echo "ERROR: found lua.h at $dir/lua.h but no matching lua and luac" - return 1 - fi - break - fi - fi - done - if [ -n "$LUAC" ]; then - break - fi - fi - done - - if [ -z "$LUAC" ]; then - echo "ERROR: no suitable lua found .. please install lua 5.1 or higher or use --with-lua" - return 1 - fi - -else - CFLAGS="$CFLAGS -I'$LUA_DIR/include'" - LUA_LDFLAGS="$LUA_LDFLAGS '$LUA_DIR/lib/liblua.a'" - LUA=$LUA_DIR/bin/lua - LUAC=$LUA_DIR/bin/luac -fi - - -cat > include.mk <<EOF -# this file was created automatically -# do not edit this file directly -# use ./configure instead - -TARGET := $TARGET -CC := $COMPILER -CFLAGS := $CFLAGS -LDFLAGS := $LDFLAGS -LUA := $LUA -LUAC := $LUAC -LUA_LDFLAGS := $LUA_LDFLAGS -EOF - -exit 0 diff --git a/src/daemon.h b/src/daemon.h deleted file mode 100644 index a75c328..0000000 --- a/src/daemon.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_daemon_h_INCLUDED -#define RHCTL_daemon_h_INCLUDED - -#include <poll.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <unistd.h> - -struct priv_info_struct { - struct passwd* pw_; - struct group* gr_; -}; -typedef struct priv_info_struct priv_info_t; - -int priv_init(priv_info_t* priv, const char* username, const char* groupname) -{ - if(!priv) - return -1; - - priv->pw_ = NULL; - priv->gr_ = NULL; - - priv->pw_ = getpwnam(username); - if(!priv->pw_) { - log_printf(ERROR, "unknown user %s", username); - return -1; - } - - if(groupname) - priv->gr_ = getgrnam(groupname); - else - priv->gr_ = getgrgid(priv->pw_->pw_gid); - - if(!priv->gr_) { - log_printf(ERROR, "unknown group %s", groupname); - return -1; - } - - return 0; -} - -int priv_drop(priv_info_t* priv) -{ - if(!priv || !priv->pw_ || !priv->gr_) { - log_printf(ERROR, "privileges not initialized properly"); - return -1; - } - - if(setgid(priv->gr_->gr_gid)) { - log_printf(ERROR, "setgid('%s') failed: %s", priv->gr_->gr_name, strerror(errno)); - return -1; - } - - gid_t gr_list[1]; - gr_list[0] = priv->gr_->gr_gid; - if(setgroups (1, gr_list)) { - log_printf(ERROR, "setgroups(['%s']) failed: %s", priv->gr_->gr_name, strerror(errno)); - return -1; - } - - if(setuid(priv->pw_->pw_uid)) { - log_printf(ERROR, "setuid('%s') failed: %s", priv->pw_->pw_name, strerror(errno)); - return -1; - } - - log_printf(NOTICE, "dropped privileges to %s:%s", priv->pw_->pw_name, priv->gr_->gr_name); - return 0; -} - - -int do_chroot(const char* chrootdir) -{ - if(getuid() != 0) { - log_printf(ERROR, "this program has to be run as root in order to run in a chroot"); - return -1; - } - - if(chroot(chrootdir)) { - log_printf(ERROR, "can't chroot to %s: %s", chrootdir, strerror(errno)); - return -1; - } - log_printf(NOTICE, "we are in chroot jail (%s) now", chrootdir); - if(chdir("/")) { - log_printf(ERROR, "can't change to /: %s", strerror(errno)); - return -1; - } - - return 0; -} - -void daemonize() -{ - pid_t pid; - - pid = fork(); - if(pid < 0) { - log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno)); - exit(-1); - } - if(pid) exit(0); - - umask(0); - - if(setsid() < 0) { - log_printf(ERROR, "daemonizing failed at setsid(): %s, exitting", strerror(errno)); - exit(-1); - } - - pid = fork(); - if(pid < 0) { - log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno)); - exit(-1); - } - if(pid) exit(0); - - if ((chdir("/")) < 0) { - log_printf(ERROR, "daemonizing failed at chdir(): %s, exitting", strerror(errno)); - exit(-1); - } - - int fd; - for (fd=0;fd<=2;fd++) // close all file descriptors - close(fd); - fd = open("/dev/null",O_RDWR); // stdin - if(fd == -1) - log_printf(WARNING, "can't open stdin (chroot and no link to /dev/null?)"); - 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"); - } - umask(027); -} - -#endif - diff --git a/src/datatypes.h b/src/datatypes.h deleted file mode 100644 index e6715b1..0000000 --- a/src/datatypes.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_datatypes_h_INCLUDED -#define RHCTL_datatypes_h_INCLUDED - -#define _GNU_SOURCE -#include <stdint.h> -#include <arpa/inet.h> - -typedef uint8_t bool; -#define FALSE 0 -#define TRUE 1 - -typedef uint8_t u_int8_t; -typedef uint16_t u_int16_t; -typedef uint32_t u_int32_t; -typedef uint64_t u_int64_t; -/* typedef int8_t int8_t; */ -/* typedef int16_t int16_t; */ -/* typedef int32_t int32_t; */ -/* typedef int64_t int64_t; */ - -struct buffer_struct { - u_int32_t length_; - u_int8_t* buf_; -}; -typedef struct buffer_struct buffer_t; - -struct read_buffer_struct { - u_int32_t offset; - u_int8_t buf[100]; -}; -typedef struct read_buffer_struct read_buffer_t; - -#endif diff --git a/src/health-watch.lua b/src/health-watch.lua deleted file mode 100644 index 2c2c32a..0000000 --- a/src/health-watch.lua +++ /dev/null @@ -1,107 +0,0 @@ --- --- rhctl --- --- Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> --- --- This file is part of rhctl. --- --- rhctl 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. --- --- rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. --- - -package.path = package.path .. ';/usr/share/rhctl/?.lua' - -socket = require("socket") -utils = require("utils") - -old_state = {} -current_state = {} - -function state_changed() - for k,v in pairs(old_state) do - if v ~= current_state[k] then - return true - end - end - for k,v in pairs(current_state) do - if old_state[k] == nil then - return true - end - end - return false -end - -function process_cmd(message) - local exps = { hs = "^Health: (%a+)$", mc = "^Master: (%a+)$", sc = "^Standby: (%a+)$", hbm = "^Hearbeat Master: (%a+, %a+)$", hbs = "^Hearbeat Standby: (%a+, %a+)$" } - for key, exp in pairs(exps) do - local state = string.match(message, exp) - if(state) then - if(key == 'hs') then - current_state = {} - end - current_state[key] = state - end - end - - if(current_state['hbs'] ~= nil) then - if(state_changed()) then - body = "RHCTL Health Output:\n\n" - body = body .. "Health: " .. current_state['hs'] .. "\n" - body = body .. "Master: " .. current_state['mc'] .. "\n" - body = body .. "Standby: " .. current_state['sc'] .. "\n" - body = body .. "Master Hearbeat: " .. current_state['hbm'] .. "\n" - body = body .. "Standby Hearbeat: " .. current_state['hbs'] .. "\n" - utils.send_mail("logs@helsinki.at", "[RHCTL] health: " .. current_state['hs'], body) - old_state = current_state - end - end - - return 0 -end - -function main_loop(opt) - log.printf(log.NOTICE, "main_loop started") - local sig = signal.init() - local cmdfd = cmd.init() - - cmd.send_string("listen health"); - cmd.send_string("health"); - - local return_value = 0 - while return_value == 0 do - local readable, _, err = socket.select({ sig , cmdfd }, nil) - if(err) then - log.printf(log.ERROR, "select returned with error: %s", err) - return_value = -1 - else - for _, input in ipairs(readable) do - if(input == sig) then - return_value = signal.handle() - if(return_value == 1) then break end - else - if(input == cmdfd) then - return_value = cmd.recv_data(process_cmd) - if(return_value ~= 0) then break end - else - log.printf(log.ERROR, "select returned invalid handle??") - return_value = -1 - break; - end - end - end - end - end - - signal.stop() - return return_value -end diff --git a/src/heartbeatclient.c b/src/heartbeatclient.c deleted file mode 100644 index 975581f..0000000 --- a/src/heartbeatclient.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "log.h" -#include "sig_handler.h" -#include "options.h" - -#include "daemon.h" -#include "utils.h" - -int process_serial(read_buffer_t* buffer, int serial_fd, int led_pipe_fd, bool *state) -{ - int ret = 0; - struct timeval tv; - fd_set fds; - FD_ZERO(&fds); - FD_SET(serial_fd, &fds); - - for(;;) { - tv.tv_sec = 0; - tv.tv_usec = 0; - ret = select(serial_fd+1, &fds, NULL, NULL, &tv); - if(!ret) - return 0; - else if(ret < 0) - return ret; - - ret = read(serial_fd, &buffer->buf[buffer->offset], 1); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - else if(ret < 0) - break; - - if(buffer->buf[buffer->offset] == '\n') { - buffer->buf[buffer->offset] = 0; - - if(buffer->offset > 0 && buffer->buf[buffer->offset-1] == '\r') - buffer->buf[buffer->offset-1] = 0; - - if(strlen((char *)(buffer->buf))) { - *state = TRUE; - if(led_pipe_fd >= 0) { - char buf = '1'; - ret = write(led_pipe_fd, &buf, 1); - if(ret == -1 && errno != EAGAIN) - log_printf(WARNING, "write to led process pipe returned with error: %s", strerror(errno)); - } - } - - buffer->offset = 0; - return 0; - } - - buffer->offset++; - if(buffer->offset >= sizeof(buffer->buf)) { - log_printf(DEBUG, "string too long (fd=%d)", serial_fd); - buffer->offset = 0; - return 0; - } - } - - return ret; -} - -int main_loop(int serial_fd, int cmd_fd, int led_pipe_fd, options_t* opt) -{ - log_printf(NOTICE, "entering main loop"); - - fd_set readfds, tmpfds; - FD_ZERO(&readfds); - FD_SET(serial_fd, &readfds); - FD_SET(cmd_fd, &readfds); - int max_fd = serial_fd > cmd_fd ? serial_fd : cmd_fd; - - 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; - - int return_value = 0; - return_value = send_string(cmd_fd, "type heartbeat\n"); - if(return_value <= 0) { - log_printf(ERROR, "error setting client type"); - return_value = -1; - } - else { - log_printf(NOTICE, "connecting as type heartbeat"); - return_value = 0; - } - - bool state = FALSE; - send_string(cmd_fd, "heartbeat 0\n"); - - read_buffer_t serial_buffer; - serial_buffer.offset = 0; - struct timeval timeout; - u_int32_t time = 0; - while(!return_value) { - memcpy(&tmpfds, &readfds, sizeof(tmpfds)); - - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - 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) - continue; - if(!ret) { - time++; - if(time >= opt->timeout_) { - if(state == TRUE) { - log_printf(WARNING, "heartbeat timeout"); - send_string(cmd_fd, "heartbeat 0\n"); - state = FALSE; - } - time = 0; - } - continue; - } - - if(FD_ISSET(sig_fd, &tmpfds)) - if(signal_handle()) - return_value = 1; - - if(FD_ISSET(serial_fd, &tmpfds)) { - bool old_state = state; - return_value = process_serial(&serial_buffer, serial_fd, led_pipe_fd, &state); - if(return_value) - break; - if(state) { - if(!old_state) { - log_printf(WARNING, "heartbeat returned"); - send_string(cmd_fd, "heartbeat 1\n"); - } - time = 0; - } - } - - if(FD_ISSET(cmd_fd, &tmpfds)) { - u_int8_t buf[100]; - int ret = recv(cmd_fd, buf, 100, 0); - if(!ret) - return_value = 3; - if(ret == -1 && errno == EAGAIN) - return_value = 0; - else if(ret < 0) - return_value = ret; - } - } - - signal_stop(); - return return_value; -} - -int led_process(int pipe_fd, int led_fd) -{ - struct timeval timeout; - char buf; - int ret; - - log_printf(INFO, "led_process: starting up"); - for(;;) { - ret = read(pipe_fd, &buf, 1); - if(ret == -1 && errno == EAGAIN) - continue; - else if(!ret || ret < 0) { - log_printf(ERROR, "led_process: read returned with error: %s", strerror(errno)); - break; - } - - buf = '1'; - ret = write(led_fd, &buf, 1); - if(ret == -1 && errno != EAGAIN) { - log_printf(ERROR, "led_process: write returned with error: %s", strerror(errno)); - break; - } - - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - ret = select(0, NULL, NULL, NULL, &timeout); - if(ret == -1 && errno != EINTR) { - log_printf(ERROR, "led_process: select returned with error: %s", strerror(errno)); - break; - } - - buf = '0'; - ret = write(led_fd, &buf, 1); - if(ret == -1 && errno != EAGAIN) { - log_printf(ERROR, "led_process: write returned with error: %s", strerror(errno)); - break; - } - } - log_printf(INFO, "led_process: stopped"); - return -1; -} - -int start_led_process(options_t* opt) -{ - int pipefd[2]; - int led_fd; - pid_t cpid; - - led_fd = open(opt->led_filename_, O_WRONLY); - if(led_fd < 0) { - log_printf(ERROR, "led_process: open() failed: %s", strerror(errno)); - return -2; - } - - if (pipe(pipefd) == -1) { - log_printf(ERROR, "led_process: pipe() failed: %s", strerror(errno)); - close(led_fd); - return -2; - } - - cpid = fork(); - if (cpid == -1) { - log_printf(ERROR, "led_process: fork() failed: %s", strerror(errno)); - close(pipefd[0]); - close(pipefd[1]); - close(led_fd); - return -2; - } - - if (cpid == 0) { - close(pipefd[1]); - return led_process(pipefd[0], led_fd); - } - - close(pipefd[0]); - close(led_fd); - return pipefd[1]; -} - -int main(int argc, char* argv[]) -{ - log_init(); - - options_t opt; - int ret = options_parse(&opt, argc, argv); - if(ret) { - if(ret > 0) { - fprintf(stderr, "syntax error near: %s\n\n", argv[ret]); - } - if(ret == -2) { - fprintf(stderr, "memory error on options_parse, exiting\n"); - } - if(ret == -5) { - fprintf(stderr, "syntax error: invalid baudrate\n"); - } - - if(ret != -2) - options_print_usage(); - - options_clear(&opt); - log_close(); - exit(ret); - } - string_list_element_t* tmp = opt.log_targets_.first_; - if(!tmp) { - log_add_target("syslog:3,heartbeatclient,daemon"); - } - else { - while(tmp) { - ret = log_add_target(tmp->string_); - if(ret) { - switch(ret) { - case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break; - case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break; - case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; - default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; - } - - options_clear(&opt); - log_close(); - exit(ret); - } - tmp = tmp->next_; - } - } - log_printf(NOTICE, "just started..."); - if(options_parse_post(&opt)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - priv_info_t priv; - if(opt.username_) - if(priv_init(&priv, opt.username_, opt.groupname_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - FILE* pid_file = NULL; - if(opt.pid_file_) { - pid_file = fopen(opt.pid_file_, "w"); - if(!pid_file) { - log_printf(WARNING, "unable to open pid file: %s", strerror(errno)); - } - } - - if(opt.chroot_dir_) - if(do_chroot(opt.chroot_dir_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - if(opt.username_) - if(priv_drop(&priv)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - if(opt.daemonize_) { - pid_t oldpid = getpid(); - daemonize(); - log_printf(INFO, "running in background now (old pid: %d)", oldpid); - } - - if(pid_file) { - pid_t pid = getpid(); - fprintf(pid_file, "%d", pid); - fclose(pid_file); - } - - int led_pipe_fd = -1; - if(opt.led_filename_) { - log_printf(NOTICE, "starting led blink process"); - led_pipe_fd = start_led_process(&opt); - if(led_pipe_fd == -1) { - options_clear(&opt); - log_close(); - exit(0); - } - if(led_pipe_fd < -1) { - options_clear(&opt); - log_close(); - exit(-1); - } - } - - int cmd_fd = 0; - int serial_fd = 0; - for(;;) { - cmd_fd = connect_command_socket(opt.command_sock_); - if(cmd_fd < 0) - ret = 3; - else { - serial_fd = open(opt.serial_dev_, O_RDWR | O_NOCTTY); - if(serial_fd < 0) { - log_printf(ERROR, "open(%s): %s", opt.serial_dev_, strerror(errno)); - ret = 2; - } - else { - ret = setup_tty(serial_fd, opt.baudrate_); - if(ret) - ret = 2; - else - ret = main_loop(serial_fd, cmd_fd, led_pipe_fd, &opt); - } - } - - if(ret == 2 || ret == 3) { - if(ret == 2) - log_printf(ERROR, "%s error, trying to reopen in 5 seconds..", opt.serial_dev_); - if(ret == 3) - log_printf(ERROR, "socket error, trying to reconnect in 5 seconds.."); - - if(cmd_fd > 0) - close(cmd_fd); - if(serial_fd > 0) - close(serial_fd); - sleep(5); - } - else - break; - } - - if(cmd_fd > 0) - close(cmd_fd); - if(serial_fd > 0) - close(serial_fd); - - if(!ret) - log_printf(NOTICE, "normal shutdown"); - else if(ret < 0) - log_printf(NOTICE, "shutdown after error (code %d)", ret); - else - log_printf(NOTICE, "shutdown after signal"); - - options_clear(&opt); - log_close(); - - return ret; -} diff --git a/src/key_value_storage.c b/src/key_value_storage.c deleted file mode 100644 index 31f48d9..0000000 --- a/src/key_value_storage.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <string.h> - -#include "key_value_storage.h" - -void key_value_storage_init(key_value_storage_t* stor) -{ - if(!stor) - return; - - string_list_init(&(stor->keys_)); - string_list_init(&(stor->values_)); -} - -void key_value_storage_clear(key_value_storage_t* stor) -{ - if(!stor) - return; - - string_list_clear(&(stor->keys_)); - string_list_clear(&(stor->values_)); -} - -int key_value_storage_add(key_value_storage_t* stor, const char* key, const char* value) -{ - if(!stor || !key || !value) - return -1; - - int ret = string_list_add(&(stor->keys_), key); - if(ret!=0) - return ret; - - ret = string_list_add(&(stor->values_), value); - if(ret!=0) - return ret; - - return 0; -} - -char* key_value_storage_find(key_value_storage_t* stor, const char* key) -{ - if(!stor || !key) - return NULL; - - string_list_element_t* k = stor->keys_.first_; - string_list_element_t* v = stor->values_.first_; - while(v && k) { - if(!strcmp(k->string_, key)) - return v->string_; - - k = k->next_; - v = v->next_; - } - - return NULL; -} - -void key_value_storage_print(key_value_storage_t* stor, const char* head, const char* sep, const char* tail) -{ - if(!stor) - return; - - string_list_element_t* k = stor->keys_.first_; - string_list_element_t* v = stor->values_.first_; - while(v && k) { - printf("%s%s%s%s%s", head, k->string_, sep, v->string_, tail); - k = k->next_; - v = v->next_; - } - printf("\n"); -} diff --git a/src/key_value_storage.h b/src/key_value_storage.h deleted file mode 100644 index 1a58a60..0000000 --- a/src/key_value_storage.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_key_value_storage_h_INCLUDED -#define RHCTL_key_value_storage_h_INCLUDED - -#include "string_list.h" - -struct key_value_storage_struct { - string_list_t keys_; - string_list_t values_; -}; -typedef struct key_value_storage_struct key_value_storage_t; - -void key_value_storage_init(key_value_storage_t* stor); -void key_value_storage_clear(key_value_storage_t* stor); -int key_value_storage_add(key_value_storage_t* stor, const char* key, const char* value); -char* key_value_storage_find(key_value_storage_t* stor, const char* key); - -void key_value_storage_print(key_value_storage_t* stor, const char* head, const char* sep, const char* tail); - - -#endif diff --git a/src/l_cmd.c b/src/l_cmd.c deleted file mode 100644 index 374535e..0000000 --- a/src/l_cmd.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <lua.h> -#include <lauxlib.h> - -#include <unistd.h> -#include <sys/socket.h> -#include <errno.h> - -#include "datatypes.h" - -#include "l_cmd.h" - -#include "options.h" -#include "command_queue.h" -#include "client_list.h" -#include "log.h" -#include "utils.h" - -int cmd_fd; -read_buffer_t cmd_buffer; - -static int l_cmd_getfd(lua_State *L) -{ - if(!lua_istable(L, -1)) - luaL_error(L, "can't retreive signal fd"); - - lua_pushliteral(L, "fd"); - lua_gettable(L, -2); - return 1; -} - -static int l_cmd_dirty(lua_State *L) -{ - lua_pushboolean(L, 0); - return 1; -} - -static int l_cmd_init(lua_State *L) -{ - lua_newtable(L); - lua_pushliteral(L, "fd"); - lua_pushinteger(L, cmd_fd); - lua_settable(L, -3); - lua_pushliteral(L, "getfd"); - lua_pushcfunction(L, l_cmd_getfd); - lua_settable(L, -3); - lua_pushliteral(L, "dirty"); - lua_pushcfunction(L, l_cmd_dirty); - lua_settable(L, -3); - return 1; -} - -// gets called by nonblock_recvline for every complete message -static int cmd_recv_data(lua_State* L) -{ - int ret = 0; - for(;;) { - ret = recv(cmd_fd, &cmd_buffer.buf[cmd_buffer.offset], 1, 0); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - else if(ret < 0) - break; - - if(cmd_buffer.buf[cmd_buffer.offset] == '\n') { - cmd_buffer.buf[cmd_buffer.offset] = 0; - - lua_pushstring(L, (char *)(cmd_buffer.buf)); - - ret = lua_pcall(L, 1, 1, 0); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRRUN: log_printf(ERROR, "lua_pcall(cmd_callback) runtime error: %s", err_str); break; - case LUA_ERRMEM: log_printf(ERROR, "lua_pcall(cmd_callback) malloc error: %s", err_str); break; - case LUA_ERRERR: log_printf(ERROR, "lua_pcall(cmd_callback) error at error handler function: %s", err_str); break; - } - return -1; - } - - ret = lua_tointeger(L, 1); - cmd_buffer.offset = 0; - break; - } - - cmd_buffer.offset++; - if(cmd_buffer.offset >= sizeof(cmd_buffer.buf)) { - log_printf(DEBUG, "string too long cmd_fd"); - cmd_buffer.offset = 0; - return 0; - } - } - - return ret; -} - -static int l_cmd_recv_data(lua_State* L) -{ - int ret = cmd_recv_data(L); - lua_pushinteger(L, ret); - return 1; -} - -static int l_cmd_send_string(lua_State* L) -{ - int ret = send_string(cmd_fd, luaL_checkstring(L,1)); - if (ret > 0) - do { - ret = write(cmd_fd, "\n", 1); - } while(!ret || (ret == -1 && errno == EINTR)); - - if(ret > 0) - ret = 0; - - lua_pushinteger(L, ret); - return 1; -} - -static const struct luaL_Reg cmd_funcs [] = { - { "init", l_cmd_init }, - { "recv_data", l_cmd_recv_data }, - { "send_string", l_cmd_send_string }, - { NULL, NULL } -}; - -LUALIB_API int luaopen_cmd(lua_State *L) -{ -#if LUA_VERSION_NUM > 501 - lua_newtable(L); - luaL_setfuncs(L, cmd_funcs, 0); - lua_pushvalue(L, -1); - lua_setglobal(L, LUA_CMDLIBNAME); -#else - luaL_register(L, LUA_CMDLIBNAME, cmd_funcs); -#endif - return 1; -} diff --git a/src/l_cmd.h b/src/l_cmd.h deleted file mode 100644 index a23f79a..0000000 --- a/src/l_cmd.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_l_cmd_h_INCLUDED -#define RHCTL_l_cmd_h_INCLUDED - -#include <lua.h> - -extern int cmd_fd; - -#define LUA_CMDLIBNAME "cmd" -LUALIB_API int luaopen_cmd(lua_State *L); - -#endif diff --git a/src/l_log.c b/src/l_log.c deleted file mode 100644 index 05111c3..0000000 --- a/src/l_log.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <lua.h> -#include <lauxlib.h> - -#include <stdlib.h> - -#include "datatypes.h" -#include "log.h" - -#include "l_log.h" - -static int l_log_init(lua_State *L) -{ - log_init(); - return 0; -} - -static int l_log_close(lua_State *L) -{ - log_close(); - return 0; -} - -static int l_log_add_target(lua_State *L) -{ - int ret = log_add_target(luaL_checkstring(L,1)); - if(ret) { - lua_pushboolean(L, 0); - switch(ret) { - case -2: lua_pushstring(L, "memory error at log_add_target"); break; - case -3: lua_pushstring(L, "unknown log target"); break; - case -4: lua_pushstring(L, "this log target is only allowed once"); break; - default: lua_pushstring(L, "syntax error"); break; - } - return 2; - } - - lua_pushboolean(L, 1); - return 1; -} - -static int l_log_printf(lua_State *L) -{ - int numargs = lua_gettop(L); - if(numargs < 2) - return luaL_error(L, "log.printf too few arguments"); - - if(numargs > 2) { - lua_getglobal(L, "string"); - lua_pushliteral(L, "format"); - lua_gettable(L, -2); - lua_insert(L, 2); - lua_remove(L, -1); - lua_call(L, numargs - 1, 1); - } - - log_prio_t prio = luaL_checkinteger(L,1); - log_printf(prio, "%s", luaL_checkstring(L, 2)); - return 0; -} - -static const struct luaL_Reg log_funcs [] = { - { "init", l_log_init }, - { "close", l_log_close }, - { "add_target", l_log_add_target }, - { "printf", l_log_printf }, - { NULL, NULL } -}; - - -LUALIB_API int luaopen_log(lua_State *L) -{ -#if LUA_VERSION_NUM > 501 - lua_newtable(L); - luaL_setfuncs(L, log_funcs, 0); - lua_pushvalue(L, -1); - lua_setglobal(L, LUA_LOGLIBNAME); -#else - luaL_register(L, LUA_LOGLIBNAME, log_funcs); -#endif - lua_pushliteral(L, "ERROR"); - lua_pushinteger(L, ERROR); - lua_settable(L, -3); - lua_pushliteral(L, "WARNING"); - lua_pushinteger(L, WARNING); - lua_settable(L, -3); - lua_pushliteral(L, "NOTICE"); - lua_pushinteger(L, NOTICE); - lua_settable(L, -3); - lua_pushliteral(L, "INFO"); - lua_pushinteger(L, INFO); - lua_settable(L, -3); - lua_pushliteral(L, "DEBUG"); - lua_pushinteger(L, DEBUG); - lua_settable(L, -3); - return 1; -} diff --git a/src/l_log.h b/src/l_log.h deleted file mode 100644 index 169b591..0000000 --- a/src/l_log.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_l_log_h_INCLUDED -#define RHCTL_l_log_h_INCLUDED - -#include <lua.h> - -#define LUA_LOGLIBNAME "log" -LUALIB_API int luaopen_log(lua_State *L); - -#endif diff --git a/src/l_sig_handler.c b/src/l_sig_handler.c deleted file mode 100644 index f0616b8..0000000 --- a/src/l_sig_handler.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <lua.h> -#include <lauxlib.h> - -#include "sig_handler.h" - -#include "l_sig_handler.h" - -static int l_signal_getfd(lua_State *L) -{ - if(!lua_istable(L, -1)) - luaL_error(L, "can't retreive signal fd"); - - lua_pushliteral(L, "fd"); - lua_gettable(L, -2); - return 1; -} - -static int l_signal_dirty(lua_State *L) -{ - lua_pushboolean(L, 0); - return 1; -} - -static int l_signal_init(lua_State *L) -{ - int sig_fd = signal_init(); - if(sig_fd < 0) - luaL_error(L, "error at signal init"); - - lua_newtable(L); - lua_pushliteral(L, "fd"); - lua_pushinteger(L, sig_fd); - lua_settable(L, -3); - lua_pushliteral(L, "getfd"); - lua_pushcfunction(L, l_signal_getfd); - lua_settable(L, -3); - lua_pushliteral(L, "dirty"); - lua_pushcfunction(L, l_signal_dirty); - lua_settable(L, -3); - return 1; -} - -static int l_signal_stop(lua_State *L) -{ - signal_stop(); - return 0; -} - -static int l_signal_handle(lua_State *L) -{ - int ret = signal_handle(); - lua_pushinteger(L, ret); - return 1; -} - -static const struct luaL_Reg signal_funcs [] = { - { "init", l_signal_init }, - { "stop", l_signal_stop }, - { "handle", l_signal_handle }, - { NULL, NULL } -}; - - -LUALIB_API int luaopen_signal(lua_State *L) -{ -#if LUA_VERSION_NUM > 501 - lua_newtable(L); - luaL_setfuncs(L, signal_funcs, 0); - lua_pushvalue(L, -1); - lua_setglobal(L, LUA_SIGNALLIBNAME); -#else - luaL_register(L, LUA_SIGNALLIBNAME, signal_funcs); -#endif - return 1; -} diff --git a/src/l_sig_handler.h b/src/l_sig_handler.h deleted file mode 100644 index 310414a..0000000 --- a/src/l_sig_handler.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_l_signal_handler_h_INCLUDED -#define RHCTL_l_signal_handler_h_INCLUDED - -#include <lua.h> - -#define LUA_SIGNALLIBNAME "signal" -LUALIB_API int luaopen_signal(lua_State *L); - -#endif diff --git a/src/log.c b/src/log.c deleted file mode 100644 index 721d7c0..0000000 --- a/src/log.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <ctype.h> -#include <string.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> - -#define SYSLOG_NAMES -#include <syslog.h> - -#include "log.h" - -log_t stdlog; - -#include "log_targets.h" - -const char* log_prio_to_string(log_prio_t prio) -{ - switch(prio) { - case ERROR: return "ERROR"; - case WARNING: return "WARNING"; - case NOTICE: return "NOTICE"; - case INFO: return "INFO"; - case DEBUG: return "DEBUG"; - } - return "UNKNOWN"; -} - -log_target_type_t log_target_parse_type(const char* conf) -{ - if(!conf) - return TARGET_UNKNOWN; - - if(!strncmp(conf, "syslog", 6)) return TARGET_SYSLOG; - if(!strncmp(conf, "file", 4)) return TARGET_FILE; - if(!strncmp(conf, "stdout", 6)) return TARGET_STDOUT; - if(!strncmp(conf, "stderr", 6)) return TARGET_STDERR; - - return TARGET_UNKNOWN; -} - -int log_targets_target_exists(log_targets_t* targets, log_target_type_t type) -{ - if(!targets && !targets->first_) - return 0; - - log_target_t* tmp = targets->first_; - while(tmp) { - if(tmp->type_ == type) - return 1; - tmp = tmp->next_; - } - return 0; -} - -int log_targets_add(log_targets_t* targets, const char* conf) -{ - if(!targets) - return -1; - - log_target_t* new_target = NULL; - int duplicates_allowed = 0; - switch(log_target_parse_type(conf)) { - case TARGET_SYSLOG: new_target = log_target_syslog_new(); break; - case TARGET_FILE: new_target = log_target_file_new(); duplicates_allowed = 1; break; - case TARGET_STDOUT: new_target = log_target_stdout_new(); break; - case TARGET_STDERR: new_target = log_target_stderr_new(); break; - default: return -3; - } - if(!new_target) - return -2; - - if(!duplicates_allowed && log_targets_target_exists(targets, new_target->type_)) { - free(new_target); - return -4; - } - - const char* prioptr = strchr(conf, ':'); - if(!prioptr || prioptr[1] == 0) { - free(new_target); - return -1; - } - prioptr++; - if(!isdigit(prioptr[0]) || (prioptr[1] != 0 && prioptr[1] != ',')) { - free(new_target); - return -1; - } - new_target->max_prio_ = prioptr[0] - '0'; - if(new_target->max_prio_ > 0) - new_target->enabled_ = 1; - - if(new_target->init != NULL) { - const char* confptr = NULL; - if(prioptr[1] != 0) - confptr = prioptr+2; - - int ret = (*new_target->init)(new_target, confptr); - if(ret) { - free(new_target); - return ret; - } - } - - if(new_target->open != NULL) - (*new_target->open)(new_target); - - - if(!targets->first_) { - targets->first_ = new_target; - } - else { - log_target_t* tmp = targets->first_; - while(tmp->next_) - tmp = tmp->next_; - - tmp->next_ = new_target; - } - return 0; -} - -void log_targets_log(log_targets_t* targets, log_prio_t prio, const char* msg) -{ - if(!targets) - return; - - log_target_t* tmp = targets->first_; - while(tmp) { - if(tmp->log != NULL && tmp->enabled_ && tmp->max_prio_ >= prio) - (*tmp->log)(tmp, prio, msg); - - tmp = tmp->next_; - } -} - -void log_targets_clear(log_targets_t* targets) -{ - if(!targets) - return; - - while(targets->first_) { - log_target_t* tmp = targets->first_; - targets->first_ = tmp->next_; - if(tmp->close != NULL) - (*tmp->close)(tmp); - if(tmp->clear != NULL) - (*tmp->clear)(tmp); - free(tmp); - } -} - - -void log_init() -{ - stdlog.max_prio_ = 0; - stdlog.targets_.first_ = NULL; -} - -void log_close() -{ - log_targets_clear(&stdlog.targets_); -} - -void update_max_prio() -{ - log_target_t* tmp = stdlog.targets_.first_; - while(tmp) { - if(tmp->enabled_ && tmp->max_prio_ > stdlog.max_prio_) - stdlog.max_prio_ = tmp->max_prio_; - - tmp = tmp->next_; - } -} - -int log_add_target(const char* conf) -{ - if(!conf) - return -1; - - int ret = log_targets_add(&stdlog.targets_, conf); - if(!ret) update_max_prio(); - return ret; -} - -void log_printf(log_prio_t prio, const char* fmt, ...) -{ - if(stdlog.max_prio_ < prio) - return; - - static char msg[MSG_LENGTH_MAX]; - va_list args; - - va_start(args, fmt); - vsnprintf(msg, MSG_LENGTH_MAX, fmt, args); - va_end(args); - - log_targets_log(&stdlog.targets_, prio, msg); -} - -void log_print_hex_dump(log_prio_t prio, const u_int8_t* buf, u_int32_t len) -{ - if(stdlog.max_prio_ < prio) - return; - - static char msg[MSG_LENGTH_MAX]; - - if(!buf) { - snprintf(msg, MSG_LENGTH_MAX, "(NULL)"); - } - else { - u_int32_t i; - int offset = snprintf(msg, MSG_LENGTH_MAX, "dump(%d): ", len); - if(offset < 0) - return; - char* ptr = &msg[offset]; - - for(i=0; i < len; i++) { - if(((i+1)*3) >= (MSG_LENGTH_MAX - offset)) - break; - snprintf(ptr, 3, "%02X ", buf[i]); - ptr+=3; - } - } - log_targets_log(&stdlog.targets_, prio, msg); -} diff --git a/src/log.h b/src/log.h deleted file mode 100644 index 872e1ee..0000000 --- a/src/log.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_log_h_INCLUDED -#define RHCTL_log_h_INCLUDED - -#define MSG_LENGTH_MAX 150 - -enum log_prio_enum { ERROR = 1, WARNING = 2, NOTICE = 3, - INFO = 4, DEBUG = 5 }; -typedef enum log_prio_enum log_prio_t; - -const char* log_prio_to_string(log_prio_t prio); - -enum log_target_type_enum { TARGET_SYSLOG , TARGET_STDOUT, TARGET_STDERR, TARGET_FILE , TARGET_UNKNOWN }; -typedef enum log_target_type_enum log_target_type_t; - -struct log_target_struct { - log_target_type_t type_; - int (*init)(struct log_target_struct* self, const char* conf); - void (*open)(struct log_target_struct* self); - void (*log)(struct log_target_struct* self, log_prio_t prio, const char* msg); - void (*close)(struct log_target_struct* self); - void (*clear)(struct log_target_struct* self); - int opened_; - int enabled_; - log_prio_t max_prio_; - void* param_; - struct log_target_struct* next_; -}; -typedef struct log_target_struct log_target_t; - - -struct log_targets_struct { - log_target_t* first_; -}; -typedef struct log_targets_struct log_targets_t; - -int log_targets_target_exists(log_targets_t* targets, log_target_type_t type); -int log_targets_add(log_targets_t* targets, const char* conf); -void log_targets_log(log_targets_t* targets, log_prio_t prio, const char* msg); -void log_targets_clear(log_targets_t* targets); - - -struct log_struct { - log_prio_t max_prio_; - log_targets_t targets_; -}; -typedef struct log_struct log_t; - -void log_init(); -void log_close(); -void update_max_prio(); -int log_add_target(const char* conf); -void log_printf(log_prio_t prio, const char* fmt, ...); -void log_print_hex_dump(log_prio_t prio, const u_int8_t* buf, u_int32_t len); - -#endif diff --git a/src/log_targets.h b/src/log_targets.h deleted file mode 100644 index d0a85b1..0000000 --- a/src/log_targets.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_log_targets_h_INCLUDED -#define RHCTL_log_targets_h_INCLUDED - -#include <time.h> - -static char* get_time_formatted() -{ - char* time_string; - time_t t = time(NULL); - if(t < 0) - time_string = "<time read error>"; - else { - time_string = ctime(&t); - if(!time_string) - time_string = "<time format error>"; - else { - char* newline = strchr(time_string, '\n'); - if(newline) - newline[0] = 0; - } - } - return time_string; -} - -enum syslog_facility_enum { USER = LOG_USER, MAIL = LOG_MAIL, - DAEMON = LOG_DAEMON, AUTH = LOG_AUTH, - SYSLOG = LOG_SYSLOG, LPR = LOG_LPR, - NEWS = LOG_NEWS, UUCP = LOG_UUCP, - CRON = LOG_CRON, AUTHPRIV = LOG_AUTHPRIV, - FTP = LOG_FTP, LOCAL0 = LOG_LOCAL0, - LOCAL1 = LOG_LOCAL1, LOCAL2 = LOG_LOCAL2, - LOCAL3 = LOG_LOCAL3, LOCAL4 = LOG_LOCAL4, - LOCAL5 = LOG_LOCAL5, LOCAL6 = LOG_LOCAL6, - LOCAL7 = LOG_LOCAL7 }; -typedef enum syslog_facility_enum syslog_facility_t; - -struct log_target_syslog_param_struct { - char* logname_; - syslog_facility_t facility_; -}; -typedef struct log_target_syslog_param_struct log_target_syslog_param_t; - -int log_target_syslog_init(log_target_t* self, const char* conf) -{ - if(!self || (conf && conf[0] == 0)) - return -1; - - self->param_ = malloc(sizeof(log_target_syslog_param_t)); - if(!self->param_) - return -2; - - char* logname; - const char* end = NULL; - if(!conf) - logname = strdup("uanytun"); - else { - end = strchr(conf, ','); - if(end) { - size_t len = (size_t)(end - conf); - if(!len) { - free(self->param_); - return -1; - } - logname = malloc(len+1); - if(logname) { - strncpy(logname, conf, len); - logname[len] = 0; - } - } - else - logname = strdup(conf); - } - - if(!logname) { - free(self->param_); - return -2; - } - ((log_target_syslog_param_t*)(self->param_))->logname_ = logname; - - if(!end) { - ((log_target_syslog_param_t*)(self->param_))->facility_ = DAEMON; - return 0; - } - - if(end[1] == 0 || end[1] == ',') { - free(logname); - free(self->param_); - return -1; - } - - const char* start = end + 1; - end = strchr(start, ','); - int i; - for(i=0;;++i) { - if(facilitynames[i].c_name == NULL) { - free(logname); - free(self->param_); - return -1; - } - - if(( end && !strncmp(start, facilitynames[i].c_name, (size_t)(end - start)) && facilitynames[i].c_name[(size_t)(end-start)] == 0) || - (!end && !strcmp(start, facilitynames[i].c_name))) { - ((log_target_syslog_param_t*)(self->param_))->facility_ = facilitynames[i].c_val; - break; - } - } - - return 0; -} - -void log_target_syslog_open(log_target_t* self) -{ - if(!self || !self->param_) - return; - - openlog(((log_target_syslog_param_t*)(self->param_))->logname_, LOG_PID, ((log_target_syslog_param_t*)(self->param_))->facility_); - self->opened_ = 1; -} - -void log_target_syslog_log(log_target_t* self, log_prio_t prio, const char* msg) -{ - if(!self || !self->param_ || !self->opened_) - return; - - syslog((prio + 2) | ((log_target_syslog_param_t*)(self->param_))->facility_, "%s", msg); -} - -void log_target_syslog_close(log_target_t* self) -{ - closelog(); - self->opened_ = 0; -} - -void log_target_syslog_clear(log_target_t* self) -{ - if(!self || !self->param_) - return; - - if(((log_target_syslog_param_t*)(self->param_))->logname_) - free(((log_target_syslog_param_t*)(self->param_))->logname_); - - free(self->param_); -} - -log_target_t* log_target_syslog_new() -{ - log_target_t* tmp = malloc(sizeof(log_target_t)); - if(!tmp) - return NULL; - - tmp->type_ = TARGET_SYSLOG; - tmp->init = &log_target_syslog_init; - tmp->open = &log_target_syslog_open; - tmp->log = &log_target_syslog_log; - tmp->close = &log_target_syslog_close; - tmp->clear = &log_target_syslog_clear; - tmp->opened_ = 0; - tmp->enabled_ = 0; - tmp->max_prio_ = NOTICE; - tmp->param_ = NULL; - tmp->next_ = NULL; - - return tmp; -} - - -struct log_target_file_param_struct { - char* logfilename_; - FILE* file_; -}; -typedef struct log_target_file_param_struct log_target_file_param_t; - -int log_target_file_init(log_target_t* self, const char* conf) -{ - if(!self || (conf && conf[0] == 0)) - return -1; - - self->param_ = malloc(sizeof(log_target_file_param_t)); - if(!self->param_) - return -2; - - char* logfilename; - if(!conf) - logfilename = strdup("uanytun.log"); - else { - const char* end = strchr(conf, ','); - if(end) { - size_t len = (size_t)(end - conf); - if(!len) { - free(self->param_); - return -1; - } - logfilename = malloc(len+1); - if(logfilename) { - strncpy(logfilename, conf, len); - logfilename[len] = 0; - } - } - else - logfilename = strdup(conf); - } - - if(!logfilename) { - free(self->param_); - return -2; - } - ((log_target_file_param_t*)(self->param_))->logfilename_ = logfilename; - ((log_target_file_param_t*)(self->param_))->file_ = NULL; - - return 0; -} - -void log_target_file_open(log_target_t* self) -{ - if(!self || !self->param_) - return; - - ((log_target_file_param_t*)(self->param_))->file_ = fopen(((log_target_file_param_t*)(self->param_))->logfilename_, "w"); - if(((log_target_file_param_t*)(self->param_))->file_) - self->opened_ = 1; -} - -void log_target_file_log(log_target_t* self, log_prio_t prio, const char* msg) -{ - if(!self || !self->param_ || !self->opened_) - return; - - fprintf(((log_target_file_param_t*)(self->param_))->file_, "%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg); - fflush(((log_target_file_param_t*)(self->param_))->file_); -} - -void log_target_file_close(log_target_t* self) -{ - if(!self || !self->param_) - return; - - fclose(((log_target_file_param_t*)(self->param_))->file_); - self->opened_ = 0; -} - -void log_target_file_clear(log_target_t* self) -{ - if(!self || !self->param_) - return; - - if(((log_target_file_param_t*)(self->param_))->logfilename_) - free(((log_target_file_param_t*)(self->param_))->logfilename_); - - free(self->param_); -} - - -log_target_t* log_target_file_new() -{ - log_target_t* tmp = malloc(sizeof(log_target_t)); - if(!tmp) - return NULL; - - tmp->type_ = TARGET_FILE; - tmp->init = &log_target_file_init; - tmp->open = &log_target_file_open; - tmp->log = &log_target_file_log; - tmp->close = &log_target_file_close; - tmp->clear = &log_target_file_clear; - tmp->opened_ = 0; - tmp->enabled_ = 0; - tmp->max_prio_ = NOTICE; - tmp->param_ = NULL; - tmp->next_ = NULL; - - return tmp; -} - - -void log_target_stdout_log(log_target_t* self, log_prio_t prio, const char* msg) -{ - printf("%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg); -} - -log_target_t* log_target_stdout_new() -{ - log_target_t* tmp = malloc(sizeof(log_target_t)); - if(!tmp) - return NULL; - - tmp->type_ = TARGET_STDOUT; - tmp->init = NULL; - tmp->open = NULL; - tmp->log = &log_target_stdout_log; - tmp->close = NULL; - tmp->clear = NULL; - tmp->opened_ = 0; - tmp->enabled_ = 0; - tmp->max_prio_ = NOTICE; - tmp->param_ = NULL; - tmp->next_ = NULL; - - return tmp; -} - - -void log_target_stderr_log(log_target_t* self, log_prio_t prio, const char* msg) -{ - fprintf(stderr, "%s %s: %s\n", get_time_formatted(), log_prio_to_string(prio), msg); -} - -log_target_t* log_target_stderr_new() -{ - log_target_t* tmp = malloc(sizeof(log_target_t)); - if(!tmp) - return NULL; - - tmp->type_ = TARGET_STDERR; - tmp->init = NULL; - tmp->open = NULL; - tmp->log = &log_target_stderr_log; - tmp->close = NULL; - tmp->clear = NULL; - tmp->opened_ = 0; - tmp->enabled_ = 0; - tmp->max_prio_ = NOTICE; - tmp->param_ = NULL; - tmp->next_ = NULL; - - return tmp; -} - -#endif diff --git a/src/luaclient.c b/src/luaclient.c deleted file mode 100644 index 104de52..0000000 --- a/src/luaclient.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> - -#include "l_log.h" -#include "l_sig_handler.h" -#include "l_cmd.h" - -#include "log.h" -#include "options.h" - -#include "daemon.h" -#include "utils.h" - - -#define LUA_MAIN_LOOP_FUNC "main_loop" - -#if LUA_VERSION_NUM > 501 -static const luaL_Reg luaclient_lualibs[] = { - {"_G", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_BITLIBNAME, luaopen_bit32}, - {LUA_LOGLIBNAME, luaopen_log}, - {LUA_SIGNALLIBNAME, luaopen_signal}, - {LUA_CMDLIBNAME, luaopen_cmd}, - {NULL, NULL} -}; -#else -static const luaL_Reg luaclient_lualibs[] = { - {"", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_LOGLIBNAME, luaopen_log}, - {LUA_SIGNALLIBNAME, luaopen_signal}, - {LUA_CMDLIBNAME, luaopen_cmd}, - {NULL, NULL} -}; -#endif - -int init_main_loop(lua_State *L, const char* filename) -{ - const luaL_Reg *lib = luaclient_lualibs; - -#if LUA_VERSION_NUM > 501 - for (; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); - } -#else - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } -#endif - - int ret = luaL_loadfile(L, filename); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRSYNTAX: log_printf(ERROR, "luaL_loadfile(%s) syntax error: %s", filename, err_str); break; - case LUA_ERRMEM: log_printf(ERROR, "luaL_loadfile(%s) malloc error: %s", filename, err_str); break; - case LUA_ERRFILE: log_printf(ERROR, "luaL_loadfile(%s) file access error: %s", filename, err_str); break; - default: log_printf(ERROR, "luaL_loadfile(%s) unknown error: %s", filename, err_str); break; - } - return -1; - } - - ret = lua_pcall(L, 0, 0, 0); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRRUN: log_printf(ERROR, "lua_pcall() runtime error: %s", err_str); break; - case LUA_ERRMEM: log_printf(ERROR, "lua_pcall() malloc error: %s", err_str); break; - case LUA_ERRERR: log_printf(ERROR, "lua_pcall() error at error handler function: %s", err_str); break; - } - return -1; - } - - return 0; -} - -int call_main_loop(lua_State* L, int cmd_fd, options_t* opt) -{ - lua_getglobal(L, LUA_MAIN_LOOP_FUNC); - if(!lua_isfunction(L, -1)) { - log_printf(ERROR, "there is no function '%s' inside the loaded file", LUA_MAIN_LOOP_FUNC); - return -1; - }; - - options_lua_push(opt, L); - - int ret = lua_pcall(L, 1, LUA_MULTRET, 0); - if(ret) { - const char* err_str = luaL_checkstring(L, -1); - switch(ret) { - case LUA_ERRRUN: log_printf(ERROR, "lua_pcall(%s) runtime error: %s", LUA_MAIN_LOOP_FUNC, err_str); break; - case LUA_ERRMEM: log_printf(ERROR, "lua_pcall(%s) malloc error: %s", LUA_MAIN_LOOP_FUNC, err_str); break; - case LUA_ERRERR: log_printf(ERROR, "lua_pcall(%s) error at error handler function: %s", LUA_MAIN_LOOP_FUNC, err_str); break; - } - return -1; - } - - int n = lua_gettop(L); - log_printf(DEBUG, "%s returned %d values", LUA_MAIN_LOOP_FUNC, n); - int i; - for (i = 1; i <= n; i++) - log_printf(DEBUG, "return value [%d] = '%s'", i, luaL_checkstring(L, i)); - - ret = lua_tointeger(L, 1); - return ret; -} - -int main_loop(int cmd_fd, options_t* opt) -{ - lua_State *L; - L = luaL_newstate(); - if(!L) { - log_printf(ERROR, "error creating lua state"); - return -1; - } - - int ret = init_main_loop(L, opt->lua_file_); - if(!ret) - ret = call_main_loop(L, cmd_fd, opt); - - lua_close(L); - return ret; -} - -int main(int argc, char* argv[]) -{ - log_init(); - - options_t opt; - int ret = options_parse(&opt, argc, argv); - if(ret) { - if(ret > 0) { - fprintf(stderr, "syntax error near: %s\n\n", argv[ret]); - } - if(ret == -2) { - fprintf(stderr, "memory error on options_parse, exiting\n"); - } - - if(ret != -2) - options_print_usage(); - - options_clear(&opt); - log_close(); - exit(ret); - } - string_list_element_t* tmp = opt.log_targets_.first_; - if(!tmp) { - log_add_target("syslog:3,luaclient,daemon"); - } - else { - while(tmp) { - ret = log_add_target(tmp->string_); - if(ret) { - switch(ret) { - case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break; - case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break; - case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; - default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; - } - - options_clear(&opt); - log_close(); - exit(ret); - } - tmp = tmp->next_; - } - } - log_printf(NOTICE, "just started..."); - if(options_parse_post(&opt)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - priv_info_t priv; - if(opt.username_) - if(priv_init(&priv, opt.username_, opt.groupname_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - FILE* pid_file = NULL; - if(opt.pid_file_) { - pid_file = fopen(opt.pid_file_, "w"); - if(!pid_file) { - log_printf(WARNING, "unable to open pid file: %s", strerror(errno)); - } - } - - if(opt.chroot_dir_) - if(do_chroot(opt.chroot_dir_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - if(opt.username_) - if(priv_drop(&priv)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - if(opt.daemonize_) { - pid_t oldpid = getpid(); - daemonize(); - log_printf(INFO, "running in background now (old pid: %d)", oldpid); - } - - if(pid_file) { - pid_t pid = getpid(); - fprintf(pid_file, "%d", pid); - fclose(pid_file); - } - - for(;;) { - // extern global variable defined in l_cmd.c - cmd_fd = connect_command_socket(opt.command_sock_); - if(cmd_fd < 0) - ret = 2; - else { - ret = main_loop(cmd_fd, &opt); - } - - if(ret == 2) { - log_printf(ERROR, "socket error, trying to reconnect in 5 seconds.."); - - if(cmd_fd > 0) - close(cmd_fd); - sleep(5); - } - else - break; - } - - if(cmd_fd > 0) - close(cmd_fd); - - if(!ret) - log_printf(NOTICE, "normal shutdown"); - else if(ret < 0) - log_printf(NOTICE, "shutdown after error (code %d)", ret); - else - log_printf(NOTICE, "shutdown after signal"); - - options_clear(&opt); - log_close(); - - return ret; -} diff --git a/src/mode-tcpserver.lua b/src/mode-tcpserver.lua deleted file mode 100644 index 7f0d217..0000000 --- a/src/mode-tcpserver.lua +++ /dev/null @@ -1,175 +0,0 @@ --- --- rhctl --- --- Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> --- --- This file is part of rhctl. --- --- rhctl 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. --- --- rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. --- - -package.path = package.path .. ';/usr/share/rhctl/?.lua' - -socket = require("socket") - -current_mode = nil - -function init_server(host, port) - local server = assert(socket.tcp()) - - assert(server:setoption('reuseaddr', true)) - assert(server:bind(host, port)) - assert(server:listen(5)) - - log.printf(log.DEBUG, "listening on " .. host .. ":" .. port) - - return server -end - -local clients = {} - -function add_client(hdl) - log.printf(log.DEBUG, "new client(" .. hdl:getfd() .. ") from " .. hdl:getpeername()) - local client = {} - if current_mode then - client.buffer = current_mode .. "\n" - else - client.buffer = "" - end - client.hdl = hdl - client.getfd = function() return hdl:getfd() end - client.dirty = function() return hdl:dirty() end - table.insert(clients, client) -end - -function remove_client(c) - local idx = -1 - for n, client in ipairs(clients) do - if client.getfd() == c.getfd() then - idx = n - break - end - end - - if idx > 0 then - log.printf(log.DEBUG, "removing client(" .. c.getfd() .. ")") - c.hdl:close() - table.remove(clients, idx) - end -end - -function cleanup_clients() - for _, client in ipairs(clients) do - client.hdl:close() - end -end - -function clients_get_writeables() - local fds = {} - - for _, client in ipairs(clients) do - if client.buffer ~= "" then - table.insert(fds, client) - end - end - - return fds -end - -function clients_senddata(data) - for _, client in ipairs(clients) do - client.buffer = client.buffer .. data .. "\n" - end -end - -function process_cmd(message) - log.printf(log.DEBUG, "received message: '%s'", message) - - local new_mode = nil - local exps = { "Current Mode: (%a+)", "new Mode: (%a+)" } - for _, exp in ipairs(exps) do - new_mode = string.match(message, exp) - if(new_mode) then - new_mode = string.lower(new_mode) - break - end - end - - if(new_mode and new_mode ~= current_mode) then - clients_senddata(new_mode) - current_mode = new_mode - end - - return 0 -end - -function main_loop(opt) - log.printf(log.NOTICE, "main_loop started") - local sig = signal.init() - local cmdfd = cmd.init() - - local server = init_server("*", "2345") - - cmd.send_string("listen mode"); - cmd.send_string("status"); - - local return_value = 0 - while return_value == 0 do - local readable, writeable, err = socket.select({ sig , cmdfd , server , unpack(clients) }, clients_get_writeables()) - if(err) then - log.printf(log.ERROR, "select returned with error: %s", err) - return_value = -1 - else - for _, input in ipairs(readable) do - if input == sig then - return_value = signal.handle() - if(return_value == 1) then break end - elseif input == cmdfd then - return_value = cmd.recv_data(process_cmd) - if(return_value ~= 0) then break end - elseif input == server then - local client = server:accept() - if(client == nil) then - return_value =-3 - break - else - add_client(client) - end - else - if input.hdl then - -- receive is insanely stupid, therefore we must always read one byte only - local _, err = input.hdl:receive(1) - if err then - remove_client(input) - end - end - end - end - for _, output in ipairs(writeable) do - local ret = output.hdl:send(output.buffer) - if(ret == nil) then - remove_client(output) - else - output.buffer = string.sub(output.buffer, ret+1) - end - end - end - end - - server:close() - cleanup_clients() - - signal.stop() - return return_value -end diff --git a/src/mode-watch.lua b/src/mode-watch.lua deleted file mode 100644 index d90c86f..0000000 --- a/src/mode-watch.lua +++ /dev/null @@ -1,119 +0,0 @@ --- --- rhctl --- --- Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> --- --- This file is part of rhctl. --- --- rhctl 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. --- --- rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. --- - -package.path = package.path .. ';/usr/share/rhctl/?.lua' - -socket = require("socket") -utils = require("utils") - -function set_master_led() - os.execute("/sbin/led.sh set master") - os.execute("/sbin/led.sh clear standby") -end - -function set_standby_led() - os.execute("/sbin/led.sh clear master") - os.execute("/sbin/led.sh set standby") -end - -function clear_leds() - os.execute("/sbin/led.sh clear master") - os.execute("/sbin/led.sh clear standby") -end - -current_mode = nil - -function process_cmd(message) - log.printf(log.DEBUG, "received message: '%s'", message) - - local new_mode = nil - local exps = { "Current Mode: (%a+)", "new Mode: (%a+)" } - for _, exp in ipairs(exps) do - new_mode = string.match(message, exp) - if(new_mode) then - new_mode = string.lower(new_mode) - if(new_mode == "master") then - set_master_led() - break - else - if(new_mode == "standby") then - set_standby_led() - break - end - end - end - end - - if(new_mode and new_mode ~= current_mode) then - log.printf(log.NOTICE, "mode is now " .. new_mode) - if(current_mode == nil) then - utils.send_mail("logs@helsinki.at", "[RHCTL] (re)started mode is now " .. new_mode, - "RHCTL just (re)started current mode is " .. new_mode) - else - utils.send_mail("logs@helsinki.at", "[RHCTL] mode changed to " .. new_mode, - "RHCTL just switched from " .. current_mode .. " to " .. new_mode) - end - current_mode = new_mode - end - - return 0 -end - -function main_loop(opt) - log.printf(log.NOTICE, "main_loop started") - local sig = signal.init() - local cmdfd = cmd.init() - - cmd.send_string("listen mode"); - cmd.send_string("status"); - - clear_leds() - - local return_value = 0 - while return_value == 0 do - local readable, _, err = socket.select({ sig , cmdfd }, nil) - if(err) then - log.printf(log.ERROR, "select returned with error: %s", err) - return_value = -1 - else - for _, input in ipairs(readable) do - if(input == sig) then - return_value = signal.handle() - if(return_value == 1) then break end - else - if(input == cmdfd) then - return_value = cmd.recv_data(process_cmd) - if(return_value ~= 0) then break end - else - log.printf(log.ERROR, "select returned invalid handle??") - return_value = -1 - break; - end - end - end - end - end - - clear_leds() - - signal.stop() - return return_value -end diff --git a/src/options.c b/src/options.c deleted file mode 100644 index bff561e..0000000 --- a/src/options.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include "options.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include "log.h" - -#define PARSE_BOOL_PARAM(SHORT, LONG, VALUE) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - VALUE = 1; - -#define PARSE_INVERSE_BOOL_PARAM(SHORT, LONG, VALUE) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - VALUE = 0; - -#define PARSE_INT_PARAM(SHORT, LONG, VALUE) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - { \ - if(argc < 1) \ - return i; \ - VALUE = atoi(argv[i+1]); \ - argc--; \ - i++; \ - } - -#define PARSE_STRING_PARAM(SHORT, LONG, VALUE) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - { \ - if(argc < 1 || argv[i+1][0] == '-') \ - return i; \ - if(VALUE) free(VALUE); \ - VALUE = strdup(argv[i+1]); \ - if(!VALUE) \ - return -2; \ - argc--; \ - i++; \ - } - -#define PARSE_STRING_PARAM_SEC(SHORT, LONG, VALUE) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - { \ - if(argc < 1 || argv[i+1][0] == '-') \ - return i; \ - if(VALUE) free(VALUE); \ - VALUE = strdup(argv[i+1]); \ - if(!VALUE) \ - return -2; \ - size_t j; \ - for(j=0; j < strlen(argv[i+1]); ++j) \ - argv[i+1][j] = '#'; \ - argc--; \ - i++; \ - } - -#define PARSE_HEXSTRING_PARAM_SEC(SHORT, LONG, VALUE) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - { \ - if(argc < 1 || argv[i+1][0] == '-') \ - return i; \ - int ret; \ - ret = options_parse_hex_string(argv[i+1], &VALUE); \ - if(ret > 0) \ - return i+1; \ - else if(ret < 0) \ - return ret; \ - size_t j; \ - for(j=0; j < strlen(argv[i+1]); ++j) \ - argv[i+1][j] = '#'; \ - argc--; \ - i++; \ - } - -#define PARSE_STRING_LIST(SHORT, LONG, LIST) \ - else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ - { \ - if(argc < 1 || argv[i+1][0] == '-') \ - return i; \ - int ret = string_list_add(&LIST, argv[i+1]); \ - if(ret == -2) \ - return ret; \ - else if(ret) \ - return i+1; \ - argc--; \ - i++; \ - } - -int options_parse_hex_string(const char* hex, buffer_t* buffer) -{ - if(!hex || !buffer) - return -1; - - u_int32_t hex_len = strlen(hex); - if(hex_len%2) - return 1; - - if(buffer->buf_) - free(buffer->buf_); - - buffer->length_ = hex_len/2; - buffer->buf_ = malloc(buffer->length_); - if(!buffer->buf_) { - buffer->length_ = 0; - return -2; - } - - const char* ptr = hex; - int i; - for(i=0;i<buffer->length_;++i) { - u_int32_t tmp; - sscanf(ptr, "%2X", &tmp); - buffer->buf_[i] = (u_int8_t)tmp; - ptr += 2; - } - - return 0; -} - - - -int options_parse(options_t* opt, int argc, char* argv[]) -{ - if(!opt) - return -1; - - options_default(opt); - - if(opt->progname_) - free(opt->progname_); - opt->progname_ = strdup(argv[0]); - if(!opt->progname_) - return -2; - - argc--; - - char* mode = NULL; - char* channel = NULL; - char* baudrate = NULL; - - int i; - for(i=1; argc > 0; ++i) - { - char* str = argv[i]; - argc--; - - if(!strcmp(str,"-h") || !strcmp(str,"--help")) - return -1; -#ifndef OPT_STDIOCLIENT - PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", opt->daemonize_) - PARSE_STRING_PARAM("-u","--username", opt->username_) - PARSE_STRING_PARAM("-g","--groupname", opt->groupname_) - PARSE_STRING_PARAM("-C","--chroot", opt->chroot_dir_) - PARSE_STRING_PARAM("-P","--write-pid", opt->pid_file_) -#endif - PARSE_STRING_LIST("-L","--log", opt->log_targets_) - PARSE_STRING_PARAM("-s","--command-sock", opt->command_sock_) -#ifndef OPT_STDIOCLIENT - PARSE_STRING_PARAM("-b","--baudrate", baudrate) -#endif -#ifdef OPT_SWITCHCTL - PARSE_STRING_PARAM("-f","--config", opt->conf_file_) - PARSE_STRING_PARAM("-d","--device", opt->switch_dev_) - PARSE_STRING_PARAM("-m","--mode", mode) - PARSE_STRING_PARAM("-c","--channel", channel) -#endif -#ifdef OPT_SERIALCLIENT - PARSE_STRING_PARAM("-d","--device", opt->serial_dev_) - PARSE_STRING_PARAM("-t","--type", opt->type_) -#endif -#ifdef OPT_HEARTBEATCLIENT - PARSE_STRING_PARAM("-d","--device", opt->serial_dev_) - PARSE_INT_PARAM("-t","--timeout", opt->timeout_) - PARSE_STRING_PARAM("-l","--led", opt->led_filename_) -#endif -#ifdef OPT_LUACLIENT - PARSE_STRING_PARAM("-f","--lua-file", opt->lua_file_) -#endif - else - return i; - } - - if(mode) { - if(!strcmp(mode, "master")) - opt->mode_ = MODE_MASTER; - else if(!strcmp(mode, "standby")) - opt->mode_ = MODE_STANDBY; - else { - free(mode); - return -3; - } - free(mode); - } - - if(channel) { - if(!strcmp(channel, "main")) { - opt->channel_master_ = CHAN_MAIN; - opt->channel_standby_ = CHAN_MAIN; - } - else if(!strcmp(channel, "music")) { - opt->channel_master_ = CHAN_MUSIC; - opt->channel_standby_ = CHAN_MUSIC; - } - else { - free(channel); - return -4; - } - free(channel); - } - - if(baudrate) { - int b = atoi(baudrate); - free(baudrate); - switch(b) { - case 1200: opt->baudrate_ = B1200; break; - case 2400: opt->baudrate_ = B2400; break; - case 4800: opt->baudrate_ = B4800; break; - case 9600: opt->baudrate_ = B9600; break; - case 19200: opt->baudrate_ = B19200; break; - case 38400: opt->baudrate_ = B38400; break; - case 57600: opt->baudrate_ = B57600; break; - case 115200: opt->baudrate_ = B115200; break; - default: return -5; - } - } - - return 0; -} - -int options_parse_post(options_t* opt) -{ - if(!opt) - return -1; -// nothing to do - -#ifdef OPT_SWITCHCTL - FILE* conf_file = fopen(opt->conf_file_, "r"); - if(conf_file) { - char buf[100]; - while(fgets(buf, 100, conf_file) != NULL) { - char* tmp, *key, *value; - for(tmp = buf;*tmp == ' '; ++tmp); - if(*(key = tmp) == 0) continue; - for(;*tmp != ' ' && *tmp != 0;++tmp); - if(*tmp == 0) continue; - *tmp=0; - ++tmp; - for(;*tmp == ' ';++tmp); - if(*(value = tmp) == 0) continue; - for(;*tmp != ' ' && *tmp != 0 && *tmp != '\n';++tmp); - *tmp = 0; - - if(key_value_storage_add(&opt->alias_table_, key, value)) - return -2; - } - fclose(conf_file); - } - else { - log_printf(ERROR,"unable to open conf file (%s): %s", opt->conf_file_, strerror(errno)); - return -1; - } -#endif - - return 0; -} - -void options_default(options_t* opt) -{ - if(!opt) - return; - -#ifdef OPT_SWITCHCTL - opt->progname_ = strdup("switchctl"); -#endif -#ifdef OPT_SERIALCLIENT - opt->progname_ = strdup("serialclient"); -#endif -#ifdef OPT_STDIOCLIENT - opt->progname_ = strdup("stdioclient"); -#endif -#ifdef OPT_HEARTBEATCLIENT - opt->progname_ = strdup("heartbeatclient"); -#endif -#ifdef OPT_LUACLIENT - opt->progname_ = strdup("luaclient"); -#endif - -/* common */ - opt->daemonize_ = 1; - opt->username_ = NULL; - opt->groupname_ = NULL; - opt->chroot_dir_ = NULL; - opt->pid_file_ = NULL; - string_list_init(&opt->log_targets_); - - opt->command_sock_ = strdup("/var/run/rhctl/switchctl.sock"); - opt->baudrate_ = B19200; - -/* switchctl */ - opt->mode_ = MODE_MASTER; - opt->channel_master_ = CHAN_MAIN; - opt->channel_standby_ = CHAN_MAIN; - opt->conf_file_ = strdup("/etc/rhctl/switchctl.conf"); - opt->switch_dev_ = strdup("/dev/audioswitch"); - key_value_storage_init(&opt->alias_table_); - -/* serialclient and heartbeatclient */ - opt->serial_dev_ = strdup("/dev/ttyUSB0"); - -/* serialclient only */ - opt->type_ = NULL; - -/* heartbeatclient only */ - opt->timeout_ = 15; - opt->led_filename_ = NULL; - -/* luaclient only */ - opt->lua_file_ = strdup("/usr/share/rhctl/mode-leds.lua"); -} - -#ifdef OPT_LUACLIENT -void options_lua_push_string(lua_State* L, const int tidx, const char* key, const char* value) -{ - lua_pushstring(L, key); - lua_pushstring(L, value); - lua_settable(L, tidx); -} - -void options_lua_push_int(lua_State* L, const int tidx, const char* key, const u_int32_t value) -{ - lua_pushstring(L, key); - lua_pushinteger(L, value); - lua_settable(L, tidx); -} - -void options_lua_push_boolean(lua_State* L, const int tidx, const char* key, const u_int32_t value) -{ - lua_pushstring(L, key); - lua_pushboolean(L, value); - lua_settable(L, tidx); -} - -void options_lua_push_string_list(lua_State* L, const int tidx, string_list_t* lst) -{ - if(!lst) - return; - - string_list_element_t* tmp = lst->first_; - if(tmp) { - lua_pushstring(L, "log_targets"); - lua_newtable(L); - int i = 1; - while(tmp) { - lua_pushinteger(L, i++); - lua_pushstring(L, tmp->string_); - lua_settable(L, -3); - tmp = tmp->next_; - } - lua_settable(L, tidx); - } -} - -void options_lua_push(options_t* opt, lua_State* L) -{ - lua_newtable(L); - - options_lua_push_string(L, -3, "progname", opt->progname_); - options_lua_push_boolean(L, -3, "daemonize", opt->daemonize_); - options_lua_push_string(L, -3, "username", opt->username_); - options_lua_push_string(L, -3, "groupname", opt->groupname_); - options_lua_push_string(L, -3, "chroot_dir", opt->chroot_dir_); - options_lua_push_string(L, -3, "pid_file", opt->pid_file_); - options_lua_push_string_list(L, -3, &(opt->log_targets_)); - options_lua_push_string(L, -3, "command_sock", opt->command_sock_); - options_lua_push_string(L, -3, "lua_file", opt->lua_file_); -} -#endif - -void options_clear(options_t* opt) -{ - if(!opt) - return; - -/* common */ - if(opt->progname_) - free(opt->progname_); - if(opt->username_) - free(opt->username_); - if(opt->groupname_) - free(opt->groupname_); - if(opt->chroot_dir_) - free(opt->chroot_dir_); - if(opt->pid_file_) - free(opt->pid_file_); - string_list_clear(&opt->log_targets_); - - if(opt->command_sock_) - free(opt->command_sock_); - -/* switchctl */ - if(opt->conf_file_) - free(opt->conf_file_); - if(opt->switch_dev_) - free(opt->switch_dev_); - key_value_storage_clear(&opt->alias_table_); - -/* serialclient and heartbeatclient */ - if(opt->serial_dev_) - free(opt->serial_dev_); - -/* serialclient only */ - if(opt->type_) - free(opt->type_); - -/* heartbeatcleint only */ - if(opt->led_filename_) - free(opt->led_filename_); - -/* luaclient only */ - if(opt->lua_file_) - free(opt->lua_file_); -} - -void options_print_usage() -{ - printf("USAGE:\n"); -#ifdef OPT_SWITCHCTL - printf("switchctl\n"); -#endif -#ifdef OPT_SERIALCLIENT - printf("serialclient\n"); -#endif -#ifdef OPT_STDIOCLIENT - printf("serialclient\n"); -#endif -#ifdef OPT_HEARTBEATCLIENT - printf("heartbeatclient\n"); -#endif - printf(" [-h|--help] prints this...\n"); -#ifndef OPT_STDIOCLIENT - printf(" [-D|--nodaemonize] don't run in background\n"); - printf(" [-u|--username] <username> change to this user\n"); - printf(" [-g|--groupname] <groupname> change to this group\n"); - printf(" [-C|--chroot] <path> chroot to this directory\n"); - printf(" [-P|--write-pid] <path> write pid to this file\n"); -#endif - printf(" [-L|--log] <target>:<level>[,<param1>[,<param2>..]]\n"); - printf(" add a log target, can be invoked several times\n"); - printf(" [-s|--command-sock] <unix sock> the command socket e.g. /var/run/rhctl/switchctl.sock\n"); -#ifndef OPT_STDIOCLIENT - printf(" [-b|--baudrate] <baudrate> the baudrate of the tty to use e.g. 19200\n"); -#endif -#ifdef OPT_SWITCHCTL - printf(" [-d|--device] <tty> the tty the audio switch is connected to e.g. /dev/audioswitch\n"); - printf(" [-f|--config] <file> the configuration file e.g. /etc/rhctl/switchctl.conf\n"); - printf(" [-m|--mode] <mode> the initial mode to use e.g. master\n"); - printf(" [-c|--channel] <channel> the initial channel to use e.g. main\n"); -#endif -#ifdef OPT_SERIALCLIENT - printf(" [-d|--device] <tty> the tty to connect to e.g. /dev/ttyUSB0\n"); - printf(" [-t|--type] <type> use this client type\n"); -#endif -#ifdef OPT_HEARTBEATCLIENT - printf(" [-d|--device] <tty> the tty to connect to e.g. /dev/ttyUSB0\n"); - printf(" [-t|--timeout] <timeout> heartbeat timeout in tenths of a second e.g. 15 -> 1.5s\n"); - printf(" [-l|--led] <led filename> sysfs filename of led device to blink\n"); -#endif -#ifdef OPT_LUACLIENT - printf(" [-f|--lua-file] <file> the configuration file e.g. /usr/share/rhctl/mode-leds.lua\n"); -#endif -} - -void options_print(options_t* opt) -{ - if(!opt) - return; - - printf("progname: '%s'\n", opt->progname_); -#ifndef OPT_STDIOCLIENT - printf("daemonize: %d\n", opt->daemonize_); - printf("username: '%s'\n", opt->username_); - printf("groupname: '%s'\n", opt->groupname_); - printf("chroot_dir: '%s'\n", opt->chroot_dir_); - printf("pid_file: '%s'\n", opt->pid_file_); -#endif - printf("log_targets: \n"); - string_list_print(&opt->log_targets_, " '", "'\n"); - - printf("command_sock: '%s'\n", opt->command_sock_); - -#ifndef OPT_STDIOCLIENT - char* br; - switch(opt->baudrate_) { - case B1200: br = "1200"; break; - case B2400: br = "2400"; break; - case B4800: br = "4800"; break; - case B9600: br = "9600"; break; - case B19200: br = "19200"; break; - case B38400: br = "38400"; break; - case B57600: br = "57600"; break; - case B115200: br = "115200"; break; - default: br = "invalid"; break; - } - printf("baudrate: '%s'\n", br); -#endif - -#ifdef OPT_SWITCHCTL - printf("mode: '%s'\n", opt->mode_ == MODE_MASTER ? "master" : "standby"); - printf("channel_master: '%s'\n", opt->channel_master_ == CHAN_MAIN ? "main" : "music"); - printf("channel_standby: '%s'\n", opt->channel_standby_ == CHAN_MAIN ? "main" : "music"); - printf("conf_file: '%s'\n", opt->conf_file_); - printf("switch_dev: '%s'\n", opt->switch_dev_); - printf("alias_table: \n"); - key_value_storage_print(&opt->alias_table_, " '", "' -> '", "'\n"); -#endif - -#ifdef OPT_SERIALCLIENT - printf("serial_dev: '%s'\n", opt->serial_dev_); - printf("type: '%s'\n", opt->type_); -#endif - -#ifdef OPT_HEARTBEATCLIENT - printf("serial_dev: '%s'\n", opt->serial_dev_); - printf("timeout: %d\n", opt->timeout_); - printf("led_filename: '%s'\n", opt->led_filename_); -#endif - -#ifdef OPT_LUACLIENT - printf("lua_file: '%s'\n", opt->lua_file_); -#endif -} diff --git a/src/options.h b/src/options.h deleted file mode 100644 index df13ebe..0000000 --- a/src/options.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_options_h_INCLUDED -#define RHCTL_options_h_INCLUDED - -#include <lua.h> - -#include "string_list.h" -#include "key_value_storage.h" -#include <termios.h> - -enum mode_enum { MODE_MASTER, MODE_STANDBY }; -typedef enum mode_enum switchctl_mode_t; - -enum channel_enum { CHAN_MAIN, CHAN_MUSIC }; -typedef enum channel_enum switchctl_channel_t; - -struct options_struct { -/* common */ - char* progname_; - int daemonize_; - char* username_; - char* groupname_; - char* chroot_dir_; - char* pid_file_; - string_list_t log_targets_; - - char* command_sock_; - speed_t baudrate_; - -/* switchctl */ - switchctl_mode_t mode_; - switchctl_channel_t channel_master_; - switchctl_channel_t channel_standby_; - char* conf_file_; - char* switch_dev_; - key_value_storage_t alias_table_; - -/* serialclient and heartbeatclient */ - char* serial_dev_; - -/* serialclient only */ - char* type_; - -/* heartbeatclient only */ - u_int32_t timeout_; - char* led_filename_; - -/* luaclient only */ - char* lua_file_; -}; -typedef struct options_struct options_t; - -int options_parse_hex_string(const char* hex, buffer_t* buffer); - -int options_parse(options_t* opt, int argc, char* argv[]); -int options_parse_post(options_t* opt); -void options_default(options_t* opt); -void options_lua_push_string(lua_State* L, const int tidx, const char* key, const char* value); -void options_lua_push_int(lua_State* L, const int tidx, const char* key, const u_int32_t value); -void options_lua_push_boolean(lua_State* L, const int tidx, const char* key, const u_int32_t value); -void options_lua_push_string_list(lua_State* L, const int tidx, string_list_t* lst); -void options_lua_push(options_t* opt, lua_State* L); -void options_clear(options_t* opt); -void options_print_usage(); -void options_print(options_t* opt); - -#endif diff --git a/src/rhctl/main.go b/src/rhctl/main.go new file mode 100644 index 0000000..430c287 --- /dev/null +++ b/src/rhctl/main.go @@ -0,0 +1,103 @@ +// +// rhctl +// +// Copyright (C) 2009-2016 Christian Pointner <equinox@helsinki.at> +// +// This file is part of rhctl. +// +// rhctl 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. +// +// rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. +// + +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "os/signal" + "sync" +) + +var ( + rhl = log.New(os.Stderr, "[rhctl]\t", log.LstdFlags) + rhdl = log.New(ioutil.Discard, "[rhctl-dbg]\t", log.LstdFlags) +) + +func init() { + if _, exists := os.LookupEnv("RHCTL_DEBUG"); exists { + rhdl.SetOutput(os.Stderr) + } +} + +type envStringValue string + +func newEnvStringValue(key, dflt string) *envStringValue { + if envval, exists := os.LookupEnv(key); exists { + return (*envStringValue)(&envval) + } else { + return (*envStringValue)(&dflt) + } +} + +func (s *envStringValue) Set(val string) error { + *s = envStringValue(val) + return nil +} + +func (s *envStringValue) Get() interface{} { return string(*s) } + +func (s *envStringValue) String() string { return fmt.Sprintf("%s", *s) } + +func main() { + webAddr := newEnvStringValue("RHCTL_WEB_ADDR", "localhost:4080") + flag.Var(webAddr, "web-addr", "addr:port to listen on (environment: RHCTL_WEB_ADDR)") + help := flag.Bool("help", false, "show usage") + + flag.Parse() + if *help { + flag.Usage() + return + } + + var wg sync.WaitGroup + + if webAddr.Get().(string) != "" { + wg.Add(1) + go func() { + defer wg.Done() + rhl.Println("starting web-api:", webAddr.Get().(string)) + //StartControlWeb(webAddr.Get().(string)) + rhl.Println("web-api finished") + }() + } + + alldone := make(chan bool) + go func() { + defer func() { alldone <- true }() + wg.Wait() + }() + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + + select { + case <-c: + rhl.Println("received interrupt, shutdown") + return + case <-alldone: + return + } +} diff --git a/src/serialclient.c b/src/serialclient.c deleted file mode 100644 index caafbbb..0000000 --- a/src/serialclient.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "log.h" -#include "sig_handler.h" -#include "options.h" - -#include "daemon.h" -#include "utils.h" - -int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - return 0; -} - -int process_data(int src_fd, int dest_fd) -{ - char* buffer[100]; - int ret = read(src_fd, buffer, 100); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - if(ret < 0) - return ret; - - log_printf(DEBUG, "read %d bytes from fd (%d)", ret, src_fd); - - int len = ret; - int offset = 0; - for(;;) { - ret = write(dest_fd, &buffer[offset], len - offset); - if(ret < 0) { - if(errno != EINTR) - return ret; - - ret = 0; - } - - offset += ret; - if(offset >= len) - break; - } - log_printf(DEBUG, "wrote %d bytes to fd (%d)", offset, dest_fd); - return 0; -} - -int main_loop(int serial_fd, int cmd_fd, options_t* opt) -{ - log_printf(NOTICE, "entering main loop"); - - fd_set readfds, tmpfds; - FD_ZERO(&readfds); - FD_SET(serial_fd, &readfds); - FD_SET(cmd_fd, &readfds); - int max_fd = serial_fd > cmd_fd ? serial_fd : cmd_fd; - - 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; - - int return_value = 0; - if(opt->type_) { - char* tmp; - int len = asprintf(&tmp, "type %s\n", opt->type_); - if(len < 0) { - log_printf(ERROR, "memory error at init"); - return_value = -2; - } - else { - return_value = send_string(cmd_fd, tmp); - free(tmp); - if(return_value <= 0) { - log_printf(ERROR, "error setting client type"); - return_value = -1; - } - else { - log_printf(NOTICE, "connecting as type '%s'", opt->type_); - return_value = 0; - } - } - } - - while(!return_value) { - memcpy(&tmpfds, &readfds, sizeof(tmpfds)); - - int ret = select(max_fd+1, &tmpfds, NULL, NULL, NULL); - if(ret == -1 && errno != EINTR) { - log_printf(ERROR, "select returned with error: %s", strerror(errno)); - return_value = -1; - break; - } - if(ret == -1 || !ret) - continue; - - if(FD_ISSET(sig_fd, &tmpfds)) - if(signal_handle()) - return_value = 1; - - if(FD_ISSET(serial_fd, &tmpfds)) - return_value = process_data(serial_fd, cmd_fd); - - if(FD_ISSET(cmd_fd, &tmpfds)) { - return_value = process_data(cmd_fd, serial_fd); - if(return_value == 2) return_value = 3; - } - } - - signal_stop(); - return return_value; -} - -int main(int argc, char* argv[]) -{ - log_init(); - - options_t opt; - int ret = options_parse(&opt, argc, argv); - if(ret) { - if(ret > 0) { - fprintf(stderr, "syntax error near: %s\n\n", argv[ret]); - } - if(ret == -2) { - fprintf(stderr, "memory error on options_parse, exiting\n"); - } - if(ret == -5) { - fprintf(stderr, "syntax error: invalid baudrate\n"); - } - - if(ret != -2) - options_print_usage(); - - options_clear(&opt); - log_close(); - exit(ret); - } - string_list_element_t* tmp = opt.log_targets_.first_; - if(!tmp) { - log_add_target("syslog:3,serialclient,daemon"); - } - else { - while(tmp) { - ret = log_add_target(tmp->string_); - if(ret) { - switch(ret) { - case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break; - case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break; - case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; - default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; - } - - options_clear(&opt); - log_close(); - exit(ret); - } - tmp = tmp->next_; - } - } - log_printf(NOTICE, "just started..."); - if(options_parse_post(&opt)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - priv_info_t priv; - if(opt.username_) - if(priv_init(&priv, opt.username_, opt.groupname_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - FILE* pid_file = NULL; - if(opt.pid_file_) { - pid_file = fopen(opt.pid_file_, "w"); - if(!pid_file) { - log_printf(WARNING, "unable to open pid file: %s", strerror(errno)); - } - } - - if(opt.chroot_dir_) - if(do_chroot(opt.chroot_dir_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - if(opt.username_) - if(priv_drop(&priv)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - if(opt.daemonize_) { - pid_t oldpid = getpid(); - daemonize(); - log_printf(INFO, "running in background now (old pid: %d)", oldpid); - } - - if(pid_file) { - pid_t pid = getpid(); - fprintf(pid_file, "%d", pid); - fclose(pid_file); - } - - int cmd_fd = 0; - int serial_fd = 0; - for(;;) { - cmd_fd = connect_command_socket(opt.command_sock_); - if(cmd_fd < 0) - ret = 3; - else { - serial_fd = open(opt.serial_dev_, O_RDWR | O_NOCTTY); - if(serial_fd < 0) { - log_printf(ERROR, "open(%s): %s", opt.serial_dev_, strerror(errno)); - ret = 2; - } - else { - ret = setup_tty(serial_fd, opt.baudrate_); - if(ret) - ret = 2; - else - ret = main_loop(serial_fd, cmd_fd, &opt); - } - } - - if(ret == 2 || ret == 3) { - if(ret == 2) - log_printf(ERROR, "%s error, trying to reopen in 5 seconds..", opt.serial_dev_); - if(ret == 3) - log_printf(ERROR, "socket error, trying to reconnect in 5 seconds.."); - - if(cmd_fd > 0) - close(cmd_fd); - if(serial_fd > 0) - close(serial_fd); - sleep(5); - } - else - break; - } - - if(cmd_fd > 0) - close(cmd_fd); - if(serial_fd > 0) - close(serial_fd); - - if(!ret) - log_printf(NOTICE, "normal shutdown"); - else if(ret < 0) - log_printf(NOTICE, "shutdown after error (code %d)", ret); - else - log_printf(NOTICE, "shutdown after signal"); - - options_clear(&opt); - log_close(); - - return ret; -} diff --git a/src/sig_handler.c b/src/sig_handler.c deleted file mode 100644 index f9043a1..0000000 --- a/src/sig_handler.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include "log.h" -#include "sig_handler.h" - -#include <signal.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> - -static int sig_pipe_fds[2]; -int reset_flag; - -static void sig_handler(int sig) -{ - sigset_t set; - int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t)); - if(ret != sizeof(sigset_t)) - sigemptyset(&set); - - sigaddset(&set, sig); - ret = write(sig_pipe_fds[1], &set, sizeof(sigset_t)); -} - - -int signal_init() -{ - if(pipe(sig_pipe_fds)) { - log_printf(ERROR, "signal handling init failed (pipe error: %s)", strerror(errno)); - return -1; - } - - int i; - for(i=0; i<2; ++i) { - int fd_flags = fcntl(sig_pipe_fds[i], F_GETFL); - if(fd_flags == -1) { - log_printf(ERROR, "signal handling init failed (pipe fd[%d] read flags error: %s)", i, strerror(errno)); - return -1; - } - if(fcntl(sig_pipe_fds[i], F_SETFL, fd_flags | O_NONBLOCK) == -1){ - log_printf(ERROR, "signal handling init failed (pipe fd[%d] write flags error: %s)", i, strerror(errno)); - return -1; - } - } - - struct sigaction act, ign; - act.sa_handler = sig_handler; - sigfillset(&act.sa_mask); - act.sa_flags = 0; - ign.sa_handler = SIG_IGN; - sigfillset(&ign.sa_mask); - ign.sa_flags = 0; - - if((sigaction(SIGINT, &act, NULL) < 0) || - (sigaction(SIGQUIT, &act, NULL) < 0) || - (sigaction(SIGTERM, &act, NULL) < 0) || - (sigaction(SIGHUP, &act, NULL) < 0) || - (sigaction(SIGUSR1, &act, NULL) < 0) || - (sigaction(SIGUSR2, &act, NULL) < 0) || - (sigaction(SIGCHLD, &ign, NULL) < 0) || - (sigaction(SIGPIPE, &ign, NULL) < 0)) { - - log_printf(ERROR, "signal handling init failed (sigaction error: %s)", strerror(errno)); - close(sig_pipe_fds[0]); - close(sig_pipe_fds[1]); - } - - return sig_pipe_fds[0]; -} - -int signal_handle() -{ - sigset_t set, oldset, tmpset; - - sigemptyset(&tmpset); - sigaddset(&tmpset, SIGINT); - sigaddset(&tmpset, SIGQUIT); - sigaddset(&tmpset, SIGTERM); - sigaddset(&tmpset, SIGHUP); - sigaddset(&tmpset, SIGUSR1); - sigaddset(&tmpset, SIGUSR2); - sigprocmask(SIG_BLOCK, &tmpset, &oldset); - - int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t)); - if(ret != sizeof(sigset_t)) - sigemptyset(&set); - - int return_value = 0; - int sig; - for(sig=1; sig < NSIG; ++sig) { - if(sigismember(&set, sig)) { - switch(sig) { - case SIGINT: log_printf(NOTICE, "SIG-Int caught, exitting"); return_value = 1; break; - case SIGQUIT: log_printf(NOTICE, "SIG-Quit caught, exitting"); return_value = 1; break; - case SIGTERM: log_printf(NOTICE, "SIG-Term caught, exitting"); return_value = 1; break; - case SIGHUP: log_printf(NOTICE, "SIG-Hup caught"); reset_flag = 1; break; - case SIGUSR1: log_printf(NOTICE, "SIG-Usr1 caught"); break; - case SIGUSR2: log_printf(NOTICE, "SIG-Usr2 caught"); break; - default: log_printf(WARNING, "unknown signal %d caught, ignoring", sig); break; - } - sigdelset(&set, sig); - } - } - - sigprocmask(SIG_SETMASK, &oldset, NULL); - return return_value; -} - -void signal_stop() -{ - struct sigaction act; - act.sa_handler = SIG_DFL; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - - sigaction(SIGINT, &act, NULL); - sigaction(SIGQUIT, &act, NULL); - sigaction(SIGTERM, &act, NULL); - sigaction(SIGHUP, &act, NULL); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGUSR2, &act, NULL); - sigaction(SIGPIPE, &act, NULL); - sigaction(SIGCHLD, &act, NULL); - - close(sig_pipe_fds[0]); - close(sig_pipe_fds[1]); -} diff --git a/src/sig_handler.h b/src/sig_handler.h deleted file mode 100644 index a923418..0000000 --- a/src/sig_handler.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_sig_handler_h_INCLUDED -#define RHCTL_sig_handler_h_INCLUDED - -extern int reset_flag; - -int signal_init(); -int signal_handle(); -void signal_stop(); - -#endif diff --git a/src/silence-watch.lua b/src/silence-watch.lua deleted file mode 100644 index aa7354d..0000000 --- a/src/silence-watch.lua +++ /dev/null @@ -1,87 +0,0 @@ --- --- rhctl --- --- Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> --- --- This file is part of rhctl. --- --- rhctl 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. --- --- rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. --- - -package.path = package.path .. ';/usr/share/rhctl/?.lua' - -socket = require("socket") -utils = require("utils") - -current_state = nil - -function process_cmd(message) - log.printf(log.DEBUG, "received message: '%s'", message) - - silence_state = string.match(message, "S0S,(%d)") - - if(silence_state and silence_state ~= current_state) then - if(silence_state == "0") then - log.printf(log.NOTICE, "seen some noise") - utils.send_mail("silence@helsinki.at", "[RHCTL] sees some noise", - "There is some noise at output 1 of the audioswitch\nCurrent State is: " .. message) - else - if (silence_state == "1") then - log.printf(log.NOTICE, "silence detected") - utils.send_mail("silence@helsinki.at", "[RHCTL] silence detected ", - "Silence detected at output 1 of the audioswitch, make some noise!!\nCurrent State is: " .. message) - end - end - current_state = silence_state - end - - return 0 -end - -function main_loop(opt) - log.printf(log.NOTICE, "main_loop started") - local sig = signal.init() - local cmdfd = cmd.init() - - cmd.send_string("listen silence"); - cmd.send_string("switch *0SS"); - - local return_value = 0 - while return_value == 0 do - local readable, _, err = socket.select({ sig , cmdfd }, nil) - if(err) then - log.printf(log.ERROR, "select returned with error: %s", err) - return_value = -1 - else - for _, input in ipairs(readable) do - if(input == sig) then - return_value = signal.handle() - if(return_value == 1) then break end - else - if(input == cmdfd) then - return_value = cmd.recv_data(process_cmd) - if(return_value ~= 0) then break end - else - log.printf(log.ERROR, "select returned invalid handle??") - return_value = -1 - break; - end - end - end - end - end - - signal.stop() - return return_value -end diff --git a/src/stdioclient.c b/src/stdioclient.c deleted file mode 100644 index a8bcad1..0000000 --- a/src/stdioclient.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "log.h" -#include "sig_handler.h" -#include "options.h" - -#include "daemon.h" -#include "utils.h" - -int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - return 0; -} - -int process_data(int src_fd, int dest_fd) -{ - char* buffer[100]; - int ret = read(src_fd, buffer, 100); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - if(ret < 0) - return ret; - - log_printf(DEBUG, "read %d bytes from fd (%d)", ret, src_fd); - - int len = ret; - int offset = 0; - for(;;) { - ret = write(dest_fd, &buffer[offset], len - offset); - if(ret < 0) { - - if(errno != EINTR) - return ret; - - ret = 0; - } - - offset += ret; - if(offset+1 >= len) - break; - } - return 0; -} - -int main_loop(int cmd_fd, options_t* opt) -{ - log_printf(NOTICE, "entering main loop"); - - fd_set readfds, tmpfds; - FD_ZERO(&readfds); - FD_SET(0, &readfds); - FD_SET(cmd_fd, &readfds); - int max_fd = cmd_fd; - - 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; - - int return_value = 0; - - while(!return_value) { - memcpy(&tmpfds, &readfds, sizeof(tmpfds)); - - int ret = select(max_fd+1, &tmpfds, NULL, NULL, NULL); - if(ret == -1 && errno != EINTR) { - log_printf(ERROR, "select returned with error: %s", strerror(errno)); - return_value = -1; - break; - } - if(ret == -1 || !ret) - continue; - - if(FD_ISSET(sig_fd, &tmpfds)) - if(signal_handle()) - return_value = 1; - - if(FD_ISSET(0, &tmpfds)) - return_value = process_data(0, cmd_fd); - - if(FD_ISSET(cmd_fd, &tmpfds)) - return_value = process_data(cmd_fd, 1); - } - - signal_stop(); - return return_value; -} - -int main(int argc, char* argv[]) -{ - log_init(); - - options_t opt; - int ret = options_parse(&opt, argc, argv); - if(ret) { - if(ret > 0) { - fprintf(stderr, "syntax error near: %s\n\n", argv[ret]); - } - if(ret == -2) { - fprintf(stderr, "memory error on options_parse, exiting\n"); - } - - if(ret != -2) - options_print_usage(); - - options_clear(&opt); - log_close(); - exit(ret); - } - string_list_element_t* tmp = opt.log_targets_.first_; - if(!tmp) { - log_add_target("stderr:2"); - } - else { - while(tmp) { - ret = log_add_target(tmp->string_); - if(ret) { - switch(ret) { - case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break; - case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break; - case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; - default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; - } - - options_clear(&opt); - log_close(); - exit(ret); - } - tmp = tmp->next_; - } - } - log_printf(NOTICE, "just started..."); - if(options_parse_post(&opt)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - int cmd_fd = connect_command_socket(opt.command_sock_); - if(cmd_fd < 0) { - options_clear(&opt); - log_close(); - exit(-1); - } - - ret = main_loop( cmd_fd, &opt); - - close(cmd_fd); - - if(!ret) - log_printf(NOTICE, "normal shutdown"); - else if(ret < 0) - log_printf(NOTICE, "shutdown after error (code %d)", ret); - else - log_printf(NOTICE, "shutdown after signal"); - - options_clear(&opt); - log_close(); - - return ret; -} diff --git a/src/string_list.c b/src/string_list.c deleted file mode 100644 index 870048b..0000000 --- a/src/string_list.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include "string_list.h" - -void string_list_init(string_list_t* list) -{ - if(!list) - return; - - list->first_ = NULL; -} - -void string_list_clear(string_list_t* list) -{ - if(!list) - return; - - while(list->first_) { - string_list_element_t* tmp; - tmp = list->first_; - list->first_ = tmp->next_; - if(tmp->string_) - free(tmp->string_); - free(tmp); - } -} - -int string_list_add(string_list_t* list, const char* string) -{ - if(!list) - return -1; - - if(!list->first_) { - list->first_ = malloc(sizeof(string_list_element_t)); - if(!list->first_) - return -2; - - list->first_->next_ = 0; - list->first_->string_ = strdup(string); - if(!list->first_->string_) { - free(list->first_); - list->first_ = NULL; - return -2; - } - } - else { - string_list_element_t* tmp = list->first_; - while(tmp->next_) - tmp = tmp->next_; - - tmp->next_ = malloc(sizeof(string_list_element_t)); - if(!tmp->next_) - return -2; - - tmp->next_->next_ = 0; - tmp->next_->string_ = strdup(string); - if(!tmp->next_->string_) { - free(tmp->next_); - tmp->next_ = NULL; - return -2; - } - } - return 0; -} - -void string_list_print(string_list_t* list, const char* head, const char* tail) -{ - if(!list) - return; - - string_list_element_t* tmp = list->first_; - while(tmp) { - printf("%s%s%s", head, tmp->string_, tail); - tmp = tmp->next_; - } -} diff --git a/src/string_list.h b/src/string_list.h deleted file mode 100644 index 6e415f9..0000000 --- a/src/string_list.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_string_list_h_INCLUDED -#define RHCTL_string_list_h_INCLUDED - -struct string_list_element_struct { - char* string_; - struct string_list_element_struct* next_; -}; -typedef struct string_list_element_struct string_list_element_t; - -struct string_list_struct { - string_list_element_t* first_; -}; -typedef struct string_list_struct string_list_t; - -void string_list_init(string_list_t* list); -void string_list_clear(string_list_t* list); -int string_list_add(string_list_t* list, const char* string); - -void string_list_print(string_list_t* list, const char* head, const char* tail); - -#endif diff --git a/src/switchctl.c b/src/switchctl.c deleted file mode 100644 index 4be2313..0000000 --- a/src/switchctl.c +++ /dev/null @@ -1,1211 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "log.h" -#include "sig_handler.h" -#include "options.h" - -#include "command_queue.h" -#include "client_list.h" -#include "key_value_storage.h" - -#include "daemon.h" -#include "utils.h" - -struct state_struct { - switchctl_mode_t mode_; - switchctl_channel_t channel_master_; - switchctl_channel_t channel_standby_; - bool hb_state_master_; - bool hb_state_standby_; -}; -typedef struct state_struct state_t; - -state_t state_; - -int send_command(int switch_fd, cmd_t* cmd) -{ - if(!cmd) - return -1; - - char* c = NULL; - switch(cmd->cmd) { - case SWITCH: - case CHANNEL: c = cmd->param; break; - case STATUS: c = "*0SL"; break; - default: break; - } - - if(c == NULL) - return 0; - - int ret = send_string(switch_fd, c); - if(ret > 0) { - cmd_sent(cmd); - return 0; - } - - return ret; -} - -int send_response(int fd, const char* response) -{ - if(!response) - return -1; - - if(fd < 0) - return 0; - - int ret = send_string(fd, response); - do { - ret = write(fd, "\n", 1); - } while(!ret || (ret == -1 && errno == EINTR)); - - if(ret > 0) - return 0; - - return ret; -} - -void send_usage(int fd) -{ - if(fd < 0) - return; - - send_response(fd, "Usage: "); - send_response(fd, " help prints this"); - send_response(fd, " quit close connection"); - send_response(fd, " type set client type, one of: master, standby, hb_master, hb_standby"); - send_response(fd, " channel switch to channel main or music"); - send_response(fd, " client type master and standby only"); - send_response(fd, " mode switch to mode master or standby (add -forced to override heartbeat control)"); - send_response(fd, " heartbeat update heartbeat status for master or standby"); - send_response(fd, " status get actual status from switch"); - send_response(fd, " health get health info"); - send_response(fd, " listen register for events, no parameter for all"); - send_response(fd, " one of: request, mode, status, health, gpi, oc, relay, silence, none"); - send_response(fd, " log add line to daemons log file"); - send_response(fd, " switch send raw commands to the switch"); -} - -int process_cmd_request(const char* cmd, cmd_id_t cmd_id, const char* param, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - client_t* c = client_find(client_lst, fd); - if(!c) { - log_printf(WARNING, "ignoring request from unknown client"); - send_response(fd, "EEE: switch: client not found in client list?!"); - return 0; - } - - char* cmd_param = NULL; - if(cmd_id == SWITCH) { - if((state_.mode_ == MODE_MASTER && c->type == STANDBY )|| - (state_.mode_ == MODE_STANDBY && c->type == MASTER )) - { - log_printf(INFO, "silently ignoring request from inactive system (%s)", c->type == MASTER ? "master" : "standby"); - return 0; - } - - if(!param) { - log_printf(INFO, "ignoring switch command without parameter"); - send_response(fd, "EEE: switch: missing parameter"); - return 0; - } - - if(param[0] == '*') { - cmd_param = strdup(param); - } - else { - const char* ch_name = NULL; - char* ch_nr = NULL; - if(!strncmp(param, "up ", 3)) { - cmd_param = strdup("*0FUii"); - ch_name = &(param[3]); - ch_nr = &(cmd_param[4]); - } - else if(!strncmp(param, "down ", 5)) { - cmd_param = strdup("*0FDii"); - ch_name = &(param[5]); - ch_nr = &(cmd_param[4]); - } - else if(!strncmp(param, "select ", 7)) { - cmd_param = strdup("*0ii1"); - ch_name = &(param[7]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "add ", 4)) { - cmd_param = strdup("*0ii3"); - ch_name = &(param[4]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "rm ", 3)) { - cmd_param = strdup("*0ii5"); - ch_name = &(param[3]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "mute ", 5)) { - cmd_param = strdup("*0iiM1"); - ch_name = &(param[5]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "select2 ", 8)) { - cmd_param = strdup("*0ii2"); - ch_name = &(param[8]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "add2 ", 5)) { - cmd_param = strdup("*0ii4"); - ch_name = &(param[5]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "rm2 ", 4)) { - cmd_param = strdup("*0ii6"); - ch_name = &(param[4]); - ch_nr = &(cmd_param[2]); - } - else if(!strncmp(param, "mute2 ", 6)) { - cmd_param = strdup("*0iiM2"); - ch_name = &(param[6]); - ch_nr = &(cmd_param[2]); - } - else { - log_printf(INFO, "ignoring invalid switch command: '%s'", param); - send_response(fd, "EEE: switch: invalid command"); - return 0; - } - char* ch_tmp = key_value_storage_find(&opt->alias_table_, ch_name); - if(!ch_tmp || ch_tmp[0] == 0 || ch_tmp[1] == 0 || ch_tmp[2] != 0) { - log_printf(ERROR, "invalid channel name or number: %s", ch_name); - send_response(fd, "EEE: switch: invalid channel name or number"); - free(cmd_param); - return 0; - } - - ch_nr[0] = ch_tmp[0]; - ch_nr[1] = ch_tmp[1]; - } - log_printf(DEBUG, "enqueing command to switch: '%s' (request was: '%s')", cmd_param, param); - } - - int ret = cmd_push(cmd_q, fd, cmd_id, cmd_param); - if(cmd_param) - free(cmd_param); - if(ret) - return ret; - - if(cmd_id == STATUS) { - char buf[3][30]; - snprintf(buf[0], 30, "Current Mode: %s", state_.mode_ == MODE_MASTER ? "Master" : "Standby"); - send_response(fd, buf[0]); - snprintf(buf[1], 30, "Master Channel: %s", state_.channel_master_ == CHAN_MAIN ? "Main" : "Music"); - send_response(fd, buf[1]); - snprintf(buf[2], 30, "Standby Channel: %s", state_.channel_standby_ == CHAN_MAIN ? "Main" : "Music"); - send_response(fd, buf[2]); - client_t* client; - int listener_cnt = 0; - for(client = client_lst; client; client = client->next) - if(client->status_listener && client->fd != fd) { - send_response(client->fd, buf[0]); - send_response(client->fd, buf[1]); - send_response(client->fd, buf[2]); - listener_cnt++; - } - log_printf(DEBUG, "sent status to %d additional listeners", listener_cnt); - } - - log_printf(NOTICE, "command: %s", cmd); - - return 0; -} - -int crossfade(const char* ch_from, const char* ch_to, int fd, cmd_t **cmd_q, options_t* opt) -{ - char* cmd_param = strdup("*0FDii*0FUii"); - - char* ch_nr_from = key_value_storage_find(&opt->alias_table_, ch_from); - if(!ch_nr_from || ch_nr_from[0] == 0 || ch_nr_from[1] == 0 || ch_nr_from[2] != 0) { - log_printf(ERROR, "invalid channel name or number: %s", ch_from); - send_response(fd, "EEE: channel: invalid channel name or number"); - free(cmd_param); - return 1; - } - - char* ch_nr_to = key_value_storage_find(&opt->alias_table_, ch_to); - if(!ch_nr_to || ch_nr_to[0] == 0 || ch_nr_to[1] == 0 || ch_nr_to[2] != 0) { - log_printf(ERROR, "invalid channel name or number: %s", ch_to); - send_response(fd, "EEE: channel: invalid channel name or number"); - free(cmd_param); - return 1; - } - - cmd_param[4] = ch_nr_from[0]; - cmd_param[5] = ch_nr_from[1]; - cmd_param[10] = ch_nr_to[0]; - cmd_param[11] = ch_nr_to[1]; - - log_printf(DEBUG, "enqueing command to switch: '%s'", cmd_param); - int ret = cmd_push(cmd_q, fd, CHANNEL, cmd_param); - free(cmd_param); - - return ret; -} - -int process_cmd_channel(const char* cmd, const char* param, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - client_t* c = client_find(client_lst, fd); - if(!c) { - log_printf(WARNING, "ignoring request from unknown client"); - send_response(fd, "EEE: channel: client not found in client list?!"); - return 0; - } - - if(c->type != MASTER && c->type != STANDBY) { - log_printf(WARNING, "ignoring request from client of wrong type"); - send_response(fd, "EEE: channel: client type doesn't fit"); - return 0; - } - - if(!param) { - log_printf(INFO, "ignoring channel command without parameter"); - send_response(fd, "EEE: channel: missing parameter"); - return 0; - } - - switchctl_channel_t old_channel; - if(c->type == MASTER) - old_channel = state_.channel_master_; - else - old_channel = state_.channel_standby_; - - char* ch_from = NULL; - char* ch_to = NULL; - if(!strcmp(param, "main")) { - if(state_.mode_ == MODE_MASTER) { - ch_from = "master_music"; - ch_to = "master_main"; - } - else { - ch_from = "standby_music"; - ch_to = "standby_main"; - } - if(c->type == MASTER) - state_.channel_master_ = CHAN_MAIN; - else - state_.channel_standby_ = CHAN_MAIN; - } - else if(!strcmp(param, "music")) { - if(state_.mode_ == MODE_MASTER) { - ch_from = "master_main"; - ch_to = "master_music"; - } - else { - ch_from = "standby_main"; - ch_to = "standby_music"; - } - if(c->type == MASTER) - state_.channel_master_ = CHAN_MUSIC; - else - state_.channel_standby_ = CHAN_MUSIC; - } - - if((state_.mode_ == MODE_MASTER && c->type == STANDBY )|| - (state_.mode_ == MODE_STANDBY && c->type == MASTER )) - { - log_printf(INFO, "no crossfade for inactive system (%s), just updated channel info", c->type == MASTER ? "master" : "standby"); - return 0; - } - - int ret = crossfade(ch_from, ch_to, fd, cmd_q, opt); - if(ret) { - if(c->type == MASTER) - state_.channel_master_ = old_channel; - else - state_.channel_standby_ = old_channel; - - if(ret > 0) - return 0; - - return ret; - } - - log_printf(NOTICE, "command: %s", cmd); - - return 0; -} - -int change_mode(switchctl_mode_t old_mode, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - char* ch_from = NULL; - if(old_mode == MODE_MASTER && state_.channel_master_ == CHAN_MAIN) - ch_from = "master_main"; - else if(old_mode == MODE_MASTER && state_.channel_master_ == CHAN_MUSIC) - ch_from = "master_music"; - else if(old_mode == MODE_STANDBY && state_.channel_standby_ == CHAN_MAIN) - ch_from = "standby_main"; - else if(old_mode == MODE_STANDBY && state_.channel_standby_ == CHAN_MUSIC) - ch_from = "standby_music"; - else { - state_.mode_ = old_mode; - log_printf(ERROR, "EEE: mode: old config is illegal?!"); - return 0; - } - - char* ch_to = NULL; - if(state_.mode_ == MODE_MASTER && state_.channel_master_ == CHAN_MAIN) - ch_to = "master_main"; - else if(state_.mode_ == MODE_MASTER && state_.channel_master_ == CHAN_MUSIC) - ch_to = "master_music"; - else if(state_.mode_ == MODE_STANDBY && state_.channel_standby_ == CHAN_MAIN) - ch_to = "standby_main"; - else if(state_.mode_ == MODE_STANDBY && state_.channel_standby_ == CHAN_MUSIC) - ch_to = "standby_music"; - else { - state_.mode_ = old_mode; - log_printf(ERROR, "EEE: mode: current config is illegal?!"); - return 0; - } - - int ret = crossfade(ch_from, ch_to, fd, cmd_q, opt); - if(ret) { - state_.mode_ = old_mode; - if(ret > 0) - return 0; - - return ret; - } - - char* mode_str; - int len = asprintf(&mode_str, "new Mode: %s", state_.mode_ == MODE_MASTER ? "master" : "standby"); - if(len > 0) { - log_printf(NOTICE, "%s", mode_str); - client_t* client; - int listener_cnt = 0; - for(client = client_lst; client; client = client->next) - if(client->mode_listener && client->fd != fd) { - send_response(client->fd, mode_str); - listener_cnt++; - } - free(mode_str); - log_printf(DEBUG, "sent new mode to %d additional listeners", listener_cnt); - } - - return 0; -} - -int process_cmd_mode(const char* param, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - switchctl_mode_t old_mode = state_.mode_; - - if(param) { - if(!strncmp(param, "master-forced", 13)) - state_.mode_ = MODE_MASTER; - else if(!strncmp(param, "master", 6)) { - if(!state_.hb_state_master_) { - log_printf(DEBUG, "mode switch to master denied because missing heartbeat", param); - send_response(fd, "EEE: mode: no heartbeat, use 'mode master-forced' to override"); - return 0; - } - state_.mode_ = MODE_MASTER; - } - else if(!strncmp(param, "standby-forced", 14)) - state_.mode_ = MODE_STANDBY; - else if(!strncmp(param, "standby", 7)) { - if(!state_.hb_state_standby_) { - log_printf(DEBUG, "mode switch to standby denied because missing heartbeat", param); - send_response(fd, "EEE: mode: no heartbeat, use 'mode standby-forced' to override"); - return 0; - } - state_.mode_ = MODE_STANDBY; - } - else { - log_printf(DEBUG, "unkown mode '%s'", param); - send_response(fd, "EEE: mode: unknown mode"); - return 0; - } - - // swap master with standby channels only when mode has changed - if(old_mode != state_.mode_) - return change_mode(old_mode, fd, cmd_q, client_lst, opt); - } - else { - log_printf(ERROR, "unable to set mode: empty parameter"); - send_response(fd, "EEE: mode: missing parameter"); - } - - return 0; -} - -int send_health_status(int fd, client_t* client_lst) -{ - bool mc, sc, hmc, hsc; - mc = sc = hmc = hsc = 0; - - client_t* client; - for(client = client_lst; client; client = client->next) { - switch(client->type) { - case MASTER: mc=1; break; - case STANDBY: sc=1; break; - case HB_MASTER: hmc=1; break; - case HB_STANDBY: hsc=1; break; - default: break; - } - } - - char buf[5][50]; - snprintf(buf[0], 50, "Health: %s", (mc && sc && hmc && hsc && state_.hb_state_master_ && state_.hb_state_standby_) ? "ok" : "error"); - snprintf(buf[1], 50, "Master: %s", (mc) ? "connected" : "offline"); - snprintf(buf[2], 50, "Standby: %s", (sc) ? "connected" : "offline"); - snprintf(buf[3], 50, "Hearbeat Master: %s, %s", (hmc) ? "connected" : "offline", (state_.hb_state_master_) ? "present" : "timeout"); - snprintf(buf[4], 50, "Hearbeat Standby: %s, %s", (hsc) ? "connected" : "offline", (state_.hb_state_standby_) ? "present" : "timeout"); - - if(fd >= 0) { - send_response(fd, buf[0]); - send_response(fd, buf[1]); - send_response(fd, buf[2]); - send_response(fd, buf[3]); - send_response(fd, buf[4]); - } - - int listener_cnt = 0; - for(client = client_lst; client; client = client->next) - if(client->health_listener && client->fd != fd) { - send_response(client->fd, buf[0]); - send_response(client->fd, buf[1]); - send_response(client->fd, buf[2]); - send_response(client->fd, buf[3]); - send_response(client->fd, buf[4]); - listener_cnt++; - } - log_printf(DEBUG, "sent health info to %d additional listeners", listener_cnt); - return 0; -} - -int update_health_status(int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - bool hmc, hsc; - hmc = hsc = 0; - - client_t* client; - for(client = client_lst; client; client = client->next) { - switch(client->type) { - case HB_MASTER: hmc=1; break; - case HB_STANDBY: hsc=1; break; - default: break; - } - } - - if(!hmc) state_.hb_state_master_ = 0; - if(!hsc) state_.hb_state_standby_ = 0; - - switchctl_mode_t old_mode = state_.mode_; - if(state_.mode_ == MODE_MASTER) { - if(!state_.hb_state_master_) { - if(state_.hb_state_standby_) { - state_.mode_ = MODE_STANDBY; - return change_mode(old_mode, fd, cmd_q, client_lst, opt); - } - } - } else { - if(!state_.hb_state_standby_) { - if(state_.hb_state_master_) { - state_.mode_ = MODE_MASTER; - return change_mode(old_mode, fd, cmd_q, client_lst, opt); - } - } - } - - send_health_status(fd, client_lst); - - return 0; -} - -void process_cmd_type(const char* param, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - bool mc, sc, hmc, hsc; - mc = sc = hmc = hsc = 0; - - client_t* client; - for(client = client_lst; client; client = client->next) { - switch(client->type) { - case MASTER: mc=1; break; - case STANDBY: sc=1; break; - case HB_MASTER: hmc=1; break; - case HB_STANDBY: hsc=1; break; - default: break; - } - } - - if(param) { - client_t* client = client_find(client_lst, fd); - if(client) { - if(client->type == DEFAULT) { - if(!strncmp(param, "master", 6)) { - if(mc) { - log_printf(DEBUG, "client of type '%s' already connected", param); - send_response(fd, "EEE: type: already connected"); - return; - } - client->type = MASTER; - client->gpi_listener = 1; - } - else if(!strncmp(param, "standby", 7)) { - if(sc) { - log_printf(DEBUG, "client of type '%s' already connected", param); - send_response(fd, "EEE: type: already connected"); - return; - } - client->type = STANDBY; - client->gpi_listener = 1; - } - else if(!strncmp(param, "hb_master", 9)) { - if(hmc) { - log_printf(DEBUG, "client of type '%s' already connected", param); - send_response(fd, "EEE: type: already connected"); - return; - } - client->type = HB_MASTER; - } - else if(!strncmp(param, "hb_standby", 10)) { - if(hsc) { - log_printf(DEBUG, "client of type '%s' already connected", param); - send_response(fd, "EEE: type: already connected"); - return; - } - client->type = HB_STANDBY; - } - else { - log_printf(DEBUG, "unkown client type '%s'", param); - send_response(fd, "EEE: type: unknown client type"); - return; - } - log_printf(DEBUG, "client %d type set to %s", fd, param); - update_health_status(-1, cmd_q, client_lst, opt); - } - else { - log_printf(ERROR, "unable to set client type for %d: type already set to %s", fd, client_type_tostring(client->type)); - send_response(fd, "EEE: type: type already set"); - } - } - else { - log_printf(ERROR, "unable to set client type for %d: client not found", fd); - send_response(fd, "EEE: type: client not found in client list?!"); - } - } - else { - log_printf(ERROR, "unable to set client type for %d: empty parameter", fd); - send_response(fd, "EEE: type: missing parameter"); - } -} - -int process_cmd_heartbeat(const char* param, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - if(param) { - client_t* client = client_find(client_lst, fd); - if(client) { - switch(client->type) { - case HB_MASTER: { - state_.hb_state_master_ = (param[0] == '1') ? TRUE : FALSE; - break; - } - case HB_STANDBY: { - state_.hb_state_standby_ = (param[0] == '1') ? TRUE : FALSE; - break; - } - default: { - log_printf(ERROR, "unable to update heartbeat status: wrong client type"); - send_response(fd, "EEE: heartbeat: wrong client type"); - break; - } - } - update_health_status(-1, cmd_q, client_lst, opt); - } - else { - log_printf(ERROR, "unable to update heartbeat status: client not found"); - send_response(fd, "EEE: heartbeat: client not found in client list?!"); - } - } - else { - log_printf(ERROR, "unable to update heartbeat status: empty parameter"); - send_response(fd, "EEE: heartbeat: missing parameter"); - } - return 0; -} - -int process_cmd_health(const char* param, int fd, client_t* client_lst) -{ - return send_health_status(fd, client_lst); -} - -void process_cmd_listen(const char* param, int fd, client_t* client_lst) -{ - client_t* listener = client_find(client_lst, fd); - if(listener) { - if(!param) { - listener->request_listener = 1; - listener->mode_listener = 1; - listener->status_listener = 1; - listener->gpi_listener = 1; - listener->oc_listener = 1; - listener->relay_listener = 1; - listener->silence_listener = 1; - listener->health_listener = 1; - } - else { - if(!strncmp(param, "request", 7)) - listener->request_listener = 1; - else if(!strncmp(param, "mode", 6)) - listener->mode_listener = 1; - else if(!strncmp(param, "status", 6)) - listener->status_listener = 1; - else if(!strncmp(param, "gpi", 3)) - listener->gpi_listener = 1; - else if(!strncmp(param, "oc", 2)) - listener->oc_listener = 1; - else if(!strncmp(param, "relay", 5)) - listener->relay_listener = 1; - else if(!strncmp(param, "silence", 7)) - listener->silence_listener = 1; - else if(!strncmp(param, "health", 6)) - listener->health_listener = 1; - else if(!strncmp(param, "none", 4)) { - listener->request_listener = 0; - listener->mode_listener = 0; - listener->status_listener = 0; - listener->gpi_listener = 0; - listener->oc_listener = 0; - listener->relay_listener = 0; - listener->silence_listener = 0; - listener->health_listener = 0; - } - else { - log_printf(DEBUG, "unkown listener type '%s'", param); - send_response(fd, "EEE: listen: unkown type"); - return; - } - } - log_printf(DEBUG, "listener %d requests %s messages", fd, param ? param:"all"); - } - else { - log_printf(ERROR, "unable to add listener %d", fd); - send_response(fd, "EEE: listen: client not found in client list?!"); - } -} - -int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt) -{ - log_printf(DEBUG, "processing command from %d", fd); - - if(!cmd_q || !cmd) - return -1; - - cmd_id_t cmd_id; - if(!strncmp(cmd, "switch", 6)) - cmd_id = SWITCH; - else if(!strncmp(cmd, "channel", 7)) - cmd_id = CHANNEL; - else if(!strncmp(cmd, "type", 4)) - cmd_id = TYPE; - else if(!strncmp(cmd, "mode", 4)) - cmd_id = MODE; - else if(!strncmp(cmd, "heartbeat", 5)) - cmd_id = HEARTBEAT; - else if(!strncmp(cmd, "status", 6)) - cmd_id = STATUS; - else if(!strncmp(cmd, "health", 6)) - cmd_id = HEALTH; - else if(!strncmp(cmd, "log", 3)) - cmd_id = LOG; - else if(!strncmp(cmd, "listen", 6)) - cmd_id = LISTEN; - else if(!strncmp(cmd, "quit", 4)) - return 2; - else { - if(!strncmp(cmd, "help", 4)) { - send_usage(fd); - } else { - log_printf(WARNING, "unknown command '%s'", cmd); - send_response(fd, "EEE: unknown command"); - } - return 0; - } - char* param = strchr(cmd, ' '); - if(param) - param++; - - if(cmd_id == SWITCH || cmd_id == CHANNEL || cmd_id == MODE) { - char* resp; - int len = asprintf(&resp, "Request: %s", cmd); - if(len > 0) { - char* linefeed = strchr(resp, '\n'); - if(linefeed) linefeed[0] = 0; - client_t* client; - int listener_cnt = 0; - for(client = client_lst; client; client = client->next) - if(client->request_listener && client->fd != fd) { - send_response(client->fd, resp); - listener_cnt++; - } - free(resp); - log_printf(DEBUG, "sent request to %d additional listeners", listener_cnt); - } -// else silently ignore memory alloc error - } - - switch(cmd_id) { - case SWITCH: - case STATUS: { - int ret = process_cmd_request(cmd, cmd_id, param, fd, cmd_q, client_lst, opt); - if(ret) - return ret; - break; - } - case CHANNEL: { - int ret = process_cmd_channel(cmd, param, fd, cmd_q, client_lst, opt); - if(ret) - return ret; - break; - } - case TYPE: process_cmd_type(param, fd, cmd_q, client_lst, opt); break; - case MODE: { - int ret = process_cmd_mode(param, fd, cmd_q, client_lst, opt); - if(ret) - return ret; - break; - } - case HEARTBEAT: { - int ret = process_cmd_heartbeat(param, fd, cmd_q, client_lst, opt); - if(ret) - return ret; - break; - } - case HEALTH: { - int ret = process_cmd_health(param, fd, client_lst); - if(ret) - return ret; - break; - } - case LOG: { - if(param && param[0]) - log_printf(NOTICE, "ext msg: %s", param); - else - log_printf(DEBUG, "ignoring empty ext log message"); - break; - } - case LISTEN: process_cmd_listen(param, fd, client_lst); break; - } - - return 0; -} - -int nonblock_recvline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst, options_t* opt) -{ - int ret = 0; - for(;;) { - ret = recv(fd, &buffer->buf[buffer->offset], 1, 0); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - else if(ret < 0) - break; - - if(buffer->buf[buffer->offset] == '\n') { - buffer->buf[buffer->offset] = 0; - ret = process_cmd((char *)(buffer->buf), fd, cmd_q, client_lst, opt); - buffer->offset = 0; - break; - } - - buffer->offset++; - if(buffer->offset >= sizeof(buffer->buf)) { - log_printf(DEBUG, "string too long (fd=%d)", fd); - buffer->offset = 0; - return 0; - } - } - - return ret; -} - -#define SEND_TO_LISTENER(STRING, LEN, FLAG) \ - if(!strncmp((char *)(buffer->buf), STRING, LEN)) { \ - client_t* client; \ - int listener_cnt = 0; \ - for(client = client_lst; client; client = client->next) \ - if(client->FLAG && client->fd != cmd_fd) { \ - send_response(client->fd, (char *)(buffer->buf)); \ - listener_cnt++; \ - } \ - log_printf(DEBUG, "sent message to %d additional listeners", listener_cnt); \ - } \ - -int process_switch(read_buffer_t* buffer, int switch_fd, cmd_t **cmd_q, client_t* client_lst) -{ - int ret = 0; - struct timeval tv; - fd_set fds; - FD_ZERO(&fds); - FD_SET(switch_fd, &fds); - - for(;;) { - tv.tv_sec = 0; - tv.tv_usec = 0; - ret = select(switch_fd+1, &fds, NULL, NULL, &tv); - if(!ret) - return 0; - else if(ret < 0) - return ret; - - ret = read(switch_fd, &buffer->buf[buffer->offset], 1); - if(!ret) - return 2; - if(ret == -1 && errno == EAGAIN) - return 0; - else if(ret < 0) - break; - - if(buffer->buf[buffer->offset] == '\n') { - buffer->buf[buffer->offset] = 0; - - if(buffer->offset > 0 && buffer->buf[buffer->offset-1] == '\r') - buffer->buf[buffer->offset-1] = 0; - - if(strlen((char *)(buffer->buf))) { - log_printf(NOTICE, "switch-firmware: '%s'", (char *)(buffer->buf)); - - int cmd_fd = -1; - if(cmd_q && (*cmd_q)) { - cmd_fd = (*cmd_q)->fd; - send_response(cmd_fd, (char *)(buffer->buf)); - } - - SEND_TO_LISTENER("S0L", 3, status_listener); - SEND_TO_LISTENER("S0P", 3, gpi_listener); - SEND_TO_LISTENER("S0O", 3, oc_listener); - SEND_TO_LISTENER("S0R", 3, relay_listener); - SEND_TO_LISTENER("S0S", 3, silence_listener); - - if((!strncmp((char *)(buffer->buf), "RRR", 3)) || - (!strncmp((char *)(buffer->buf), "EEE", 3))) - cmd_pop(cmd_q); - } - - buffer->offset = 0; - return 0; - } - - buffer->offset++; - if(buffer->offset >= sizeof(buffer->buf)) { - log_printf(DEBUG, "string too long (fd=%d)", switch_fd); - buffer->offset = 0; - return 0; - } - } - - return ret; -} - -int main_loop(int switch_fd, int cmd_listen_fd, options_t* opt) -{ - log_printf(NOTICE, "entering main loop"); - - fd_set readfds, tmpfds; - FD_ZERO(&readfds); - FD_SET(switch_fd, &readfds); - FD_SET(cmd_listen_fd, &readfds); - int max_fd = switch_fd > cmd_listen_fd ? switch_fd : cmd_listen_fd; - cmd_t* cmd_q = NULL; - client_t* client_lst = NULL; - - read_buffer_t switch_buffer; - switch_buffer.offset = 0; - - 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; - - int return_value = 0; - - char* channel = "unknown"; - if(state_.mode_ == MODE_MASTER && state_.channel_master_ == CHAN_MAIN) channel = "master_main"; - else if(state_.mode_ == MODE_MASTER && state_.channel_master_ == CHAN_MUSIC) channel = "master_music"; - else if(state_.mode_ == MODE_STANDBY && state_.channel_standby_ == CHAN_MAIN) channel = "standby_main"; - else if(state_.mode_ == MODE_STANDBY && state_.channel_standby_ == CHAN_MUSIC) channel = "standby_music"; - - char* cmd_param = strdup("*0M1*0ii1"); - char* ch_nr = key_value_storage_find(&opt->alias_table_, channel); - if(!ch_nr || ch_nr[0] == 0 || ch_nr[1] == 0 || ch_nr[2] != 0) { - log_printf(ERROR, "invalid channel name or number: %s", channel); - free(cmd_param); - return_value = -1; - } - else { - cmd_param[6] = ch_nr[0]; - cmd_param[7] = ch_nr[1]; - return_value = cmd_push(&cmd_q, -1, SWITCH, cmd_param); - free(cmd_param); - send_command(switch_fd, cmd_q); - } - - struct timeval timeout; - while(!return_value) { - memcpy(&tmpfds, &readfds, sizeof(tmpfds)); - - 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) - continue; - if(!ret) { - if(cmd_q && cmd_has_expired(*cmd_q)) { - log_printf(ERROR, "last command expired"); - cmd_pop(&cmd_q); - } - else - continue; - } - - if(FD_ISSET(sig_fd, &tmpfds)) { - if(signal_handle()) { - return_value = 1; - break; - } - } - - if(FD_ISSET(switch_fd, &tmpfds)) { - return_value = process_switch(&switch_buffer, switch_fd, &cmd_q, client_lst); - if(return_value) - break; - } - - if(FD_ISSET(cmd_listen_fd, &tmpfds)) { - int new_fd = accept(cmd_listen_fd, NULL, NULL); - if(new_fd < 0) { - log_printf(ERROR, "accept returned with error: %s", strerror(errno)); - return_value = -1; - break; - } - log_printf(DEBUG, "new command connection (fd=%d)", new_fd); - FD_SET(new_fd, &readfds); - max_fd = (max_fd < new_fd) ? new_fd : max_fd; - fcntl(new_fd, F_SETFL, O_NONBLOCK); - client_add(&client_lst, new_fd); - } - - client_t* lst = client_lst; - while(lst) { - if(FD_ISSET(lst->fd, &tmpfds)) { - return_value = nonblock_recvline(&(lst->buffer), lst->fd, &cmd_q, client_lst, opt); - if(return_value == 2) { - log_printf(DEBUG, "removing closed command connection (fd=%d)", lst->fd); - client_t* deletee = lst; - lst = lst->next; - FD_CLR(deletee->fd, &readfds); - client_remove(&client_lst, deletee->fd); - update_health_status(-1, &cmd_q, client_lst, opt); - return_value = 0; - continue; - } - if(return_value) - break; - - } - if(lst) - lst = lst->next; - } - - if(cmd_q && !cmd_q->sent) - send_command(switch_fd, cmd_q); - } - - cmd_clear(&cmd_q); - client_clear(&client_lst); - signal_stop(); - return return_value; -} - -int main(int argc, char* argv[]) -{ - log_init(); - - options_t opt; - int ret = options_parse(&opt, argc, argv); - if(ret) { - if(ret > 0) { - fprintf(stderr, "syntax error near: %s\n\n", argv[ret]); - } - if(ret == -2) { - fprintf(stderr, "memory error on options_parse, exiting\n"); - } - if(ret == -3) { - fprintf(stderr, "syntax error: mode name must be either master or standby\n"); - } - if(ret == -4) { - fprintf(stderr, "syntax error: channel name must be either main or music\n"); - } - if(ret == -5) { - fprintf(stderr, "syntax error: invalid baudrate\n"); - } - - if(ret != -2) - options_print_usage(); - - options_clear(&opt); - log_close(); - exit(ret); - } - string_list_element_t* tmp = opt.log_targets_.first_; - if(!tmp) { - log_add_target("syslog:3,switchctl,daemon"); - } - else { - while(tmp) { - ret = log_add_target(tmp->string_); - if(ret) { - switch(ret) { - case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break; - case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break; - case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; - default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; - } - - options_clear(&opt); - log_close(); - exit(ret); - } - tmp = tmp->next_; - } - } - log_printf(NOTICE, "just started..."); - if(options_parse_post(&opt)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - priv_info_t priv; - if(opt.username_) - if(priv_init(&priv, opt.username_, opt.groupname_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - FILE* pid_file = NULL; - if(opt.pid_file_) { - pid_file = fopen(opt.pid_file_, "w"); - if(!pid_file) { - log_printf(WARNING, "unable to open pid file: %s", strerror(errno)); - } - } - - if(opt.chroot_dir_) - if(do_chroot(opt.chroot_dir_)) { - options_clear(&opt); - log_close(); - exit(-1); - } - if(opt.username_) - if(priv_drop(&priv)) { - options_clear(&opt); - log_close(); - exit(-1); - } - - if(opt.daemonize_) { - pid_t oldpid = getpid(); - daemonize(); - log_printf(INFO, "running in background now (old pid: %d)", oldpid); - } - - if(pid_file) { - pid_t pid = getpid(); - fprintf(pid_file, "%d", pid); - fclose(pid_file); - } - - int cmd_listen_fd = init_command_socket(opt.command_sock_); - if(cmd_listen_fd < 0) { - options_clear(&opt); - log_close(); - exit(-1); - } - - state_.mode_ = opt.mode_; - state_.channel_master_ = opt.channel_master_; - state_.channel_standby_ = opt.channel_standby_; - state_.hb_state_master_ = FALSE; - state_.hb_state_standby_ = FALSE; - - int switch_fd = 0; - for(;;) { - switch_fd = open(opt.switch_dev_, O_RDWR | O_NOCTTY); - if(switch_fd < 0) { - log_printf(ERROR, "open(%s): %s", opt.switch_dev_, strerror(errno)); - ret = 2; - } else { - ret = setup_tty(switch_fd, opt.baudrate_); - if(ret) - ret = 2; - else - ret = main_loop(switch_fd, cmd_listen_fd, &opt); - } - - if(ret == 2) { - log_printf(ERROR, "%s error, trying to reopen in 5 seconds..", opt.switch_dev_); - if(switch_fd > 0) - close(switch_fd); - sleep(5); - } - else - break; - } - - close(cmd_listen_fd); - if(switch_fd > 0) - close(switch_fd); - - if(!ret) - log_printf(NOTICE, "normal shutdown"); - else if(ret < 0) - log_printf(NOTICE, "shutdown after error (code %d)", ret); - else - log_printf(NOTICE, "shutdown after signal"); - - options_clear(&opt); - log_close(); - - return ret; -} diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index 99a609b..0000000 --- a/src/utils.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "datatypes.h" - -#include <sys/un.h> -#include <termios.h> -#include <unistd.h> -#include <errno.h> - -#include "log.h" - -#include "utils.h" - -int init_command_socket(const char* path) -{ - int fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(fd < 0) { - log_printf(ERROR, "unable to open socket: %s", strerror(errno)); - return -1; - } - - struct sockaddr_un local; - local.sun_family = AF_UNIX; - if(sizeof(local.sun_path) <= strlen(path)) { - log_printf(ERROR, "socket path is to long (max %d)", sizeof(local.sun_path)-1); - return -1; - } - strcpy(local.sun_path, path); - unlink(local.sun_path); - int len = SUN_LEN(&local); - int ret = bind(fd, (struct sockaddr*)&local, len); - if(ret) { - log_printf(ERROR, "unable to bind to '%s': %s", local.sun_path, strerror(errno)); - return -1; - } - - ret = listen(fd, 4); - if(ret) { - log_printf(ERROR, "unable to listen on command socket: %s", local.sun_path, strerror(errno)); - return -1; - } - - log_printf(INFO, "now listening on %s for incoming commands", path); - - return fd; -} - -int connect_command_socket(const char* path) -{ - int fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(fd < 0) { - log_printf(ERROR, "unable to open socket: %s", strerror(errno)); - return -1; - } - - struct sockaddr_un remote; - remote.sun_family = AF_UNIX; - if(sizeof(remote.sun_path) <= strlen(path)) { - log_printf(ERROR, "socket path is to long (max %d)", sizeof(remote.sun_path)-1); - return -1; - } - strcpy(remote.sun_path, path); - int len = SUN_LEN(&remote); - int ret = connect(fd, (struct sockaddr*)&remote, len); - if(ret) { - log_printf(ERROR, "unable to connect to '%s': %s", remote.sun_path, strerror(errno)); - return -1; - } - - return fd; -} - -int send_string(int fd, const char* string) -{ - int len = strlen(string); - int offset = 0; - int ret; - for(;;) { - ret = write(fd, &string[offset], len - offset); - if(ret < 0) { - if(errno != EINTR) - return ret; - - ret = 0; - } - - offset += ret; - if(offset+1 >= len) - break; - } - return ret; -} - -int setup_tty(int fd, speed_t speed) -{ - struct termios tmio; - - int ret = tcgetattr(fd, &tmio); - if(ret) { - log_printf(ERROR, "Error on tcgetattr(): %s", strerror(errno)); - return ret; - } - - tmio.c_iflag &= ~(INLCR | ICRNL | IGNCR | IXON | IXOFF); - tmio.c_oflag &= ~(ONLCR | OCRNL | ONOCR | ONLRET); - tmio.c_cflag |= CS8 | CLOCAL | CREAD; - tmio.c_cflag &= ~(CSTOPB | PARENB); - tmio.c_lflag &= ~(ICANON | ECHO); - tmio.c_cc[VTIME] = 0; - tmio.c_cc[VMIN] = 1; - - ret = cfsetospeed(&tmio, speed); - if(ret) { - log_printf(ERROR, "Error on cfsetospeed(): %s", strerror(errno)); - return ret; - } - - ret = cfsetispeed(&tmio, speed); - if(ret) { - log_printf(ERROR, "Error on cfsetispeed(): %s", strerror(errno)); - return ret; - } - - ret = tcsetattr(fd, TCSANOW, &tmio); - if(ret) { - log_printf(ERROR, "Error on tcsetattr(): %s", strerror(errno)); - return ret; - } - - ret = tcflush(fd, TCIFLUSH); - if(ret) { - log_printf(ERROR, "Error on tcflush(): %s", strerror(errno)); - return ret; - } - - fd_set fds; - struct timeval tv; - FD_ZERO(&fds); - FD_SET(fd, &fds); - tv.tv_sec = 0; - tv.tv_usec = 50000; - for(;;) { - ret = select(fd+1, &fds, NULL, NULL, &tv); - if(ret > 0) { - char buffer[100]; - ret = read(fd, buffer, sizeof(buffer)); - } - else - break; - } - - return 0; -} diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index 5b86b90..0000000 --- a/src/utils.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * rhctl - * - * Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> - * - * This file is part of rhctl. - * - * rhctl 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. - * - * rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RHCTL_utils_h_INCLUDED -#define RHCTL_utils_h_INCLUDED - -#include "command_queue.h" -#include "client_list.h" -#include "options.h" -#include <termios.h> - -int init_command_socket(const char* path); -int connect_command_socket(const char* path); -int send_string(int fd, const char* string); -int setup_tty(int fd, speed_t speed); - -#endif diff --git a/src/utils.lua b/src/utils.lua deleted file mode 100644 index 0fb7377..0000000 --- a/src/utils.lua +++ /dev/null @@ -1,35 +0,0 @@ --- --- rhctl --- --- Copyright (C) 2009-2015 Christian Pointner <equinox@helsinki.at> --- --- This file is part of rhctl. --- --- rhctl 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. --- --- rhctl 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 rhctl. If not, see <http://www.gnu.org/licenses/>. --- - -local utils = {} - -function utils.send_mail(address, subject, bodytext) - local fp = assert(io.popen("/usr/bin/msmtp " .. address, "w")) - - fp:write("Subject: " .. subject .. "\n") - fp:write("To: " .. address .. "\n") - fp:write("\n") - fp:write(bodytext) - fp:write("\n") - fp:close() -end - -return utils |