Home | History | Annotate | Download | only in posix
      1 /* uudecode.c - uudecode / base64 decode
      2  *
      3  * Copyright 2013 Erich Plondke <toybox (at) erich.wreck.org>
      4  *
      5  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html
      6 
      7 USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
      8 
      9 config UUDECODE
     10   bool "uudecode"
     11   default y
     12   help
     13     usage: uudecode [-o OUTFILE] [INFILE]
     14 
     15     Decode file from stdin (or INFILE).
     16 
     17     -o	Write to OUTFILE instead of filename in header
     18 */
     19 
     20 #define FOR_uudecode
     21 #include "toys.h"
     22 
     23 GLOBALS(
     24   char *o;
     25 )
     26 
     27 void uudecode_main(void)
     28 {
     29   int ifd = 0, ofd, idx = 0, m = m;
     30   char *line = 0, mode[16],
     31        *class[] = {"begin%*[ ]%15s%*[ ]%n", "begin-base64%*[ ]%15s%*[ ]%n"};
     32 
     33   if (toys.optc) ifd = xopenro(*toys.optargs);
     34 
     35   while (!idx) {
     36     free(line);
     37     if (!(line = get_line(ifd))) error_exit("bad EOF");
     38     for (m=0; m < 2; m++) {
     39       sscanf(line, class[m], mode, &idx);
     40       if (idx) break;
     41     }
     42   }
     43 
     44   if (TT.o && !strcmp(TT.o, "-")) ofd = 1;
     45   else ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC,
     46     string_to_mode(mode, 0777^toys.old_umask));
     47 
     48   for(;;) {
     49     char *in, *out;
     50     int olen;
     51 
     52     free(line);
     53     if (m == 2 || !(line = get_line(ifd))) break;
     54     if (!strcmp(line, m ? "====" : "end")) {
     55       m = 2;
     56       continue;
     57     }
     58 
     59     olen = 0;
     60     in = out = line;
     61     if (!m) olen = (*(in++) - 32) & 0x3f;
     62 
     63     for (;;) {
     64       int i = 0, x = 0, len = 4;
     65       char c = 0;
     66 
     67       if (!m) {
     68         if (olen < 1) break;
     69         if (olen < 3) len = olen + 1;
     70       }
     71 
     72       while (i < len) {
     73         if (!(c = *(in++))) goto line_done;
     74 
     75         if (m) {
     76           if (c == '=') {
     77             len--;
     78             continue;
     79           } else if (len != 4) break;
     80 
     81           if (c >= 'A' && c <= 'Z') c -= 'A';
     82           else if (c >= 'a' && c <= 'z') c += 26 - 'a';
     83           else if (c >= '0' && c <= '9') c += 52 - '0';
     84           else if (c == '+') c = 62;
     85           else if (c == '/') c = 63;
     86           else continue;
     87         } else c = (c - 32) & 0x3f;
     88 
     89         x |= c << (6*(3-i));
     90 
     91         if (i && i < len) {
     92           *(out++) = (x>>(8*(3-i))) & 0xff;
     93           olen--;
     94         }
     95         i++;
     96       }
     97 
     98       if (i && i!=len) error_exit("bad %s", line);
     99     }
    100 line_done:
    101     xwrite(ofd, line, out-line);
    102   }
    103 
    104   if (CFG_TOYBOX_FREE) {
    105     if (ifd) close(ifd);
    106     close(ofd);
    107   }
    108 }
    109