1implement Uuencode; 2 3include "sys.m"; 4 sys : Sys; 5include "draw.m"; 6 7Uuencode : module 8{ 9 init : fn(nil : ref Draw->Context, argv : list of string); 10}; 11 12fatal(s : string) 13{ 14 sys->fprint(sys->fildes(2), "%s\n", s); 15 exit; 16} 17 18usage() 19{ 20 fatal("usage: uuencode [ sourcefile ] remotefile"); 21} 22 23init(nil : ref Draw->Context, argv : list of string) 24{ 25 fd : ref Sys->FD; 26 mode : int; 27 28 sys = load Sys Sys->PATH; 29 argv = tl argv; 30 if (argv == nil) 31 usage(); 32 if (tl argv != nil) { 33 fd = sys->open(hd argv, Sys->OREAD); 34 if (fd == nil) 35 fatal(sys->sprint("cannot open %s", hd argv)); 36 (ok, d) := sys->fstat(fd); 37 if (ok < 0) 38 fatal(sys->sprint("cannot stat %s: %r", hd argv)); 39 if (d.mode & Sys->DMDIR) 40 fatal("cannot uuencode a directory"); 41 mode = d.mode; 42 argv = tl argv; 43 } 44 else { 45 fd = sys->fildes(0); 46 mode = 8r666; 47 } 48 if (tl argv != nil) 49 usage(); 50 sys->print("begin %o %s\n", mode, hd argv); 51 encode(fd); 52 sys->print("end\n"); 53} 54 55LEN : con 45; 56 57code(c : int) : byte 58{ 59 return byte ((c&16r3f) + ' '); 60} 61 62encode(ifd : ref Sys->FD) 63{ 64 c, d, e : int; 65 66 ofd := sys->fildes(1); 67 ib := array[LEN] of byte; 68 ob := array[4*LEN/3 + 2] of byte; 69 for (;;) { 70 n := sys->read(ifd, ib, LEN); 71 if (n < 0) 72 fatal("cannot read input file: %r"); 73 if (n == 0) 74 break; 75 i := 0; 76 ob[i++] = code(n); 77 for (j := 0; j < n; j += 3) { 78 c = int ib[j]; 79 ob[i++] = code((0<<6)&16r00 | (c>>2)&16r3f); 80 if (j+1 < n) 81 d = int ib[j+1]; 82 else 83 d = 0; 84 ob[i++] = code((c<<4)&16r30 | (d>>4)&16r0f); 85 if (j+2 < n) 86 e = int ib[j+2]; 87 else 88 e = 0; 89 ob[i++] = code((d<<2)&16r3c | (e>>6)&16r03); 90 ob[i++] = code((e<<0)&16r3f | (0>>8)&16r00); 91 } 92 ob[i++] = byte '\n'; 93 if (sys->write(ofd, ob, i) != i) 94 fatal("bad write to output: %r"); 95 } 96 ob[0] = code(0); 97 ob[1] = byte '\n'; 98 if (sys->write(ofd, ob, 2) != 2) 99 fatal("bad write to output: %r"); 100} 101 102