SRI-NOSC/s1/ndd.c

Compare this file to the similar file:
Show the results in this format:

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