forked from aklomp/base64
-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.c
124 lines (113 loc) · 2.29 KB
/
main.c
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <stddef.h> /* size_t */
#include <stdio.h> /* fopen() */
#include <string.h> /* strlen() */
#include <getopt.h>
#include "base64.h"
#define BUFSIZE 1024 * 1024
static char buf[BUFSIZE];
static char out[(BUFSIZE * 5) / 3]; /* Technically 4/3 of input, but take some margin */
size_t nread;
size_t nout;
static int
enc (FILE *fp)
{
int ret = 1;
struct base64_state state;
base64_stream_encode_init(&state);
while ((nread = fread(buf, 1, BUFSIZE, fp)) > 0) {
(*base64_stream_encode)(&state, buf, nread, out, &nout);
if (nout) {
fwrite(out, nout, 1, stdout);
}
if (feof(fp)) {
break;
}
}
if (ferror(fp)) {
fprintf(stderr, "read error\n");
ret = 0;
goto out;
}
base64_stream_encode_final(&state, out, &nout);
if (nout) {
fwrite(out, nout, 1, stdout);
}
out: fclose(fp);
fclose(stdout);
return ret;
}
static int
dec (FILE *fp)
{
int ret = 1;
struct base64_state state;
base64_stream_decode_init(&state);
while ((nread = fread(buf, 1, BUFSIZE, fp)) > 0) {
if (!(*base64_stream_decode)(&state, buf, nread, out, &nout)) {
fprintf(stderr, "decoding error\n");
ret = 0;
goto out;
}
if (nout) {
fwrite(out, nout, 1, stdout);
}
if (feof(fp)) {
break;
}
}
if (ferror(fp)) {
fprintf(stderr, "read error\n");
ret = 0;
}
out: fclose(fp);
fclose(stdout);
return ret;
}
int
main (int argc, char **argv)
{
char *file;
FILE *fp;
int decode = 0;
/* Parse options: */
for (;;)
{
int c;
int opt_index = 0;
static struct option opt_long[] = {
{ "decode", 0, 0, 'd' },
{ 0, 0, 0, 0 }
};
if ((c = getopt_long(argc, argv, "d", opt_long, &opt_index)) == -1) {
break;
}
switch (c)
{
case 'd':
decode = 1;
break;
}
}
/* No options left on command line? Read from stdin: */
if (optind >= argc) {
fp = stdin;
}
/* One option left on command line? Treat it as a file: */
else if (optind + 1 == argc) {
file = argv[optind];
if (strcmp(file, "-") == 0) {
fp = stdin;
}
else if ((fp = fopen(file, "rb")) == NULL) {
printf("cannot open %s\n", file);
return 1;
}
}
/* More than one option left on command line? Syntax error: */
else {
printf("Usage: %s <file>\n", argv[0]);
return 1;
}
/* Invert return codes to create shell return code: */
return (decode) ? !dec(fp) : !enc(fp);
}