comparison simtool/pbupd_file.c @ 13:d4f8c511affe

simtool: pbupdate.c split into separate modules for each command
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 12 Feb 2021 01:28:53 +0000
parents simtool/pbupdate.c@8a34f5b7c812
children 2ef261371347
comparison
equal deleted inserted replaced
12:8a34f5b7c812 13:d4f8c511affe
1 /*
2 * This module implements the original read-from-file pb-update command.
3 */
4
5 #include <sys/types.h>
6 #include <ctype.h>
7 #include <string.h>
8 #include <strings.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "curfile.h"
12
13 extern u_char gsm7_encode_table[256];
14
15 static char *
16 decode_qstring_alpha(cp, record, maxlen, filename_for_errs, lineno_for_errs)
17 char *cp, *filename_for_errs;
18 u_char *record;
19 unsigned maxlen;
20 {
21 unsigned acclen, nadd;
22 int c;
23
24 for (acclen = 0; ; ) {
25 if (*cp == '\0') {
26 unterm_qstring: fprintf(stderr,
27 "%s line %d: unterminated quoted string\n",
28 filename_for_errs, lineno_for_errs);
29 return(0);
30 }
31 if (*cp == '"')
32 break;
33 c = *cp++;
34 if (c == '\\') {
35 if (*cp == '\0')
36 goto unterm_qstring;
37 c = *cp++;
38 switch (c) {
39 case 'n':
40 c = '\n';
41 break;
42 case 'r':
43 c = '\r';
44 break;
45 case '"':
46 case '\\':
47 break;
48 default:
49 fprintf(stderr,
50 "%s line %d: non-understood backslash escape\n",
51 filename_for_errs, lineno_for_errs);
52 return(0);
53 }
54 }
55 c = gsm7_encode_table[c];
56 if (c == 0xFF) {
57 fprintf(stderr,
58 "%s line %d: character in quoted string cannot be encoded in GSM7\n",
59 filename_for_errs, lineno_for_errs);
60 return(0);
61 }
62 if (c & 0x80)
63 nadd = 2;
64 else
65 nadd = 1;
66 if (acclen + nadd > maxlen) {
67 fprintf(stderr,
68 "%s line %d: alpha tag string is longer than SIM limit\n",
69 filename_for_errs, lineno_for_errs);
70 return(0);
71 }
72 if (c & 0x80)
73 record[acclen++] = 0x1B;
74 record[acclen++] = c & 0x7F;
75 }
76 return(cp + 1);
77 }
78
79 static char *
80 decode_hex_alpha(cp, record, maxlen, filename_for_errs, lineno_for_errs)
81 char *cp, *filename_for_errs;
82 u_char *record;
83 unsigned maxlen;
84 {
85 unsigned acclen;
86
87 for (acclen = 0; ; ) {
88 if (!isxdigit(cp[0]) || !isxdigit(cp[1]))
89 break;
90 if (acclen >= maxlen) {
91 fprintf(stderr,
92 "%s line %d: alpha tag string is longer than SIM limit\n",
93 filename_for_errs, lineno_for_errs);
94 return(0);
95 }
96 record[acclen++] = (decode_hex_digit(cp[0]) << 4) |
97 decode_hex_digit(cp[1]);
98 cp += 2;
99 }
100 return(cp);
101 }
102
103 static
104 process_record(line, pb_record_len, pb_record_count, filename_for_errs,
105 lineno_for_errs)
106 char *line, *filename_for_errs;
107 unsigned pb_record_len, pb_record_count;
108 {
109 unsigned recno;
110 u_char record[255], *fixp;
111 u_char digits[20];
112 unsigned ndigits, num_digit_bytes;
113 char *cp;
114 int c;
115
116 recno = strtoul(line+1, 0, 10);
117 if (recno < 1 || recno > pb_record_count) {
118 fprintf(stderr, "%s line %d: record number is out of range\n",
119 filename_for_errs, lineno_for_errs);
120 return(-1);
121 }
122 cp = line + 1;
123 while (isdigit(*cp))
124 cp++;
125 if (*cp++ != ':') {
126 inv_syntax: fprintf(stderr, "%s line %d: invalid syntax\n",
127 filename_for_errs, lineno_for_errs);
128 return(-1);
129 }
130 while (isspace(*cp))
131 cp++;
132 memset(record, 0xFF, pb_record_len);
133 fixp = record + pb_record_len - 14;
134 if (digit_char_to_gsm(*cp) < 0)
135 goto inv_syntax;
136 for (ndigits = 0; ; ndigits++) {
137 c = digit_char_to_gsm(*cp);
138 if (c < 0)
139 break;
140 cp++;
141 if (ndigits >= 20) {
142 fprintf(stderr, "%s line %d: too many number digits\n",
143 filename_for_errs, lineno_for_errs);
144 return(-1);
145 }
146 digits[ndigits] = c;
147 }
148 if (ndigits & 1)
149 digits[ndigits++] = 0xF;
150 num_digit_bytes = ndigits >> 1;
151 fixp[0] = num_digit_bytes + 1;
152 pack_digit_bytes(digits, fixp + 2, num_digit_bytes);
153 if (*cp++ != ',')
154 goto inv_syntax;
155 if (cp[0] != '0' || cp[1] != 'x' && cp[1] != 'X' || !isxdigit(cp[2]) ||
156 !isxdigit(cp[3]) || !isspace(cp[4]))
157 goto inv_syntax;
158 fixp[1] = strtoul(cp, 0, 16);
159 cp += 5;
160 while (isspace(*cp))
161 cp++;
162 if (!strncasecmp(cp, "CCP=", 4)) {
163 cp += 4;
164 fixp[12] = strtoul(cp, 0, 0);
165 while (*cp && !isspace(*cp))
166 cp++;
167 while (isspace(*cp))
168 cp++;
169 }
170 if (!strncasecmp(cp, "EXT=", 4)) {
171 cp += 4;
172 fixp[13] = strtoul(cp, 0, 0);
173 while (*cp && !isspace(*cp))
174 cp++;
175 while (isspace(*cp))
176 cp++;
177 }
178 if (*cp == '"') {
179 cp++;
180 cp = decode_qstring_alpha(cp, record, pb_record_len - 14,
181 filename_for_errs, lineno_for_errs);
182 if (!cp)
183 return(-1);
184 } else if (!strncasecmp(cp, "HEX", 3)) {
185 cp += 3;
186 while (isspace(*cp))
187 cp++;
188 cp = decode_hex_alpha(cp, record, pb_record_len - 14,
189 filename_for_errs, lineno_for_errs);
190 if (!cp)
191 return(-1);
192 } else
193 goto inv_syntax;
194 while (isspace(*cp))
195 cp++;
196 if (*cp)
197 goto inv_syntax;
198 return update_rec_op(recno, 0x04, record, pb_record_len);
199 }
200
201 cmd_pb_update(argc, argv)
202 char **argv;
203 {
204 int rc;
205 FILE *inf;
206 int lineno;
207 char linebuf[1024];
208
209 rc = phonebook_op_common(argv[1]);
210 if (rc < 0)
211 return(rc);
212 inf = fopen(argv[2], "r");
213 if (!inf) {
214 perror(argv[2]);
215 return(-1);
216 }
217 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
218 if (!index(linebuf, '\n')) {
219 fprintf(stderr,
220 "%s line %d: too long or missing newline\n",
221 argv[2], lineno);
222 fclose(inf);
223 return(-1);
224 }
225 if (linebuf[0] != '#' || !isdigit(linebuf[1]))
226 continue;
227 rc = process_record(linebuf, curfile_record_len,
228 curfile_record_count, argv[2], lineno);
229 if (rc < 0) {
230 fclose(inf);
231 return(rc);
232 }
233 }
234 fclose(inf);
235 return(0);
236 }