summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2009-11-17 16:46:17 (GMT)
committerChristian Pointner <equinox@helsinki.at>2009-11-17 16:46:17 (GMT)
commite4a30ac897423a0acebeb2aea205855f04e4e627 (patch)
tree96f6ea1718c5c723e8130332ea778f905a07112b
parenta56061ac8f3e5b79823e6b7b99198967407adf6b (diff)
added stdioclient
-rw-r--r--Makefile15
-rw-r--r--options.c18
-rw-r--r--stdioclient.c189
3 files changed, 220 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index cee4877..174f06d 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ endif
EXE_SWITCHCTL := switchctl
EXE_SERIALCLIENT := serialclient
+EXE_STDIOCLIENT := stdioclient
COMMONOBJ := log.o \
sig_handler.o \
@@ -40,12 +41,15 @@ SWITCHCTLOBJ := command_queue.o \
SERIALCLIENTOBJ := opt-serialclient.o \
serialclient.o
+STDIOCLIENTOBJ := opt-stdioclient.o \
+ stdioclient.o
-SRC := $(COMMONOBJ:%.o=%.c) $(SWITCHCTLOBJ:%.o=%.c) $(SERIALCLIENTOBJ:%.o=%.c) options.c
+
+SRC := $(COMMONOBJ:%.o=%.c) $(SWITCHCTLOBJ:%.o=%.c) $(SERIALCLIENTOBJ:%.o=%.c) $(STDIOCLIENTOBJ:%.o=%.c) options.c
.PHONY: clean distclean
-all: $(EXE_SWITCHCTL) $(EXE_SERIALCLIENT)
+all: $(EXE_SWITCHCTL) $(EXE_SERIALCLIENT) $(EXE_STDIOCLIENT)
%.d: %.c
@set -e; rm -f $@; \
@@ -63,12 +67,18 @@ $(EXE_SWITCHCTL): $(COMMONOBJ) $(SWITCHCTLOBJ)
$(EXE_SERIALCLIENT): $(COMMONOBJ) $(SERIALCLIENTOBJ)
$(CC) $(COMMONOBJ) $(SERIALCLIENTOBJ) -o $@ $(LDFLAGS)
+$(EXE_STDIOCLIENT): $(COMMONOBJ) $(STDIOCLIENTOBJ)
+ $(CC) $(COMMONOBJ) $(STDIOCLIENTOBJ) -o $@ $(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 $<
+
%.o: %.c
$(CC) $(CFLAGS) -c $<
@@ -84,3 +94,4 @@ clean:
rm -f *.d.*
rm -f $(EXE_SWITCHCTL)
rm -f $(EXE_SERIALCLIENT)
+ rm -f $(EXE_STDIOCLIENT)
diff --git a/options.c b/options.c
index 47ef618..358766e 100644
--- a/options.c
+++ b/options.c
@@ -170,14 +170,18 @@ int options_parse(options_t* opt, int argc, char* argv[])
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_)
@@ -283,6 +287,9 @@ void options_default(options_t* opt)
#ifdef OPT_SERIALCLIENT
opt->progname_ = strdup("serialclient");
#endif
+#ifdef OPT_STDIOCLIENT
+ opt->progname_ = strdup("stdioclient");
+#endif
/* common */
opt->daemonize_ = 1;
@@ -351,16 +358,23 @@ void options_print_usage()
#ifdef OPT_SERIALCLIENT
printf("serialclient\n");
#endif
+#ifdef OPT_STDIOCLIENT
+ printf("serialclient\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");
@@ -379,16 +393,19 @@ void options_print(options_t* 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;
@@ -402,6 +419,7 @@ void options_print(options_t* opt)
default: br = "invalid"; break;
}
printf("baudrate: '%s'\n", br);
+#endif
#ifdef OPT_SWITCHCTL
printf("mode: '%s'\n", opt->mode_ == MODE_MASTER ? "master" : "standby");
diff --git a/stdioclient.c b/stdioclient.c
new file mode 100644
index 0000000..62ab9c6
--- /dev/null
+++ b/stdioclient.c
@@ -0,0 +1,189 @@
+/*
+ * rhctl
+ *
+ * Copyright (C) 2009 Christian Pointner <equinox@spreadspace.org>
+ *
+ * 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)
+{
+}
+
+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");
+ else
+ log_printf(NOTICE, "shutdown after signal");
+
+ options_clear(&opt);
+ log_close();
+
+ return ret;
+}