diff --git a/moxanix.cfg b/moxanix.cfg index f6a0595..e2920d5 100644 --- a/moxanix.cfg +++ b/moxanix.cfg @@ -1,34 +1,17 @@ -; port config format: -; -; [tcp_port] -; dev = {tty dev path} -; speed = {port baud rate} +# Configuration format: +# tcp= tty= baud= +# +# Example: +# tcp=4001 tty=/dev/ttyS0 baud=115200 +# +# Supported baud rates: +# 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, +# 4800, 9600, 19200, 38400, 57600, 115200 +# -; supported baud rates: -; 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, -; 4800, 9600, 19200, 38400, 57600, 115200; - - -[4001] -dev = /dev/ttyS1 -speed = 115200 - -[4002] -dev = /dev/ttyS2 -speed = 115200 - -[4003] -dev = /dev/ttyS3 -speed = 115200 - -[4004] -dev = /dev/ttyS4 -speed = 115200 - -[4005] -dev = /dev/ttyS5 -speed = 115200 - -[4006] -dev = /dev/ttyS6 -speed = 115200 +tcp=4001 tty=/dev/ttyS1 baud=115200 +tcp=4002 tty=/dev/ttyS2 baud=115200 +tcp=4003 tty=/dev/ttyS3 baud=115200 +tcp=4004 tty=/dev/ttyS4 baud=115200 +tcp=4005 tty=/dev/ttyS5 baud=115200 +tcp=4006 tty=/dev/ttyS6 baud=115200 \ No newline at end of file diff --git a/moxanix.sh b/moxanix.sh index 0a78a74..03b72be 100755 --- a/moxanix.sh +++ b/moxanix.sh @@ -1,174 +1,234 @@ #!/bin/bash -# Main script for controlling servers. +# ===== +# setup +# ===== + +# parameters +CONFIGURATION_FILE="./moxanix.cfg" +SERVER_BINARY="./moxerver" +LOG_DIRECTORY="./logs" -# Call: usage -# Shows help. -usage () +# global variables for configuration +CONF_SIZE=0 +CONF_LINES=() +CONF_ARGS=() + + +# ================ +# helper functions +# ================ + +# do_usage +# Shows instructions. +do_usage () { - echo "Usage: ./$(basename $0) ..." - echo " " - echo " start - starts server identified by " - echo " stop - stops server identified by " - echo " status - displays status for server identified by " - echo " " - echo " number 1-7 for specific server, 0 for all servers" + echo "Usage:" + echo " $(basename $0) " + echo + echo " " + echo " config - displays current server configuration" + echo " start - starts server identified by " + echo " stop - stops server identified by " + echo " status - displays status for server identified by " + echo " log - prints the log for server identified by " + echo " " + echo " 0 for all servers or [1..MAX] for a specific server," + echo " where MAX is the number of configured servers" echo } -# Call: start ID -# Starts specific server with output redirected to a logfile. -start () +# do_read_config +# Reads current configuration from a file and populates global variables +do_read_config() { - # grab parameters - ID=$1 - - # set variables - TCP_PORT=$((4000 + $ID)) - - # check if requested server is already up - pid=$(ps axf | grep "[m]oxerver -p $TCP_PORT" | awk '{print $1}') - if [ "$pid" != "" ]; then - echo "server $ID is already up" - return 0 - fi - - SERVER_RUN="./moxerver" - - LOGDIR="./logs" - LOGFILE="$LOGDIR/moxerver$ID.log" + # read lines from the configuration file + readarray lines < $CONFIGURATION_FILE - # create log directory if it doesn't exist - if [ ! -d $LOGDIR ]; then - mkdir -p $LOGDIR - fi - - # start server, redirect stdout and stderr to logfile - # nohup keeps it running when the script ends - nohup $SERVER_RUN -p $TCP_PORT > $LOGFILE 2>&1 & - echo "server $ID started" + # count the number of configured connections and extract arguments + # - skip comment lines and empty lines + # - use current configuration size as array index + CONF_SIZE=0 + count=0 + while [ "${lines[count]}" != "" ] + do + line=${lines[count]} + # filter lines and arguments according to the configuration format: + # tcp= tty= baud= + line_valid=$(echo $line | grep -E "^tcp=") + if [ -n "$line_valid" ]; then + # configuration lines + CONF_LINES[$CONF_SIZE]=$(echo -n $line) + # extract configuration arguments + tcp=$(echo $line | awk '{print $1}' | tr -d "tcp=") + tty=$(echo $line | awk '{print $2}' | tr -d "tty=") + baud=$(echo $line | awk '{print $3}' | tr -d "baud=") + # compose configuration argument lines for passing to the servers + CONF_ARGS[$CONF_SIZE]="-p $tcp -t $tty -b $baud" + # increment configuration size (array index) + CONF_SIZE=$((CONF_SIZE + 1)) + fi + # increment line counter + count=$(( $count + 1 )) + done } -# Call: stop ID -# Stops specific server. -stop () +# run_config +# Shows current configuration based on the configuration file +run_config() { - # grab parameters - ID=$1 - - # set variables - TCP_PORT=$((4000 + $ID)) - - # check if requested server is already down - pid=$(ps axf | grep "[m]oxerver -p $TCP_PORT" | awk '{print $1}') - if [ "$pid" = "" ]; then - echo "server $ID is already down" - return 0 - fi - - # kill requested server - kill -s SIGTERM $pid - echo "server $ID stopped" + echo "Reading configuration from: $CONFIGURATION_FILE" + echo ""; echo "Configured servers:" + # IDs start from 1, array index starts from 0 + for id in $(seq 1 $CONF_SIZE); do + echo "|$id| ${CONF_LINES[((id - 1))]}" + done } -# Call: status ID -# Displays if specific server is running or not. -status () +# foo=$(do_print_server_pid $ID) +# Prints server PID based on ID, capture the output in a variable to use as a function (foo=$(bar)) +do_print_server_pid() { - # grab parameters ID=$1 - - # set variables - TCP_PORT=$((4000 + $ID)) - - # check if requested server is up or down - pid=$(ps axf | grep "[m]oxerver -p $TCP_PORT" | awk '{print $1}') - if [ "$pid" = "" ]; then - echo "server $ID is down" + # find server PID by searching for the "start command" in the list of open processes + START_COMMAND="$SERVER_BINARY ${CONF_ARGS[((ID - 1))]}" + echo $(pgrep -f "$START_COMMAND") +} + +# run_start $ID +# Starts a server based on ID, with output redirected to a logfile +run_start() +{ + ID=$1 + # use PID to check if a server is already running + pid=$(do_print_server_pid $ID) + if [ "$pid" == "" ]; then + # IDs start from 1, array index starts from 0 + START_COMMAND="$SERVER_BINARY ${CONF_ARGS[((ID - 1))]}" + # prepare log file + LOG_FILE="$LOG_DIRECTORY/server_$ID.log" + # create log directory if it doesn't exist + if [ ! -d $LOG_DIRECTORY ]; then + mkdir -p $LOG_DIRECTORY + fi + # start server, redirect stdout and stderr to the log file + # nohup keeps it running when the script ends + echo "Starting server $ID" + nohup $START_COMMAND > $LOG_FILE 2>&1 & else - echo "server $ID is up" + echo "Server $ID is already up" fi } -########## +# run_stop $ID +# Stops a running server based on ID +run_stop() +{ + ID=$1 + # use PID to send SIGTERM to the server process + pid=$(do_print_server_pid $ID) + if [ "$pid" == "" ]; then + echo "Server $ID is already down" + else + echo "Stopping server $ID" + kill -s SIGTERM $pid + fi +} -# check parameter count -if [ $# -lt 1 ]; then - usage - exit -fi +# run_status $ID +# Shows status of a server based on ID +run_status() +{ + ID=$1 + # use PID to check if a server is running + pid=$(do_print_server_pid $ID) + if [ "$pid" = "" ]; then + echo "Server $ID is down" + else + echo "Server $ID is up" + fi +} -# grab parameter - command +# run_log $ID +# Prints the log file for a server based on ID +run_log() +{ + ID=$1 + LOG_FILE="$LOG_DIRECTORY/server_$ID.log" + echo "Log of server $ID from \"$LOG_FILE\"" + echo "================" + cat $LOG_FILE + echo "================" +} + +# run_command $COMMAND $ID +# Runs a given command for a single or all servers, based on ID +run_command() +{ + COMMAND=run_$1 + ID=$2 + # ID 0 runs the command for all servers + if [ $ID -eq 0 ]; then + # IDs start from 1, array index starts from 0 + for idx in $(seq 1 $CONF_SIZE); do + $COMMAND $idx + done + # ID >= 1 runs the command for a single server + elif [ $ID -ge 1 ] && [ $ID -le $CONF_SIZE ] ; then + $COMMAND $ID + # error if ID is out of range + else + echo "ID out of range: $ID" + fi +} + +# ========== +# entrypoint +# ========== + +# read configuration +do_read_config + +# execute command COMMAND=$1 +ID=$2 -if [ "$COMMAND" = "start" ]; then +if [ "$COMMAND" == "start" ]; then if [ $# -ne 2 ]; then - usage + do_usage exit - fi - # grab parameter - id - ID=$2 - # if ID is 1-7 run command for specific server - if [ $ID -ge 1 ] && [ $ID -le 7 ]; then - start $ID - # if ID is 0 run command for all servers - elif [ $ID -eq 0 ]; then - for NUM in {1..7} - do - start $NUM - done - # wrong ID value else - usage - exit + run_command start $ID fi - -elif [ "$COMMAND" = "stop" ]; then +elif [ "$COMMAND" == "stop" ]; then if [ $# -ne 2 ]; then - usage + do_usage exit - fi - # grab parameter - id - ID=$2 - # if ID is 1-7 run command for specific server - if [ $ID -ge 1 ] && [ $ID -le 7 ]; then - stop $ID - # if ID is 0 run command for all servers - elif [ $ID -eq 0 ]; then - for NUM in {1..7} - do - stop $NUM - done - # wrong ID value else - usage - exit + run_command stop $ID fi - -elif [ "$COMMAND" = "status" ]; then +elif [ "$COMMAND" == "status" ]; then if [ $# -ne 2 ]; then - usage + do_usage exit - fi - # grab parameter - id - ID=$2 - # if ID is 1-7 run command for specific server - if [ $ID -ge 1 ] && [ $ID -le 7 ]; then - status $ID - # if ID is 0 run command for all servers - elif [ $ID -eq 0 ]; then - for NUM in {1..7} - do - status $NUM - done - # wrong ID value else - usage - exit + run_command status $ID + fi +elif [ "$COMMAND" == "log" ]; then + if [ $# -ne 2 ]; then + do_usage + exit + else + run_command log $ID + fi +elif [ "$COMMAND" == "config" ]; then + if [ $# -ne 1 ]; then + do_usage + exit + else + run_config fi - else - # unsupported command - usage + do_usage fi diff --git a/moxanix2.cfg b/moxanix2.cfg deleted file mode 100644 index e2920d5..0000000 --- a/moxanix2.cfg +++ /dev/null @@ -1,17 +0,0 @@ -# Configuration format: -# tcp= tty= baud= -# -# Example: -# tcp=4001 tty=/dev/ttyS0 baud=115200 -# -# Supported baud rates: -# 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, -# 4800, 9600, 19200, 38400, 57600, 115200 -# - -tcp=4001 tty=/dev/ttyS1 baud=115200 -tcp=4002 tty=/dev/ttyS2 baud=115200 -tcp=4003 tty=/dev/ttyS3 baud=115200 -tcp=4004 tty=/dev/ttyS4 baud=115200 -tcp=4005 tty=/dev/ttyS5 baud=115200 -tcp=4006 tty=/dev/ttyS6 baud=115200 \ No newline at end of file diff --git a/moxanix2.sh b/moxanix2.sh deleted file mode 100755 index 4c36418..0000000 --- a/moxanix2.sh +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/bash - -# ===== -# setup -# ===== - -# parameters -CONFIGURATION_FILE="./moxanix2.cfg" -SERVER_BINARY="./moxerver" -LOG_DIRECTORY="./logs" - - -# global variables for configuration -CONF_SIZE=0 -CONF_LINES=() -CONF_ARGS=() - - -# ================ -# helper functions -# ================ - -# do_usage -# Shows instructions. -do_usage () -{ - echo "Usage:" - echo " $(basename $0) " - echo - echo " " - echo " config - displays current server configuration" - echo " start - starts server identified by " - echo " stop - stops server identified by " - echo " status - displays status for server identified by " - echo " log - prints the log for server identified by " - echo " " - echo " 0 for all servers or [1..MAX] for a specific server," - echo " where MAX is the number of configured servers" - echo -} - -# do_read_config -# Reads current configuration from a file and populates global variables -do_read_config() -{ - # read lines from the configuration file - readarray lines < $CONFIGURATION_FILE - - # count the number of configured connections and extract arguments - # - skip comment lines and empty lines - # - use current configuration size as array index - CONF_SIZE=0 - count=0 - while [ "${lines[count]}" != "" ] - do - line=${lines[count]} - # filter lines and arguments according to the configuration format: - # tcp= tty= baud= - line_valid=$(echo $line | grep -E "^tcp=") - if [ -n "$line_valid" ]; then - # configuration lines - CONF_LINES[$CONF_SIZE]=$(echo -n $line) - # extract configuration arguments - tcp=$(echo $line | awk '{print $1}' | tr -d "tcp=") - tty=$(echo $line | awk '{print $2}' | tr -d "tty=") - baud=$(echo $line | awk '{print $3}' | tr -d "baud=") - # compose configuration argument lines for passing to the servers - CONF_ARGS[$CONF_SIZE]="-p $tcp -t $tty -b $baud" - # increment configuration size (array index) - CONF_SIZE=$((CONF_SIZE + 1)) - fi - # increment line counter - count=$(( $count + 1 )) - done -} - -# run_config -# Shows current configuration based on the configuration file -run_config() -{ - echo "Reading configuration from: $CONFIGURATION_FILE" - echo ""; echo "Configured servers:" - # IDs start from 1, array index starts from 0 - for id in $(seq 1 $CONF_SIZE); do - echo "|$id| ${CONF_LINES[((id - 1))]}" - done -} - -# foo=$(do_print_server_pid $ID) -# Prints server PID based on ID, capture the output in a variable to use as a function (foo=$(bar)) -do_print_server_pid() -{ - ID=$1 - # find server PID by searching for the "start command" in the list of open processes - START_COMMAND="$SERVER_BINARY ${CONF_ARGS[((ID - 1))]}" - echo $(pgrep -f "$START_COMMAND") -} - -# run_start $ID -# Starts a server based on ID, with output redirected to a logfile -run_start() -{ - ID=$1 - # use PID to check if a server is already running - pid=$(do_print_server_pid $ID) - if [ "$pid" == "" ]; then - # IDs start from 1, array index starts from 0 - START_COMMAND="$SERVER_BINARY ${CONF_ARGS[((ID - 1))]}" - # prepare log file - LOG_FILE="$LOG_DIRECTORY/server_$ID.log" - # create log directory if it doesn't exist - if [ ! -d $LOG_DIRECTORY ]; then - mkdir -p $LOG_DIRECTORY - fi - # start server, redirect stdout and stderr to the log file - # nohup keeps it running when the script ends - echo "Starting server $ID" - nohup $START_COMMAND > $LOG_FILE 2>&1 & - else - echo "Server $ID is already up" - fi -} - -# run_stop $ID -# Stops a running server based on ID -run_stop() -{ - ID=$1 - # use PID to send SIGTERM to the server process - pid=$(do_print_server_pid $ID) - if [ "$pid" == "" ]; then - echo "Server $ID is already down" - else - echo "Stopping server $ID" - kill -s SIGTERM $pid - fi -} - -# run_status $ID -# Shows status of a server based on ID -run_status() -{ - ID=$1 - # use PID to check if a server is running - pid=$(do_print_server_pid $ID) - if [ "$pid" = "" ]; then - echo "Server $ID is down" - else - echo "Server $ID is up" - fi -} - -# run_log $ID -# Prints the log file for a server based on ID -run_log() -{ - ID=$1 - LOG_FILE="$LOG_DIRECTORY/server_$ID.log" - echo "Log of server $ID from \"$LOG_FILE\"" - echo "================" - cat $LOG_FILE - echo "================" -} - -# run_command $COMMAND $ID -# Runs a given command for a single or all servers, based on ID -run_command() -{ - COMMAND=run_$1 - ID=$2 - # ID 0 runs the command for all servers - if [ $ID -eq 0 ]; then - # IDs start from 1, array index starts from 0 - for idx in $(seq 1 $CONF_SIZE); do - $COMMAND $idx - done - # ID >= 1 runs the command for a single server - elif [ $ID -ge 1 ] && [ $ID -le $CONF_SIZE ] ; then - $COMMAND $ID - # error if ID is out of range - else - echo "ID out of range: $ID" - fi -} - -# ========== -# entrypoint -# ========== - -# read configuration -do_read_config - -# execute command -COMMAND=$1 -ID=$2 - -if [ "$COMMAND" == "start" ]; then - if [ $# -ne 2 ]; then - do_usage - exit - else - run_command start $ID - fi -elif [ "$COMMAND" == "stop" ]; then - if [ $# -ne 2 ]; then - do_usage - exit - else - run_command stop $ID - fi -elif [ "$COMMAND" == "status" ]; then - if [ $# -ne 2 ]; then - do_usage - exit - else - run_command status $ID - fi -elif [ "$COMMAND" == "log" ]; then - if [ $# -ne 2 ]; then - do_usage - exit - else - run_command log $ID - fi -elif [ "$COMMAND" == "config" ]; then - if [ $# -ne 1 ]; then - do_usage - exit - else - run_config - fi -else - do_usage -fi diff --git a/moxerver.c b/moxerver.c index bb5d3c3..4dfafcf 100644 --- a/moxerver.c +++ b/moxerver.c @@ -6,11 +6,8 @@ #include #include -#include #include /* handling quit signals */ -#define CONFILE "moxanix.cfg" - /* ========================================================================== */ /* global resources */ @@ -25,8 +22,7 @@ tty_t tty_dev; /* connected tty device */ static void usage() { //TODO maybe some styling should be done - fprintf(stdout, "Usage: %s -p tcp_port [-t tty_path] [-d] [-h]\n", APPNAME); - fprintf(stdout, "\t-t\ttty dev path (if not specified %s needs to be defined)\n", CONFILE); + fprintf(stdout, "Usage: %s -p tcp_port -t tty_path -b baud_rate [-d] [-h]\n", APPNAME); fprintf(stdout, "\t-d\tturns on debug messages\n"); fprintf(stdout, "\n"); } @@ -60,31 +56,6 @@ void quit_handler(int signum) exit(0); } -/* Parse handler function, used to configure serial port */ -int parse_handler(void *user, const char *section, const char *name, const char *value) -{ - //printf("[%s] section = %s, name = %s, value = %s\n", __func__, section, name, value); - - if (!strcmp(name, "speed") && (unsigned int)atoi(section) == server.port) - { - LOG("setting %s speed for port %s", value, section); - - if (cfsetispeed(&(tty_dev.ttyset), baud_to_speed(atoi(value))) < 0 || - cfsetospeed(&(tty_dev.ttyset), baud_to_speed(atoi(value))) < 0) - { - LOG("error configuring tty device speed"); - return -1; - } - } - - if (!strcmp(name, "dev") && (unsigned int)atoi(section) == server.port) - { - strcpy(tty_dev.path, value); - } - - return 1; -} - void time2string(time_t time, char* timestamp) { strftime(timestamp, TIMESTAMP_LEN, TIMESTAMP_FORMAT, localtime(&time)); @@ -95,13 +66,13 @@ int main(int argc, char *argv[]) { int ret; unsigned int tcp_port = -1; - int def_conf = 0; // is default config used or from .cfg file pthread_t tty_thread; - /* zero init tty_dev */ - if (cfsetispeed(&(tty_dev.ttyset), B0) < 0 || - cfsetospeed(&(tty_dev.ttyset), B0) < 0) { + /* initialize tty_dev */ + if (cfsetispeed(&(tty_dev.ttyset), B0) < 0 || + cfsetospeed(&(tty_dev.ttyset), B0) < 0) + { LOG("error configuring tty device speed"); return -1; } @@ -112,30 +83,54 @@ int main(int argc, char *argv[]) signal(SIGINT, quit_handler); /* check argument count */ - if (argc <= 1) { + if (argc <= 1) + { usage(); return -1; } /* grab arguments */ debug_messages = 0; - while ((ret = getopt(argc, argv, ":p:t:dh")) != -1) { - switch (ret) { + while ((ret = getopt(argc, argv, ":p:t:b:dh")) != -1) + { + size_t path_len; + speed_t baudrate; + switch (ret) + { /* get server port number */ case 'p': tcp_port = (unsigned int) atoi(optarg); - break; - /* get tty device path, default config used */ - case 't': - if ((strnlen(optarg, TTY_DEV_PATH_LEN) == 0) || - (strnlen(optarg, TTY_DEV_PATH_LEN) > (TTY_DEV_PATH_LEN - 1))) { - LOG("error: tty path was not specified\n"); + if (tcp_port < 0) + { + LOG("error, invalid TCP port value\n"); usage(); return -1; - } else { - /* set tty device path in tty_dev struct */ + } + break; + /* get tty device path */ + case 't': + path_len = strnlen(optarg, TTY_DEV_PATH_LEN); + /* check correct path size */ + if ((path_len == 0) || (path_len > (TTY_DEV_PATH_LEN - 1))) + { + LOG("error with tty path length: should be <%d\n", TTY_DEV_PATH_LEN); + usage(); + return -1; + } + /* otherwise, set tty device path in tty_dev struct */ + else + { strcpy(tty_dev.path, optarg); } - def_conf = 1; + break; + /* get tty device baud rate */ + case 'b': + baudrate = baud_to_speed(atoi(optarg)); + if (cfsetispeed(&(tty_dev.ttyset), baudrate) < 0 || + cfsetospeed(&(tty_dev.ttyset), baudrate) < 0) + { + LOG("error configuring tty device baud rate, check configuration"); + return -1; + } break; /* enable debug messages */ case 'd': @@ -152,38 +147,25 @@ int main(int argc, char *argv[]) } } - /* initialize */ - if (server_setup(&server, tcp_port) < 0) return -1; + /* start server */ client.socket = -1; new_client.socket = -1; - tty_dev.fd = -1; - - /* parse config file if any */ - if (!def_conf && ((ret = ini_parse(CONFILE, &parse_handler, NULL)) == -1)) { - LOG("error opening config file %s", CONFILE); - usage(); - return -1; - } - else if (!def_conf && ret) { - LOG("error parsing config file %s on line %d", CONFILE, ret); - return -1; - } - - if (!strcmp(tty_dev.path, "")) { - LOG("error: no tty device path given for TCP port: %d\n" - "\t\t-> check config file %s", tcp_port, CONFILE); + if (server_setup(&server, tcp_port) < 0) + { return -1; } /* open tty device */ - if (tty_open(&tty_dev) < 0) { + tty_dev.fd = -1; + if (tty_open(&tty_dev) < 0) + { LOG("error: opening of tty device at %s failed\n" "\t\t-> continuing in echo mode", tty_dev.path); debug_messages = 1; } - LOG("TCP port: %d, TTY device path: %s", tcp_port, tty_dev.path); - + LOG("Running with TCP port: %d, TTY device path: %s", tcp_port, tty_dev.path); + /* start thread function that handles tty device */ resources_t r = {&server, &client, &new_client, &tty_dev}; ret = pthread_create(&tty_thread, NULL, thread_tty_data, &r); diff --git a/parser.c b/parser.c deleted file mode 100644 index 6db49ae..0000000 --- a/parser.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * simple .INI file parser - */ - -#include -#include -#include - -#include "parser.h" - -#define MAX_SECTION 50 -#define MAX_NAME 50 - -/* Strip whitespace chars off end of given string, in place. Return s. */ -static char* rstrip(char* s) -{ - char* p = s + strlen(s); - while (p > s && isspace((unsigned char)(*--p))) - *p = '\0'; - return s; -} - -/* Return pointer to first non-whitespace char in given string. */ -static char* lskip(const char* s) -{ - while (*s && isspace((unsigned char)(*s))) - s++; - return (char*)s; -} - -/* Return pointer to first char c or ';' comment in given string, or pointer to - null at end of string if neither found. ';' must be prefixed by a whitespace - character to register as a comment. */ -static char* find_char_or_comment(const char* s, char c) -{ - int was_whitespace = 0; - while (*s && *s != c && !(was_whitespace && *s == ';')) { - was_whitespace = isspace((unsigned char)(*s)); - s++; - } - return (char*)s; -} - -/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ -static char* strncpy0(char* dest, const char* src, size_t size) -{ - strncpy(dest, src, size); - dest[size - 1] = '\0'; - return dest; -} - -/* See documentation in header file. */ -int ini_parse_file(FILE* file, - int (*handler)(void*, const char*, const char*, - const char*), - void* user) -{ - /* Uses a fair bit of stack (use heap instead if you need to) */ - char line[INI_MAX_LINE]; - char section[MAX_SECTION] = ""; - char prev_name[MAX_NAME] = ""; - - char* start; - char* end; - char* name; - char* value; - int lineno = 0; - int error = 0; - - /* Scan through file line by line */ - while (fgets(line, INI_MAX_LINE, file) != NULL) { - lineno++; - - start = line; -#if INI_ALLOW_BOM - if (lineno == 1 && (unsigned char)start[0] == 0xEF && - (unsigned char)start[1] == 0xBB && - (unsigned char)start[2] == 0xBF) { - start += 3; - } -#endif - start = lskip(rstrip(start)); - - if (*start == ';' || *start == '#') { - /* Per Python ConfigParser, allow '#' comments at start of line */ - } - else if (*start == '[') { - /* A "[section]" line */ - end = find_char_or_comment(start + 1, ']'); - if (*end == ']') { - *end = '\0'; - strncpy0(section, start + 1, sizeof(section)); - *prev_name = '\0'; - } - else if (!error) { - /* No ']' found on section line */ - error = lineno; - } - } - else if (*start && *start != ';') { - /* Not a comment, must be a name[=:]value pair */ - end = find_char_or_comment(start, '='); - if (*end != '=') { - end = find_char_or_comment(start, ':'); - } - if (*end == '=' || *end == ':') { - *end = '\0'; - name = rstrip(start); - value = lskip(end + 1); - end = find_char_or_comment(value, '\0'); - if (*end == ';') - *end = '\0'; - rstrip(value); - - /* Valid name[=:]value pair found, call handler */ - strncpy0(prev_name, name, sizeof(prev_name)); - if (!handler(user, section, name, value) && !error) - error = lineno; - } - else if (!error) { - /* No '=' or ':' found on name[=:]value line */ - error = lineno; - } - } - - if (error) - break; - } - - return error; -} - -/* See documentation in header file. */ -int ini_parse(const char* filename, - int (*handler)(void*, const char*, const char*, const char*), - void* user) -{ - FILE* file; - int error; - - file = fopen(filename, "r"); - if (!file) - return -1; - error = ini_parse_file(file, handler, user); - fclose(file); - return error; -} diff --git a/parser.h b/parser.h deleted file mode 100644 index d817192..0000000 --- a/parser.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * .INI file parser - */ - -#include - -/* Parse given INI-style file. May have [section]s, name=value pairs - (whitespace stripped), and comments starting with ';' (semicolon). Section - is "" if name=value pair parsed before any section heading. name:value - pairs are also supported as a concession to Python's ConfigParser. - - For each name=value pair parsed, call handler function with given user - pointer as well as section, name, and value (data only valid for duration - of handler call). Handler should return nonzero on success, zero on error. - - Returns 0 on success, line number of first error on parse error (doesn't - stop on first error), -1 on file open erro. -*/ -int ini_parse(const char* filename, - int (*handler)(void* user, const char* section, - const char* name, const char* value), - void* user); - -/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't - close the file when it's finished -- the caller must do that. */ -int ini_parse_file(FILE* file, - int (*handler)(void* user, const char* section, - const char* name, const char* value), - void* user); - -/* Maximum line length for any line in INI file. */ -#ifndef INI_MAX_LINE -#define INI_MAX_LINE 200 -#endif diff --git a/tty.h b/tty.h index 8651618..4ed5253 100644 --- a/tty.h +++ b/tty.h @@ -3,7 +3,6 @@ #pragma once #include -#include #include #define TTY_DEV_PATH_LEN 128