/* * 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; }