FreeCalypso > hg > themwi-system-sw
diff sip-out/readconf.c @ 154:e54b0a9e322f
beginning of themwi-sip-out
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 11 Oct 2022 23:04:01 -0800 |
parents | sip-in/readconf.c@7e04d28fae8b |
children | 0bacca1f2f7b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-out/readconf.c Tue Oct 11 23:04:01 2022 -0800 @@ -0,0 +1,237 @@ +/* + * In this module we implement the reading of /var/gsm/themwi-sip-out.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; +unsigned cfg_retrans_timeout = 500; +unsigned cfg_retrans_count = 10; +unsigned max_forwards = 70; +unsigned sip_linger_timeout = 10; +unsigned sip_linger_invite_err = 10; +unsigned sip_linger_gotbye = 30; +unsigned sip_linger_bye_out_ok = 5; +unsigned sip_linger_bye_out_err = 180; +int block_1900_numbers = 1; + +static char config_file_pathname[] = "/var/gsm/themwi-sip-out.cfg"; + +struct parse_state { + int lineno; + int set_mask; +}; + +static void +require_one_arg(st, kw, arg) + struct parse_state *st; + char *kw, *arg; +{ + char *cp; + + if (*arg == '\0' || *arg == '#') { +inv_syntax: fprintf(stderr, + "%s line %d: %s setting requires one argument\n", + config_file_pathname, st->lineno, kw); + exit(1); + } + for (cp = arg; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv_syntax; +} + +static void +handle_ip(st, kw, arg, var) + struct parse_state *st; + char *kw, *arg; + struct in_addr *var; +{ + require_one_arg(st, kw, arg); + 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, arg, var) + struct parse_state *st; + char *kw, *arg; + unsigned *var; +{ + char *endp; + + require_one_arg(st, kw, arg); + *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, arg, var) + struct parse_state *st; + char *kw, *arg; + int *var; +{ + require_one_arg(st, kw, arg); + 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 +handle_retrans_conf(st, kw, arg) + struct parse_state *st; + char *kw, *arg; +{ + char *cp = arg; + + if (!isdigit(*cp)) { +inv: fprintf(stderr, + "%s line %d: %s setting requires two numeric arguments\n", + config_file_pathname, st->lineno, kw); + exit(1); + } + cfg_retrans_timeout = strtoul(cp, &cp, 10); + while (isspace(*cp)) + cp++; + if (!isdigit(*cp)) + goto inv; + cfg_retrans_count = strtoul(cp, &cp, 10); + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv; +} + +static void +process_line(st, line) + struct parse_state *st; + char *line; +{ + char *cp, *kw; + 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 (kw = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(kw, "bind-ip")) { + handler = handle_ip; + var = &sip_bind_ip; + set_id = 1; + } else if (!strcmp(kw, "bind-port")) { + handler = handle_num; + var = &sip_bind_port; + set_id = 2; + } else if (!strcmp(kw, "sip-udp-retrans")) { + handler = handle_retrans_conf; + var = (void *) 0; + set_id = 0; + } else if (!strcmp(kw, "sip-linger-timeout")) { + handler = handle_num; + var = &sip_linger_timeout; + set_id = 0; + } else if (!strcmp(kw, "sip-linger-invite-error")) { + handler = handle_num; + var = &sip_linger_invite_err; + set_id = 0; + } else if (!strcmp(kw, "sip-linger-got-bye")) { + handler = handle_num; + var = &sip_linger_gotbye; + set_id = 0; + } else if (!strcmp(kw, "sip-linger-bye-out-ok")) { + handler = handle_num; + var = &sip_linger_bye_out_ok; + set_id = 0; + } else if (!strcmp(kw, "sip-linger-bye-out-error")) { + handler = handle_num; + var = &sip_linger_bye_out_err; + set_id = 0; + } else if (!strcmp(kw, "max-forwards")) { + handler = &handle_num; + var = &max_forwards; + set_id = 0; + } else if (!strcmp(kw, "block-1900")) { + handler = handle_bool; + var = &block_1900_numbers; + set_id = 0; + } else { + fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n", + config_file_pathname, st->lineno, kw); + exit(1); + } + if (st->set_mask & set_id) { + fprintf(stderr, "%s line %d: duplicate %s setting\n", + config_file_pathname, st->lineno, kw); + exit(1); + } + while (isspace(*cp)) + cp++; + handler(st, kw, cp, var); + 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); + } +}