xref: /freebsd/usr.bin/bintrans/bintrans.c (revision ed016aa4354156a6e778902035fc0186d3b93a4f)
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