147bcbde9SPiotr Pawel Stefaniak /*-
247bcbde9SPiotr Pawel Stefaniak * SPDX-License-Identifier: BSD-2-Clause
347bcbde9SPiotr Pawel Stefaniak *
447bcbde9SPiotr Pawel Stefaniak * Copyright (c) 2022 The FreeBSD Foundation
547bcbde9SPiotr Pawel Stefaniak *
647bcbde9SPiotr Pawel Stefaniak * Redistribution and use in source and binary forms, with or without
747bcbde9SPiotr Pawel Stefaniak * modification, are permitted provided that the following conditions
847bcbde9SPiotr Pawel Stefaniak * are met:
947bcbde9SPiotr Pawel Stefaniak * 1. Redistributions of source code must retain the above copyright
1047bcbde9SPiotr Pawel Stefaniak * notice, this list of conditions and the following disclaimer.
1147bcbde9SPiotr Pawel Stefaniak * 2. Redistributions in binary form must reproduce the above copyright
1247bcbde9SPiotr Pawel Stefaniak * notice, this list of conditions and the following disclaimer in the
1347bcbde9SPiotr Pawel Stefaniak * documentation and/or other materials provided with the distribution.
1447bcbde9SPiotr Pawel Stefaniak *
1547bcbde9SPiotr Pawel Stefaniak * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1647bcbde9SPiotr Pawel Stefaniak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1747bcbde9SPiotr Pawel Stefaniak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1847bcbde9SPiotr Pawel Stefaniak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1947bcbde9SPiotr Pawel Stefaniak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2047bcbde9SPiotr Pawel Stefaniak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2147bcbde9SPiotr Pawel Stefaniak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2247bcbde9SPiotr Pawel Stefaniak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2347bcbde9SPiotr Pawel Stefaniak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2447bcbde9SPiotr Pawel Stefaniak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2547bcbde9SPiotr Pawel Stefaniak * SUCH DAMAGE.
2647bcbde9SPiotr Pawel Stefaniak */
2747bcbde9SPiotr Pawel Stefaniak
2847bcbde9SPiotr Pawel Stefaniak #include <sys/param.h>
29540a9928SPiotr Pawel Stefaniak #include <getopt.h>
3047bcbde9SPiotr Pawel Stefaniak #include <libgen.h>
31540a9928SPiotr Pawel Stefaniak #include <stdbool.h>
3247bcbde9SPiotr Pawel Stefaniak #include <stdio.h>
3347bcbde9SPiotr Pawel Stefaniak #include <stdlib.h>
3447bcbde9SPiotr Pawel Stefaniak #include <string.h>
3547bcbde9SPiotr Pawel Stefaniak #include <sysexits.h>
3647bcbde9SPiotr Pawel Stefaniak
3747bcbde9SPiotr Pawel Stefaniak extern int main_decode(int, char *[]);
3847bcbde9SPiotr Pawel Stefaniak extern int main_encode(int, char *[]);
39540a9928SPiotr Pawel Stefaniak extern int main_base64_decode(const char *);
40540a9928SPiotr Pawel Stefaniak extern int main_base64_encode(const char *, const char *);
41aad4fd54SPiotr Pawel Stefaniak extern int main_quotedprintable(int, char*[]);
4247bcbde9SPiotr Pawel Stefaniak
4347bcbde9SPiotr Pawel Stefaniak static int search(const char *const);
44540a9928SPiotr Pawel Stefaniak static void usage_base64(bool);
45540a9928SPiotr Pawel Stefaniak static void version_base64(void);
46540a9928SPiotr Pawel Stefaniak static void base64_encode_or_decode(int, char *[]);
4747bcbde9SPiotr Pawel Stefaniak
4847bcbde9SPiotr Pawel Stefaniak enum coders {
49aad4fd54SPiotr Pawel Stefaniak uuencode, uudecode, b64encode, b64decode, base64, qp
5047bcbde9SPiotr Pawel Stefaniak };
5147bcbde9SPiotr Pawel Stefaniak
5247bcbde9SPiotr Pawel Stefaniak int
main(int argc,char * argv[])5347bcbde9SPiotr Pawel Stefaniak main(int argc, char *argv[])
5447bcbde9SPiotr Pawel Stefaniak {
5547bcbde9SPiotr Pawel Stefaniak const char *const progname = getprogname();
5647bcbde9SPiotr Pawel Stefaniak int coder = search(progname);
5747bcbde9SPiotr Pawel Stefaniak
5847bcbde9SPiotr Pawel Stefaniak if (coder == -1 && argc > 1) {
5947bcbde9SPiotr Pawel Stefaniak argc--;
6047bcbde9SPiotr Pawel Stefaniak argv++;
6147bcbde9SPiotr Pawel Stefaniak coder = search(argv[0]);
6247bcbde9SPiotr Pawel Stefaniak }
6347bcbde9SPiotr Pawel Stefaniak switch (coder) {
6447bcbde9SPiotr Pawel Stefaniak case uuencode:
6547bcbde9SPiotr Pawel Stefaniak case b64encode:
6647bcbde9SPiotr Pawel Stefaniak main_encode(argc, argv);
6747bcbde9SPiotr Pawel Stefaniak break;
6847bcbde9SPiotr Pawel Stefaniak case uudecode:
6947bcbde9SPiotr Pawel Stefaniak case b64decode:
7047bcbde9SPiotr Pawel Stefaniak main_decode(argc, argv);
7147bcbde9SPiotr Pawel Stefaniak break;
72540a9928SPiotr Pawel Stefaniak case base64:
73540a9928SPiotr Pawel Stefaniak base64_encode_or_decode(argc, argv);
74540a9928SPiotr Pawel Stefaniak break;
75aad4fd54SPiotr Pawel Stefaniak case qp:
76aad4fd54SPiotr Pawel Stefaniak main_quotedprintable(argc, argv);
77aad4fd54SPiotr Pawel Stefaniak break;
7847bcbde9SPiotr Pawel Stefaniak default:
7947bcbde9SPiotr Pawel Stefaniak (void)fprintf(stderr,
80540a9928SPiotr Pawel Stefaniak "usage: %1$s <uuencode | uudecode> ...\n"
81540a9928SPiotr Pawel Stefaniak " %1$s <b64encode | b64decode> ...\n"
82aad4fd54SPiotr Pawel Stefaniak " %1$s <base64> ...\n"
83aad4fd54SPiotr Pawel Stefaniak " %1$s <qp> ...\n",
84540a9928SPiotr Pawel Stefaniak progname);
8547bcbde9SPiotr Pawel Stefaniak exit(EX_USAGE);
8647bcbde9SPiotr Pawel Stefaniak }
8747bcbde9SPiotr Pawel Stefaniak }
8847bcbde9SPiotr Pawel Stefaniak
8947bcbde9SPiotr Pawel Stefaniak static int
search(const char * const progname)9047bcbde9SPiotr Pawel Stefaniak search(const char *const progname)
9147bcbde9SPiotr Pawel Stefaniak {
9247bcbde9SPiotr Pawel Stefaniak #define DESIGNATE(item) [item] = #item
9347bcbde9SPiotr Pawel Stefaniak const char *const known[] = {
9447bcbde9SPiotr Pawel Stefaniak DESIGNATE(uuencode),
9547bcbde9SPiotr Pawel Stefaniak DESIGNATE(uudecode),
9647bcbde9SPiotr Pawel Stefaniak DESIGNATE(b64encode),
97540a9928SPiotr Pawel Stefaniak DESIGNATE(b64decode),
98aad4fd54SPiotr Pawel Stefaniak DESIGNATE(base64),
99aad4fd54SPiotr Pawel Stefaniak DESIGNATE(qp)
10047bcbde9SPiotr Pawel Stefaniak };
10147bcbde9SPiotr Pawel Stefaniak
10247bcbde9SPiotr Pawel Stefaniak for (size_t i = 0; i < nitems(known); i++)
10347bcbde9SPiotr Pawel Stefaniak if (strcmp(progname, known[i]) == 0)
10447bcbde9SPiotr Pawel Stefaniak return ((int)i);
10547bcbde9SPiotr Pawel Stefaniak return (-1);
10647bcbde9SPiotr Pawel Stefaniak }
107540a9928SPiotr Pawel Stefaniak
108540a9928SPiotr Pawel Stefaniak static void
usage_base64(bool failure)109540a9928SPiotr Pawel Stefaniak usage_base64(bool failure)
110540a9928SPiotr Pawel Stefaniak {
111540a9928SPiotr Pawel Stefaniak (void)fputs("usage: base64 [-w col | --wrap=col] "
112540a9928SPiotr Pawel Stefaniak "[-d | --decode] [FILE]\n"
113540a9928SPiotr Pawel Stefaniak " base64 --help\n"
114540a9928SPiotr Pawel Stefaniak " base64 --version\n", stderr);
115540a9928SPiotr Pawel Stefaniak exit(failure ? EXIT_FAILURE : EXIT_SUCCESS);
116540a9928SPiotr Pawel Stefaniak }
117540a9928SPiotr Pawel Stefaniak
118540a9928SPiotr Pawel Stefaniak static void
version_base64(void)119540a9928SPiotr Pawel Stefaniak version_base64(void)
120540a9928SPiotr Pawel Stefaniak {
121540a9928SPiotr Pawel Stefaniak (void)fputs("FreeBSD base64\n", stderr);
122540a9928SPiotr Pawel Stefaniak exit(EXIT_SUCCESS);
123540a9928SPiotr Pawel Stefaniak }
124540a9928SPiotr Pawel Stefaniak
125540a9928SPiotr Pawel Stefaniak static void
base64_encode_or_decode(int argc,char * argv[])126540a9928SPiotr Pawel Stefaniak base64_encode_or_decode(int argc, char *argv[])
127540a9928SPiotr Pawel Stefaniak {
128540a9928SPiotr Pawel Stefaniak int ch;
129540a9928SPiotr Pawel Stefaniak bool decode = false;
130540a9928SPiotr Pawel Stefaniak const char *w = NULL;
131540a9928SPiotr Pawel Stefaniak enum { HELP, VERSION };
132540a9928SPiotr Pawel Stefaniak static const struct option opts[] =
133540a9928SPiotr Pawel Stefaniak {
134540a9928SPiotr Pawel Stefaniak {"decode", no_argument, NULL, 'd'},
135540a9928SPiotr Pawel Stefaniak {"ignore-garbage",no_argument, NULL, 'i'},
136540a9928SPiotr Pawel Stefaniak {"wrap", required_argument, NULL, 'w'},
137540a9928SPiotr Pawel Stefaniak {"help", no_argument, NULL, HELP},
138540a9928SPiotr Pawel Stefaniak {"version", no_argument, NULL, VERSION},
139540a9928SPiotr Pawel Stefaniak {NULL, no_argument, NULL, 0}
140540a9928SPiotr Pawel Stefaniak };
141540a9928SPiotr Pawel Stefaniak
142540a9928SPiotr Pawel Stefaniak while ((ch = getopt_long(argc, argv, "diw:", opts, NULL)) != -1)
143540a9928SPiotr Pawel Stefaniak switch (ch) {
144540a9928SPiotr Pawel Stefaniak case 'd':
145540a9928SPiotr Pawel Stefaniak decode = true;
146540a9928SPiotr Pawel Stefaniak break;
147540a9928SPiotr Pawel Stefaniak case 'w':
148540a9928SPiotr Pawel Stefaniak w = optarg;
149540a9928SPiotr Pawel Stefaniak break;
150*ed016aa4SPiotr Pawel Stefaniak case 'i':
151*ed016aa4SPiotr Pawel Stefaniak /* silently ignore */
152*ed016aa4SPiotr Pawel Stefaniak break;
153540a9928SPiotr Pawel Stefaniak case VERSION:
154540a9928SPiotr Pawel Stefaniak version_base64();
155*ed016aa4SPiotr Pawel Stefaniak break;
156540a9928SPiotr Pawel Stefaniak case HELP:
157540a9928SPiotr Pawel Stefaniak default:
158540a9928SPiotr Pawel Stefaniak usage_base64(ch == '?');
159540a9928SPiotr Pawel Stefaniak }
160540a9928SPiotr Pawel Stefaniak
161540a9928SPiotr Pawel Stefaniak if (decode)
162540a9928SPiotr Pawel Stefaniak main_base64_decode(argv[optind]);
163540a9928SPiotr Pawel Stefaniak else
164540a9928SPiotr Pawel Stefaniak main_base64_encode(argv[optind], w);
165540a9928SPiotr Pawel Stefaniak }
166