# HG changeset patch # User Mychaela Falconia # Date 1665119999 28800 # Node ID 5c7109183c8c0da159dfa1113c2b818fb1dcfd9f # Parent 44dc809ffec0db7481d0309ca6c3a19e26efa37d shorten new program name to themwi-update-outrt diff -r 44dc809ffec0 -r 5c7109183c8c .hgignore --- a/.hgignore Thu Oct 06 20:56:14 2022 -0800 +++ b/.hgignore Thu Oct 06 21:19:59 2022 -0800 @@ -19,4 +19,4 @@ ^utils/themwi-dump-numdb$ ^utils/themwi-short-dial$ ^utils/themwi-update-numdb$ -^utils/themwi-update-out-routes$ +^utils/themwi-update-outrt$ diff -r 44dc809ffec0 -r 5c7109183c8c utils/Makefile --- a/utils/Makefile Thu Oct 06 20:56:14 2022 -0800 +++ b/utils/Makefile Thu Oct 06 21:19:59 2022 -0800 @@ -2,7 +2,7 @@ CFLAGS= -O2 PROGS= sip-out-test sip-rx-test sip-udp-dump themwi-check-own \ themwi-dump-numdb themwi-short-dial themwi-update-numdb \ - themwi-update-out-routes + themwi-update-outrt LIBNUMDB=../libnumdb/libnumdb.a LIBSIP= ../libsip/libsip.a LIBUTIL=../libutil/libutil.a @@ -31,7 +31,7 @@ themwi-update-numdb: themwi-update-numdb.o ${LIBUTIL} ${CC} ${CFLAGS} -o $@ $@.o ${LIBUTIL} -themwi-update-out-routes: themwi-update-out-routes.o ${LIBUTIL} +themwi-update-outrt: themwi-update-outrt.o ${LIBUTIL} ${CC} ${CFLAGS} -o $@ $@.o ${LIBUTIL} install: diff -r 44dc809ffec0 -r 5c7109183c8c utils/themwi-update-out-routes.c --- a/utils/themwi-update-out-routes.c Thu Oct 06 20:56:14 2022 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,473 +0,0 @@ -/* - * This program reads (parses) ThemWi config file /var/gsm/out-routes, - * generates the compiled binary form of this database, and then makes - * it live via atomic rename. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../include/out_routes.h" - -#define MAX_DEST_ENTRIES 16 -#define MAX_INN_ENTRIES 64 -#define MAX_SPC_NUM_ENTRIES 64 - -static struct sip_out_dest dest_records[MAX_DEST_ENTRIES]; -static char *dest_names[MAX_DEST_ENTRIES]; -static struct inn_route inn_records[MAX_INN_ENTRIES]; -static struct special_num_route special_num_records[MAX_SPC_NUM_ENTRIES]; -static unsigned dest_rec_count, inn_rec_count, special_num_count; - -static char *system_dir; -static FILE *inf; -static int lineno; -static char linebuf[256]; - -static int -find_dest_by_name(sought_name) - char *sought_name; -{ - unsigned n; - - for (n = 0; n < dest_rec_count; n++) - if (!strcmp(dest_names[n], sought_name)) - return n; - return -1; -} - -static int -find_dest_by_number(target_num) - char *target_num; -{ - unsigned inn_index; - struct inn_route *rec; - char *pp, *tp; - - for (inn_index = 0; inn_index < inn_rec_count; inn_index++) { - rec = inn_records + inn_index; - pp = rec->prefix; - tp = target_num; - while (*pp && *pp == *tp) { - pp++; - tp++; - } - if (*pp) - continue; - return rec->sip_dest_id; - } - return -1; -} - -static void -handle_dest_line(cp) - char *cp; -{ - char *name, *name_copy, *domain, *ip_str, *port_str; - struct sip_out_dest *rec; - unsigned portnum; - int rc; - - for (name = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') { -inv_syntax: fprintf(stderr, "out-routes line %d: invalid syntax for dest\n", - lineno); - exit(1); - } - for (domain = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') - goto inv_syntax; - for (ip_str = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') - port_str = 0; - else { - for (port_str = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp != '\0' && *cp != '#') - goto inv_syntax; - } - rc = find_dest_by_name(name); - if (rc >= 0) { - fprintf(stderr, - "out-routes line %d: duplicate destination name \"%s\"\n", - lineno, name); - exit(1); - } - if (dest_rec_count >= MAX_DEST_ENTRIES) { - fprintf(stderr, - "out-routes line %d: MAX_DEST_ENTRIES exceeded\n", - lineno); - exit(1); - } - name_copy = strdup(name); - if (!name_copy) { - perror("strdup"); - exit(1); - } - dest_names[dest_rec_count] = name_copy; - rec = dest_records + dest_rec_count; - if (strlen(domain) > MAX_SIP_DEST_DOMAIN) { - fprintf(stderr, - "out-routes line %d: dest domain string is too long\n", - lineno); - exit(1); - } - strcpy(rec->domain, domain); - rec->sin.sin_family = AF_INET; - rec->sin.sin_addr.s_addr = inet_addr(ip_str); - if (rec->sin.sin_addr.s_addr == INADDR_NONE) { - fprintf(stderr, - "out-routes line %d: dest IP address is invalid\n", - lineno); - exit(1); - } - if (port_str) { - portnum = strtoul(port_str, &cp, 10); - if (*cp) - goto inv_syntax; - } else - portnum = 5060; - rec->sin.sin_port = htons(portnum); - dest_rec_count++; -} - -static void -handle_inn_route(cp) - char *cp; -{ - char *prefix, *dest_name; - struct inn_route *rec; - int rc, dest_id; - - for (prefix = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') { -inv_syntax: fprintf(stderr, - "out-routes line %d: invalid syntax for inn-route\n", - lineno); - exit(1); - } - for (dest_name = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp != '\0' && *cp != '#') - goto inv_syntax; - rc = grok_number_string(prefix, 1); - if (rc < 1) - goto inv_syntax; - if (rc > MAX_INN_PREFIX) { - fprintf(stderr, - "out-routes line %d: inn-route prefix is too long\n", - lineno); - exit(1); - } - dest_id = find_dest_by_name(dest_name); - if (dest_id < 0) { - fprintf(stderr, - "out-routes line %d: SIP destination \"%s\" not defined\n", - lineno, dest_name); - exit(1); - } - if (inn_rec_count >= MAX_INN_ENTRIES) { - fprintf(stderr, - "out-routes line %d: MAX_INN_ENTRIES exceeded\n", - lineno); - exit(1); - } - rec = inn_records + inn_rec_count; - dehyphen_number_string(prefix, rec->prefix); - rec->sip_dest_id = dest_id; - inn_rec_count++; -} - -static void -preen_special_num_code(num_code) - char *num_code; -{ - char *cp; - int c; - unsigned n; - - n = 0; - for (cp = num_code; *cp; ) { - c = *cp++; - if (is_valid_ext_digit(c)) - n++; - else { - fprintf(stderr, - "out-routes line %d: special-num string \"%s\" is invalid\n", - lineno, num_code); - exit(1); - } - } - if (n > MAX_SPECIAL_NUM) { - fprintf(stderr, - "out-routes line %d: special-num string \"%s\" is too long\n", - lineno, num_code); - exit(1); - } -} - -static void -handle_special_num_map_to(num_code, cp) - char *num_code, *cp; -{ - struct special_num_route *rec; - char *tgt_num_src; - int rc, dest_id; - - while (isspace(*cp)) - cp++; - if (*cp++ != '+') { -inv_syntax: fprintf(stderr, - "out-routes line %d: invalid syntax for special-num map-to\n", - lineno); - exit(1); - } - if (!isdigit(*cp)) - goto inv_syntax; - for (tgt_num_src = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp != '\0' && *cp != '#') - goto inv_syntax; - rc = grok_number_string(tgt_num_src, 1); - if (rc < 1) - goto inv_syntax; - if (rc > MAX_E164_NUMBER) { - fprintf(stderr, - "out-routes line %d: map-to number is too long for E.164\n", - lineno); - exit(1); - } - rec = special_num_records + special_num_count; - strcpy(rec->special_num, num_code); - rec->sip_user[0] = '+'; - dehyphen_number_string(tgt_num_src, rec->sip_user+1); - dest_id = find_dest_by_number(rec->sip_user+1); - if (dest_id < 0) { - fprintf(stderr, - "out-routes line %d: no inn-route for map-to number\n", - lineno); - exit(1); - } - rec->sip_dest_id = dest_id; - special_num_count++; -} - -static void -handle_special_num_route_to(num_code, cp) - char *num_code, *cp; -{ - struct special_num_route *rec; - char *dest_name; - int dest_id; - - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') { -inv_syntax: fprintf(stderr, - "out-routes line %d: invalid syntax for special-num route-to\n", - lineno); - exit(1); - } - for (dest_name = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - if (*cp != '\0' && *cp != '#') - goto inv_syntax; - dest_id = find_dest_by_name(dest_name); - if (dest_id < 0) { - fprintf(stderr, - "out-routes line %d: SIP destination \"%s\" not defined\n", - lineno, dest_name); - exit(1); - } - rec = special_num_records + special_num_count; - strcpy(rec->special_num, num_code); - strcpy(rec->sip_user, num_code); - rec->sip_dest_id = dest_id; - special_num_count++; -} - -static void -handle_special_num(cp) - char *cp; -{ - char *num_code, *handling_kw; - - for (num_code = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - preen_special_num_code(num_code); - if (special_num_count >= MAX_SPC_NUM_ENTRIES) { - fprintf(stderr, - "out-routes line %d: MAX_SPC_NUM_ENTRIES exceeded\n", - lineno); - exit(1); - } - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') { -inv_syntax: fprintf(stderr, - "out-routes line %d: invalid syntax for special-num\n", - lineno); - exit(1); - } - for (handling_kw = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - if (!strcmp(handling_kw, "map-to")) - handle_special_num_map_to(num_code, cp); - else if (!strcmp(handling_kw, "route-to")) - handle_special_num_route_to(num_code, cp); - else - goto inv_syntax; -} - -static void -process_line() -{ - char *cp, *np; - void (*handler)(); - - if (!index(linebuf, '\n')) { - fprintf(stderr, - "out-routes line %d: too long or missing newline\n", - lineno); - exit(1); - } - for (cp = linebuf; isspace(*cp); cp++) - ; - if (*cp == '\0' || *cp == '#') - return; - for (np = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - if (!strcmp(np, "dest")) - handler = handle_dest_line; - else if (!strcmp(np, "inn-route")) - handler = handle_inn_route; - else if (!strcmp(np, "special-num")) - handler = handle_special_num; - else { - fprintf(stderr, - "out-routes line %d: non-understood keyword \"%s\"\n", - lineno, np); - exit(1); - } - while (isspace(*cp)) - cp++; - if (*cp == '\0' || *cp == '#') { - fprintf(stderr, - "out-routes line %d: missing argument after \"%s\" keyword\n", - lineno, np); - exit(1); - } - handler(cp); -} - -static void -emit_output() -{ - FILE *outf; - struct out_routes_header hdr; - - outf = fopen("out-routes.newbin", "w"); - if (!outf) { - perror("creating out-routes.newbin"); - exit(1); - } - hdr.num_dest = dest_rec_count; - hdr.num_inn = inn_rec_count; - hdr.num_special = special_num_count; - if (fwrite(&hdr, sizeof hdr, 1, outf) != 1) { -write_err: fprintf(stderr, "error writing to new binary file\n"); - exit(1); - } - if (fwrite(dest_records, sizeof(dest_records[0]), dest_rec_count, outf) - != dest_rec_count) - goto write_err; - if (fwrite(inn_records, sizeof(inn_records[0]), inn_rec_count, outf) - != inn_rec_count) - goto write_err; - if (fwrite(special_num_records, sizeof(special_num_records[0]), - special_num_count, outf) != special_num_count) - goto write_err; - fclose(outf); -} - -main(argc, argv) - char **argv; -{ - if (argc > 2) { - fprintf(stderr, "usage: %s [directory]\n", argv[0]); - exit(1); - } - if (argv[1]) - system_dir = argv[1]; - else - system_dir = "/var/gsm"; - if (chdir(system_dir) < 0) { - perror(system_dir); - exit(1); - } - inf = fopen("out-routes", "r"); - if (!inf) { - perror("opening out-routes"); - exit(1); - } - for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) - process_line(); - fclose(inf); - emit_output(); - /* make it live */ - if (rename("out-routes.newbin", "out-routes.bin") < 0) { - perror("rename"); - exit(1); - } - exit(0); -} diff -r 44dc809ffec0 -r 5c7109183c8c utils/themwi-update-outrt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utils/themwi-update-outrt.c Thu Oct 06 21:19:59 2022 -0800 @@ -0,0 +1,473 @@ +/* + * This program reads (parses) ThemWi config file /var/gsm/out-routes, + * generates the compiled binary form of this database, and then makes + * it live via atomic rename. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/out_routes.h" + +#define MAX_DEST_ENTRIES 16 +#define MAX_INN_ENTRIES 64 +#define MAX_SPC_NUM_ENTRIES 64 + +static struct sip_out_dest dest_records[MAX_DEST_ENTRIES]; +static char *dest_names[MAX_DEST_ENTRIES]; +static struct inn_route inn_records[MAX_INN_ENTRIES]; +static struct special_num_route special_num_records[MAX_SPC_NUM_ENTRIES]; +static unsigned dest_rec_count, inn_rec_count, special_num_count; + +static char *system_dir; +static FILE *inf; +static int lineno; +static char linebuf[256]; + +static int +find_dest_by_name(sought_name) + char *sought_name; +{ + unsigned n; + + for (n = 0; n < dest_rec_count; n++) + if (!strcmp(dest_names[n], sought_name)) + return n; + return -1; +} + +static int +find_dest_by_number(target_num) + char *target_num; +{ + unsigned inn_index; + struct inn_route *rec; + char *pp, *tp; + + for (inn_index = 0; inn_index < inn_rec_count; inn_index++) { + rec = inn_records + inn_index; + pp = rec->prefix; + tp = target_num; + while (*pp && *pp == *tp) { + pp++; + tp++; + } + if (*pp) + continue; + return rec->sip_dest_id; + } + return -1; +} + +static void +handle_dest_line(cp) + char *cp; +{ + char *name, *name_copy, *domain, *ip_str, *port_str; + struct sip_out_dest *rec; + unsigned portnum; + int rc; + + for (name = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { +inv_syntax: fprintf(stderr, "out-routes line %d: invalid syntax for dest\n", + lineno); + exit(1); + } + for (domain = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + goto inv_syntax; + for (ip_str = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + port_str = 0; + else { + for (port_str = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv_syntax; + } + rc = find_dest_by_name(name); + if (rc >= 0) { + fprintf(stderr, + "out-routes line %d: duplicate destination name \"%s\"\n", + lineno, name); + exit(1); + } + if (dest_rec_count >= MAX_DEST_ENTRIES) { + fprintf(stderr, + "out-routes line %d: MAX_DEST_ENTRIES exceeded\n", + lineno); + exit(1); + } + name_copy = strdup(name); + if (!name_copy) { + perror("strdup"); + exit(1); + } + dest_names[dest_rec_count] = name_copy; + rec = dest_records + dest_rec_count; + if (strlen(domain) > MAX_SIP_DEST_DOMAIN) { + fprintf(stderr, + "out-routes line %d: dest domain string is too long\n", + lineno); + exit(1); + } + strcpy(rec->domain, domain); + rec->sin.sin_family = AF_INET; + rec->sin.sin_addr.s_addr = inet_addr(ip_str); + if (rec->sin.sin_addr.s_addr == INADDR_NONE) { + fprintf(stderr, + "out-routes line %d: dest IP address is invalid\n", + lineno); + exit(1); + } + if (port_str) { + portnum = strtoul(port_str, &cp, 10); + if (*cp) + goto inv_syntax; + } else + portnum = 5060; + rec->sin.sin_port = htons(portnum); + dest_rec_count++; +} + +static void +handle_inn_route(cp) + char *cp; +{ + char *prefix, *dest_name; + struct inn_route *rec; + int rc, dest_id; + + for (prefix = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { +inv_syntax: fprintf(stderr, + "out-routes line %d: invalid syntax for inn-route\n", + lineno); + exit(1); + } + for (dest_name = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv_syntax; + rc = grok_number_string(prefix, 1); + if (rc < 1) + goto inv_syntax; + if (rc > MAX_INN_PREFIX) { + fprintf(stderr, + "out-routes line %d: inn-route prefix is too long\n", + lineno); + exit(1); + } + dest_id = find_dest_by_name(dest_name); + if (dest_id < 0) { + fprintf(stderr, + "out-routes line %d: SIP destination \"%s\" not defined\n", + lineno, dest_name); + exit(1); + } + if (inn_rec_count >= MAX_INN_ENTRIES) { + fprintf(stderr, + "out-routes line %d: MAX_INN_ENTRIES exceeded\n", + lineno); + exit(1); + } + rec = inn_records + inn_rec_count; + dehyphen_number_string(prefix, rec->prefix); + rec->sip_dest_id = dest_id; + inn_rec_count++; +} + +static void +preen_special_num_code(num_code) + char *num_code; +{ + char *cp; + int c; + unsigned n; + + n = 0; + for (cp = num_code; *cp; ) { + c = *cp++; + if (is_valid_ext_digit(c)) + n++; + else { + fprintf(stderr, + "out-routes line %d: special-num string \"%s\" is invalid\n", + lineno, num_code); + exit(1); + } + } + if (n > MAX_SPECIAL_NUM) { + fprintf(stderr, + "out-routes line %d: special-num string \"%s\" is too long\n", + lineno, num_code); + exit(1); + } +} + +static void +handle_special_num_map_to(num_code, cp) + char *num_code, *cp; +{ + struct special_num_route *rec; + char *tgt_num_src; + int rc, dest_id; + + while (isspace(*cp)) + cp++; + if (*cp++ != '+') { +inv_syntax: fprintf(stderr, + "out-routes line %d: invalid syntax for special-num map-to\n", + lineno); + exit(1); + } + if (!isdigit(*cp)) + goto inv_syntax; + for (tgt_num_src = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv_syntax; + rc = grok_number_string(tgt_num_src, 1); + if (rc < 1) + goto inv_syntax; + if (rc > MAX_E164_NUMBER) { + fprintf(stderr, + "out-routes line %d: map-to number is too long for E.164\n", + lineno); + exit(1); + } + rec = special_num_records + special_num_count; + strcpy(rec->special_num, num_code); + rec->sip_user[0] = '+'; + dehyphen_number_string(tgt_num_src, rec->sip_user+1); + dest_id = find_dest_by_number(rec->sip_user+1); + if (dest_id < 0) { + fprintf(stderr, + "out-routes line %d: no inn-route for map-to number\n", + lineno); + exit(1); + } + rec->sip_dest_id = dest_id; + special_num_count++; +} + +static void +handle_special_num_route_to(num_code, cp) + char *num_code, *cp; +{ + struct special_num_route *rec; + char *dest_name; + int dest_id; + + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { +inv_syntax: fprintf(stderr, + "out-routes line %d: invalid syntax for special-num route-to\n", + lineno); + exit(1); + } + for (dest_name = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv_syntax; + dest_id = find_dest_by_name(dest_name); + if (dest_id < 0) { + fprintf(stderr, + "out-routes line %d: SIP destination \"%s\" not defined\n", + lineno, dest_name); + exit(1); + } + rec = special_num_records + special_num_count; + strcpy(rec->special_num, num_code); + strcpy(rec->sip_user, num_code); + rec->sip_dest_id = dest_id; + special_num_count++; +} + +static void +handle_special_num(cp) + char *cp; +{ + char *num_code, *handling_kw; + + for (num_code = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + preen_special_num_code(num_code); + if (special_num_count >= MAX_SPC_NUM_ENTRIES) { + fprintf(stderr, + "out-routes line %d: MAX_SPC_NUM_ENTRIES exceeded\n", + lineno); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { +inv_syntax: fprintf(stderr, + "out-routes line %d: invalid syntax for special-num\n", + lineno); + exit(1); + } + for (handling_kw = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(handling_kw, "map-to")) + handle_special_num_map_to(num_code, cp); + else if (!strcmp(handling_kw, "route-to")) + handle_special_num_route_to(num_code, cp); + else + goto inv_syntax; +} + +static void +process_line() +{ + char *cp, *np; + void (*handler)(); + + if (!index(linebuf, '\n')) { + fprintf(stderr, + "out-routes line %d: too long or missing newline\n", + lineno); + exit(1); + } + for (cp = linebuf; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + return; + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "dest")) + handler = handle_dest_line; + else if (!strcmp(np, "inn-route")) + handler = handle_inn_route; + else if (!strcmp(np, "special-num")) + handler = handle_special_num; + else { + fprintf(stderr, + "out-routes line %d: non-understood keyword \"%s\"\n", + lineno, np); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "out-routes line %d: missing argument after \"%s\" keyword\n", + lineno, np); + exit(1); + } + handler(cp); +} + +static void +emit_output() +{ + FILE *outf; + struct out_routes_header hdr; + + outf = fopen("out-routes.newbin", "w"); + if (!outf) { + perror("creating out-routes.newbin"); + exit(1); + } + hdr.num_dest = dest_rec_count; + hdr.num_inn = inn_rec_count; + hdr.num_special = special_num_count; + if (fwrite(&hdr, sizeof hdr, 1, outf) != 1) { +write_err: fprintf(stderr, "error writing to new binary file\n"); + exit(1); + } + if (fwrite(dest_records, sizeof(dest_records[0]), dest_rec_count, outf) + != dest_rec_count) + goto write_err; + if (fwrite(inn_records, sizeof(inn_records[0]), inn_rec_count, outf) + != inn_rec_count) + goto write_err; + if (fwrite(special_num_records, sizeof(special_num_records[0]), + special_num_count, outf) != special_num_count) + goto write_err; + fclose(outf); +} + +main(argc, argv) + char **argv; +{ + if (argc > 2) { + fprintf(stderr, "usage: %s [directory]\n", argv[0]); + exit(1); + } + if (argv[1]) + system_dir = argv[1]; + else + system_dir = "/var/gsm"; + if (chdir(system_dir) < 0) { + perror(system_dir); + exit(1); + } + inf = fopen("out-routes", "r"); + if (!inf) { + perror("opening out-routes"); + exit(1); + } + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) + process_line(); + fclose(inf); + emit_output(); + /* make it live */ + if (rename("out-routes.newbin", "out-routes.bin") < 0) { + perror("rename"); + exit(1); + } + exit(0); +}