work with more sophisticated addresses as well as garbage ones
[unix-history] / usr / src / bin / dd / dd.c
CommitLineData
ae2da14a
BJ
1static char *sccsid = "@(#)dd.c 4.1 (Berkeley) %G%";
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
11int cflag;
12int fflag;
13int skip;
14int seekn;
15int count;
16int files = 1;
17char *string;
18char *ifile;
19char *ofile;
20char *ibuf;
21char *obuf;
22char *sbrk();
23int ibs = 512;
24int obs = 512;
25int bs;
26int cbs;
27int ibc;
28int obc;
29int cbc;
30int nifr;
31int nipr;
32int nofr;
33int nopr;
34int ntrunc;
35int ibf;
36int obf;
37char *op;
38int nspace;
39char 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};
73char 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};
107char 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
144main(argc, argv)
145int argc;
146char **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
300loop:
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
354flsh()
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
371match(s)
372char *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
383true:
384 cs--;
385 string = cs;
386 return(1);
387}
388
389number(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
428cnull(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
440null(c)
441{
442
443 *op = c;
444 op++;
445 if(++obc >= obs) {
446 flsh();
447 op = obuf;
448 }
449}
450
451ascii(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
470out:
471 if(++cbc >= cbs) {
472 null('\n');
473 cbc = 0;
474 nspace = 0;
475 }
476}
477
478unblock(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
497out:
498 if(++cbc >= cbs) {
499 null('\n');
500 cbc = 0;
501 nspace = 0;
502 }
503}
504
505ebcdic(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
534ibm(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
563block(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
592term()
593{
594
595 stats();
596 exit(0);
597}
598
599stats()
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}