aboutsummaryrefslogtreecommitdiff
path: root/toys/other/base64.c
blob: f1b617d6c2fc1e15b48c57da4742a8bbf851fa3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* base64.c - Encode and decode base64
 *
 * Copyright 2014 Rob Landley <rob@landley.net>
 *
 * No standard

USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))

config BASE64
  bool "base64"
  default y
  help
    usage: base64 [-di] [-w COLUMNS] [FILE...]

    Encode or decode in base64.

    -d	Decode
    -i	Ignore non-alphabetic characters
    -w	Wrap output at COLUMNS (default 76 or 0 for no wrap)
*/

#define FOR_base64
#include "toys.h"

GLOBALS(
  long w;

  unsigned total;
)

static void wraputchar(int c, int *x)
{
  putchar(c);
  TT.total++;
  if (TT.w && ++*x == TT.w) {
    *x = 0;
    xputc('\n');
  };
}

static void do_base64(int fd, char *name)
{
  int out = 0, bits = 0, x = 0, i, len;
  char *buf = toybuf+128;

  TT.total = 0;

  for (;;) {
    // If no more data, flush buffer
    if (!(len = xread(fd, buf, sizeof(toybuf)-128))) {
      if (!(toys.optflags & FLAG_d)) {
        if (bits) wraputchar(toybuf[out<<(6-bits)], &x);
        while (TT.total&3) wraputchar('=', &x);
        if (x) xputc('\n');
      }

      return;
    }

    for (i=0; i<len; i++) {
      if (toys.optflags & FLAG_d) {
        if (buf[i] == '=') return;

        if ((x = stridx(toybuf, buf[i])) != -1) {
          out = (out<<6) + x;
          bits += 6;
          if (bits >= 8) {
            putchar(out >> (bits -= 8));
            out &= (1<<bits)-1;
            if (ferror(stdout)) perror_exit(0);
          }

          continue;
        }
        if (buf[i] == '\n' || (toys.optflags & FLAG_i)) continue;

        break;
      } else {
        out = (out<<8) + buf[i];
        bits += 8;
        while (bits >= 6) {
          wraputchar(toybuf[out >> (bits -= 6)], &x);
          out &= (1<<bits)-1;
        }
      }
    }
  }
}

void base64_main(void)
{
  base64_init(toybuf);
  loopfiles(toys.optargs, do_base64);
}