#/* Module Name: ndd.c -- special-purpose dd command Installation: if $1x = finalx goto final cc ndd.c chmod 755 a.out mv a.out ndd exit : final cc -O -s ndd.c su cp a.out /usr/bin/ndd rm a.out ndd Synopsis: ndd [if=filename] [of=filename] .... [pass=number] Function: This iis a variant of the dd command that gives access to multiple files on a tape volume. The operation is identical to dd except that the default input and output is the tape drive instead of the standard input or output, respectivly. One additional option is supported: "pass=number" causes that number of files (filemarks) to be bypassed before the operation commenses. Compile time parameters and effects: Module History: Created 10 Jan 78 by Greg Noel from ddd, a modified version of dd that handled the pass option for input files. All else new. */ #define LCASE 01 #define UCASE 02 #define SWAB 04 #define NERR 010 #define SYNC 020 int cflag; int fflag; int skip; int count; char *string; char *ifile; char *ofile; char *ibuf; char *obuf; char *ibs 1024; char *obs 1024; char *bs; char *cbs; char *ibc; char *obc; char *cbc; int nifr; int nipr; int nofr; int nopr; int ntrunc; int ibf; int obf; char *op; int nspace; /*****************************************************************************/ int pass; int psf; /*****************************************************************************/ char etoa[] { 0000,0001,0002,0003,0234,0011,0206,0177, 0227,0215,0216,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0235,0205,0010,0207, 0030,0031,0222,0217,0034,0035,0036,0037, 0200,0201,0202,0203,0204,0012,0027,0033, 0210,0211,0212,0213,0214,0005,0006,0007, 0220,0221,0026,0223,0224,0225,0226,0004, 0230,0231,0232,0233,0024,0025,0236,0032, 0040,0240,0241,0242,0243,0244,0245,0246, 0247,0250,0133,0056,0074,0050,0053,0041, 0046,0251,0252,0253,0254,0255,0256,0257, 0260,0261,0135,0044,0052,0051,0073,0136, 0055,0057,0262,0263,0264,0265,0266,0267, 0270,0271,0174,0054,0045,0137,0076,0077, 0272,0273,0274,0275,0276,0277,0300,0301, 0302,0140,0072,0043,0100,0047,0075,0042, 0303,0141,0142,0143,0144,0145,0146,0147, 0150,0151,0304,0305,0306,0307,0310,0311, 0312,0152,0153,0154,0155,0156,0157,0160, 0161,0162,0313,0314,0315,0316,0317,0320, 0321,0176,0163,0164,0165,0166,0167,0170, 0171,0172,0322,0323,0324,0325,0326,0327, 0330,0331,0332,0333,0334,0335,0336,0337, 0340,0341,0342,0343,0344,0345,0346,0347, 0173,0101,0102,0103,0104,0105,0106,0107, 0110,0111,0350,0351,0352,0353,0354,0355, 0175,0112,0113,0114,0115,0116,0117,0120, 0121,0122,0356,0357,0360,0361,0362,0363, 0134,0237,0123,0124,0125,0126,0127,0130, 0131,0132,0364,0365,0366,0367,0370,0371, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0372,0373,0374,0375,0376,0377, }; char atoe[] { 0000,0001,0002,0003,0067,0055,0056,0057, 0026,0005,0045,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0074,0075,0062,0046, 0030,0031,0077,0047,0034,0035,0036,0037, 0100,0117,0177,0173,0133,0154,0120,0175, 0115,0135,0134,0116,0153,0140,0113,0141, 0360,0361,0362,0363,0364,0365,0366,0367, 0370,0371,0172,0136,0114,0176,0156,0157, 0174,0301,0302,0303,0304,0305,0306,0307, 0310,0311,0321,0322,0323,0324,0325,0326, 0327,0330,0331,0342,0343,0344,0345,0346, 0347,0350,0351,0112,0340,0132,0137,0155, 0171,0201,0202,0203,0204,0205,0206,0207, 0210,0211,0221,0222,0223,0224,0225,0226, 0227,0230,0231,0242,0243,0244,0245,0246, 0247,0250,0251,0300,0152,0320,0241,0007, 0040,0041,0042,0043,0044,0025,0006,0027, 0050,0051,0052,0053,0054,0011,0012,0033, 0060,0061,0032,0063,0064,0065,0066,0010, 0070,0071,0072,0073,0004,0024,0076,0341, 0101,0102,0103,0104,0105,0106,0107,0110, 0111,0121,0122,0123,0124,0125,0126,0127, 0130,0131,0142,0143,0144,0145,0146,0147, 0150,0151,0160,0161,0162,0163,0164,0165, 0166,0167,0170,0200,0212,0213,0214,0215, 0216,0217,0220,0232,0233,0234,0235,0236, 0237,0240,0252,0253,0254,0255,0256,0257, 0260,0261,0262,0263,0264,0265,0266,0267, 0270,0271,0272,0273,0274,0275,0276,0277, 0312,0313,0314,0315,0316,0317,0332,0333, 0334,0335,0336,0337,0352,0353,0354,0355, 0356,0357,0372,0373,0374,0375,0376,0377, }; main(argc, argv) int argc; char **argv; { register (*conv)(); register char *ip; register c; int ebcdic(), ascii(), null(), cnull(), term(); int a; conv = null; for(c=1; c<argc; c++) { string = argv[c]; if(match("ibs=")) { ibs = number(); continue; } if(match("obs=")) { obs = number(); continue; } if(match("cbs=")) { cbs = number(); continue; } if (match("bs=")) { bs = number(); continue; } if(match("if=")) { ifile = string; continue; } if(match("of=")) { ofile = string; continue; } if(match("skip=")) { skip = number(); continue; } if(match("count=")) { count = number(); continue; } /***************************************************************************/ if(match("pass=")) { pass = number(); continue; } /**************************************************************************/ if(match("conv=")) { cloop: if(match(",")) goto cloop; if(*string == '\0') continue; if(match("ebcdic")) { conv = ebcdic; goto cloop; } if(match("ascii")) { conv = ascii; goto cloop; } if(match("lcase")) { cflag =| LCASE; goto cloop; } if(match("ucase")) { cflag =| UCASE; goto cloop; } if(match("swab")) { cflag =| SWAB; goto cloop; } if(match("noerror")) { cflag =| NERR; goto cloop; } if(match("sync")) { cflag =| SYNC; goto cloop; } } printf("bad arg: %s\n", string); exit(); } if(conv == null && cflag&(LCASE|UCASE)) conv = cnull; if (ifile) ibf = open(ifile, 0); else psf = ibf = open("/dev/rmt0", 0); if(ibf < 0) { printf("cannot open: %s\n", ifile); exit(); } if (ofile) obf = creat(ofile, 0666); else psf = obf = open("/dev/rmt0", 2); if(obf < 0) { printf("cannot create: %s\n", ofile); exit(); } if (bs) { ibs = obs = bs; if (conv == null) fflag++; } if(ibs == 0 || obs == 0) { printf("counts: cannot be zero\n"); exit(); } /*****************************************************************************/ if(pass) { if(psf == 0) { printf("pass specified, but no tape operation\n"); exit(); } if( (ibuf = sbrk(8192)) < 0) { printf("Can't get memory to pass files\n"); exit(); } while(pass) { printf("passed:"); while((ibc=read(psf, ibuf, 8192)) != -1 && ibc != 0) { printf("%7d", ibc); if(!(++obc & 07)) printf("\n "); } printf(" EOF\n"); ibc = obc = 0; pass--; } brk(ibuf); /* set back to original status */ } /*****************************************************************************/ ibuf = sbrk(ibs); if (fflag) obuf = ibuf; else obuf = sbrk(obs); if(ibuf == -1 || obuf == -1) { printf("not enough memory\n"); exit(); } ibc = 0; obc = 0; cbc = 0; op = obuf; if ((signal(2, 1) & 01) == 0) signal(2, term); while(skip) { read(ibf, ibuf, ibs); skip--; } loop: if(ibc-- == 0) { ibc = 0; if(count==0 || nifr+nipr!=count) { if(cflag&(NERR|SYNC)) for(ip=ibuf+ibs; ip>ibuf;) *--ip = 0; ibc = read(ibf, ibuf, ibs); } if(ibc == -1) { perror("read"); if((cflag&NERR) == 0) { flsh(); term(); } ibc = 0; for(c=0; c<ibs; c++) if(ibuf[c] != 0) ibc = c; stats(); } if(ibc == 0) { flsh(); term(); } if(ibc != ibs) { nipr++; if(cflag&SYNC) ibc = ibs; } else nifr++; ip = ibuf; c = (ibc>>1) & ~1; if(cflag&SWAB && c) do { a = *ip++; ip[-1] = *ip; *ip++ = a; } while(--c); ip = ibuf; if (fflag) { obc = ibc; flsh(); ibc = 0; } goto loop; } c = 0; c =| *ip++; (*conv)(c); goto loop; } flsh() { register c; if(obc) { if(obc == obs) nofr++; else nopr++; c = write(obf, obuf, obc); if(c != obc) { perror("write"); term(); } obc = 0; } } match(s) char *s; { register char *cs; cs = string; while(*cs++ == *s) if(*s++ == '\0') goto true; if(*s != '\0') return(0); true: cs--; string = cs; return(1); } number() { register char *cs; register n; cs = string; n = 0; while(*cs >= '0' && *cs <= '9') n = n*10 + *cs++ - '0'; for(;;) switch(*cs++) { case 'k': n =* 1024; continue; case 'w': n =* 2; continue; case 'b': n =* 512; continue; case '*': case 'x': string = cs; n =* number(); case '\0': return(n); } printf("not a number: %s\n", string); exit(); } cnull(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c =+ 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c =+ 'a'-'A'; null(c); } null(c) { *op = c; op++; if(++obc >= obs) { flsh(); op = obuf; } } ascii(cc) { register c; c = 0; c =| etoa[cc]; if(cbs == 0) { cnull(c); return; } if(c == ' ') { nspace++; goto out; } while(nspace > 0) { null(' '); nspace--; } cnull(c); out: if(++cbc >= cbs) { null('\n'); cbc = 0; nspace = 0; } } ebcdic(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c =+ 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c =+ 'a'-'A'; c = atoe[c] & 0377; if(cbs == 0) { null(c); return; } if(cc == '\n') { while(cbc < cbs) { null(atoe[' ']); cbc++; } cbc = 0; return; } if(cbc == cbs) ntrunc++; cbc++; if(cbc <= cbs) null(c); } term() { stats(); exit(); } stats() { printf("%l+%l records in\n", nifr, nipr); printf("%l+%l records out\n", nofr, nopr); if(ntrunc) printf("%l truncated records\n", ntrunc); } putchar(c) { write(2, &c, 1); }