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