Start using the new control script

This commit is contained in:
Igor Socec 2016-12-22 17:20:00 +01:00
parent 8c35a6c1a7
commit 1c20be41e3
8 changed files with 260 additions and 668 deletions

View file

@ -1,34 +1,17 @@
; port config format:
;
; [tcp_port]
; dev = {tty dev path}
; speed = {port baud rate}
# Configuration format:
# tcp=<tcp_port> tty=<tty_device> baud=<tty_baudrate>
#
# 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

View file

@ -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) <command> <id>..."
echo " <command>"
echo " start - starts server identified by <id>"
echo " stop - stops server identified by <id>"
echo " status - displays status for server identified by <id>"
echo " <id>"
echo " number 1-7 for specific server, 0 for all servers"
echo "Usage:"
echo " $(basename $0) <command> <id>"
echo
echo " <command>"
echo " config - displays current server configuration"
echo " start <id> - starts server identified by <id>"
echo " stop <id> - stops server identified by <id>"
echo " status <id> - displays status for server identified by <id>"
echo " log <id> - prints the log for server identified by <id>"
echo " <id>"
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=<tcp_port> tty=<tty_device> baud=<tty_baudrate>
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

View file

@ -1,17 +0,0 @@
# Configuration format:
# tcp=<tcp_port> tty=<tty_device> baud=<tty_baudrate>
#
# 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

View file

@ -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) <command> <id>"
echo
echo " <command>"
echo " config - displays current server configuration"
echo " start <id> - starts server identified by <id>"
echo " stop <id> - stops server identified by <id>"
echo " status <id> - displays status for server identified by <id>"
echo " log <id> - prints the log for server identified by <id>"
echo " <id>"
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=<tcp_port> tty=<tty_device> baud=<tty_baudrate>
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

View file

@ -6,11 +6,8 @@
#include <common.h>
#include <task_threads.h>
#include <parser.h>
#include <signal.h> /* 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);

147
parser.c
View file

@ -1,147 +0,0 @@
/*
* simple .INI file parser
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#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;
}

View file

@ -1,34 +0,0 @@
/*
* .INI file parser
*/
#include <stdio.h>
/* 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

1
tty.h
View file

@ -3,7 +3,6 @@
#pragma once
#include <common.h>
#include <client.h>
#include <termios.h>
#define TTY_DEV_PATH_LEN 128