/*
* uudecode [input]
*
* create the specified file, decoding as you go.
* used with uuencode.
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
/* single character decode */
#define DEC(c) (((c) - ' ') & 077)
static void decode(Biobuf*, Biobuf*);
static void outdec(char*, Biobuf*, int);
void
main(int argc, char **argv)
{
int mode;
int fd;
char *line, *dest;
static Biobuf bin, bout;
/* optional input arg */
if(argc > 1) {
if((fd = open(argv[1], OREAD)) < 0) {
fprint(2, "uudecode: can't open %s: %r\n", argv[1]);
exits("open");
}
argc--; argv++;
USED(argv);
} else
fd = 0;
if(argc != 1) {
fprint(2, "Usage: uudecode [infile]\n");
exits("usage");
}
Binit(&bin, fd, OREAD);
/* search for header line */
do {
if((line = Brdline(&bin, '\n')) == 0) {
fprint(2, "uudecode: no begin line\n");
exits("format");
}
} while(Blinelen(&bin) < 5 || strncmp(line, "begin", 5) != 0);
line[Blinelen(&bin)-1] = 0;
mode = strtoul(line+5, &dest, 8);
while(*dest == ' ')
dest++;
if(*dest == 0) {
fprint(2, "uudecode: bad header line\n");
exits("format");
}
if(*dest == '~') {
/* can't be bothered */
fprint(2, "uudecode: ~user format not supported\n");
exits("open");
}
fd = create(dest, OWRITE, mode);
if(fd < 0) {
fprint(2, "uudecode: can't create %s: %r\n", dest);
exits("open");
}
Binit(&bout, fd, OWRITE);
decode(&bin, &bout);
if((line = Brdline(&bin, '\n')) == 0 || strncmp(line, "end\n", 4) != 0) {
fprint(2, "uudecode: no end line\n");
exits("format");
}
if(Bterm(&bout)) {
fprint(2, "uudecode: error writing %s: %r\n", dest);
exits("output");
}
exits(0);
}
/*
* copy from in to out, decoding as you go along.
*/
static void
decode(Biobuf *in, Biobuf *out)
{
char *lp;
int n;
for(;;) {
/* for each input line */
lp = Brdline(in, '\n');
if(lp == 0) {
fprint(2, "uudecode: unexpected end-of-file\n");
exits("format");
}
n = DEC(*lp++);
if(n <= 0)
break;
if(n >= Blinelen(in)) {
fprint(2, "uudecode: corrupt input file\n");
exits("format");
}
for(; n > 0; lp += 4, n -= 3)
outdec(lp, out, n);
}
}
/*
* output a group of 3 bytes (4 input characters).
* the input chars are pointed to by p, they are to
* be output to file f. n is used to tell us not to
* output all of them at the end of the file.
*/
static void
outdec(char *p, Biobuf *f, int n)
{
int c1, c2, c3;
c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
c3 = DEC(p[2]) << 6 | DEC(p[3]);
if(n >= 1)
BPUTC(f, c1);
if(n >= 2)
BPUTC(f, c2);
if(n >= 3)
BPUTC(f, c3);
}
|