xref: /plan9/sys/src/cmd/dd.c (revision 51f48f69b4c3e5c9d9f7955d28612ef2d4048ccc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier 
417629263SDavid du Colombier #define	BIG	((1UL<<31)-1)
517629263SDavid du Colombier #define VBIG	((1ULL<<63)-1)
63e12c5d1SDavid du Colombier #define	LCASE	(1<<0)
73e12c5d1SDavid du Colombier #define	UCASE	(1<<1)
83e12c5d1SDavid du Colombier #define	SWAB	(1<<2)
93e12c5d1SDavid du Colombier #define NERR	(1<<3)
103e12c5d1SDavid du Colombier #define SYNC	(1<<4)
1141dd6b47SDavid du Colombier 
123e12c5d1SDavid du Colombier int	cflag;
133e12c5d1SDavid du Colombier int	fflag;
1417629263SDavid du Colombier 
153e12c5d1SDavid du Colombier char	*string;
163e12c5d1SDavid du Colombier char	*ifile;
173e12c5d1SDavid du Colombier char	*ofile;
183e12c5d1SDavid du Colombier char	*ibuf;
193e12c5d1SDavid du Colombier char	*obuf;
2017629263SDavid du Colombier 
217dd7cddfSDavid du Colombier vlong	skip;
227dd7cddfSDavid du Colombier vlong	oseekn;
237dd7cddfSDavid du Colombier vlong	iseekn;
24*51f48f69SDavid du Colombier vlong	oseekb;
25*51f48f69SDavid du Colombier vlong	iseekb;
267dd7cddfSDavid du Colombier vlong	count;
2717629263SDavid du Colombier 
283e12c5d1SDavid du Colombier long	files	= 1;
293e12c5d1SDavid du Colombier long	ibs	= 512;
303e12c5d1SDavid du Colombier long	obs	= 512;
313e12c5d1SDavid du Colombier long	bs;
323e12c5d1SDavid du Colombier long	cbs;
333e12c5d1SDavid du Colombier long	ibc;
343e12c5d1SDavid du Colombier long	obc;
353e12c5d1SDavid du Colombier long	cbc;
363e12c5d1SDavid du Colombier long	nifr;
373e12c5d1SDavid du Colombier long	nipr;
383e12c5d1SDavid du Colombier long	nofr;
393e12c5d1SDavid du Colombier long	nopr;
403e12c5d1SDavid du Colombier long	ntrunc;
4117629263SDavid du Colombier 
429a747e4fSDavid du Colombier int dotrunc = 1;
433e12c5d1SDavid du Colombier int	ibf;
443e12c5d1SDavid du Colombier int	obf;
4517629263SDavid du Colombier 
463e12c5d1SDavid du Colombier char	*op;
473e12c5d1SDavid du Colombier int	nspace;
4817629263SDavid du Colombier 
493e12c5d1SDavid du Colombier uchar	etoa[256];
503e12c5d1SDavid du Colombier uchar	atoe[256];
513e12c5d1SDavid du Colombier uchar	atoibm[256];
5217629263SDavid du Colombier 
53dc5a79c1SDavid du Colombier int	quiet;
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier void	flsh(void);
563e12c5d1SDavid du Colombier int	match(char *s);
5717629263SDavid du Colombier vlong	number(vlong big);
583e12c5d1SDavid du Colombier void	cnull(int cc);
593e12c5d1SDavid du Colombier void	null(int c);
603e12c5d1SDavid du Colombier void	ascii(int cc);
613e12c5d1SDavid du Colombier void	unblock(int cc);
623e12c5d1SDavid du Colombier void	ebcdic(int cc);
633e12c5d1SDavid du Colombier void	ibm(int cc);
643e12c5d1SDavid du Colombier void	block(int cc);
65f425ee0bSDavid du Colombier void	term(char*);
663e12c5d1SDavid du Colombier void	stats(void);
673e12c5d1SDavid du Colombier 
683e12c5d1SDavid du Colombier #define	iskey(s)	((key[0] == '-') && (strcmp(key+1, s) == 0))
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier int
main(int argc,char * argv[])713e12c5d1SDavid du Colombier main(int argc, char *argv[])
723e12c5d1SDavid du Colombier {
733e12c5d1SDavid du Colombier 	void (*conv)(int);
743e12c5d1SDavid du Colombier 	char *ip;
753e12c5d1SDavid du Colombier 	char *key;
763e12c5d1SDavid du Colombier 	int a, c;
773e12c5d1SDavid du Colombier 
783e12c5d1SDavid du Colombier 	conv = null;
793e12c5d1SDavid du Colombier 	for(c=1; c<argc; c++) {
803e12c5d1SDavid du Colombier 		key = argv[c++];
813e12c5d1SDavid du Colombier 		if(c >= argc){
82219b2ee8SDavid du Colombier 			fprint(2, "dd: arg %s needs a value\n", key);
833e12c5d1SDavid du Colombier 			exits("arg");
843e12c5d1SDavid du Colombier 		}
853e12c5d1SDavid du Colombier 		string = argv[c];
863e12c5d1SDavid du Colombier 		if(iskey("ibs")) {
873e12c5d1SDavid du Colombier 			ibs = number(BIG);
883e12c5d1SDavid du Colombier 			continue;
893e12c5d1SDavid du Colombier 		}
903e12c5d1SDavid du Colombier 		if(iskey("obs")) {
913e12c5d1SDavid du Colombier 			obs = number(BIG);
923e12c5d1SDavid du Colombier 			continue;
933e12c5d1SDavid du Colombier 		}
943e12c5d1SDavid du Colombier 		if(iskey("cbs")) {
953e12c5d1SDavid du Colombier 			cbs = number(BIG);
963e12c5d1SDavid du Colombier 			continue;
973e12c5d1SDavid du Colombier 		}
983e12c5d1SDavid du Colombier 		if(iskey("bs")) {
993e12c5d1SDavid du Colombier 			bs = number(BIG);
1003e12c5d1SDavid du Colombier 			continue;
1013e12c5d1SDavid du Colombier 		}
102219b2ee8SDavid du Colombier 		if(iskey("if")) {
1033e12c5d1SDavid du Colombier 			ifile = string;
1043e12c5d1SDavid du Colombier 			continue;
1053e12c5d1SDavid du Colombier 		}
1063e12c5d1SDavid du Colombier 		if(iskey("of")) {
1073e12c5d1SDavid du Colombier 			ofile = string;
1083e12c5d1SDavid du Colombier 			continue;
1093e12c5d1SDavid du Colombier 		}
1109a747e4fSDavid du Colombier 		if(iskey("trunc")) {
1119a747e4fSDavid du Colombier 			dotrunc = number(BIG);
1129a747e4fSDavid du Colombier 			continue;
1139a747e4fSDavid du Colombier 		}
114dc5a79c1SDavid du Colombier 		if(iskey("quiet")) {
115dc5a79c1SDavid du Colombier 			quiet = number(BIG);
116dc5a79c1SDavid du Colombier 			continue;
117dc5a79c1SDavid du Colombier 		}
1183e12c5d1SDavid du Colombier 		if(iskey("skip")) {
11917629263SDavid du Colombier 			skip = number(VBIG);
1203e12c5d1SDavid du Colombier 			continue;
1213e12c5d1SDavid du Colombier 		}
1223e12c5d1SDavid du Colombier 		if(iskey("seek") || iskey("oseek")) {
12317629263SDavid du Colombier 			oseekn = number(VBIG);
1243e12c5d1SDavid du Colombier 			continue;
1253e12c5d1SDavid du Colombier 		}
1263e12c5d1SDavid du Colombier 		if(iskey("iseek")) {
12717629263SDavid du Colombier 			iseekn = number(VBIG);
1283e12c5d1SDavid du Colombier 			continue;
1293e12c5d1SDavid du Colombier 		}
130*51f48f69SDavid du Colombier 		if(iskey("iseekb")) {
131*51f48f69SDavid du Colombier 			iseekb = number(VBIG);
132*51f48f69SDavid du Colombier 			continue;
133*51f48f69SDavid du Colombier 		}
134*51f48f69SDavid du Colombier 		if(iskey("oseekb")) {
135*51f48f69SDavid du Colombier 			oseekb = number(VBIG);
136*51f48f69SDavid du Colombier 			continue;
137*51f48f69SDavid du Colombier 		}
1383e12c5d1SDavid du Colombier 		if(iskey("count")) {
13917629263SDavid du Colombier 			count = number(VBIG);
1403e12c5d1SDavid du Colombier 			continue;
1413e12c5d1SDavid du Colombier 		}
1423e12c5d1SDavid du Colombier 		if(iskey("files")) {
1433e12c5d1SDavid du Colombier 			files = number(BIG);
1443e12c5d1SDavid du Colombier 			continue;
1453e12c5d1SDavid du Colombier 		}
1463e12c5d1SDavid du Colombier 		if(iskey("conv")) {
1473e12c5d1SDavid du Colombier 		cloop:
1483e12c5d1SDavid du Colombier 			if(match(","))
1493e12c5d1SDavid du Colombier 				goto cloop;
1503e12c5d1SDavid du Colombier 			if(*string == '\0')
1513e12c5d1SDavid du Colombier 				continue;
1523e12c5d1SDavid du Colombier 			if(match("ebcdic")) {
1533e12c5d1SDavid du Colombier 				conv = ebcdic;
1543e12c5d1SDavid du Colombier 				goto cloop;
1553e12c5d1SDavid du Colombier 			}
1563e12c5d1SDavid du Colombier 			if(match("ibm")) {
1573e12c5d1SDavid du Colombier 				conv = ibm;
1583e12c5d1SDavid du Colombier 				goto cloop;
1593e12c5d1SDavid du Colombier 			}
1603e12c5d1SDavid du Colombier 			if(match("ascii")) {
1613e12c5d1SDavid du Colombier 				conv = ascii;
1623e12c5d1SDavid du Colombier 				goto cloop;
1633e12c5d1SDavid du Colombier 			}
1643e12c5d1SDavid du Colombier 			if(match("block")) {
1653e12c5d1SDavid du Colombier 				conv = block;
1663e12c5d1SDavid du Colombier 				goto cloop;
1673e12c5d1SDavid du Colombier 			}
1683e12c5d1SDavid du Colombier 			if(match("unblock")) {
1693e12c5d1SDavid du Colombier 				conv = unblock;
1703e12c5d1SDavid du Colombier 				goto cloop;
1713e12c5d1SDavid du Colombier 			}
1723e12c5d1SDavid du Colombier 			if(match("lcase")) {
1733e12c5d1SDavid du Colombier 				cflag |= LCASE;
1743e12c5d1SDavid du Colombier 				goto cloop;
1753e12c5d1SDavid du Colombier 			}
1763e12c5d1SDavid du Colombier 			if(match("ucase")) {
1773e12c5d1SDavid du Colombier 				cflag |= UCASE;
1783e12c5d1SDavid du Colombier 				goto cloop;
1793e12c5d1SDavid du Colombier 			}
1803e12c5d1SDavid du Colombier 			if(match("swab")) {
1813e12c5d1SDavid du Colombier 				cflag |= SWAB;
1823e12c5d1SDavid du Colombier 				goto cloop;
1833e12c5d1SDavid du Colombier 			}
1843e12c5d1SDavid du Colombier 			if(match("noerror")) {
1853e12c5d1SDavid du Colombier 				cflag |= NERR;
1863e12c5d1SDavid du Colombier 				goto cloop;
1873e12c5d1SDavid du Colombier 			}
1883e12c5d1SDavid du Colombier 			if(match("sync")) {
1893e12c5d1SDavid du Colombier 				cflag |= SYNC;
1903e12c5d1SDavid du Colombier 				goto cloop;
1913e12c5d1SDavid du Colombier 			}
19241dd6b47SDavid du Colombier 			fprint(2, "dd: bad conv %s\n", argv[c]);
19341dd6b47SDavid du Colombier 			exits("arg");
1943e12c5d1SDavid du Colombier 		}
195219b2ee8SDavid du Colombier 		fprint(2, "dd: bad arg: %s\n", key);
1963e12c5d1SDavid du Colombier 		exits("arg");
1973e12c5d1SDavid du Colombier 	}
1983e12c5d1SDavid du Colombier 	if(conv == null && cflag&(LCASE|UCASE))
1993e12c5d1SDavid du Colombier 		conv = cnull;
2003e12c5d1SDavid du Colombier 	if(ifile)
2013e12c5d1SDavid du Colombier 		ibf = open(ifile, 0);
2023e12c5d1SDavid du Colombier 	else
2033e12c5d1SDavid du Colombier 		ibf = dup(0, -1);
2043e12c5d1SDavid du Colombier 	if(ibf < 0) {
205219b2ee8SDavid du Colombier 		fprint(2, "dd: open %s: %r\n", ifile);
2063e12c5d1SDavid du Colombier 		exits("open");
2073e12c5d1SDavid du Colombier 	}
208219b2ee8SDavid du Colombier 	if(ofile){
2099a747e4fSDavid du Colombier 		if(dotrunc)
2103e12c5d1SDavid du Colombier 			obf = create(ofile, 1, 0664);
2119a747e4fSDavid du Colombier 		else
2129a747e4fSDavid du Colombier 			obf = open(ofile, 1);
213219b2ee8SDavid du Colombier 		if(obf < 0) {
214219b2ee8SDavid du Colombier 			fprint(2, "dd: create %s: %r\n", ofile);
215219b2ee8SDavid du Colombier 			exits("create");
216219b2ee8SDavid du Colombier 		}
217219b2ee8SDavid du Colombier 	}else{
2183e12c5d1SDavid du Colombier 		obf = dup(1, -1);
2193e12c5d1SDavid du Colombier 		if(obf < 0) {
2207dd7cddfSDavid du Colombier 			fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
221219b2ee8SDavid du Colombier 			exits("dup");
222219b2ee8SDavid du Colombier 		}
2233e12c5d1SDavid du Colombier 	}
2243e12c5d1SDavid du Colombier 	if(bs)
2253e12c5d1SDavid du Colombier 		ibs = obs = bs;
2263e12c5d1SDavid du Colombier 	if(ibs == obs && conv == null)
2273e12c5d1SDavid du Colombier 		fflag++;
2283e12c5d1SDavid du Colombier 	if(ibs == 0 || obs == 0) {
229219b2ee8SDavid du Colombier 		fprint(2, "dd: counts: cannot be zero\n");
2303e12c5d1SDavid du Colombier 		exits("counts");
2313e12c5d1SDavid du Colombier 	}
2323e12c5d1SDavid du Colombier 	ibuf = sbrk(ibs);
2333e12c5d1SDavid du Colombier 	if(fflag)
2343e12c5d1SDavid du Colombier 		obuf = ibuf;
2353e12c5d1SDavid du Colombier 	else
2363e12c5d1SDavid du Colombier 		obuf = sbrk(obs);
2373e12c5d1SDavid du Colombier 	sbrk(64);	/* For good measure */
2383e12c5d1SDavid du Colombier 	if(ibuf == (char *)-1 || obuf == (char *)-1) {
239219b2ee8SDavid du Colombier 		fprint(2, "dd: not enough memory: %r\n");
2403e12c5d1SDavid du Colombier 		exits("memory");
2413e12c5d1SDavid du Colombier 	}
2423e12c5d1SDavid du Colombier 	ibc = 0;
2433e12c5d1SDavid du Colombier 	obc = 0;
2443e12c5d1SDavid du Colombier 	cbc = 0;
2453e12c5d1SDavid du Colombier 	op = obuf;
2463e12c5d1SDavid du Colombier 
2473e12c5d1SDavid du Colombier /*
2483e12c5d1SDavid du Colombier 	if(signal(SIGINT, SIG_IGN) != SIG_IGN)
2493e12c5d1SDavid du Colombier 		signal(SIGINT, term);
2503e12c5d1SDavid du Colombier */
2513e12c5d1SDavid du Colombier 	seek(obf, obs*oseekn, 1);
2523e12c5d1SDavid du Colombier 	seek(ibf, ibs*iseekn, 1);
253*51f48f69SDavid du Colombier 	if(iseekb)
254*51f48f69SDavid du Colombier 		seek(ibf, iseekb, 0);
255*51f48f69SDavid du Colombier 	if(oseekb)
256*51f48f69SDavid du Colombier 		seek(obf, oseekb, 0);
2573e12c5d1SDavid du Colombier 	while(skip) {
2583e12c5d1SDavid du Colombier 		read(ibf, ibuf, ibs);
2593e12c5d1SDavid du Colombier 		skip--;
2603e12c5d1SDavid du Colombier 	}
2613e12c5d1SDavid du Colombier 
262219b2ee8SDavid du Colombier 	ip = 0;
2633e12c5d1SDavid du Colombier loop:
2643e12c5d1SDavid du Colombier 	if(ibc-- == 0) {
2653e12c5d1SDavid du Colombier 		ibc = 0;
2663e12c5d1SDavid du Colombier 		if(count==0 || nifr+nipr!=count) {
2673e12c5d1SDavid du Colombier 			if(cflag&(NERR|SYNC))
2683e12c5d1SDavid du Colombier 			for(ip=ibuf+ibs; ip>ibuf;)
2693e12c5d1SDavid du Colombier 				*--ip = 0;
2703e12c5d1SDavid du Colombier 			ibc = read(ibf, ibuf, ibs);
2713e12c5d1SDavid du Colombier 		}
2723e12c5d1SDavid du Colombier 		if(ibc == -1) {
2733e12c5d1SDavid du Colombier 			perror("read");
2743e12c5d1SDavid du Colombier 			if((cflag&NERR) == 0) {
2753e12c5d1SDavid du Colombier 				flsh();
276f425ee0bSDavid du Colombier 				term("errors");
2773e12c5d1SDavid du Colombier 			}
2783e12c5d1SDavid du Colombier 			ibc = 0;
2793e12c5d1SDavid du Colombier 			for(c=0; c<ibs; c++)
2803e12c5d1SDavid du Colombier 				if(ibuf[c] != 0)
281dc5a79c1SDavid du Colombier 					ibc = c+1;
282dc5a79c1SDavid du Colombier 			seek(ibf, ibs, 1);
2833e12c5d1SDavid du Colombier 			stats();
284dc5a79c1SDavid du Colombier 		}else if(ibc == 0 && --files<=0) {
2853e12c5d1SDavid du Colombier 			flsh();
286f425ee0bSDavid du Colombier 			term(nil);
2873e12c5d1SDavid du Colombier 		}
2883e12c5d1SDavid du Colombier 		if(ibc != ibs) {
2893e12c5d1SDavid du Colombier 			nipr++;
2903e12c5d1SDavid du Colombier 			if(cflag&SYNC)
2913e12c5d1SDavid du Colombier 				ibc = ibs;
2923e12c5d1SDavid du Colombier 		} else
2933e12c5d1SDavid du Colombier 			nifr++;
2943e12c5d1SDavid du Colombier 		ip = ibuf;
2953e12c5d1SDavid du Colombier 		c = (ibc>>1) & ~1;
2963e12c5d1SDavid du Colombier 		if(cflag&SWAB && c)
2973e12c5d1SDavid du Colombier 		do {
2983e12c5d1SDavid du Colombier 			a = *ip++;
2993e12c5d1SDavid du Colombier 			ip[-1] = *ip;
3003e12c5d1SDavid du Colombier 			*ip++ = a;
3013e12c5d1SDavid du Colombier 		} while(--c);
3023e12c5d1SDavid du Colombier 		ip = ibuf;
3033e12c5d1SDavid du Colombier 		if(fflag) {
3043e12c5d1SDavid du Colombier 			obc = ibc;
3053e12c5d1SDavid du Colombier 			flsh();
3063e12c5d1SDavid du Colombier 			ibc = 0;
3073e12c5d1SDavid du Colombier 		}
3083e12c5d1SDavid du Colombier 		goto loop;
3093e12c5d1SDavid du Colombier 	}
3103e12c5d1SDavid du Colombier 	c = 0;
3113e12c5d1SDavid du Colombier 	c |= *ip++;
3123e12c5d1SDavid du Colombier 	c &= 0377;
3133e12c5d1SDavid du Colombier 	(*conv)(c);
3143e12c5d1SDavid du Colombier 	goto loop;
3153e12c5d1SDavid du Colombier }
3163e12c5d1SDavid du Colombier 
3173e12c5d1SDavid du Colombier void
flsh(void)3183e12c5d1SDavid du Colombier flsh(void)
3193e12c5d1SDavid du Colombier {
3203e12c5d1SDavid du Colombier 	int c;
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier 	if(obc) {
323d7459b31SDavid du Colombier 		/* don't perror dregs of previous errors on a short write */
324d7459b31SDavid du Colombier 		werrstr("");
3253e12c5d1SDavid du Colombier 		c = write(obf, obuf, obc);
3263e12c5d1SDavid du Colombier 		if(c != obc) {
3273ff48bf5SDavid du Colombier 			if(c > 0)
3283ff48bf5SDavid du Colombier 				++nopr;
3293e12c5d1SDavid du Colombier 			perror("write");
330f425ee0bSDavid du Colombier 			term("errors");
3313e12c5d1SDavid du Colombier 		}
3323ff48bf5SDavid du Colombier 		if(obc == obs)
3333ff48bf5SDavid du Colombier 			nofr++;
3343ff48bf5SDavid du Colombier 		else
3353ff48bf5SDavid du Colombier 			nopr++;
3363e12c5d1SDavid du Colombier 		obc = 0;
3373e12c5d1SDavid du Colombier 	}
3383e12c5d1SDavid du Colombier }
3393e12c5d1SDavid du Colombier 
3403e12c5d1SDavid du Colombier int
match(char * s)3413e12c5d1SDavid du Colombier match(char *s)
3423e12c5d1SDavid du Colombier {
3433e12c5d1SDavid du Colombier 	char *cs;
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier 	cs = string;
3463e12c5d1SDavid du Colombier 	while(*cs++ == *s)
3473e12c5d1SDavid du Colombier 		if(*s++ == '\0')
3483e12c5d1SDavid du Colombier 			goto true;
3493e12c5d1SDavid du Colombier 	if(*s != '\0')
3503e12c5d1SDavid du Colombier 		return 0;
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier true:
3533e12c5d1SDavid du Colombier 	cs--;
3543e12c5d1SDavid du Colombier 	string = cs;
3553e12c5d1SDavid du Colombier 	return 1;
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier 
3587dd7cddfSDavid du Colombier vlong
number(vlong big)35917629263SDavid du Colombier number(vlong big)
3603e12c5d1SDavid du Colombier {
3613e12c5d1SDavid du Colombier 	char *cs;
36217629263SDavid du Colombier 	uvlong n;
3633e12c5d1SDavid du Colombier 
3643e12c5d1SDavid du Colombier 	cs = string;
3653e12c5d1SDavid du Colombier 	n = 0;
3663e12c5d1SDavid du Colombier 	while(*cs >= '0' && *cs <= '9')
3673e12c5d1SDavid du Colombier 		n = n*10 + *cs++ - '0';
3683e12c5d1SDavid du Colombier 	for(;;)
3693e12c5d1SDavid du Colombier 	switch(*cs++) {
3703e12c5d1SDavid du Colombier 
3713e12c5d1SDavid du Colombier 	case 'k':
3723e12c5d1SDavid du Colombier 		n *= 1024;
3733e12c5d1SDavid du Colombier 		continue;
3743e12c5d1SDavid du Colombier 
3753e12c5d1SDavid du Colombier 	case 'b':
3763e12c5d1SDavid du Colombier 		n *= 512;
3773e12c5d1SDavid du Colombier 		continue;
3783e12c5d1SDavid du Colombier 
3793e12c5d1SDavid du Colombier /*	case '*':*/
3803e12c5d1SDavid du Colombier 	case 'x':
3813e12c5d1SDavid du Colombier 		string = cs;
38217629263SDavid du Colombier 		n *= number(VBIG);
3833e12c5d1SDavid du Colombier 
3843e12c5d1SDavid du Colombier 	case '\0':
38517629263SDavid du Colombier 		if(n > big) {
38617629263SDavid du Colombier 			fprint(2, "dd: argument %llud out of range\n", n);
3873e12c5d1SDavid du Colombier 			exits("range");
3883e12c5d1SDavid du Colombier 		}
3893e12c5d1SDavid du Colombier 		return n;
3903e12c5d1SDavid du Colombier 	}
3913e12c5d1SDavid du Colombier 	/* never gets here */
3923e12c5d1SDavid du Colombier }
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier void
cnull(int cc)3953e12c5d1SDavid du Colombier cnull(int cc)
3963e12c5d1SDavid du Colombier {
3973e12c5d1SDavid du Colombier 	int c;
3983e12c5d1SDavid du Colombier 
3993e12c5d1SDavid du Colombier 	c = cc;
4003e12c5d1SDavid du Colombier 	if((cflag&UCASE) && c>='a' && c<='z')
4013e12c5d1SDavid du Colombier 		c += 'A'-'a';
4023e12c5d1SDavid du Colombier 	if((cflag&LCASE) && c>='A' && c<='Z')
4033e12c5d1SDavid du Colombier 		c += 'a'-'A';
4043e12c5d1SDavid du Colombier 	null(c);
4053e12c5d1SDavid du Colombier }
4063e12c5d1SDavid du Colombier 
4073e12c5d1SDavid du Colombier void
null(int c)4083e12c5d1SDavid du Colombier null(int c)
4093e12c5d1SDavid du Colombier {
4103e12c5d1SDavid du Colombier 
4113e12c5d1SDavid du Colombier 	*op = c;
4123e12c5d1SDavid du Colombier 	op++;
4133e12c5d1SDavid du Colombier 	if(++obc >= obs) {
4143e12c5d1SDavid du Colombier 		flsh();
4153e12c5d1SDavid du Colombier 		op = obuf;
4163e12c5d1SDavid du Colombier 	}
4173e12c5d1SDavid du Colombier }
4183e12c5d1SDavid du Colombier 
4193e12c5d1SDavid du Colombier void
ascii(int cc)4203e12c5d1SDavid du Colombier ascii(int cc)
4213e12c5d1SDavid du Colombier {
4223e12c5d1SDavid du Colombier 	int c;
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier 	c = etoa[cc];
4253e12c5d1SDavid du Colombier 	if(cbs == 0) {
4263e12c5d1SDavid du Colombier 		cnull(c);
4273e12c5d1SDavid du Colombier 		return;
4283e12c5d1SDavid du Colombier 	}
4293e12c5d1SDavid du Colombier 	if(c == ' ') {
4303e12c5d1SDavid du Colombier 		nspace++;
4313e12c5d1SDavid du Colombier 		goto out;
4323e12c5d1SDavid du Colombier 	}
4333e12c5d1SDavid du Colombier 	while(nspace > 0) {
4343e12c5d1SDavid du Colombier 		null(' ');
4353e12c5d1SDavid du Colombier 		nspace--;
4363e12c5d1SDavid du Colombier 	}
4373e12c5d1SDavid du Colombier 	cnull(c);
4383e12c5d1SDavid du Colombier 
4393e12c5d1SDavid du Colombier out:
4403e12c5d1SDavid du Colombier 	if(++cbc >= cbs) {
4413e12c5d1SDavid du Colombier 		null('\n');
4423e12c5d1SDavid du Colombier 		cbc = 0;
4433e12c5d1SDavid du Colombier 		nspace = 0;
4443e12c5d1SDavid du Colombier 	}
4453e12c5d1SDavid du Colombier }
4463e12c5d1SDavid du Colombier 
4473e12c5d1SDavid du Colombier void
unblock(int cc)4483e12c5d1SDavid du Colombier unblock(int cc)
4493e12c5d1SDavid du Colombier {
4503e12c5d1SDavid du Colombier 	int c;
4513e12c5d1SDavid du Colombier 
4523e12c5d1SDavid du Colombier 	c = cc & 0377;
4533e12c5d1SDavid du Colombier 	if(cbs == 0) {
4543e12c5d1SDavid du Colombier 		cnull(c);
4553e12c5d1SDavid du Colombier 		return;
4563e12c5d1SDavid du Colombier 	}
4573e12c5d1SDavid du Colombier 	if(c == ' ') {
4583e12c5d1SDavid du Colombier 		nspace++;
4593e12c5d1SDavid du Colombier 		goto out;
4603e12c5d1SDavid du Colombier 	}
4613e12c5d1SDavid du Colombier 	while(nspace > 0) {
4623e12c5d1SDavid du Colombier 		null(' ');
4633e12c5d1SDavid du Colombier 		nspace--;
4643e12c5d1SDavid du Colombier 	}
4653e12c5d1SDavid du Colombier 	cnull(c);
4663e12c5d1SDavid du Colombier 
4673e12c5d1SDavid du Colombier out:
4683e12c5d1SDavid du Colombier 	if(++cbc >= cbs) {
4693e12c5d1SDavid du Colombier 		null('\n');
4703e12c5d1SDavid du Colombier 		cbc = 0;
4713e12c5d1SDavid du Colombier 		nspace = 0;
4723e12c5d1SDavid du Colombier 	}
4733e12c5d1SDavid du Colombier }
4743e12c5d1SDavid du Colombier 
4753e12c5d1SDavid du Colombier void
ebcdic(int cc)4763e12c5d1SDavid du Colombier ebcdic(int cc)
4773e12c5d1SDavid du Colombier {
4783e12c5d1SDavid du Colombier 	int c;
4793e12c5d1SDavid du Colombier 
4803e12c5d1SDavid du Colombier 	c = cc;
4813e12c5d1SDavid du Colombier 	if(cflag&UCASE && c>='a' && c<='z')
4823e12c5d1SDavid du Colombier 		c += 'A'-'a';
4833e12c5d1SDavid du Colombier 	if(cflag&LCASE && c>='A' && c<='Z')
4843e12c5d1SDavid du Colombier 		c += 'a'-'A';
4853e12c5d1SDavid du Colombier 	c = atoe[c];
4863e12c5d1SDavid du Colombier 	if(cbs == 0) {
4873e12c5d1SDavid du Colombier 		null(c);
4883e12c5d1SDavid du Colombier 		return;
4893e12c5d1SDavid du Colombier 	}
4903e12c5d1SDavid du Colombier 	if(cc == '\n') {
4913e12c5d1SDavid du Colombier 		while(cbc < cbs) {
4923e12c5d1SDavid du Colombier 			null(atoe[' ']);
4933e12c5d1SDavid du Colombier 			cbc++;
4943e12c5d1SDavid du Colombier 		}
4953e12c5d1SDavid du Colombier 		cbc = 0;
4963e12c5d1SDavid du Colombier 		return;
4973e12c5d1SDavid du Colombier 	}
4983e12c5d1SDavid du Colombier 	if(cbc == cbs)
4993e12c5d1SDavid du Colombier 		ntrunc++;
5003e12c5d1SDavid du Colombier 	cbc++;
5013e12c5d1SDavid du Colombier 	if(cbc <= cbs)
5023e12c5d1SDavid du Colombier 		null(c);
5033e12c5d1SDavid du Colombier }
5043e12c5d1SDavid du Colombier 
5053e12c5d1SDavid du Colombier void
ibm(int cc)5063e12c5d1SDavid du Colombier ibm(int cc)
5073e12c5d1SDavid du Colombier {
5083e12c5d1SDavid du Colombier 	int c;
5093e12c5d1SDavid du Colombier 
5103e12c5d1SDavid du Colombier 	c = cc;
5113e12c5d1SDavid du Colombier 	if(cflag&UCASE && c>='a' && c<='z')
5123e12c5d1SDavid du Colombier 		c += 'A'-'a';
5133e12c5d1SDavid du Colombier 	if(cflag&LCASE && c>='A' && c<='Z')
5143e12c5d1SDavid du Colombier 		c += 'a'-'A';
5153e12c5d1SDavid du Colombier 	c = atoibm[c] & 0377;
5163e12c5d1SDavid du Colombier 	if(cbs == 0) {
5173e12c5d1SDavid du Colombier 		null(c);
5183e12c5d1SDavid du Colombier 		return;
5193e12c5d1SDavid du Colombier 	}
5203e12c5d1SDavid du Colombier 	if(cc == '\n') {
5213e12c5d1SDavid du Colombier 		while(cbc < cbs) {
5223e12c5d1SDavid du Colombier 			null(atoibm[' ']);
5233e12c5d1SDavid du Colombier 			cbc++;
5243e12c5d1SDavid du Colombier 		}
5253e12c5d1SDavid du Colombier 		cbc = 0;
5263e12c5d1SDavid du Colombier 		return;
5273e12c5d1SDavid du Colombier 	}
5283e12c5d1SDavid du Colombier 	if(cbc == cbs)
5293e12c5d1SDavid du Colombier 		ntrunc++;
5303e12c5d1SDavid du Colombier 	cbc++;
5313e12c5d1SDavid du Colombier 	if(cbc <= cbs)
5323e12c5d1SDavid du Colombier 		null(c);
5333e12c5d1SDavid du Colombier }
5343e12c5d1SDavid du Colombier 
5353e12c5d1SDavid du Colombier void
block(int cc)5363e12c5d1SDavid du Colombier block(int cc)
5373e12c5d1SDavid du Colombier {
5383e12c5d1SDavid du Colombier 	int c;
5393e12c5d1SDavid du Colombier 
5403e12c5d1SDavid du Colombier 	c = cc;
5413e12c5d1SDavid du Colombier 	if(cflag&UCASE && c>='a' && c<='z')
5423e12c5d1SDavid du Colombier 		c += 'A'-'a';
5433e12c5d1SDavid du Colombier 	if(cflag&LCASE && c>='A' && c<='Z')
5443e12c5d1SDavid du Colombier 		c += 'a'-'A';
5453e12c5d1SDavid du Colombier 	c &= 0377;
5463e12c5d1SDavid du Colombier 	if(cbs == 0) {
5473e12c5d1SDavid du Colombier 		null(c);
5483e12c5d1SDavid du Colombier 		return;
5493e12c5d1SDavid du Colombier 	}
5503e12c5d1SDavid du Colombier 	if(cc == '\n') {
5513e12c5d1SDavid du Colombier 		while(cbc < cbs) {
5523e12c5d1SDavid du Colombier 			null(' ');
5533e12c5d1SDavid du Colombier 			cbc++;
5543e12c5d1SDavid du Colombier 		}
5553e12c5d1SDavid du Colombier 		cbc = 0;
5563e12c5d1SDavid du Colombier 		return;
5573e12c5d1SDavid du Colombier 	}
5583e12c5d1SDavid du Colombier 	if(cbc == cbs)
5593e12c5d1SDavid du Colombier 		ntrunc++;
5603e12c5d1SDavid du Colombier 	cbc++;
5613e12c5d1SDavid du Colombier 	if(cbc <= cbs)
5623e12c5d1SDavid du Colombier 		null(c);
5633e12c5d1SDavid du Colombier }
5643e12c5d1SDavid du Colombier 
5653e12c5d1SDavid du Colombier void
term(char * status)566f425ee0bSDavid du Colombier term(char *status)
5673e12c5d1SDavid du Colombier {
5683e12c5d1SDavid du Colombier 	stats();
569f425ee0bSDavid du Colombier 	exits(status);
5703e12c5d1SDavid du Colombier }
5713e12c5d1SDavid du Colombier 
5723e12c5d1SDavid du Colombier void
stats(void)5733e12c5d1SDavid du Colombier stats(void)
5743e12c5d1SDavid du Colombier {
575dc5a79c1SDavid du Colombier 	if(quiet)
576dc5a79c1SDavid du Colombier 		return;
5773e12c5d1SDavid du Colombier 	fprint(2, "%lud+%lud records in\n", nifr, nipr);
5783e12c5d1SDavid du Colombier 	fprint(2, "%lud+%lud records out\n", nofr, nopr);
5793e12c5d1SDavid du Colombier 	if(ntrunc)
5803e12c5d1SDavid du Colombier 		fprint(2, "%lud truncated records\n", ntrunc);
5813e12c5d1SDavid du Colombier }
5823e12c5d1SDavid du Colombier 
5833e12c5d1SDavid du Colombier uchar	etoa[] =
5843e12c5d1SDavid du Colombier {
5853e12c5d1SDavid du Colombier 	0000,0001,0002,0003,0234,0011,0206,0177,
5863e12c5d1SDavid du Colombier 	0227,0215,0216,0013,0014,0015,0016,0017,
5873e12c5d1SDavid du Colombier 	0020,0021,0022,0023,0235,0205,0010,0207,
5883e12c5d1SDavid du Colombier 	0030,0031,0222,0217,0034,0035,0036,0037,
5893e12c5d1SDavid du Colombier 	0200,0201,0202,0203,0204,0012,0027,0033,
5903e12c5d1SDavid du Colombier 	0210,0211,0212,0213,0214,0005,0006,0007,
5913e12c5d1SDavid du Colombier 	0220,0221,0026,0223,0224,0225,0226,0004,
5923e12c5d1SDavid du Colombier 	0230,0231,0232,0233,0024,0025,0236,0032,
5933e12c5d1SDavid du Colombier 	0040,0240,0241,0242,0243,0244,0245,0246,
5943e12c5d1SDavid du Colombier 	0247,0250,0133,0056,0074,0050,0053,0041,
5953e12c5d1SDavid du Colombier 	0046,0251,0252,0253,0254,0255,0256,0257,
5963e12c5d1SDavid du Colombier 	0260,0261,0135,0044,0052,0051,0073,0136,
5973e12c5d1SDavid du Colombier 	0055,0057,0262,0263,0264,0265,0266,0267,
5983e12c5d1SDavid du Colombier 	0270,0271,0174,0054,0045,0137,0076,0077,
5993e12c5d1SDavid du Colombier 	0272,0273,0274,0275,0276,0277,0300,0301,
6003e12c5d1SDavid du Colombier 	0302,0140,0072,0043,0100,0047,0075,0042,
6013e12c5d1SDavid du Colombier 	0303,0141,0142,0143,0144,0145,0146,0147,
6023e12c5d1SDavid du Colombier 	0150,0151,0304,0305,0306,0307,0310,0311,
6033e12c5d1SDavid du Colombier 	0312,0152,0153,0154,0155,0156,0157,0160,
6043e12c5d1SDavid du Colombier 	0161,0162,0313,0314,0315,0316,0317,0320,
6053e12c5d1SDavid du Colombier 	0321,0176,0163,0164,0165,0166,0167,0170,
6063e12c5d1SDavid du Colombier 	0171,0172,0322,0323,0324,0325,0326,0327,
6073e12c5d1SDavid du Colombier 	0330,0331,0332,0333,0334,0335,0336,0337,
6083e12c5d1SDavid du Colombier 	0340,0341,0342,0343,0344,0345,0346,0347,
6093e12c5d1SDavid du Colombier 	0173,0101,0102,0103,0104,0105,0106,0107,
6103e12c5d1SDavid du Colombier 	0110,0111,0350,0351,0352,0353,0354,0355,
6113e12c5d1SDavid du Colombier 	0175,0112,0113,0114,0115,0116,0117,0120,
6123e12c5d1SDavid du Colombier 	0121,0122,0356,0357,0360,0361,0362,0363,
6133e12c5d1SDavid du Colombier 	0134,0237,0123,0124,0125,0126,0127,0130,
6143e12c5d1SDavid du Colombier 	0131,0132,0364,0365,0366,0367,0370,0371,
6153e12c5d1SDavid du Colombier 	0060,0061,0062,0063,0064,0065,0066,0067,
6163e12c5d1SDavid du Colombier 	0070,0071,0372,0373,0374,0375,0376,0377,
6173e12c5d1SDavid du Colombier };
6183e12c5d1SDavid du Colombier uchar	atoe[] =
6193e12c5d1SDavid du Colombier {
6203e12c5d1SDavid du Colombier 	0000,0001,0002,0003,0067,0055,0056,0057,
6213e12c5d1SDavid du Colombier 	0026,0005,0045,0013,0014,0015,0016,0017,
6223e12c5d1SDavid du Colombier 	0020,0021,0022,0023,0074,0075,0062,0046,
6233e12c5d1SDavid du Colombier 	0030,0031,0077,0047,0034,0035,0036,0037,
6243e12c5d1SDavid du Colombier 	0100,0117,0177,0173,0133,0154,0120,0175,
6253e12c5d1SDavid du Colombier 	0115,0135,0134,0116,0153,0140,0113,0141,
6263e12c5d1SDavid du Colombier 	0360,0361,0362,0363,0364,0365,0366,0367,
6273e12c5d1SDavid du Colombier 	0370,0371,0172,0136,0114,0176,0156,0157,
6283e12c5d1SDavid du Colombier 	0174,0301,0302,0303,0304,0305,0306,0307,
6293e12c5d1SDavid du Colombier 	0310,0311,0321,0322,0323,0324,0325,0326,
6303e12c5d1SDavid du Colombier 	0327,0330,0331,0342,0343,0344,0345,0346,
6313e12c5d1SDavid du Colombier 	0347,0350,0351,0112,0340,0132,0137,0155,
6323e12c5d1SDavid du Colombier 	0171,0201,0202,0203,0204,0205,0206,0207,
6333e12c5d1SDavid du Colombier 	0210,0211,0221,0222,0223,0224,0225,0226,
6343e12c5d1SDavid du Colombier 	0227,0230,0231,0242,0243,0244,0245,0246,
6353e12c5d1SDavid du Colombier 	0247,0250,0251,0300,0152,0320,0241,0007,
6363e12c5d1SDavid du Colombier 	0040,0041,0042,0043,0044,0025,0006,0027,
6373e12c5d1SDavid du Colombier 	0050,0051,0052,0053,0054,0011,0012,0033,
6383e12c5d1SDavid du Colombier 	0060,0061,0032,0063,0064,0065,0066,0010,
6393e12c5d1SDavid du Colombier 	0070,0071,0072,0073,0004,0024,0076,0341,
6403e12c5d1SDavid du Colombier 	0101,0102,0103,0104,0105,0106,0107,0110,
6413e12c5d1SDavid du Colombier 	0111,0121,0122,0123,0124,0125,0126,0127,
6423e12c5d1SDavid du Colombier 	0130,0131,0142,0143,0144,0145,0146,0147,
6433e12c5d1SDavid du Colombier 	0150,0151,0160,0161,0162,0163,0164,0165,
6443e12c5d1SDavid du Colombier 	0166,0167,0170,0200,0212,0213,0214,0215,
6453e12c5d1SDavid du Colombier 	0216,0217,0220,0232,0233,0234,0235,0236,
6463e12c5d1SDavid du Colombier 	0237,0240,0252,0253,0254,0255,0256,0257,
6473e12c5d1SDavid du Colombier 	0260,0261,0262,0263,0264,0265,0266,0267,
6483e12c5d1SDavid du Colombier 	0270,0271,0272,0273,0274,0275,0276,0277,
6493e12c5d1SDavid du Colombier 	0312,0313,0314,0315,0316,0317,0332,0333,
6503e12c5d1SDavid du Colombier 	0334,0335,0336,0337,0352,0353,0354,0355,
6513e12c5d1SDavid du Colombier 	0356,0357,0372,0373,0374,0375,0376,0377,
6523e12c5d1SDavid du Colombier };
6533e12c5d1SDavid du Colombier uchar	atoibm[] =
6543e12c5d1SDavid du Colombier {
6553e12c5d1SDavid du Colombier 	0000,0001,0002,0003,0067,0055,0056,0057,
6563e12c5d1SDavid du Colombier 	0026,0005,0045,0013,0014,0015,0016,0017,
6573e12c5d1SDavid du Colombier 	0020,0021,0022,0023,0074,0075,0062,0046,
6583e12c5d1SDavid du Colombier 	0030,0031,0077,0047,0034,0035,0036,0037,
6593e12c5d1SDavid du Colombier 	0100,0132,0177,0173,0133,0154,0120,0175,
6603e12c5d1SDavid du Colombier 	0115,0135,0134,0116,0153,0140,0113,0141,
6613e12c5d1SDavid du Colombier 	0360,0361,0362,0363,0364,0365,0366,0367,
6623e12c5d1SDavid du Colombier 	0370,0371,0172,0136,0114,0176,0156,0157,
6633e12c5d1SDavid du Colombier 	0174,0301,0302,0303,0304,0305,0306,0307,
6643e12c5d1SDavid du Colombier 	0310,0311,0321,0322,0323,0324,0325,0326,
6653e12c5d1SDavid du Colombier 	0327,0330,0331,0342,0343,0344,0345,0346,
6663e12c5d1SDavid du Colombier 	0347,0350,0351,0255,0340,0275,0137,0155,
6673e12c5d1SDavid du Colombier 	0171,0201,0202,0203,0204,0205,0206,0207,
6683e12c5d1SDavid du Colombier 	0210,0211,0221,0222,0223,0224,0225,0226,
6693e12c5d1SDavid du Colombier 	0227,0230,0231,0242,0243,0244,0245,0246,
6703e12c5d1SDavid du Colombier 	0247,0250,0251,0300,0117,0320,0241,0007,
6713e12c5d1SDavid du Colombier 	0040,0041,0042,0043,0044,0025,0006,0027,
6723e12c5d1SDavid du Colombier 	0050,0051,0052,0053,0054,0011,0012,0033,
6733e12c5d1SDavid du Colombier 	0060,0061,0032,0063,0064,0065,0066,0010,
6743e12c5d1SDavid du Colombier 	0070,0071,0072,0073,0004,0024,0076,0341,
6753e12c5d1SDavid du Colombier 	0101,0102,0103,0104,0105,0106,0107,0110,
6763e12c5d1SDavid du Colombier 	0111,0121,0122,0123,0124,0125,0126,0127,
6773e12c5d1SDavid du Colombier 	0130,0131,0142,0143,0144,0145,0146,0147,
6783e12c5d1SDavid du Colombier 	0150,0151,0160,0161,0162,0163,0164,0165,
6793e12c5d1SDavid du Colombier 	0166,0167,0170,0200,0212,0213,0214,0215,
6803e12c5d1SDavid du Colombier 	0216,0217,0220,0232,0233,0234,0235,0236,
6813e12c5d1SDavid du Colombier 	0237,0240,0252,0253,0254,0255,0256,0257,
6823e12c5d1SDavid du Colombier 	0260,0261,0262,0263,0264,0265,0266,0267,
6833e12c5d1SDavid du Colombier 	0270,0271,0272,0273,0274,0275,0276,0277,
6843e12c5d1SDavid du Colombier 	0312,0313,0314,0315,0316,0317,0332,0333,
6853e12c5d1SDavid du Colombier 	0334,0335,0336,0337,0352,0353,0354,0355,
6863e12c5d1SDavid du Colombier 	0356,0357,0372,0373,0374,0375,0376,0377,
6873e12c5d1SDavid du Colombier };
688