return error message to the user
[unix-history] / usr / src / bin / dd / dd.c
CommitLineData
794629bf 1#ifndef lint
6b536233 2static char *sccsid = "@(#)dd.c 4.7 (Berkeley) %G%";
794629bf
RC
3#endif
4
618938d5 5#include <sys/file.h>
ae2da14a
BJ
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
15int cflag;
16int fflag;
17int skip;
18int seekn;
19int count;
20int files = 1;
21char *string;
22char *ifile;
23char *ofile;
24char *ibuf;
25char *obuf;
26char *sbrk();
27int ibs = 512;
28int obs = 512;
29int bs;
30int cbs;
31int ibc;
32int obc;
33int cbc;
34int nifr;
35int nipr;
36int nofr;
37int nopr;
38int ntrunc;
39int ibf;
40int obf;
41char *op;
42int nspace;
43char 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};
77char 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};
111char 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
148main(argc, argv)
149int argc;
150char **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);
794629bf 249 exit(1);
ae2da14a
BJ
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) {
78d90aa3 258 perror(ifile);
794629bf 259 exit(1);
ae2da14a 260 }
618938d5 261 obf = ofile ? open(ofile, O_WRONLY|O_CREAT, 0666) : dup(1);
ae2da14a
BJ
262 if(obf < 0) {
263 fprintf(stderr,"cannot create: %s\n", ofile);
794629bf 264 exit(1);
ae2da14a
BJ
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");
794629bf 273 exit(1);
ae2da14a
BJ
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");
794629bf 283 exit(1);
ae2da14a
BJ
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
301loop:
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;
bdaac907 333 c = ibc >> 1;
ae2da14a
BJ
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
355flsh()
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
372match(s)
373char *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
384true:
385 cs--;
386 string = cs;
387 return(1);
388}
389
390number(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) {
5997b76f 421 fprintf(stderr, "dd: argument %ld out of range\n", n);
ae2da14a
BJ
422 exit(1);
423 }
424 return(n);
425 }
426 /* never gets here */
427}
428
429cnull(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
441null(c)
442{
443
444 *op = c;
445 op++;
446 if(++obc >= obs) {
447 flsh();
448 op = obuf;
449 }
450}
451
452ascii(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
471out:
472 if(++cbc >= cbs) {
473 null('\n');
474 cbc = 0;
475 nspace = 0;
476 }
477}
478
479unblock(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
498out:
499 if(++cbc >= cbs) {
500 null('\n');
501 cbc = 0;
502 nspace = 0;
503 }
504}
505
506ebcdic(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
535ibm(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
564block(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
593term()
594{
595
596 stats();
597 exit(0);
598}
599
600stats()
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}