1/* base64.c - Encode and decode base64
2 *
3 * Copyright 2014 Rob Landley <rob@landley.net>
4 *
5 * No standard
6
7USE_BASE64(NEWTOY(base64, "diw#<1[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
8
9config BASE64
10  bool "base64"
11  default y
12  help
13    usage: base64 [-di] [-w COLUMNS] [FILE...]
14
15    Encode or decode in base64.
16
17    -d	decode
18    -i	ignore non-alphabetic characters
19    -w	wrap output at COLUMNS (default 76)
20*/
21
22#define FOR_base64
23#include "toys.h"
24
25GLOBALS(
26  long columns;
27)
28
29static void do_base64(int fd, char *name)
30{
31  int out = 0, bits = 0, x = 0, i, len;
32  char *buf = toybuf+128;
33
34  for (;;) {
35    if (!(len = xread(fd, buf, sizeof(toybuf)-128))) {
36      if (!(toys.optflags & FLAG_d)) {
37        if (bits) {
38          putchar(toybuf[out<<(6-bits)]);
39          x++;
40        }
41        while (x++&3)  putchar('=');
42        if (x != 1) xputc('\n');
43      }
44
45      return;
46    }
47    for (i=0; i<len; i++) {
48      if (toys.optflags & FLAG_d) {
49        if (buf[i] == '=') return;
50
51        if ((x = stridx(toybuf, buf[i])) != -1) {
52          out = (out<<6) + x;
53          bits += 6;
54          if (bits >= 8) {
55            putchar(out >> (bits -= 8));
56            out &= (1<<bits)-1;
57            if (ferror(stdout)) perror_exit(0);
58          }
59
60          continue;
61        }
62        if (buf[i] == '\n' || (toys.optflags & FLAG_i)) continue;
63
64        break;
65      } else {
66        out = (out<<8) + buf[i];
67        bits += 8;
68        while (bits >= 6) {
69          putchar(toybuf[out >> (bits -= 6)]);
70          out &= (1<<bits)-1;
71          if (TT.columns == ++x) {
72            xputc('\n');
73            x = 0;
74          }
75        }
76      }
77    }
78  }
79}
80
81void base64_main(void)
82{
83  if (!TT.columns) TT.columns = 76;
84
85  base64_init(toybuf);
86  loopfiles(toys.optargs, do_base64);
87}
88