12edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley/* uudecode.c - uudecode / base64 decode
22edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley *
32edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley * Copyright 2013 Erich Plondke <toybox@erich.wreck.org>
42edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley *
52edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html
62edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
72edb485af88410fba64649d2bded8c5af0f5cc08Rob LandleyUSE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
82edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
92edb485af88410fba64649d2bded8c5af0f5cc08Rob Landleyconfig UUDECODE
102edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  bool "uudecode"
112edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  default y
122edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  help
132edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    usage: uudecode [-o OUTFILE] [INFILE]
142edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
152edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    Decode file from stdin (or INFILE).
162edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
172edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    -o	write to OUTFILE instead of filename in header
182edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley*/
192edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
202edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley#define FOR_uudecode
212edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley#include "toys.h"
222edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
232edb485af88410fba64649d2bded8c5af0f5cc08Rob LandleyGLOBALS(
242edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  char *o;
252edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley)
262edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
272edb485af88410fba64649d2bded8c5af0f5cc08Rob Landleyvoid uudecode_main(void)
282edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley{
292edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  int ifd = 0, ofd, idx = 0, m = m;
302edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  char *line = 0, mode[16],
312edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley       *class[] = {"begin%*[ ]%15s%*[ ]%n", "begin-base64%*[ ]%15s%*[ ]%n"};
322edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
332edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  if (toys.optc) ifd = xopen(*toys.optargs, O_RDONLY);
342edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
352edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  while (!idx) {
362edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    free(line);
372edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    if (!(line = get_line(ifd))) error_exit("bad EOF");
382edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    for (m=0; m < 2; m++) {
392edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      sscanf(line, class[m], mode, &idx);
402edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      if (idx) break;
412edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    }
422edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  }
432edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
442edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC,
452edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    string_to_mode(mode, 0777^toys.old_umask));
462edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
472edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  for(;;) {
482edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    char *in, *out;
492edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    int olen;
502edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
512edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    free(line);
522edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    if (m == 2 || !(line = get_line(ifd))) break;
532edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    if (!strcmp(line, m ? "====" : "end")) {
542edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      m = 2;
552edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      continue;
562edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    }
572edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
582edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    olen = 0;
592edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    in = out = line;
602edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    if (!m) olen = (*(in++) - 32) & 0x3f;
612edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
622edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    for (;;) {
632edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      int i = 0, x = 0, len = 4;
642edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      char c = 0;
652edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
662edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      if (!m) {
672edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        if (olen < 1) break;
682edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        if (olen < 3) len = olen + 1;
692edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      }
702edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
712edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      while (i < len) {
722edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        if (!(c = *(in++))) goto line_done;
732edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
742edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        if (m) {
752edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          if (c == '=') {
762edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley            len--;
772edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley            continue;
782edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          } else if (len != 4) break;
792edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
802edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          if (c >= 'A' && c <= 'Z') c -= 'A';
812edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          else if (c >= 'a' && c <= 'z') c += 26 - 'a';
822edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          else if (c >= '0' && c <= '9') c += 52 - '0';
832edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          else if (c == '+') c = 62;
842edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          else if (c == '/') c = 63;
852edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          else continue;
862edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        } else c = (c - 32) & 0x3f;
872edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
882edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        x |= c << (6*(3-i));
892edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
902edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        if (i && i < len) {
912edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          *(out++) = (x>>(8*(3-i))) & 0xff;
922edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley          olen--;
932edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        }
942edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley        i++;
952edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      }
962edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
972edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley      if (i && i!=len) error_exit("bad %s", line);
982edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    }
992edb485af88410fba64649d2bded8c5af0f5cc08Rob Landleyline_done:
1002edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    xwrite(ofd, line, out-line);
1012edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  }
1022edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley
1032edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  if (CFG_TOYBOX_FREE) {
1042edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    if (ifd) close(ifd);
1052edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley    close(ofd);
1062edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley  }
1072edb485af88410fba64649d2bded8c5af0f5cc08Rob Landley}
108