/* * uudecode [input] * * create the specified file, decoding as you go. * used with uuencode. */ #include #include #include /* 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); }