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