FreeCalypso > hg > themwi-system-sw
comparison 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 |
comparison
equal
deleted
inserted
replaced
3:d712d518059e | 4:4ad5deafaa87 |
---|---|
1 /* | |
2 * This program reads (parses) ThemWi config file /var/gsm/number-db, | |
3 * generates the compiled binary form of this database, and then makes | |
4 * it live via atomic rename. | |
5 */ | |
6 | |
7 #include <ctype.h> | |
8 #include <stdio.h> | |
9 #include <stdint.h> | |
10 #include <stdlib.h> | |
11 #include <string.h> | |
12 #include <strings.h> | |
13 #include <unistd.h> | |
14 #include "../include/number_db_file.h" | |
15 | |
16 #define MAX_OWNED_NUMBERS 1000 | |
17 #define MAX_SHORT_NUMBERS 1000 | |
18 | |
19 static uint64_t owned_number_buf[MAX_OWNED_NUMBERS]; | |
20 static struct short_number_map short_number_buf[MAX_SHORT_NUMBERS]; | |
21 static unsigned owned_number_count, short_number_count; | |
22 | |
23 static char *system_dir; | |
24 static FILE *inf; | |
25 static int lineno; | |
26 static char linebuf[256], prefix[7]; | |
27 static int prefix_allows_abbrev; | |
28 static uint32_t prefix_int; | |
29 | |
30 static void | |
31 enter_owned_number(numstr) | |
32 char *numstr; | |
33 { | |
34 if (owned_number_count >= MAX_OWNED_NUMBERS) { | |
35 fprintf(stderr, "error: MAX_OWNED_NUMBERS exceeded\n"); | |
36 exit(1); | |
37 } | |
38 owned_number_buf[owned_number_count++] = strtoull(numstr, 0, 10); | |
39 } | |
40 | |
41 static void | |
42 enter_short_number(numstr, prefix) | |
43 char *numstr; | |
44 uint32_t prefix; | |
45 { | |
46 if (short_number_count >= MAX_SHORT_NUMBERS) { | |
47 fprintf(stderr, "error: MAX_SHORT_NUMBERS exceeded\n"); | |
48 exit(1); | |
49 } | |
50 short_number_buf[short_number_count].short_code = | |
51 strtoul(numstr, 0, 10); | |
52 short_number_buf[short_number_count].prefix = prefix; | |
53 short_number_count++; | |
54 } | |
55 | |
56 static void | |
57 handle_prefix_line(cp) | |
58 char *cp; | |
59 { | |
60 char *np; | |
61 | |
62 for (np = cp; *cp && !isspace(*cp); cp++) | |
63 ; | |
64 if (*cp) | |
65 *cp++ = '\0'; | |
66 if (grok_number_string(np, 1) != 6) { | |
67 fprintf(stderr, | |
68 "number-db line %d: prefix requires 6-digit argument\n", | |
69 lineno); | |
70 exit(1); | |
71 } | |
72 dehyphen_number_string(np, prefix); | |
73 if (!is_nanp_valid_prefix(prefix)) { | |
74 fprintf(stderr, | |
75 "number-db line %d: prefix violates NANP rules\n", | |
76 lineno); | |
77 exit(1); | |
78 } | |
79 while (isspace(*cp)) | |
80 cp++; | |
81 if (*cp == '\0' || *cp == '#') { | |
82 prefix_allows_abbrev = 0; | |
83 return; | |
84 } | |
85 for (np = cp; *cp && !isspace(*cp); cp++) | |
86 ; | |
87 if (*cp) | |
88 *cp++ = '\0'; | |
89 if (!strcmp(np, "allow-abbrev")) { | |
90 prefix_allows_abbrev = 1; | |
91 prefix_int = strtoul(prefix, 0, 10); | |
92 return; | |
93 } | |
94 fprintf(stderr, | |
95 "number-db line %d: non-understood notation \"%s\" after prefix\n", | |
96 lineno, np); | |
97 exit(1); | |
98 } | |
99 | |
100 static void | |
101 handle_suffix_line(cp) | |
102 char *cp; | |
103 { | |
104 char *np, full10[11]; | |
105 | |
106 if (!prefix[0]) { | |
107 fprintf(stderr, | |
108 "number-db line %d: suffix not valid without preceding prefix\n", | |
109 lineno); | |
110 exit(1); | |
111 } | |
112 for (np = cp; *cp && !isspace(*cp); cp++) | |
113 ; | |
114 if (*cp) | |
115 *cp++ = '\0'; | |
116 if (grok_number_string(np, 0) != 4) { | |
117 fprintf(stderr, | |
118 "number-db line %d: suffix requires 4-digit argument\n", | |
119 lineno); | |
120 exit(1); | |
121 } | |
122 strcpy(full10, prefix); | |
123 strcat(full10, np); | |
124 enter_owned_number(full10); | |
125 if (!prefix_allows_abbrev) | |
126 return; | |
127 enter_short_number(np, prefix_int); | |
128 } | |
129 | |
130 static void | |
131 handle_full10_line(cp) | |
132 char *cp; | |
133 { | |
134 char *np, full10[11]; | |
135 | |
136 prefix[0] = '\0'; /* cancel any previous prefix line */ | |
137 for (np = cp; *cp && !isspace(*cp); cp++) | |
138 ; | |
139 if (*cp) | |
140 *cp++ = '\0'; | |
141 if (grok_number_string(np, 1) != 10) { | |
142 fprintf(stderr, | |
143 "number-db line %d: full10 requires 10-digit argument\n", | |
144 lineno); | |
145 exit(1); | |
146 } | |
147 dehyphen_number_string(np, full10); | |
148 if (!is_nanp_valid_prefix(full10)) { | |
149 fprintf(stderr, | |
150 "number-db line %d: number violates NANP rules\n", | |
151 lineno); | |
152 exit(1); | |
153 } | |
154 enter_owned_number(full10); | |
155 } | |
156 | |
157 static void | |
158 handle_itn_line(cp) | |
159 char *cp; | |
160 { | |
161 char *np; | |
162 | |
163 prefix[0] = '\0'; /* cancel any previous prefix line */ | |
164 for (np = cp; *cp && !isspace(*cp); cp++) | |
165 ; | |
166 if (*cp) | |
167 *cp++ = '\0'; | |
168 if (grok_number_string(np, 0) != 4) { | |
169 fprintf(stderr, | |
170 "number-db line %d: itn requires 4-digit argument\n", | |
171 lineno); | |
172 exit(1); | |
173 } | |
174 enter_short_number(np, 0); | |
175 } | |
176 | |
177 static void | |
178 process_line() | |
179 { | |
180 char *cp, *np; | |
181 void (*handler)(); | |
182 | |
183 if (!index(linebuf, '\n')) { | |
184 fprintf(stderr, | |
185 "number-db line %d: too long or missing newline\n", | |
186 lineno); | |
187 exit(1); | |
188 } | |
189 for (cp = linebuf; isspace(*cp); cp++) | |
190 ; | |
191 if (*cp == '\0' || *cp == '#') | |
192 return; | |
193 for (np = cp; *cp && !isspace(*cp); cp++) | |
194 ; | |
195 if (*cp) | |
196 *cp++ = '\0'; | |
197 if (!strcmp(np, "prefix")) | |
198 handler = handle_prefix_line; | |
199 else if (!strcmp(np, "suffix")) | |
200 handler = handle_suffix_line; | |
201 else if (!strcmp(np, "full10")) | |
202 handler = handle_full10_line; | |
203 else if (!strcmp(np, "itn")) | |
204 handler = handle_itn_line; | |
205 else { | |
206 fprintf(stderr, | |
207 "number-db line %d: non-understood keyword \"%s\"\n", | |
208 lineno, np); | |
209 exit(1); | |
210 } | |
211 while (isspace(*cp)) | |
212 cp++; | |
213 if (*cp == '\0' || *cp == '#') { | |
214 fprintf(stderr, | |
215 "number-db line %d: missing argument after \"%s\" keyword\n", | |
216 lineno, np); | |
217 exit(1); | |
218 } | |
219 handler(cp); | |
220 } | |
221 | |
222 static int | |
223 compare_owned_num(p1, p2) | |
224 uint64_t *p1, *p2; | |
225 { | |
226 if (*p1 < *p2) | |
227 return(-1); | |
228 else if (*p1 > *p2) | |
229 return(1); | |
230 else | |
231 return(0); | |
232 } | |
233 | |
234 static int | |
235 compare_short_num(p1, p2) | |
236 struct short_number_map *p1, *p2; | |
237 { | |
238 if (p1->short_code < p2->short_code) | |
239 return(-1); | |
240 else if (p1->short_code > p2->short_code) | |
241 return(1); | |
242 else | |
243 return(0); | |
244 } | |
245 | |
246 static void | |
247 owned_num_check_dup() | |
248 { | |
249 uint64_t *p, *endp; | |
250 | |
251 endp = owned_number_buf + owned_number_count - 1; | |
252 for (p = owned_number_buf; p < endp; p++) { | |
253 if (p[0] == p[1]) { | |
254 fprintf(stderr, | |
255 "error: NANP number %llu appears more than once\n", | |
256 (unsigned long long) *p); | |
257 exit(1); | |
258 } | |
259 } | |
260 } | |
261 | |
262 static void | |
263 short_num_check_dup() | |
264 { | |
265 struct short_number_map *p, *endp; | |
266 | |
267 endp = short_number_buf + short_number_count - 1; | |
268 for (p = short_number_buf; p < endp; p++) { | |
269 if (p[0].short_code == p[1].short_code) { | |
270 fprintf(stderr, | |
271 "error: short number %04u appears more than once\n", | |
272 (unsigned) p->short_code); | |
273 exit(1); | |
274 } | |
275 } | |
276 } | |
277 | |
278 static void | |
279 emit_output() | |
280 { | |
281 FILE *outf; | |
282 struct numdb_file_hdr hdr; | |
283 | |
284 outf = fopen("number-db.newbin", "w"); | |
285 if (!outf) { | |
286 perror("creating number-db.newbin"); | |
287 exit(1); | |
288 } | |
289 hdr.owned_number_count = owned_number_count; | |
290 hdr.short_number_count = short_number_count; | |
291 if (fwrite(&hdr, sizeof hdr, 1, outf) != 1) { | |
292 write_err: fprintf(stderr, "error writing to new binary file\n"); | |
293 exit(1); | |
294 } | |
295 if (fwrite(owned_number_buf, sizeof(owned_number_buf[0]), | |
296 owned_number_count, outf) != owned_number_count) | |
297 goto write_err; | |
298 if (fwrite(short_number_buf, sizeof(short_number_buf[0]), | |
299 short_number_count, outf) != short_number_count) | |
300 goto write_err; | |
301 fclose(outf); | |
302 } | |
303 | |
304 main(argc, argv) | |
305 char **argv; | |
306 { | |
307 if (argc > 2) { | |
308 fprintf(stderr, "usage: %s [directory]\n", argv[0]); | |
309 exit(1); | |
310 } | |
311 if (argv[1]) | |
312 system_dir = argv[1]; | |
313 else | |
314 system_dir = "/var/gsm"; | |
315 if (chdir(system_dir) < 0) { | |
316 perror(system_dir); | |
317 exit(1); | |
318 } | |
319 inf = fopen("number-db", "r"); | |
320 if (!inf) { | |
321 perror("opening number-db"); | |
322 exit(1); | |
323 } | |
324 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) | |
325 process_line(); | |
326 fclose(inf); | |
327 if (owned_number_count >= 2) { | |
328 qsort(owned_number_buf, owned_number_count, | |
329 sizeof(owned_number_buf[0]), compare_owned_num); | |
330 owned_num_check_dup(); | |
331 } | |
332 if (short_number_count >= 2) { | |
333 qsort(short_number_buf, short_number_count, | |
334 sizeof(short_number_buf[0]), compare_short_num); | |
335 short_num_check_dup(); | |
336 } | |
337 emit_output(); | |
338 /* make it live */ | |
339 if (rename("number-db.newbin", "number-db.bin") < 0) { | |
340 perror("rename"); | |
341 exit(1); | |
342 } | |
343 exit(0); | |
344 } |