annotate toys/pending/uudecode.c @ 839:a315fb343e2b

More uudecode cleanup.
author Rob Landley <rob@landley.net>
date Thu, 28 Mar 2013 23:33:27 -0500
parents a60c572a8218
children
rev   line source
rob@823 1 /* uudecode.c - uudecode / base64 decode
rob@823 2 *
rob@823 3 * Copyright 2013 Erich Plondke <toybox@erich.wreck.org>
rob@823 4 *
rob@823 5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html
rob@823 6
rob@835 7 USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
rob@823 8
rob@823 9 config UUDECODE
rob@823 10 bool "uudecode"
rob@823 11 default n
rob@823 12 help
rob@834 13 usage: uudecode [-o OUTFILE] [INFILE]
rob@823 14
rob@834 15 Decode file from stdin (or INFILE).
rob@834 16
rob@834 17 -o write to OUTFILE instead of filename in header
rob@823 18 */
rob@823 19
rob@823 20 #define FOR_uudecode
rob@823 21 #include "toys.h"
rob@823 22
rob@823 23 GLOBALS(
rob@823 24 char *o;
rob@823 25 )
rob@823 26
rob@838 27 static int uudecode_b64_4bytes(char *out, char *in)
rob@823 28 {
rob@838 29 int i, len = 3;
rob@838 30 unsigned x = 0;
rob@834 31
rob@838 32 for (i=0; i<4; i++) {
rob@838 33 int c = in[i];
rob@838 34
rob@839 35 if (c == '=') {
rob@839 36 len--;
rob@839 37 c = 'A';
rob@839 38 } else if (len != 3) len = 0;
rob@839 39 if (!len) goto bad;
rob@838 40
rob@839 41 if (c >= 'A' && c <= 'Z') c -= 'A';
rob@839 42 else if (c >= 'a' && c <= 'z') c += 26 - 'a';
rob@839 43 else if (c >= '0' && c <= '9') c += 52 - '0';
rob@839 44 else if (c == '+') c = 62;
rob@839 45 else if (c == '/') c =63;
rob@839 46 else goto bad;
rob@839 47
rob@839 48 x |= c << (6*(3-i));
rob@838 49 if (i && i <= len) *(out++) = (x>>(8*(3-i))) & 0xff;
rob@838 50 }
rob@834 51
rob@823 52 return len;
rob@839 53
rob@839 54 bad:
rob@839 55 error_exit("bad input");
rob@823 56 }
rob@823 57
rob@838 58 static void uudecode_b64_line(int ofd, char *in, int ilen)
rob@823 59 {
rob@823 60 int olen;
rob@823 61 char out[4];
rob@834 62
rob@823 63 while (ilen >= 4) {
rob@838 64 olen = uudecode_b64_4bytes(out, in);
rob@823 65 xwrite(ofd,out,olen);
rob@823 66 in += 4;
rob@823 67 ilen -= 4;
rob@823 68 };
rob@823 69 }
rob@823 70
rob@838 71 static void uudecode_uu_4bytes(char *out, char *in, int len)
rob@823 72 {
rob@823 73 unsigned int i,x=0;
rob@834 74
rob@834 75 for (i = 0; i < 4; i++) x |= ((in[i] - 32) & 0x03f) << (6*(3-i));
rob@823 76 if (len > 3) len = 3;
rob@834 77 for (i = 0; i < len; i++) *out++ = x >> (8*(2-i));
rob@823 78 }
rob@823 79
rob@838 80 static void uudecode_uu_line(int ofd, char *in)
rob@823 81 {
rob@839 82 int olen = (in[0] - 32) & 0x3f;
rob@823 83 char buf[4];
rob@834 84
rob@823 85 in++;
rob@823 86 while (olen > 0) {
rob@823 87 uudecode_uu_4bytes(buf,in,olen);
rob@823 88 xwrite(ofd,buf,olen < 3 ? olen : 3);
rob@823 89 olen -= 3;
rob@823 90 in += 4;
rob@823 91 }
rob@823 92 }
rob@823 93
rob@823 94 void uudecode_main(void)
rob@823 95 {
rob@839 96 int ifd = 0, ofd, idx = 0, m;
rob@839 97 char *line = 0,
rob@839 98 *class[] = {"begin%*[ ]%15s%*[ ]%n", "begin-base64%*[ ]%15s%*[ ]%n"};
rob@839 99
rob@834 100
rob@835 101 if (toys.optc) ifd = xopen(*toys.optargs, O_RDONLY);
rob@834 102
rob@835 103 for (;;) {
rob@835 104 char mode[16];
rob@834 105
rob@839 106 free(line);
rob@839 107 if (!(line = get_line(ifd))) error_exit("bad EOF");
rob@839 108 for (m=0; m < 2; m++) {
rob@839 109 sscanf(line, class[m], mode, &idx);
rob@839 110 if (idx) break;
rob@835 111 }
rob@835 112
rob@839 113 if (!idx) continue;
rob@835 114
rob@835 115 ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC,
rob@835 116 string_to_mode(mode, 0777^toys.old_umask));
rob@835 117 free(line);
rob@835 118 break;
rob@835 119 }
rob@835 120
rob@839 121 while ((line = get_line(ifd)) != NULL) {
rob@839 122 if (strcmp(line, m ? "====" : "end")) {
rob@839 123 if (m) uudecode_b64_line(ofd, line, strlen(line));
rob@839 124 else uudecode_uu_line(ofd, line);
rob@839 125 } else m = 2;
rob@839 126 free(line);
rob@839 127 if (m == 2) break;
rob@839 128 }
rob@839 129
rob@835 130 if (CFG_TOYBOX_FREE) {
rob@835 131 if (ifd) close(ifd);
rob@835 132 close(ofd);
rob@835 133 }
rob@823 134 }