X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fuudecode.c;h=0298a4bdb7ae6afb2d5ddf7f2594fec2f624fa5d;hb=4e5b07b0fed4be34ab3b22666e2a68e7ec2738d8;hp=dc7d2aef827876923013157a2316fc590224de77;hpb=f7996f3b700a22797565e9aa57e251e6e3ac1e4d;p=oweals%2Fbusybox.git diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index dc7d2aef8..0298a4bdb 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -1,6 +1,6 @@ /* vi: set sw=4 ts=4: */ /* - * Copyright 2003, Glenn McGrath + * Copyright 2003, Glenn McGrath * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * @@ -12,65 +12,72 @@ */ -#include "busybox.h" +#include "libbb.h" -static int read_stduu(FILE *src_stream, FILE *dst_stream) +static void read_stduu(FILE *src_stream, FILE *dst_stream) { char *line; - while ((line = xmalloc_getline(src_stream)) != NULL) { - int length; - char *line_ptr = line; + while ((line = xmalloc_fgetline(src_stream)) != NULL) { + int encoded_len, str_len; + char *line_ptr, *dst; if (strcmp(line, "end") == 0) { - return EXIT_SUCCESS; + return; /* the only non-error exit */ } - length = ((*line_ptr - 0x20) & 0x3f)* 4 / 3; - if (length <= 0) { + line_ptr = line; + while (*line_ptr) { + *line_ptr = (*line_ptr - 0x20) & 0x3f; + line_ptr++; + } + str_len = line_ptr - line; + + encoded_len = line[0] * 4 / 3; + /* Check that line is not too short. (we tolerate + * overly _long_ line to accomodate possible extra '`'). + * Empty line case is also caught here. */ + if (str_len <= encoded_len) { + break; /* go to bb_error_msg_and_die("short file"); */ + } + if (encoded_len <= 0) { /* Ignore the "`\n" line, why is it even in the encode file ? */ + free(line); continue; } - if (length > 60) { + if (encoded_len > 60) { bb_error_msg_and_die("line too long"); } - line_ptr++; - /* Tolerate an overly long line to accomodate a possible exta '`' */ - if (strlen(line_ptr) < (size_t)length) { - bb_error_msg_and_die("short file"); - } - - while (length > 0) { + dst = line; + line_ptr = line + 1; + do { /* Merge four 6 bit chars to three 8 bit chars */ - fputc(((line_ptr[0] - 0x20) & 077) << 2 | ((line_ptr[1] - 0x20) & 077) >> 4, dst_stream); - line_ptr++; - length--; - if (length == 0) { + *dst++ = line_ptr[0] << 2 | line_ptr[1] >> 4; + encoded_len--; + if (encoded_len == 0) { break; } - fputc(((line_ptr[0] - 0x20) & 077) << 4 | ((line_ptr[1] - 0x20) & 077) >> 2, dst_stream); - line_ptr++; - length--; - if (length == 0) { + *dst++ = line_ptr[1] << 4 | line_ptr[2] >> 2; + encoded_len--; + if (encoded_len == 0) { break; } - fputc(((line_ptr[0] - 0x20) & 077) << 6 | ((line_ptr[1] - 0x20) & 077), dst_stream); - line_ptr += 2; - length -= 2; - } + *dst++ = line_ptr[2] << 6 | line_ptr[3]; + line_ptr += 4; + encoded_len -= 2; + } while (encoded_len > 0); + fwrite(line, 1, dst - line, dst_stream); free(line); } bb_error_msg_and_die("short file"); } -static int read_base64(FILE *src_stream, FILE *dst_stream) +static void read_base64(FILE *src_stream, FILE *dst_stream) { - static const char base64_table[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n"; - char term_count = 0; + int term_count = 1; while (1) { char translated[4]; @@ -80,28 +87,31 @@ static int read_base64(FILE *src_stream, FILE *dst_stream) char *table_ptr; int ch; - /* Get next _valid_ character */ + /* Get next _valid_ character. + * global vector bb_uuenc_tbl_base64[] contains this string: + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" + */ do { ch = fgetc(src_stream); if (ch == EOF) { bb_error_msg_and_die("short file"); } - } while ((table_ptr = strchr(base64_table, ch)) == NULL); + table_ptr = strchr(bb_uuenc_tbl_base64, ch); + } while (table_ptr == NULL); - /* Convert encoded charcter to decimal */ - ch = table_ptr - base64_table; + /* Convert encoded character to decimal */ + ch = table_ptr - bb_uuenc_tbl_base64; if (*table_ptr == '=') { if (term_count == 0) { - translated[count] = 0; + translated[count] = '\0'; break; } term_count++; - } - else if (*table_ptr == '\n') { + } else if (*table_ptr == '\n') { /* Check for terminating line */ if (term_count == 5) { - return EXIT_SUCCESS; + return; } term_count = 1; continue; @@ -113,7 +123,9 @@ static int read_base64(FILE *src_stream, FILE *dst_stream) } /* Merge 6 bit chars to 8 bit */ - fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); + if (count > 1) { + fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); + } if (count > 2) { fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); } @@ -123,29 +135,27 @@ static int read_base64(FILE *src_stream, FILE *dst_stream) } } -int uudecode_main(int argc, char **argv) +int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int uudecode_main(int argc UNUSED_PARAM, char **argv) { FILE *src_stream; char *outname = NULL; char *line; - getopt32(argc, argv, "o:", &outname); + opt_complementary = "?1"; /* 1 argument max */ + getopt32(argv, "o:", &outname); + argv += optind; - if (optind == argc) { - src_stream = stdin; - } else if (optind + 1 == argc) { - src_stream = xfopen(argv[optind], "r"); - } else { - bb_show_usage(); - } + if (!*argv) + *--argv = (char*)"-"; + src_stream = xfopen_stdin(*argv); /* Search for the start of the encoding */ - while ((line = xmalloc_getline(src_stream)) != NULL) { - int (*decode_fn_ptr)(FILE * src, FILE * dst); + while ((line = xmalloc_fgetline(src_stream)) != NULL) { + void (*decode_fn_ptr)(FILE *src, FILE *dst); char *line_ptr; FILE *dst_stream; int mode; - int ret; if (strncmp(line, "begin-base64 ", 13) == 0) { line_ptr = line + 13; @@ -158,7 +168,8 @@ int uudecode_main(int argc, char **argv) continue; } - mode = strtoul(line_ptr, NULL, 8); + /* begin line found. decode and exit */ + mode = bb_strtou(line_ptr, NULL, 8); if (outname == NULL) { outname = strchr(line_ptr, ' '); if ((outname == NULL) || (*outname == '\0')) { @@ -166,16 +177,48 @@ int uudecode_main(int argc, char **argv) } outname++; } - if (LONE_DASH(outname)) { - dst_stream = stdout; - } else { - dst_stream = xfopen(outname, "w"); - chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + dst_stream = stdout; + if (NOT_LONE_DASH(outname)) { + dst_stream = xfopen_for_write(outname); + fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO)); } free(line); - ret = decode_fn_ptr(src_stream, dst_stream); - fclose_if_not_stdin(src_stream); - return ret; + decode_fn_ptr(src_stream, dst_stream); + /* fclose_if_not_stdin(src_stream); - redundant */ + return EXIT_SUCCESS; } bb_error_msg_and_die("no 'begin' line"); } + +/* Test script. +Put this into an empty dir with busybox binary, an run. + +#!/bin/sh +test -x busybox || { echo "No ./busybox?"; exit; } +ln -sf busybox uudecode +ln -sf busybox uuencode +>A_null +echo -n A >A +echo -n AB >AB +echo -n ABC >ABC +echo -n ABCD >ABCD +echo -n ABCDE >ABCDE +echo -n ABCDEF >ABCDEF +cat busybox >A_bbox +for f in A*; do + echo uuencode $f + ./uuencode $f <$f >u_$f + ./uuencode -m $f <$f >m_$f +done +mkdir unpk_u unpk_m 2>/dev/null +for f in u_*; do + ./uudecode <$f -o unpk_u/${f:2} + diff -a ${f:2} unpk_u/${f:2} >/dev/null 2>&1 + echo uudecode $f: $? +done +for f in m_*; do + ./uudecode <$f -o unpk_m/${f:2} + diff -a ${f:2} unpk_m/${f:2} >/dev/null 2>&1 + echo uudecode $f: $? +done +*/