1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022 The FreeBSD Foundation 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <getopt.h> 30 #include <libgen.h> 31 #include <stdbool.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <sysexits.h> 36 37 extern int main_decode(int, char *[]); 38 extern int main_encode(int, char *[]); 39 extern int main_base64_decode(const char *); 40 extern int main_base64_encode(const char *, const char *); 41 extern int main_quotedprintable(int, char*[]); 42 43 static int search(const char *const); 44 static void usage_base64(bool); 45 static void version_base64(void); 46 static void base64_encode_or_decode(int, char *[]); 47 48 enum coders { 49 uuencode, uudecode, b64encode, b64decode, base64, qp 50 }; 51 52 int 53 main(int argc, char *argv[]) 54 { 55 const char *const progname = getprogname(); 56 int coder = search(progname); 57 58 if (coder == -1 && argc > 1) { 59 argc--; 60 argv++; 61 coder = search(argv[0]); 62 } 63 switch (coder) { 64 case uuencode: 65 case b64encode: 66 main_encode(argc, argv); 67 break; 68 case uudecode: 69 case b64decode: 70 main_decode(argc, argv); 71 break; 72 case base64: 73 base64_encode_or_decode(argc, argv); 74 break; 75 case qp: 76 main_quotedprintable(argc, argv); 77 break; 78 default: 79 (void)fprintf(stderr, 80 "usage: %1$s <uuencode | uudecode> ...\n" 81 " %1$s <b64encode | b64decode> ...\n" 82 " %1$s <base64> ...\n" 83 " %1$s <qp> ...\n", 84 progname); 85 exit(EX_USAGE); 86 } 87 } 88 89 static int 90 search(const char *const progname) 91 { 92 #define DESIGNATE(item) [item] = #item 93 const char *const known[] = { 94 DESIGNATE(uuencode), 95 DESIGNATE(uudecode), 96 DESIGNATE(b64encode), 97 DESIGNATE(b64decode), 98 DESIGNATE(base64), 99 DESIGNATE(qp) 100 }; 101 102 for (size_t i = 0; i < nitems(known); i++) 103 if (strcmp(progname, known[i]) == 0) 104 return ((int)i); 105 return (-1); 106 } 107 108 static void 109 usage_base64(bool failure) 110 { 111 (void)fputs("usage: base64 [-w col | --wrap=col] " 112 "[-d | --decode] [FILE]\n" 113 " base64 --help\n" 114 " base64 --version\n", stderr); 115 exit(failure ? EXIT_FAILURE : EXIT_SUCCESS); 116 } 117 118 static void 119 version_base64(void) 120 { 121 (void)fputs("FreeBSD base64\n", stderr); 122 exit(EXIT_SUCCESS); 123 } 124 125 static void 126 base64_encode_or_decode(int argc, char *argv[]) 127 { 128 int ch; 129 bool decode = false; 130 const char *w = NULL; 131 enum { HELP, VERSION }; 132 static const struct option opts[] = 133 { 134 {"decode", no_argument, NULL, 'd'}, 135 {"ignore-garbage",no_argument, NULL, 'i'}, 136 {"wrap", required_argument, NULL, 'w'}, 137 {"help", no_argument, NULL, HELP}, 138 {"version", no_argument, NULL, VERSION}, 139 {NULL, no_argument, NULL, 0} 140 }; 141 142 while ((ch = getopt_long(argc, argv, "diw:", opts, NULL)) != -1) 143 switch (ch) { 144 case 'd': 145 decode = true; 146 break; 147 case 'w': 148 w = optarg; 149 break; 150 case 'i': 151 /* silently ignore */ 152 break; 153 case VERSION: 154 version_base64(); 155 break; 156 case HELP: 157 default: 158 usage_base64(ch == '?'); 159 } 160 161 if (decode) 162 main_base64_decode(argv[optind]); 163 else 164 main_base64_encode(argv[optind], w); 165 } 166