FreeCalypso > hg > themwi-system-sw
diff utils/themwi-update-numdb.c @ 4:4ad5deafaa87
themwi-update-numdb utility written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 26 Jun 2022 11:39:14 -0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utils/themwi-update-numdb.c Sun Jun 26 11:39:14 2022 -0800 @@ -0,0 +1,344 @@ +/* + * This program reads (parses) ThemWi config file /var/gsm/number-db, + * generates the compiled binary form of this database, and then makes + * it live via atomic rename. + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include "../include/number_db_file.h" + +#define MAX_OWNED_NUMBERS 1000 +#define MAX_SHORT_NUMBERS 1000 + +static uint64_t owned_number_buf[MAX_OWNED_NUMBERS]; +static struct short_number_map short_number_buf[MAX_SHORT_NUMBERS]; +static unsigned owned_number_count, short_number_count; + +static char *system_dir; +static FILE *inf; +static int lineno; +static char linebuf[256], prefix[7]; +static int prefix_allows_abbrev; +static uint32_t prefix_int; + +static void +enter_owned_number(numstr) + char *numstr; +{ + if (owned_number_count >= MAX_OWNED_NUMBERS) { + fprintf(stderr, "error: MAX_OWNED_NUMBERS exceeded\n"); + exit(1); + } + owned_number_buf[owned_number_count++] = strtoull(numstr, 0, 10); +} + +static void +enter_short_number(numstr, prefix) + char *numstr; + uint32_t prefix; +{ + if (short_number_count >= MAX_SHORT_NUMBERS) { + fprintf(stderr, "error: MAX_SHORT_NUMBERS exceeded\n"); + exit(1); + } + short_number_buf[short_number_count].short_code = + strtoul(numstr, 0, 10); + short_number_buf[short_number_count].prefix = prefix; + short_number_count++; +} + +static void +handle_prefix_line(cp) + char *cp; +{ + char *np; + + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (grok_number_string(np, 1) != 6) { + fprintf(stderr, + "number-db line %d: prefix requires 6-digit argument\n", + lineno); + exit(1); + } + dehyphen_number_string(np, prefix); + if (!is_nanp_valid_prefix(prefix)) { + fprintf(stderr, + "number-db line %d: prefix violates NANP rules\n", + lineno); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { + prefix_allows_abbrev = 0; + return; + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "allow-abbrev")) { + prefix_allows_abbrev = 1; + prefix_int = strtoul(prefix, 0, 10); + return; + } + fprintf(stderr, + "number-db line %d: non-understood notation \"%s\" after prefix\n", + lineno, np); + exit(1); +} + +static void +handle_suffix_line(cp) + char *cp; +{ + char *np, full10[11]; + + if (!prefix[0]) { + fprintf(stderr, + "number-db line %d: suffix not valid without preceding prefix\n", + lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (grok_number_string(np, 0) != 4) { + fprintf(stderr, + "number-db line %d: suffix requires 4-digit argument\n", + lineno); + exit(1); + } + strcpy(full10, prefix); + strcat(full10, np); + enter_owned_number(full10); + if (!prefix_allows_abbrev) + return; + enter_short_number(np, prefix_int); +} + +static void +handle_full10_line(cp) + char *cp; +{ + char *np, full10[11]; + + prefix[0] = '\0'; /* cancel any previous prefix line */ + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (grok_number_string(np, 1) != 10) { + fprintf(stderr, + "number-db line %d: full10 requires 10-digit argument\n", + lineno); + exit(1); + } + dehyphen_number_string(np, full10); + if (!is_nanp_valid_prefix(full10)) { + fprintf(stderr, + "number-db line %d: number violates NANP rules\n", + lineno); + exit(1); + } + enter_owned_number(full10); +} + +static void +handle_itn_line(cp) + char *cp; +{ + char *np; + + prefix[0] = '\0'; /* cancel any previous prefix line */ + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (grok_number_string(np, 0) != 4) { + fprintf(stderr, + "number-db line %d: itn requires 4-digit argument\n", + lineno); + exit(1); + } + enter_short_number(np, 0); +} + +static void +process_line() +{ + char *cp, *np; + void (*handler)(); + + if (!index(linebuf, '\n')) { + fprintf(stderr, + "number-db 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, "prefix")) + handler = handle_prefix_line; + else if (!strcmp(np, "suffix")) + handler = handle_suffix_line; + else if (!strcmp(np, "full10")) + handler = handle_full10_line; + else if (!strcmp(np, "itn")) + handler = handle_itn_line; + else { + fprintf(stderr, + "number-db line %d: non-understood keyword \"%s\"\n", + lineno, np); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "number-db line %d: missing argument after \"%s\" keyword\n", + lineno, np); + exit(1); + } + handler(cp); +} + +static int +compare_owned_num(p1, p2) + uint64_t *p1, *p2; +{ + if (*p1 < *p2) + return(-1); + else if (*p1 > *p2) + return(1); + else + return(0); +} + +static int +compare_short_num(p1, p2) + struct short_number_map *p1, *p2; +{ + if (p1->short_code < p2->short_code) + return(-1); + else if (p1->short_code > p2->short_code) + return(1); + else + return(0); +} + +static void +owned_num_check_dup() +{ + uint64_t *p, *endp; + + endp = owned_number_buf + owned_number_count - 1; + for (p = owned_number_buf; p < endp; p++) { + if (p[0] == p[1]) { + fprintf(stderr, + "error: NANP number %llu appears more than once\n", + (unsigned long long) *p); + exit(1); + } + } +} + +static void +short_num_check_dup() +{ + struct short_number_map *p, *endp; + + endp = short_number_buf + short_number_count - 1; + for (p = short_number_buf; p < endp; p++) { + if (p[0].short_code == p[1].short_code) { + fprintf(stderr, + "error: short number %04u appears more than once\n", + (unsigned) p->short_code); + exit(1); + } + } +} + +static void +emit_output() +{ + FILE *outf; + struct numdb_file_hdr hdr; + + outf = fopen("number-db.newbin", "w"); + if (!outf) { + perror("creating number-db.newbin"); + exit(1); + } + hdr.owned_number_count = owned_number_count; + hdr.short_number_count = short_number_count; + if (fwrite(&hdr, sizeof hdr, 1, outf) != 1) { +write_err: fprintf(stderr, "error writing to new binary file\n"); + exit(1); + } + if (fwrite(owned_number_buf, sizeof(owned_number_buf[0]), + owned_number_count, outf) != owned_number_count) + goto write_err; + if (fwrite(short_number_buf, sizeof(short_number_buf[0]), + short_number_count, outf) != short_number_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("number-db", "r"); + if (!inf) { + perror("opening number-db"); + exit(1); + } + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) + process_line(); + fclose(inf); + if (owned_number_count >= 2) { + qsort(owned_number_buf, owned_number_count, + sizeof(owned_number_buf[0]), compare_owned_num); + owned_num_check_dup(); + } + if (short_number_count >= 2) { + qsort(short_number_buf, short_number_count, + sizeof(short_number_buf[0]), compare_short_num); + short_num_check_dup(); + } + emit_output(); + /* make it live */ + if (rename("number-db.newbin", "number-db.bin") < 0) { + perror("rename"); + exit(1); + } + exit(0); +}