/* * basE91 command line front-end * * Copyright (c) 2000-2006 Joachim Henke * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Joachim Henke nor the names of his contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #ifdef _WIN32 #include #include #endif #include #include "base91.h" #define FLG_D 1 #define FLG_V 2 #define FLG_VV 4 static char status[32]; static const char *progname; static char *ibuf, *obuf; static size_t ibuf_size, llen; static struct basE91 b91; static void stream_b91enc_p(void) { size_t itotal = 0; size_t ototal = 0; size_t s; while ((s = fread(ibuf, 1, ibuf_size, stdin)) > 0) { itotal += s; s = basE91_encode(&b91, ibuf, s, obuf); ototal += s; fwrite(obuf, 1, s, stdout); } s = basE91_encode_end(&b91, obuf); /* empty bit queue */ ototal += s; fwrite(obuf, 1, s, stdout); sprintf(status, "\t%.2f%%\n", itotal ? (float) ototal / itotal * 100.0 : 1.0); } static void stream_b91enc_w(void) { size_t l = llen; size_t ltotal = 0; size_t i, s; char x; while ((s = fread(ibuf, 1, ibuf_size, stdin)) > 0) { s = basE91_encode(&b91, ibuf, s, obuf); for (i = 0; l <= s; l += llen) { x = obuf[l]; obuf[l] = '\0'; puts(obuf + i); ++ltotal; obuf[l] = x; i = l; } fwrite(obuf + i, 1, s - i, stdout); l -= s; } s = basE91_encode_end(&b91, obuf); if (s || l < llen) { obuf[s] = '\0'; if (s > l) { x = obuf[1]; obuf[1] = '\0'; puts(obuf); ++ltotal; obuf[0] = x; } puts(obuf); ++ltotal; } sprintf(status, "\t%lu lines\n", (unsigned long) ltotal); } static void stream_b91dec(void) { size_t s; while ((s = fread(ibuf, 1, ibuf_size, stdin)) > 0) { s = basE91_decode(&b91, ibuf, s, obuf); fwrite(obuf, 1, s, stdout); } s = basE91_decode_end(&b91, obuf); /* empty bit queue */ fwrite(obuf, 1, s, stdout); sprintf(status, "done\n"); } static int init_flags(const char *p) { size_t l = strlen(p); if (l > 5) { progname = p + l - 6; if (!strcmp(progname, "b91enc")) return 0; if (!strcmp(progname, "b91dec")) return FLG_D; } llen = 76; progname = "base91"; return 0; } int main(int argc, char **argv) { size_t buf_size = 65536; /* buffer memory defaults to 64 KiB */ int flags = init_flags(*argv); char *ifile = "from standard input"; char *ofile = NULL; int opt; struct option longopts[8] = { {"decode", no_argument, NULL, 'd'}, {"output", required_argument, NULL, 'o'}, {"verbose", no_argument, NULL, 'v'}, {"wrap", required_argument, NULL, 'w'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; while ((opt = getopt_long(argc, argv, "dem:o:vw:hV", longopts, NULL)) != -1) switch (opt) { case 'd': flags |= FLG_D; break; case 'e': flags &= ~FLG_D; break; case 'm': { char *t; long l = strtol(optarg, &t, 0); if (t == optarg || strlen(t) > 1 || l < 0) { fprintf(stderr, "invalid SIZE argument: `%s'\n", optarg); return EXIT_FAILURE; } buf_size = l; switch (*t | 32) { case ' ': case 'b': break; case 'k': buf_size <<= 10; break; case 'm': buf_size <<= 20; break; default: fprintf(stderr, "invalid SIZE suffix: `%s'\n", t); return EXIT_FAILURE; } } break; case 'o': if (strcmp(optarg, "-")) ofile = optarg; break; case 'v': flags |= (flags & FLG_V) ? FLG_VV : FLG_V; break; case 'w': { char *t; long l = strtol(optarg, &t, 0); if (*t || l < 0) { fprintf(stderr, "invalid number of columns: `%s'\n", optarg); return EXIT_FAILURE; } llen = l; } break; case 'h': printf("Usage: %s [OPTION]... [FILE]\n" "basE91 encode or decode FILE, or standard input, to standard output.\n", progname); puts("\n -d, --decode\t\tdecode data\n" " -m SIZE\t\tuse SIZE bytes of memory for buffers (suffixes b, K, M)\n" " -o, --output=FILE\twrite to FILE instead of standard output\n" " -v, --verbose\t\tverbose mode\n" " -w, --wrap=COLS\twrap encoded lines after COLS characters (default 76)\n" " --help\t\tdisplay this help and exit\n" " --version\t\toutput version information and exit\n\n" "With no FILE, or when FILE is -, read standard input."); return EXIT_SUCCESS; case 'V': printf("%s 0.6.0\nCopyright (c) 2000-2006 Joachim Henke\n", progname); return EXIT_SUCCESS; default: fprintf(stderr, "Try `%s --help' for more information.\n", *argv); return EXIT_FAILURE; } if (flags & FLG_D) { ibuf_size = (buf_size - 1) << 3; if (ibuf_size < 15) { fputs("SIZE must be >= 3 for decoding\n", stderr); return EXIT_FAILURE; } ibuf_size /= 15; } else { ibuf_size = (buf_size - 2) << 4; if (ibuf_size < 29) { fputs("SIZE must be >= 4 for encoding\n", stderr); return EXIT_FAILURE; } ibuf_size /= 29; } if (optind < argc && strcmp(argv[optind], "-")) { ifile = argv[optind]; if (freopen(ifile, "r", stdin) != stdin) { perror(ifile); return EXIT_FAILURE; } } if (ofile) if (freopen(ofile, "w", stdout) != stdout) { perror(ofile); return EXIT_FAILURE; } if (flags & FLG_VV) fprintf(stderr, "using %lu bytes for buffers; input buffer: %lu bytes\n", (unsigned long) buf_size, (unsigned long) ibuf_size); obuf = malloc(buf_size); if (!obuf) { fputs("failed to allocate buffer memory\n", stderr); return EXIT_FAILURE; } basE91_init(&b91); #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif if (flags & FLG_D) { #ifdef _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif ibuf = obuf + 1; /* create overlapping buffers to use memory efficiently */ if (flags & FLG_V) fprintf(stderr, "decoding %s ...", ifile); stream_b91dec(); } else { ibuf = obuf + buf_size - ibuf_size; /* partial overlap */ if (flags & FLG_V) fprintf(stderr, "encoding %s ...", ifile); if (llen) stream_b91enc_w(); else stream_b91enc_p(); } free(obuf); if (flags & FLG_V) fputs(status, stderr); return EXIT_SUCCESS; }