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