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 } | 
