X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=coreutils%2Fuudecode.c;h=56ed254e516bd299055e607b80d337bb2d630d24;hb=ea684c6aaf23ead57fac74c3ceaa651c1ae625ec;hp=da6490a819b2c3b3bc58fdbcb4514346983c2c21;hpb=c1ef7bdd8d002ae0889efcf883d0e1b7faa938d4;p=oweals%2Fbusybox.git diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index da6490a81..56ed254e5 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -1,200 +1,227 @@ +/* vi: set sw=4 ts=4: */ /* - * GPLv2 - * Copyright 2003, Glenn McGrath + * Copyright 2003, Glenn McGrath * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation; either version 2 of the License. + * Licensed under GPLv2 or later, see file LICENSE in this source tree. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. + * Based on specification from + * http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Based on specification from - * http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html - * - * Bugs: the spec doesnt mention anything about "`\n`\n" prior to the "end" line + * Bugs: the spec doesn't mention anything about "`\n`\n" prior to the + * "end" line */ +#include "libbb.h" - -#include -#include -#include /* optind */ -#include -#include -#include "busybox.h" - -static int read_stduu(FILE *src_stream, FILE *dst_stream) +#if ENABLE_UUDECODE +static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM) { char *line; - while ((line = bb_get_chomped_line_from_file(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) { - bb_error_msg_and_die("Line too long"); + if (encoded_len > 60) { + bb_error_msg_and_die("line too long"); } - line_ptr++; - /* Tolerate an overly long line to acomadate a possible exta '`' */ - if (strlen(line_ptr) < 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"); + bb_error_msg_and_die("short file"); } +#endif -static int read_base64(FILE *src_stream, FILE *dst_stream) +#if ENABLE_UUDECODE +int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int uudecode_main(int argc UNUSED_PARAM, char **argv) { - const char *base64_table = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n"; - char term_count = 0; - - while (1) { - char translated[4]; - int count = 0; - - while (count < 4) { - char *table_ptr; - char ch; - - /* Get next _valid_ character */ - do { - ch = fgetc(src_stream); - if (ch == EOF) { - bb_error_msg_and_die("Short file"); - } - } while ((table_ptr = strchr(base64_table, ch)) == NULL); - - /* Convert encoded charcter to decimal */ - ch = table_ptr - base64_table; - - if (*table_ptr == '=') { - if (term_count == 0) { - translated[count] = 0; - break; - } - term_count++; - } - else if (*table_ptr == '\n') { - /* Check for terminating line */ - if (term_count == 5) { - return(EXIT_SUCCESS); - } - term_count = 1; - continue; - } else { - translated[count] = ch; - count++; - term_count = 0; - } - } - - /* Merge 6 bit chars to 8 bit */ - fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); - if (count > 2) { - fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); - } - if (count > 3) { - fputc(translated[2] << 6 | translated[3], dst_stream); - } - } -} - -extern int uudecode_main(int argc, char **argv) -{ - int (*decode_fn_ptr) (FILE * src, FILE * dst); FILE *src_stream; char *outname = NULL; char *line; - int opt; - opt = bb_getopt_ulflags(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 = bb_xfopen(argv[optind], "r"); - } else { - bb_show_usage(); - } + if (!argv[0]) + *--argv = (char*)"-"; + src_stream = xfopen_stdin(argv[0]); /* Search for the start of the encoding */ - while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) { - char *line_ptr = NULL; + while ((line = xmalloc_fgetline(src_stream)) != NULL) { + void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags); + char *line_ptr; + FILE *dst_stream; + int mode; - if (line == NULL) { - break; - } else if (strncmp(line, "begin-base64 ", 13) == 0) { + if (strncmp(line, "begin-base64 ", 13) == 0) { line_ptr = line + 13; decode_fn_ptr = read_base64; } else if (strncmp(line, "begin ", 6) == 0) { line_ptr = line + 6; decode_fn_ptr = read_stduu; + } else { + free(line); + continue; } - if (line_ptr) { - FILE *dst_stream; - int mode; - int ret; - - mode = strtoul(line_ptr, NULL, 8); - if (outname == NULL) { - outname = strchr(line_ptr, ' '); - if ((outname == NULL) || (*outname == '\0')) { - break; - } - outname++; - } - if (strcmp(outname, "-") == 0) { - dst_stream = stdout; - } else { - dst_stream = bb_xfopen(outname, "w"); - chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + /* 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')) { + break; } - free(line); - ret = decode_fn_ptr(src_stream, dst_stream); - bb_fclose_nonstdin(src_stream); - return(ret); + outname++; + } + 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); + decode_fn_ptr(src_stream, dst_stream, /*flags:*/ BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR); + /* fclose_if_not_stdin(src_stream); - redundant */ + return EXIT_SUCCESS; } - bb_error_msg_and_die("No `begin' line"); + bb_error_msg_and_die("no 'begin' line"); +} +#endif + +//applet:IF_BASE64(APPLET(base64, BB_DIR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_BASE64) += uudecode.o + +//config:config BASE64 +//config: bool "base64" +//config: default y +//config: help +//config: Base64 encode and decode + +//usage:#define base64_trivial_usage +//usage: "[-d] [FILE]" +//usage:#define base64_full_usage "\n\n" +//usage: "Base64 encode or decode FILE to standard output" +//usage: "\nOptions:" +//usage: "\n -d Decode data" +////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" +////usage: "\n -i When decoding, ignore non-alphabet characters" + +#if ENABLE_BASE64 +int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int base64_main(int argc UNUSED_PARAM, char **argv) +{ + FILE *src_stream; + unsigned opts; + + opt_complementary = "?1"; /* 1 argument max */ + opts = getopt32(argv, "d"); + argv += optind; + + if (!argv[0]) + *--argv = (char*)"-"; + src_stream = xfopen_stdin(argv[0]); + if (opts) { + read_base64(src_stream, stdout, /*flags:*/ (char)EOF); + } else { + enum { + SRC_BUF_SIZE = 76/4*3, /* This *MUST* be a multiple of 3 */ + DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), + }; + char src_buf[SRC_BUF_SIZE]; + char dst_buf[DST_BUF_SIZE + 1]; + int src_fd = fileno(src_stream); + while (1) { + size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); + if (!size) + break; + if ((ssize_t)size < 0) + bb_perror_msg_and_die(bb_msg_read_error); + /* Encode the buffer we just read in */ + bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); + xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3)); + bb_putchar('\n'); + fflush(stdout); + } + } + + fflush_stdout_and_exit(EXIT_SUCCESS); } +#endif + +/* 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 +*/