/* * rhctl * * Copyright (C) 2009 Christian Pointner * * 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 . */ #include "datatypes.h" #include "options.h" #include #include #include #include #include #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;ilength_;++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_) #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_ = CHAN_MAIN; else if(!strcmp(channel, "music")) opt->channel_ = 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 /* 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_ = 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; } 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_); } 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] change to this user\n"); printf(" [-g|--groupname] change to this group\n"); printf(" [-C|--chroot] chroot to this directory\n"); printf(" [-P|--write-pid] write pid to this file\n"); #endif printf(" [-L|--log] :[,[,..]]\n"); printf(" add a log target, can be invoked several times\n"); printf(" [-s|--command-sock] the command socket e.g. /var/run/rhctl/switchctl.sock\n"); #ifndef OPT_STDIOCLIENT printf(" [-b|--baudrate] the baudrate of the tty to use e.g. 19200\n"); #endif #ifdef OPT_SWITCHCTL printf(" [-d|--device] the tty the audio switch is connected to e.g. /dev/audioswitch\n"); printf(" [-f|--config] the configuration file e.g. /etc/rhctl/switchctl.conf\n"); printf(" [-m|--mode] the initial mode to use e.g. master\n"); printf(" [-c|--channel] the initial channel to use e.g. main\n"); #endif #ifdef OPT_SERIALCLIENT printf(" [-d|--device] the tty to connect to e.g. /dev/ttyUSB0\n"); printf(" [-t|--type] use this client type\n"); #endif #ifdef OPT_HEARTBEATCLIENT printf(" [-d|--device] the tty to connect to e.g. /dev/ttyUSB0\n"); printf(" [-t|--timeout] heartbeat timeout in tenths of a second e.g. 15 -> 1.5s\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: '%s'\n", opt->channel_ == 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_); #endif }