/*
* card--Extracts files written by the CMS CARD dumper utility
* Copyright (C) 2001 Peter Backes
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include /* For read/write */
#include /* For open */
#include /* For open */
#include /* For open */
#include /* For tolower */
/* EBCDIC to ASCII translation tables */
char etoa[256] = {
0x00,0x01,0x02,0x03,0x00,0x09,0x00,0x7f,
0x00,0x00,0x00,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x00,0x00,0x08,0x00,
0x18,0x19,0x00,0x00,0x1c,0x1d,0x1e,0x1f,
0x00,0x00,0x00,0x00,0x00,0x0a,0x17,0x1b,
0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x07,
0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x04,
0x00,0x00,0x00,0x00,0x14,0x15,0x00,0x1a,
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x2e,0x3c,0x28,0x2b,0x7c,
0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x21,0x24,0x2a,0x29,0x3b,0x5e,
0x2d,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x2c,0x25,0x5f,0x3e,0x3f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22,
0x00,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
0x68,0x69,0x00,0x7b,0x00,0x00,0x00,0x00,
0x00,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,
0x71,0x72,0x00,0x7d,0x00,0x00,0x00,0x00,
0x00,0x7e,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7a,0x00,0x00,0x00,0x5b,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x5d,0x00,0x00,
0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
0x48,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,
0x51,0x52,0x00,0x00,0x00,0x00,0x00,0x00,
0x5c,0x00,0x53,0x54,0x55,0x56,0x57,0x58,
0x59,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
0x38,0x39,0x00,0x00,0x00,0x00,0x00,0x00,
};
char atoe[256] = {
0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,
0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26,
0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d,
0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,
0xe7,0xe8,0xe9,0xad,0xe0,0xbd,0x5f,0x6d,
0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6,
0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,
/* repeated for 8-bit parity */
0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,
0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26,
0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d,
0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,
0xe7,0xe8,0xe9,0xad,0xe0,0xbd,0x5f,0x6d,
0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6,
0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,
};
struct crdhdr_t {
unsigned char magic[8], /* ":CARD " */
fn[8], ft[8], r1[8], fm[2], r2[4], recfm, flag, lrecl[4],
r3[4], u1[4], u2[4], nrecs[4], time[6], r4[6], u3[4], pad[4];
};
int main(int argc, char *argv[])
{
struct crdhdr_t ch;
int nrecs, lrecl;
char recfm;
unsigned char buf[128000];
/* unsigned char tok[128]; */
int i, len, rep, bl, fpo;
int fd, of = 1; /* By default print to stdout */
char file[18]; /* "FILENAME.FILETYPE\0" */
unsigned char chr, *ptr, *top; /* Token pointer */
fprintf (stderr, "FN FT FM RECFM NRECS LRECL\n");
fd = open(argv[1], O_RDONLY);
while (read(fd, &ch, 80) == 80) {
recfm = ch.recfm = etoa[ch.recfm];
for (i = 0; i < 8; i++) {
ch.magic[i] = etoa[ch.magic[i]];
ch.fn[i] = etoa[ch.fn[i]];
ch.ft[i] = etoa[ch.ft[i]];
}
for (i = 0; i < 2; i++)
ch.fm[i] = etoa[ch.fm[i]];
nrecs = ch.nrecs[2] << 8;
nrecs |= ch.nrecs[3];
lrecl = ch.lrecl[2] << 8;
lrecl |= ch.lrecl[3];
top = file;
ptr = ch.fn;
for (i = 0; i < 8 && *ptr != 0x20; i++)
*top++ = tolower(*ptr++);
*top++ = 0x2E;
ptr = ch.ft;
for (i = 0; i < 8 && *ptr != 0x20; i++)
*top++ = tolower(*ptr++);
*top = 0x00;
fprintf(stderr, "%.8s %.8s %.2s %c %-5d %-5d\n", ch.fn, ch.ft, ch.fm,
recfm, nrecs, lrecl);
top = buf;
fpo = 80;
len = 0;
of = open(file, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (of == -1)
of = 0;
while (nrecs > 0) {
/* fprintf(stderr, "> %d recs left, %d LEN, %d FPO\n", nrecs, len, fpo); */
read(fd, &chr, 1);
fpo++;
if ((chr & 0x80) != 0x00) {
rep = chr & 0x3F;
rep++;
chr &= 0x40;
len += rep;
for (; rep > 0; rep--)
*top++ = chr;
} else {
chr++;
read(fd, top, chr);
fpo += chr;
top += chr;
len += chr;
}
switch (recfm) {
case 'V':
while (len > 2) {
/* compute block length */
bl = buf[0] << 8;
bl |= buf[1];
if (len < bl + 2)
break;
write(of, buf + 2, bl);
write(of, "\x25", 1);
ptr = buf + bl + 2;
top = buf;
len -= bl + 2;
for (i = len; i > 0; i--)
*top++ = *ptr++;
nrecs--;
}
break;
case 'F':
while (len > lrecl) {
write (of, buf, lrecl);
ptr = buf + lrecl;
top = buf;
len -= lrecl;
for (i = len; i > 0; i--)
*top++ = *ptr++;
nrecs--;
}
break;
}
}
do {
read(fd, &chr, 1);
fpo++;
} while (chr == 0xBF);
/* fprintf(stderr, "Currently %d bytes in file.\n", fpo); */
fpo %= 80;
/* fprintf(stderr, "Currently %d bytes in card.\n", fpo); */
if (fpo > 0)
fpo -= 80;
fpo *= -1;
/* fprintf(stderr, "Skipping %d bytes of junk.\n", fpo); */
read(fd, buf, fpo);
if (of != 0)
close(of);
}
close(fd);
return 0;
}