FreeCalypso > hg > fc-pcsc-tools
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 } |