FreeCalypso > hg > fc-pcsc-tools
diff simtool/smsp_restore.c @ 39:2467b7acad1f
fc-simtool smsp-restore implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 12 Feb 2021 21:54:01 +0000 |
parents | simtool/pbupd_file.c@2ef261371347 |
children | 8cb269f5a902 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simtool/smsp_restore.c Fri Feb 12 21:54:01 2021 +0000 @@ -0,0 +1,243 @@ +/* + * This module implements the smsp-restore command. + */ + +#include <sys/types.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <stdio.h> +#include <stdlib.h> +#include "curfile.h" + +extern char *alpha_from_file_qstring(); +extern char *alpha_from_file_hex(); + +static char * +parse_da(cp, bina, filename_for_errs, lineno_for_errs) + char *cp, *filename_for_errs; + u_char *bina; +{ + u_char digits[20]; + unsigned ndigits, num_digit_bytes; + int c; + + if (digit_char_to_gsm(*cp) < 0) { +inv_syntax: fprintf(stderr, "%s line %d: DA= parameter invalid syntax\n", + filename_for_errs, lineno_for_errs); + return(0); + } + for (ndigits = 0; ; ndigits++) { + c = digit_char_to_gsm(*cp); + if (c < 0) + break; + cp++; + if (ndigits >= 20) { + fprintf(stderr, "%s line %d: too many number digits\n", + filename_for_errs, lineno_for_errs); + return(0); + } + digits[ndigits] = c; + } + bina[0] = ndigits; + if (ndigits & 1) + digits[ndigits++] = 0xF; + num_digit_bytes = ndigits >> 1; + pack_digit_bytes(digits, bina + 2, num_digit_bytes); + if (*cp++ != ',') + goto inv_syntax; + if (cp[0] != '0' || cp[1] != 'x' && cp[1] != 'X' || !isxdigit(cp[2]) || + !isxdigit(cp[3]) || !isspace(cp[4])) + goto inv_syntax; + bina[1] = strtoul(cp, 0, 16); + cp += 5; + while (isspace(*cp)) + cp++; + return(cp); +} + +static char * +parse_sc(cp, bina, filename_for_errs, lineno_for_errs) + char *cp, *filename_for_errs; + u_char *bina; +{ + u_char digits[20]; + unsigned ndigits, num_digit_bytes; + int c; + + if (digit_char_to_gsm(*cp) < 0) { +inv_syntax: fprintf(stderr, "%s line %d: SC= parameter invalid syntax\n", + filename_for_errs, lineno_for_errs); + return(0); + } + for (ndigits = 0; ; ndigits++) { + c = digit_char_to_gsm(*cp); + if (c < 0) + break; + cp++; + if (ndigits >= 20) { + fprintf(stderr, "%s line %d: too many number digits\n", + filename_for_errs, lineno_for_errs); + return(0); + } + digits[ndigits] = c; + } + if (ndigits & 1) + digits[ndigits++] = 0xF; + num_digit_bytes = ndigits >> 1; + bina[0] = num_digit_bytes + 1; + pack_digit_bytes(digits, bina + 2, num_digit_bytes); + if (*cp++ != ',') + goto inv_syntax; + if (cp[0] != '0' || cp[1] != 'x' && cp[1] != 'X' || !isxdigit(cp[2]) || + !isxdigit(cp[3]) || !isspace(cp[4])) + goto inv_syntax; + bina[1] = strtoul(cp, 0, 16); + cp += 5; + while (isspace(*cp)) + cp++; + return(cp); +} + +static +process_record(line, filename_for_errs, lineno_for_errs) + char *line, *filename_for_errs; +{ + unsigned recno; + u_char record[255], *fixp; + char *cp; + + recno = strtoul(line+1, 0, 10); + if (recno < 1 || recno > curfile_record_count) { + fprintf(stderr, "%s line %d: record number is out of range\n", + filename_for_errs, lineno_for_errs); + return(-1); + } + cp = line + 1; + while (isdigit(*cp)) + cp++; + if (*cp++ != ':') { +inv_syntax: fprintf(stderr, "%s line %d: invalid syntax\n", + filename_for_errs, lineno_for_errs); + return(-1); + } + while (isspace(*cp)) + cp++; + memset(record, 0xFF, curfile_record_len); + fixp = record + curfile_record_len - 28; + if (!strncasecmp(cp, "DA=", 3)) { + cp += 3; + cp = parse_da(cp, fixp + 1, filename_for_errs, lineno_for_errs); + if (!cp) + return(-1); + fixp[0] &= 0xFE; + } + if (!strncasecmp(cp, "SC=", 3)) { + cp += 3; + cp = parse_sc(cp, fixp+13, filename_for_errs, lineno_for_errs); + if (!cp) + return(-1); + fixp[0] &= 0xFD; + } + if (!strncasecmp(cp, "PID=", 4)) { + cp += 4; + if (!isdigit(*cp)) { + fprintf(stderr, + "%s line %d: PID= parameter invalid syntax\n", + filename_for_errs, lineno_for_errs); + return(-1); + } + fixp[25] = strtoul(cp, 0, 0); + while (*cp && !isspace(*cp)) + cp++; + while (isspace(*cp)) + cp++; + } + if (!strncasecmp(cp, "DCS=", 4)) { + cp += 4; + if (!isdigit(*cp)) { + fprintf(stderr, + "%s line %d: DCS= parameter invalid syntax\n", + filename_for_errs, lineno_for_errs); + return(-1); + } + fixp[26] = strtoul(cp, 0, 0); + while (*cp && !isspace(*cp)) + cp++; + while (isspace(*cp)) + cp++; + } + if (!strncasecmp(cp, "VP=", 3)) { + cp += 3; + if (!isdigit(*cp)) { + fprintf(stderr, + "%s line %d: VP= parameter invalid syntax\n", + filename_for_errs, lineno_for_errs); + return(-1); + } + fixp[27] = strtoul(cp, 0, 0); + while (*cp && !isspace(*cp)) + cp++; + while (isspace(*cp)) + cp++; + } + if (*cp == '"') { + cp++; + cp = alpha_from_file_qstring(cp, record, + curfile_record_len - 28, + filename_for_errs, + lineno_for_errs); + if (!cp) + return(-1); + } else if (!strncasecmp(cp, "HEX", 3)) { + cp += 3; + while (isspace(*cp)) + cp++; + cp = alpha_from_file_hex(cp, record, curfile_record_len - 28, + filename_for_errs, lineno_for_errs); + if (!cp) + return(-1); + } else + goto inv_syntax; + while (isspace(*cp)) + cp++; + if (*cp) + goto inv_syntax; + return update_rec_op(recno, 0x04, record, curfile_record_len); +} + +cmd_smsp_restore(argc, argv) + char **argv; +{ + int rc; + FILE *inf; + int lineno; + char linebuf[1024]; + + rc = select_ef_smsp(); + if (rc < 0) + return(rc); + inf = fopen(argv[1], "r"); + if (!inf) { + perror(argv[1]); + return(-1); + } + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { + if (!index(linebuf, '\n')) { + fprintf(stderr, + "%s line %d: too long or missing newline\n", + argv[1], lineno); + fclose(inf); + return(-1); + } + if (linebuf[0] != '#' || !isdigit(linebuf[1])) + continue; + rc = process_record(linebuf, argv[1], lineno); + if (rc < 0) { + fclose(inf); + return(rc); + } + } + fclose(inf); + return(0); +}