summaryrefslogtreecommitdiff
path: root/appl/cmd/uudecode.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/uudecode.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/uudecode.b')
-rw-r--r--appl/cmd/uudecode.b132
1 files changed, 132 insertions, 0 deletions
diff --git a/appl/cmd/uudecode.b b/appl/cmd/uudecode.b
new file mode 100644
index 00000000..12894aa3
--- /dev/null
+++ b/appl/cmd/uudecode.b
@@ -0,0 +1,132 @@
+implement Uudecode;
+
+include "sys.m";
+ sys : Sys;
+include "draw.m";
+include "string.m";
+ str : String;
+include "bufio.m";
+ bufio : Bufio;
+ Iobuf : import bufio;
+
+Uudecode : module
+{
+ init : fn(nil : ref Draw->Context, argv : list of string);
+};
+
+fatal(s : string)
+{
+ sys->fprint(sys->fildes(2), "%s\n", s);
+ exit;
+}
+
+usage()
+{
+ fatal("usage: uudecode [ -p ] [ encodedfile... ]");
+}
+
+init(nil : ref Draw->Context, argv : list of string)
+{
+ fd : ref Sys->FD;
+
+ tostdout := 0;
+ sys = load Sys Sys->PATH;
+ str = load String String->PATH;
+ bufio = load Bufio Bufio->PATH;
+ argv = tl argv;
+ if (argv != nil && hd argv == "-p") {
+ tostdout = 1;
+ argv = tl argv;
+ }
+ if (argv != nil) {
+ for (; argv != nil; argv = tl argv) {
+ fd = sys->open(hd argv, Sys->OREAD);
+ if (fd == nil)
+ fatal(sys->sprint("cannot open %s", hd argv));
+ decode(fd, tostdout);
+ }
+ }
+ else
+ decode(sys->fildes(0), tostdout);
+}
+
+code(c : byte) : int
+{
+ return (int c - ' ')&16r3f;
+}
+
+LEN : con 45;
+
+decode(ifd : ref Sys->FD, tostdout : int)
+{
+ mode : int;
+ ofile : string;
+
+ bio := bufio->fopen(ifd, Bufio->OREAD);
+ if (bio == nil)
+ fatal("cannot open input for buffered io: %r");
+ while ((s := bio.gets('\n')) != nil) {
+ if (len s >= 6 && s[0:6] == "begin ") {
+ (n, l) := sys->tokenize(s, " \n");
+ if (n < 3)
+ fatal("bad begin line");
+ (mode, nil) = str->toint(hd tl l, 8);
+ ofile = hd tl tl l;
+ break;
+ }
+ }
+ if (ofile == nil)
+ fatal("no begin line");
+ if (tostdout)
+ ofd := sys->fildes(1);
+ else {
+ if (ofile[0] == '~') # ~user/file
+ ofile = "/usr/" + ofile[1:];
+ ofd = sys->create(ofile, Sys->OWRITE, 8r666);
+ if (ofd == nil)
+ fatal(sys->sprint("cannot create %s: %r", ofile));
+ }
+ ob := array[LEN] of byte;
+ while ((s = bio.gets('\n')) != nil) {
+ b := array of byte s;
+ n := code(b[0]);
+ if (n == 0 && (len b != 2 || b[1] != byte '\n'))
+ fatal("bad 0 count line");
+ if (n <= 0)
+ break;
+ if (n > LEN)
+ fatal("too many bytes on line");
+ e := 0; f := 0;
+ if (n%3 == 1) {
+ e = 2; f = 4;
+ }
+ else if (n%3 == 2) {
+ e = 3; f = 4;
+ }
+ if (len b < 4*(n/3)+e+2 || len b > 4*(n/3)+f+2)
+ fatal("bad uuencode count");
+ b = b[1:];
+ i := 0;
+ nl := n;
+ for (j := 0; nl > 0; j += 4) {
+ if (nl >= 1)
+ ob[i++] = byte (code(b[j+0])<<2 | code(b[j+1])>>4);
+ if (nl >= 2)
+ ob[i++] = byte (code(b[j+1])<<4 | code(b[j+2])>>2);
+ if (nl >= 3)
+ ob[i++] = byte (code(b[j+2])<<6 | code(b[j+3])>>0);
+ nl -= 3;
+ }
+ if (sys->write(ofd, ob, i) != i)
+ fatal("bad write to output: %r");
+ }
+ s = bio.gets('\n');
+ if (s == nil || len s < 4 || s[0:4] != "end\n")
+ fatal("missing end line");
+ if (!tostdout) {
+ d := sys->nulldir;
+ d.mode = mode;
+ if (sys->fwstat(ofd, d) < 0)
+ fatal(sys->sprint("cannot wstat %s: %r", ofile));
+ }
+}