11507Shannesw/*- 21507Shannesw * SPDX-License-Identifier: BSD-2-Clause 31507Shannesw * 41507Shannesw * Copyright (c) 2022 The FreeBSD Foundation 51507Shannesw * 61507Shannesw * Redistribution and use in source and binary forms, with or without 71507Shannesw * modification, are permitted provided that the following conditions 81507Shannesw * are met: 91507Shannesw * 1. Redistributions of source code must retain the above copyright 101507Shannesw * notice, this list of conditions and the following disclaimer. 111507Shannesw * 2. Redistributions in binary form must reproduce the above copyright 121507Shannesw * notice, this list of conditions and the following disclaimer in the 131507Shannesw * documentation and/or other materials provided with the distribution. 141507Shannesw * 151507Shannesw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161507Shannesw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171507Shannesw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181507Shannesw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 191507Shannesw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201507Shannesw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211507Shannesw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221507Shannesw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231507Shannesw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241507Shannesw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251507Shannesw * SUCH DAMAGE. 261507Shannesw */ 271507Shannesw 281507Shannesw#include <sys/param.h> 291507Shannesw#include <getopt.h> 301507Shannesw#include <libgen.h> 311507Shannesw#include <stdbool.h> 321507Shannesw#include <stdio.h> 331507Shannesw#include <stdlib.h> 341507Shannesw#include <string.h> 351507Shannesw#include <sysexits.h> 361507Shannesw 371507Shanneswextern int main_decode(int, char *[]); 381507Shanneswextern int main_encode(int, char *[]); 391507Shanneswextern int main_base64_decode(const char *); 401507Shanneswextern int main_base64_encode(const char *, const char *); 411507Shanneswextern int main_quotedprintable(int, char*[]); 421507Shannesw 431507Shanneswstatic int search(const char *const); 441507Shanneswstatic void usage_base64(bool); 451507Shanneswstatic void version_base64(void); 461507Shanneswstatic void base64_encode_or_decode(int, char *[]); 471507Shannesw 481507Shanneswenum coders { 491507Shannesw uuencode, uudecode, b64encode, b64decode, base64, qp 501507Shannesw}; 511507Shannesw 521507Shanneswint 531507Shanneswmain(int argc, char *argv[]) 541507Shannesw{ 551507Shannesw const char *const progname = getprogname(); 561507Shannesw int coder = search(progname); 571507Shannesw 581507Shannesw if (coder == -1 && argc > 1) { 591507Shannesw argc--; 601507Shannesw argv++; 611507Shannesw coder = search(argv[0]); 621507Shannesw } 631507Shannesw switch (coder) { 641507Shannesw case uuencode: 651507Shannesw case b64encode: 661507Shannesw main_encode(argc, argv); 671507Shannesw break; 681507Shannesw case uudecode: 691507Shannesw case b64decode: 701507Shannesw main_decode(argc, argv); 711507Shannesw break; 721507Shannesw case base64: 731507Shannesw base64_encode_or_decode(argc, argv); 741507Shannesw break; 751507Shannesw case qp: 761507Shannesw main_quotedprintable(argc, argv); 771507Shannesw break; 781507Shannesw default: 791507Shannesw (void)fprintf(stderr, 801507Shannesw "usage: %1$s <uuencode | uudecode> ...\n" 811507Shannesw " %1$s <b64encode | b64decode> ...\n" 821507Shannesw " %1$s <base64> ...\n" 831507Shannesw " %1$s <qp> ...\n", 841507Shannesw progname); 851507Shannesw exit(EX_USAGE); 861507Shannesw } 871507Shannesw} 881507Shannesw 891507Shanneswstatic int 901507Shanneswsearch(const char *const progname) 911507Shannesw{ 921507Shannesw#define DESIGNATE(item) [item] = #item 931507Shannesw const char *const known[] = { 941507Shannesw DESIGNATE(uuencode), 951507Shannesw DESIGNATE(uudecode), 961507Shannesw DESIGNATE(b64encode), 971507Shannesw DESIGNATE(b64decode), 981507Shannesw DESIGNATE(base64), 991507Shannesw DESIGNATE(qp) 1001507Shannesw }; 1011507Shannesw 1021507Shannesw for (size_t i = 0; i < nitems(known); i++) 1031507Shannesw if (strcmp(progname, known[i]) == 0) 1041507Shannesw return ((int)i); 1051507Shannesw return (-1); 1061507Shannesw} 1071507Shannesw 1081507Shanneswstatic void 1091507Shanneswusage_base64(bool failure) 1101507Shannesw{ 1111507Shannesw (void)fputs("usage: base64 [-w col | --wrap=col] " 1121507Shannesw "[-d | --decode] [FILE]\n" 1131507Shannesw " base64 --help\n" 1141507Shannesw " base64 --version\n", stderr); 1151507Shannesw exit(failure ? EXIT_FAILURE : EXIT_SUCCESS); 1161507Shannesw} 1171507Shannesw 1181507Shanneswstatic void 1191507Shanneswversion_base64(void) 1201507Shannesw{ 1211507Shannesw (void)fputs("FreeBSD base64\n", stderr); 1221507Shannesw exit(EXIT_SUCCESS); 1231507Shannesw} 1241507Shannesw 1251507Shanneswstatic void 1261507Shanneswbase64_encode_or_decode(int argc, char *argv[]) 1271507Shannesw{ 1281507Shannesw int ch; 1291507Shannesw bool decode = false; 1301507Shannesw const char *w = NULL; 1311507Shannesw enum { HELP, VERSION }; 1321507Shannesw static const struct option opts[] = 1331507Shannesw { 1341507Shannesw {"decode", no_argument, NULL, 'd'}, 1351507Shannesw {"ignore-garbage",no_argument, NULL, 'i'}, 1361507Shannesw {"wrap", required_argument, NULL, 'w'}, 1371507Shannesw {"help", no_argument, NULL, HELP}, 1381507Shannesw {"version", no_argument, NULL, VERSION}, 1391507Shannesw {NULL, no_argument, NULL, 0} 1401507Shannesw }; 1411507Shannesw 1421507Shannesw while ((ch = getopt_long(argc, argv, "diw:", opts, NULL)) != -1) 1431507Shannesw switch (ch) { 1441507Shannesw case 'd': 1451507Shannesw decode = true; 1461507Shannesw break; 1471507Shannesw case 'w': 1481507Shannesw w = optarg; 1491507Shannesw break; 1501507Shannesw case 'i': 1511507Shannesw /* silently ignore */ 1521507Shannesw break; 1531507Shannesw case VERSION: 1541507Shannesw version_base64(); 1551507Shannesw break; 1561507Shannesw case HELP: 1571507Shannesw default: 1581507Shannesw usage_base64(ch == '?'); 1591507Shannesw } 1601507Shannesw 1611507Shannesw if (decode) 1621507Shannesw main_base64_decode(argv[optind]); 1631507Shannesw else 1641507Shannesw main_base64_encode(argv[optind], w); 1651507Shannesw} 1661507Shannesw