xref: /original-bsd/bin/dd/dd.c (revision 447ecad6)
1 static char *sccsid = "@(#)dd.c	4.1 (Berkeley) 10/01/80";
2 #include <stdio.h>
3 #include <signal.h>
4 
5 #define	BIG	2147483647
6 #define	LCASE	01
7 #define	UCASE	02
8 #define	SWAB	04
9 #define NERR	010
10 #define SYNC	020
11 int	cflag;
12 int	fflag;
13 int	skip;
14 int	seekn;
15 int	count;
16 int	files	= 1;
17 char	*string;
18 char	*ifile;
19 char	*ofile;
20 char	*ibuf;
21 char	*obuf;
22 char	*sbrk();
23 int	ibs	= 512;
24 int	obs	= 512;
25 int	bs;
26 int	cbs;
27 int	ibc;
28 int	obc;
29 int	cbc;
30 int	nifr;
31 int	nipr;
32 int	nofr;
33 int	nopr;
34 int	ntrunc;
35 int	ibf;
36 int	obf;
37 char	*op;
38 int	nspace;
39 char	etoa[] = {
40 	0000,0001,0002,0003,0234,0011,0206,0177,
41 	0227,0215,0216,0013,0014,0015,0016,0017,
42 	0020,0021,0022,0023,0235,0205,0010,0207,
43 	0030,0031,0222,0217,0034,0035,0036,0037,
44 	0200,0201,0202,0203,0204,0012,0027,0033,
45 	0210,0211,0212,0213,0214,0005,0006,0007,
46 	0220,0221,0026,0223,0224,0225,0226,0004,
47 	0230,0231,0232,0233,0024,0025,0236,0032,
48 	0040,0240,0241,0242,0243,0244,0245,0246,
49 	0247,0250,0133,0056,0074,0050,0053,0041,
50 	0046,0251,0252,0253,0254,0255,0256,0257,
51 	0260,0261,0135,0044,0052,0051,0073,0136,
52 	0055,0057,0262,0263,0264,0265,0266,0267,
53 	0270,0271,0174,0054,0045,0137,0076,0077,
54 	0272,0273,0274,0275,0276,0277,0300,0301,
55 	0302,0140,0072,0043,0100,0047,0075,0042,
56 	0303,0141,0142,0143,0144,0145,0146,0147,
57 	0150,0151,0304,0305,0306,0307,0310,0311,
58 	0312,0152,0153,0154,0155,0156,0157,0160,
59 	0161,0162,0313,0314,0315,0316,0317,0320,
60 	0321,0176,0163,0164,0165,0166,0167,0170,
61 	0171,0172,0322,0323,0324,0325,0326,0327,
62 	0330,0331,0332,0333,0334,0335,0336,0337,
63 	0340,0341,0342,0343,0344,0345,0346,0347,
64 	0173,0101,0102,0103,0104,0105,0106,0107,
65 	0110,0111,0350,0351,0352,0353,0354,0355,
66 	0175,0112,0113,0114,0115,0116,0117,0120,
67 	0121,0122,0356,0357,0360,0361,0362,0363,
68 	0134,0237,0123,0124,0125,0126,0127,0130,
69 	0131,0132,0364,0365,0366,0367,0370,0371,
70 	0060,0061,0062,0063,0064,0065,0066,0067,
71 	0070,0071,0372,0373,0374,0375,0376,0377,
72 };
73 char	atoe[] = {
74 	0000,0001,0002,0003,0067,0055,0056,0057,
75 	0026,0005,0045,0013,0014,0015,0016,0017,
76 	0020,0021,0022,0023,0074,0075,0062,0046,
77 	0030,0031,0077,0047,0034,0035,0036,0037,
78 	0100,0117,0177,0173,0133,0154,0120,0175,
79 	0115,0135,0134,0116,0153,0140,0113,0141,
80 	0360,0361,0362,0363,0364,0365,0366,0367,
81 	0370,0371,0172,0136,0114,0176,0156,0157,
82 	0174,0301,0302,0303,0304,0305,0306,0307,
83 	0310,0311,0321,0322,0323,0324,0325,0326,
84 	0327,0330,0331,0342,0343,0344,0345,0346,
85 	0347,0350,0351,0112,0340,0132,0137,0155,
86 	0171,0201,0202,0203,0204,0205,0206,0207,
87 	0210,0211,0221,0222,0223,0224,0225,0226,
88 	0227,0230,0231,0242,0243,0244,0245,0246,
89 	0247,0250,0251,0300,0152,0320,0241,0007,
90 	0040,0041,0042,0043,0044,0025,0006,0027,
91 	0050,0051,0052,0053,0054,0011,0012,0033,
92 	0060,0061,0032,0063,0064,0065,0066,0010,
93 	0070,0071,0072,0073,0004,0024,0076,0341,
94 	0101,0102,0103,0104,0105,0106,0107,0110,
95 	0111,0121,0122,0123,0124,0125,0126,0127,
96 	0130,0131,0142,0143,0144,0145,0146,0147,
97 	0150,0151,0160,0161,0162,0163,0164,0165,
98 	0166,0167,0170,0200,0212,0213,0214,0215,
99 	0216,0217,0220,0232,0233,0234,0235,0236,
100 	0237,0240,0252,0253,0254,0255,0256,0257,
101 	0260,0261,0262,0263,0264,0265,0266,0267,
102 	0270,0271,0272,0273,0274,0275,0276,0277,
103 	0312,0313,0314,0315,0316,0317,0332,0333,
104 	0334,0335,0336,0337,0352,0353,0354,0355,
105 	0356,0357,0372,0373,0374,0375,0376,0377,
106 };
107 char	atoibm[] =
108 {
109 	0000,0001,0002,0003,0067,0055,0056,0057,
110 	0026,0005,0045,0013,0014,0015,0016,0017,
111 	0020,0021,0022,0023,0074,0075,0062,0046,
112 	0030,0031,0077,0047,0034,0035,0036,0037,
113 	0100,0132,0177,0173,0133,0154,0120,0175,
114 	0115,0135,0134,0116,0153,0140,0113,0141,
115 	0360,0361,0362,0363,0364,0365,0366,0367,
116 	0370,0371,0172,0136,0114,0176,0156,0157,
117 	0174,0301,0302,0303,0304,0305,0306,0307,
118 	0310,0311,0321,0322,0323,0324,0325,0326,
119 	0327,0330,0331,0342,0343,0344,0345,0346,
120 	0347,0350,0351,0255,0340,0275,0137,0155,
121 	0171,0201,0202,0203,0204,0205,0206,0207,
122 	0210,0211,0221,0222,0223,0224,0225,0226,
123 	0227,0230,0231,0242,0243,0244,0245,0246,
124 	0247,0250,0251,0300,0117,0320,0241,0007,
125 	0040,0041,0042,0043,0044,0025,0006,0027,
126 	0050,0051,0052,0053,0054,0011,0012,0033,
127 	0060,0061,0032,0063,0064,0065,0066,0010,
128 	0070,0071,0072,0073,0004,0024,0076,0341,
129 	0101,0102,0103,0104,0105,0106,0107,0110,
130 	0111,0121,0122,0123,0124,0125,0126,0127,
131 	0130,0131,0142,0143,0144,0145,0146,0147,
132 	0150,0151,0160,0161,0162,0163,0164,0165,
133 	0166,0167,0170,0200,0212,0213,0214,0215,
134 	0216,0217,0220,0232,0233,0234,0235,0236,
135 	0237,0240,0252,0253,0254,0255,0256,0257,
136 	0260,0261,0262,0263,0264,0265,0266,0267,
137 	0270,0271,0272,0273,0274,0275,0276,0277,
138 	0312,0313,0314,0315,0316,0317,0332,0333,
139 	0334,0335,0336,0337,0352,0353,0354,0355,
140 	0356,0357,0372,0373,0374,0375,0376,0377,
141 };
142 
143 
144 main(argc, argv)
145 int	argc;
146 char	**argv;
147 {
148 	int (*conv)();
149 	register char *ip;
150 	register c;
151 	int ebcdic(), ibm(), ascii(), null(), cnull(), term(), block(), unblock();
152 	int a;
153 
154 	conv = null;
155 	for(c=1; c<argc; c++) {
156 		string = argv[c];
157 		if(match("ibs=")) {
158 			ibs = number(BIG);
159 			continue;
160 		}
161 		if(match("obs=")) {
162 			obs = number(BIG);
163 			continue;
164 		}
165 		if(match("cbs=")) {
166 			cbs = number(BIG);
167 			continue;
168 		}
169 		if (match("bs=")) {
170 			bs = number(BIG);
171 			continue;
172 		}
173 		if(match("if=")) {
174 			ifile = string;
175 			continue;
176 		}
177 		if(match("of=")) {
178 			ofile = string;
179 			continue;
180 		}
181 		if(match("skip=")) {
182 			skip = number(BIG);
183 			continue;
184 		}
185 		if(match("seek=")) {
186 			seekn = number(BIG);
187 			continue;
188 		}
189 		if(match("count=")) {
190 			count = number(BIG);
191 			continue;
192 		}
193 		if(match("files=")) {
194 			files = number(BIG);
195 			continue;
196 		}
197 		if(match("conv=")) {
198 		cloop:
199 			if(match(","))
200 				goto cloop;
201 			if(*string == '\0')
202 				continue;
203 			if(match("ebcdic")) {
204 				conv = ebcdic;
205 				goto cloop;
206 			}
207 			if(match("ibm")) {
208 				conv = ibm;
209 				goto cloop;
210 			}
211 			if(match("ascii")) {
212 				conv = ascii;
213 				goto cloop;
214 			}
215 			if(match("block")) {
216 				conv = block;
217 				goto cloop;
218 			}
219 			if(match("unblock")) {
220 				conv = unblock;
221 				goto cloop;
222 			}
223 			if(match("lcase")) {
224 				cflag |= LCASE;
225 				goto cloop;
226 			}
227 			if(match("ucase")) {
228 				cflag |= UCASE;
229 				goto cloop;
230 			}
231 			if(match("swab")) {
232 				cflag |= SWAB;
233 				goto cloop;
234 			}
235 			if(match("noerror")) {
236 				cflag |= NERR;
237 				goto cloop;
238 			}
239 			if(match("sync")) {
240 				cflag |= SYNC;
241 				goto cloop;
242 			}
243 		}
244 		fprintf(stderr,"bad arg: %s\n", string);
245 		exit(0);
246 	}
247 	if(conv == null && cflag&(LCASE|UCASE))
248 		conv = cnull;
249 	if (ifile)
250 		ibf = open(ifile, 0);
251 	else
252 		ibf = dup(0);
253 	if(ibf < 0) {
254 		fprintf(stderr,"cannot open: %s\n", ifile);
255 		exit(0);
256 	}
257 	if (ofile)
258 		obf = creat(ofile, 0666);
259 	else
260 		obf = dup(1);
261 	if(obf < 0) {
262 		fprintf(stderr,"cannot create: %s\n", ofile);
263 		exit(0);
264 	}
265 	if (bs) {
266 		ibs = obs = bs;
267 		if (conv == null)
268 			fflag++;
269 	}
270 	if(ibs == 0 || obs == 0) {
271 		fprintf(stderr,"counts: cannot be zero\n");
272 		exit(0);
273 	}
274 	ibuf = sbrk(ibs);
275 	if (fflag)
276 		obuf = ibuf;
277 	else
278 		obuf = sbrk(obs);
279 	sbrk(64);	/* For good measure */
280 	if(ibuf == (char *)-1 || obuf == (char *)-1) {
281 		fprintf(stderr, "not enough memory\n");
282 		exit(0);
283 	}
284 	ibc = 0;
285 	obc = 0;
286 	cbc = 0;
287 	op = obuf;
288 
289 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
290 		signal(SIGINT, term);
291 	while(skip) {
292 		read(ibf, ibuf, ibs);
293 		skip--;
294 	}
295 	while(seekn) {
296 		lseek(obf, (long)obs, 1);
297 		seekn--;
298 	}
299 
300 loop:
301 	if(ibc-- == 0) {
302 		ibc = 0;
303 		if(count==0 || nifr+nipr!=count) {
304 			if(cflag&(NERR|SYNC))
305 			for(ip=ibuf+ibs; ip>ibuf;)
306 				*--ip = 0;
307 			ibc = read(ibf, ibuf, ibs);
308 		}
309 		if(ibc == -1) {
310 			perror("read");
311 			if((cflag&NERR) == 0) {
312 				flsh();
313 				term();
314 			}
315 			ibc = 0;
316 			for(c=0; c<ibs; c++)
317 				if(ibuf[c] != 0)
318 					ibc = c;
319 			stats();
320 		}
321 		if(ibc == 0 && --files<=0) {
322 			flsh();
323 			term();
324 		}
325 		if(ibc != ibs) {
326 			nipr++;
327 			if(cflag&SYNC)
328 				ibc = ibs;
329 		} else
330 			nifr++;
331 		ip = ibuf;
332 		c = (ibc>>1) & ~1;
333 		if(cflag&SWAB && c)
334 		do {
335 			a = *ip++;
336 			ip[-1] = *ip;
337 			*ip++ = a;
338 		} while(--c);
339 		ip = ibuf;
340 		if (fflag) {
341 			obc = ibc;
342 			flsh();
343 			ibc = 0;
344 		}
345 		goto loop;
346 	}
347 	c = 0;
348 	c |= *ip++;
349 	c &= 0377;
350 	(*conv)(c);
351 	goto loop;
352 }
353 
354 flsh()
355 {
356 	register c;
357 
358 	if(obc) {
359 		if(obc == obs)
360 			nofr++; else
361 			nopr++;
362 		c = write(obf, obuf, obc);
363 		if(c != obc) {
364 			perror("write");
365 			term();
366 		}
367 		obc = 0;
368 	}
369 }
370 
371 match(s)
372 char *s;
373 {
374 	register char *cs;
375 
376 	cs = string;
377 	while(*cs++ == *s)
378 		if(*s++ == '\0')
379 			goto true;
380 	if(*s != '\0')
381 		return(0);
382 
383 true:
384 	cs--;
385 	string = cs;
386 	return(1);
387 }
388 
389 number(big)
390 {
391 	register char *cs;
392 	long n;
393 
394 	cs = string;
395 	n = 0;
396 	while(*cs >= '0' && *cs <= '9')
397 		n = n*10 + *cs++ - '0';
398 	for(;;)
399 	switch(*cs++) {
400 
401 	case 'k':
402 		n *= 1024;
403 		continue;
404 
405 	case 'w':
406 		n *= sizeof(int);
407 		continue;
408 
409 	case 'b':
410 		n *= 512;
411 		continue;
412 
413 	case '*':
414 	case 'x':
415 		string = cs;
416 		n *= number(BIG);
417 
418 	case '\0':
419 		if (n>=big || n<0) {
420 			fprintf(stderr, "dd: argument %D out of range\n", n);
421 			exit(1);
422 		}
423 		return(n);
424 	}
425 	/* never gets here */
426 }
427 
428 cnull(cc)
429 {
430 	register c;
431 
432 	c = cc;
433 	if(cflag&UCASE && c>='a' && c<='z')
434 		c += 'A'-'a';
435 	if(cflag&LCASE && c>='A' && c<='Z')
436 		c += 'a'-'A';
437 	null(c);
438 }
439 
440 null(c)
441 {
442 
443 	*op = c;
444 	op++;
445 	if(++obc >= obs) {
446 		flsh();
447 		op = obuf;
448 	}
449 }
450 
451 ascii(cc)
452 {
453 	register c;
454 
455 	c = etoa[cc] & 0377;
456 	if(cbs == 0) {
457 		cnull(c);
458 		return;
459 	}
460 	if(c == ' ') {
461 		nspace++;
462 		goto out;
463 	}
464 	while(nspace > 0) {
465 		null(' ');
466 		nspace--;
467 	}
468 	cnull(c);
469 
470 out:
471 	if(++cbc >= cbs) {
472 		null('\n');
473 		cbc = 0;
474 		nspace = 0;
475 	}
476 }
477 
478 unblock(cc)
479 {
480 	register c;
481 
482 	c = cc & 0377;
483 	if(cbs == 0) {
484 		cnull(c);
485 		return;
486 	}
487 	if(c == ' ') {
488 		nspace++;
489 		goto out;
490 	}
491 	while(nspace > 0) {
492 		null(' ');
493 		nspace--;
494 	}
495 	cnull(c);
496 
497 out:
498 	if(++cbc >= cbs) {
499 		null('\n');
500 		cbc = 0;
501 		nspace = 0;
502 	}
503 }
504 
505 ebcdic(cc)
506 {
507 	register c;
508 
509 	c = cc;
510 	if(cflag&UCASE && c>='a' && c<='z')
511 		c += 'A'-'a';
512 	if(cflag&LCASE && c>='A' && c<='Z')
513 		c += 'a'-'A';
514 	c = atoe[c] & 0377;
515 	if(cbs == 0) {
516 		null(c);
517 		return;
518 	}
519 	if(cc == '\n') {
520 		while(cbc < cbs) {
521 			null(atoe[' ']);
522 			cbc++;
523 		}
524 		cbc = 0;
525 		return;
526 	}
527 	if(cbc == cbs)
528 		ntrunc++;
529 	cbc++;
530 	if(cbc <= cbs)
531 		null(c);
532 }
533 
534 ibm(cc)
535 {
536 	register c;
537 
538 	c = cc;
539 	if(cflag&UCASE && c>='a' && c<='z')
540 		c += 'A'-'a';
541 	if(cflag&LCASE && c>='A' && c<='Z')
542 		c += 'a'-'A';
543 	c = atoibm[c] & 0377;
544 	if(cbs == 0) {
545 		null(c);
546 		return;
547 	}
548 	if(cc == '\n') {
549 		while(cbc < cbs) {
550 			null(atoibm[' ']);
551 			cbc++;
552 		}
553 		cbc = 0;
554 		return;
555 	}
556 	if(cbc == cbs)
557 		ntrunc++;
558 	cbc++;
559 	if(cbc <= cbs)
560 		null(c);
561 }
562 
563 block(cc)
564 {
565 	register c;
566 
567 	c = cc;
568 	if(cflag&UCASE && c>='a' && c<='z')
569 		c += 'A'-'a';
570 	if(cflag&LCASE && c>='A' && c<='Z')
571 		c += 'a'-'A';
572 	c &= 0377;
573 	if(cbs == 0) {
574 		null(c);
575 		return;
576 	}
577 	if(cc == '\n') {
578 		while(cbc < cbs) {
579 			null(' ');
580 			cbc++;
581 		}
582 		cbc = 0;
583 		return;
584 	}
585 	if(cbc == cbs)
586 		ntrunc++;
587 	cbc++;
588 	if(cbc <= cbs)
589 		null(c);
590 }
591 
592 term()
593 {
594 
595 	stats();
596 	exit(0);
597 }
598 
599 stats()
600 {
601 
602 	fprintf(stderr,"%u+%u records in\n", nifr, nipr);
603 	fprintf(stderr,"%u+%u records out\n", nofr, nopr);
604 	if(ntrunc)
605 		fprintf(stderr,"%u truncated records\n", ntrunc);
606 }
607