FreeCalypso > hg > themwi-system-sw
view utils/themwi-update-numdb.c @ 97:9aed16c30622
mgw p2g: set M bit when restarting forwarding after no-forward
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 25 Sep 2022 20:05:02 -0800 |
parents | 4ad5deafaa87 |
children |
line wrap: on
line source
/* * 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); }