FreeCalypso > hg > themwi-system-sw
diff sip-in/readconf.c @ 47:62f39c7cee15
themwi-sip-in skeleton started
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 06 Sep 2022 20:33:56 -0800 |
parents | |
children | 709b78a4ebf0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-in/readconf.c Tue Sep 06 20:33:56 2022 -0800 @@ -0,0 +1,164 @@ +/* + * In this module we implement the reading of /var/gsm/themwi-sip-in.cfg: + * the main settings are bind-ip and bind-port, but we also have some + * optional config settings. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +struct in_addr sip_bind_ip; +unsigned sip_bind_port; +int cfg_use_100rel; + +static char config_file_pathname[] = "/var/gsm/themwi-sip-in.cfg"; + +struct parse_state { + int lineno; + int set_mask; +}; + +static void +handle_ip(st, kw, var, arg) + struct parse_state *st; + char *kw, *arg; + struct in_addr *var; +{ + var->s_addr = inet_addr(arg); + if (var->s_addr == INADDR_NONE) { + fprintf(stderr, + "%s line %d: invalid IP address argument \"%s\"\n", + config_file_pathname, st->lineno, arg); + exit(1); + } +} + +static void +handle_num(st, kw, var, arg) + struct parse_state *st; + char *kw, *arg; + unsigned *var; +{ + char *endp; + + *var = strtoul(arg, &endp, 10); + if (*endp) { + fprintf(stderr, "%s line %d: invalid numeric argument \"%s\"\n", + config_file_pathname, st->lineno, arg); + exit(1); + } +} + +static void +handle_bool(st, kw, var, arg) + struct parse_state *st; + char *kw, *arg; + int *var; +{ + if (!strcmp(arg, "true") || !strcmp(arg, "on") || !strcmp(arg, "yes") + || !strcmp(arg, "1")) { + *var = 1; + return; + } + if (!strcmp(arg, "false") || !strcmp(arg, "off") || !strcmp(arg, "no") + || !strcmp(arg, "0")) { + *var = 0; + return; + } + fprintf(stderr, "%s line %d: invalid boolean argument \"%s\"\n", + config_file_pathname, st->lineno, arg); + exit(1); +} + +static void +process_line(st, line) + struct parse_state *st; + char *line; +{ + char *cp, *np, *arg; + void (*handler)(), *var; + int set_id; + + if (!index(line, '\n')) { + fprintf(stderr, "%s line %d: too long or missing newline\n", + config_file_pathname, st->lineno); + exit(1); + } + for (cp = line; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + return; + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "bind-ip")) { + handler = handle_ip; + var = &sip_bind_ip; + set_id = 1; + } else if (!strcmp(np, "bind-port")) { + handler = handle_num; + var = &sip_bind_port; + set_id = 2; + } else if (!strcmp(np, "use-100rel")) { + handler = handle_bool; + var = &cfg_use_100rel; + set_id = 0; + } else { + fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n", + config_file_pathname, st->lineno, np); + exit(1); + } + if (st->set_mask & set_id) { + fprintf(stderr, "%s line %d: duplicate %s setting\n", + config_file_pathname, st->lineno, np); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { +inv_syntax: fprintf(stderr, + "%s line %d: %s setting requires one argument\n", + config_file_pathname, st->lineno, np); + exit(1); + } + for (arg = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv_syntax; + handler(st, np, var, arg); + st->set_mask |= set_id; +} + +read_config_file() +{ + FILE *inf; + struct parse_state pst; + char linebuf[256]; + + inf = fopen(config_file_pathname, "r"); + if (!inf) { + perror(config_file_pathname); + exit(1); + } + pst.set_mask = 0; + for (pst.lineno = 1; fgets(linebuf, sizeof linebuf, inf); pst.lineno++) + process_line(&pst, linebuf); + fclose(inf); + if (pst.set_mask != 3) { + fprintf(stderr, "error: %s did not set all required settings\n", + config_file_pathname); + exit(1); + } +}