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