xref: /inferno-os/appl/cmd/uuencode.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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