view simtool/smsp_restore.c @ 41:8cb269f5a902

fc-simtool smsp-restore: forgot to set parameter indicator bits
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 12 Feb 2021 22:10:32 +0000
parents 2467b7acad1f
children 9c10afbb745a
line wrap: on
line source

/*
 * 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);
		fixp[0] &= 0xFB;
		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);
		fixp[0] &= 0xF7;
		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);
		fixp[0] &= 0xEF;
		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);
}