/*
* uuencode [input] output
*
* Encode a file so it can be mailed to a remote system.
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) (((c) & 077) + ' ')
static void encode(int, Biobuf*);
static void chunk(char*, int, Biobuf*);
static void outdec(char*, Biobuf*);
void
main(int argc, char **argv)
{
Dir *d;
int fd;
Biobuf bout;
/* optional 1st argument */
if (argc > 2) {
if ((fd = open(argv[1], OREAD)) < 0) {
fprint(2, "uuencode: can't open %s: %r\n", argv[1]);
exits("open");
}
argv++; argc--; USED(argv);
} else
fd = 0;
if (argc != 2) {
fprint(2, "Usage: uuencode [infile] remotefile\n");
exits("usage");
}
Binit(&bout, 1, OWRITE);
d = dirfstat(fd);
Bprint(&bout, "begin %ulo %s\n", (d)? d->mode & 0777: 0666, argv[1]);
free(d);
encode(fd, &bout);
Bprint(&bout, "end\n");
if (Bflush(&bout)) {
fprint(2, "uuencode: error writing output: %r\n");
exits("output");
}
exits(0);
}
/*
* copy from in to out, encoding as you go along.
*/
static void
encode(int in, Biobuf *out)
{
char buf[(Bsize/45)*45]; /* chunks of up to 45 characters */
char *p;
int n, r;
r = 0;
p = buf;
while((n = read(in, buf, sizeof(buf))) > 0)
for(p = buf, r = n; r >= 45; r -= 45, p += 45)
chunk(p, 45, out);
if(n < 0) {
fprint(2, "uuencode: read error: %r\n");
exits("read");
}
if(r)
chunk(p, r, out);
chunk(buf, 0, out);
}
static void
chunk(char *p, int n, Biobuf *out)
{
int i;
BPUTC(out, ENC(n));
for(i = 0; i < n; i += 3)
outdec(p+i, out);
BPUTC(out, '\n');
}
/*
* output one group of 3 bytes, pointed at by p, on file f.
*/
static void
outdec(char *p, Biobuf *f)
{
int c1, c2, c3, c4;
c1 = *p >> 2;
c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
c4 = p[2] & 077;
BPUTC(f, ENC(c1));
BPUTC(f, ENC(c2));
BPUTC(f, ENC(c3));
BPUTC(f, ENC(c4));
}
|