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