diff options
-rw-r--r-- | toys/pending/uudecode.c | 89 |
1 files changed, 37 insertions, 52 deletions
diff --git a/toys/pending/uudecode.c b/toys/pending/uudecode.c index abd8414f..576b8faf 100644 --- a/toys/pending/uudecode.c +++ b/toys/pending/uudecode.c @@ -24,66 +24,44 @@ GLOBALS( char *o; ) -/* - * Turn a character back into a value. - * The smallest valid character is 0x2B ('+') - * The biggest valid character is 0x7A ('z') - * We can make a table of 16*5 entries to cover 0x2B - 0x7A - */ - static inline signed char uudecode_b64_1byte(char in) { - char ret; - static const signed char table[16*5] = { - /* '+' (0x2B) is 62, '/'(0x2F) is 63, rest invalid */ - 62, -1, -1, -1, 63, - /* '0'-'9' are values 52-61, rest of 0x3A - 0x3F is invalid, = is special... */ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - /* '@' is invalid, 'A'-'Z' are values 0-25, 0x5b - 0x5F are invalid */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - /* '`' is invalid, 'a'-'z' are values 26-51, 0x7B - 0x7F are invalid */ - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - in &= 0x7f; - if (in < '+') return -1; - if (in > 'z') return -1; - in -= '+'; - ret = table[in]; + if (in >= 'A' && in <= 'Z') return in-'A'; + if (in >= 'a' && in <= 'z') return in-'a'+26; + if (in >= '0' && in <= '9') return in-'0'+52; + if (in == '+') return 62; + if (in == '/') return 63; - return ret; + return -1; }; -/* Returns length put in out */ -static int uudecode_b64_4bytes(char *out, const char *in) +static int uudecode_b64_4bytes(char *out, char *in) { - unsigned int i, x=0; - signed char b0, b1, b2, b3; - int len = 3; - - b0 = uudecode_b64_1byte(in[0]); - b1 = uudecode_b64_1byte(in[1]); - b2 = uudecode_b64_1byte(in[2]); - b3 = uudecode_b64_1byte(in[3]); - if ((b1 < 0) || (b0 < 0)) return 0; - if (b3 < 0) len--; - if (b2 < 0) len--; - x = ((b0 & 0x3f)<<18) | ((b1 & 0x3f)<<12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); - for (i = 0; i < len; i++) *out++ = (x>>(8*(2-i))) & 0x0ff; + int i, len = 3; + unsigned x = 0; + + for (i=0; i<4; i++) { + int c = in[i]; + + if (c == '=') len--; + else if (len != 3) len = 0; + if (!len) error_exit("bad input"); + + x |= uudecode_b64_1byte(c) << (6*(3-i)); + if (i && i <= len) *(out++) = (x>>(8*(3-i))) & 0xff; + } return len; } -static void uudecode_b64_line(int ofd, const char *in, int ilen) +static void uudecode_b64_line(int ofd, char *in, int ilen) { int olen; char out[4]; while (ilen >= 4) { - olen = uudecode_b64_4bytes(out,in); + olen = uudecode_b64_4bytes(out, in); xwrite(ofd,out,olen); in += 4; ilen -= 4; @@ -104,7 +82,7 @@ static void uudecode_b64(int ifd, int ofd) } -static void uudecode_uu_4bytes(char *out, const char *in, int len) +static void uudecode_uu_4bytes(char *out, char *in, int len) { unsigned int i,x=0; @@ -113,7 +91,7 @@ static void uudecode_uu_4bytes(char *out, const char *in, int len) for (i = 0; i < len; i++) *out++ = x >> (8*(2-i)); } -static void uudecode_uu_line(int ofd, const char *in) +static void uudecode_uu_line(int ofd, char *in) { int olen = in[0] - 32; char buf[4]; @@ -131,11 +109,15 @@ static void uudecode_uu(int ifd, int ofd) { char *line = NULL; - while ((line = get_line(ifd)) != NULL) { - if (line[0] == '`') break; - if (!strncmp(line, "end", 3)) break; - if (strlen(line) < 1) break; - uudecode_uu_line(ofd,line); + for (;;) { + if (!(line = get_line(ifd))) break; + if (*line) { + if (!strncmp(line, "end", 3)) { + free(line); + break; + } + uudecode_uu_line(ofd,line); + } free(line); } } @@ -159,7 +141,10 @@ void uudecode_main(void) if (idx) decoder = uudecode_b64; } - if (!idx) continue; + if (!idx) { + free(line); + continue; + } ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC, string_to_mode(mode, 0777^toys.old_umask)); |