uudecode.c 2.5 KB

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