uuencode.c revision 105519
1132744Skan/*- 290285Sobrien * Copyright (c) 1983, 1993 3169706Skan * The Regents of the University of California. All rights reserved. 418334Speter * 5132744Skan * Redistribution and use in source and binary forms, with or without 618334Speter * modification, are permitted provided that the following conditions 7132744Skan * are met: 818334Speter * 1. Redistributions of source code must retain the above copyright 918334Speter * notice, this list of conditions and the following disclaimer. 1018334Speter * 2. Redistributions in binary form must reproduce the above copyright 1118334Speter * notice, this list of conditions and the following disclaimer in the 12132744Skan * documentation and/or other materials provided with the distribution. 1318334Speter * 3. All advertising materials mentioning features or use of this software 1418334Speter * must display the following acknowledgement: 1518334Speter * This product includes software developed by the University of 1618334Speter * California, Berkeley and its contributors. 1718334Speter * 4. Neither the name of the University nor the names of its contributors 18132744Skan * may be used to endorse or promote products derived from this software 19169706Skan * without specific prior written permission. 20169706Skan * 2118334Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2218334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2318334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2418334Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2518334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2618334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2718334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2818334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2918334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3018334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3118334Speter * SUCH DAMAGE. 3218334Speter */ 3390285Sobrien 3490285Sobrien#ifndef lint 3590285Sobrienstatic const char copyright[] = 3618334Speter"@(#) Copyright (c) 1983, 1993\n\ 3750654Sobrien The Regents of the University of California. All rights reserved.\n"; 3850654Sobrien#endif /* not lint */ 3950654Sobrien 4090285Sobrien#if 0 4190285Sobrien#ifndef lint 4290285Sobrienstatic char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94"; 4390285Sobrien#endif /* not lint */ 44169706Skan#endif 45132744Skan 4690285Sobrien#include <sys/cdefs.h> 47169706Skan__FBSDID("$FreeBSD: head/usr.bin/uuencode/uuencode.c 105519 2002-10-20 14:18:25Z fanf $"); 48132744Skan 4990285Sobrien/* 5090285Sobrien * uuencode [input] output 5190285Sobrien * 5290285Sobrien * Encode a file so it can be mailed to a remote system. 5390285Sobrien */ 5490285Sobrien#include <sys/param.h> 5590285Sobrien#include <sys/socket.h> 5690285Sobrien#include <sys/stat.h> 5790285Sobrien 5890285Sobrien#include <netinet/in.h> 5990285Sobrien 6090285Sobrien#include <err.h> 6190285Sobrien#include <libgen.h> 6290285Sobrien#include <resolv.h> 6390285Sobrien#include <stdio.h> 6490285Sobrien#include <stdlib.h> 6590285Sobrien#include <string.h> 6690285Sobrien#include <unistd.h> 6790285Sobrien 6890285Sobrienvoid encode(void); 6990285Sobrienvoid base64_encode(void); 7090285Sobrienstatic void usage(void); 7190285Sobrien 7290285SobrienFILE *output; 7390285Sobrienint mode; 7490285Sobrienchar **av; 7590285Sobrien 7690285Sobrienint 7790285Sobrienmain(int argc, char *argv[]) 7890285Sobrien{ 7990285Sobrien struct stat sb; 80132744Skan int base64; 81117407Skan char ch; 82117407Skan char *outfile; 83117407Skan 84117407Skan base64 = 0; 85117407Skan outfile = NULL; 86117407Skan 8750654Sobrien if (strcmp(basename(argv[0]), "b64encode") == 0) 8850654Sobrien base64 = 1; 8990285Sobrien 9050654Sobrien while ((ch = getopt(argc, argv, "mo:")) != -1) { 9118334Speter switch (ch) { 9218334Speter case 'm': 9318334Speter base64 = 1; 9490285Sobrien break; 9518334Speter case 'o': 96169706Skan outfile = optarg; 9718334Speter break; 98169706Skan case '?': 99169706Skan default: 100169706Skan usage(); 101169706Skan } 102132744Skan } 10318334Speter argv += optind; 104169706Skan argc -= optind; 105117407Skan 106117407Skan switch(argc) { 107117407Skan case 2: /* optional first argument is input file */ 108117407Skan if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb)) 109169706Skan err(1, "%s", *argv); 110117407Skan#define RWX (S_IRWXU|S_IRWXG|S_IRWXO) 111117407Skan mode = sb.st_mode & RWX; 112117407Skan ++argv; 113117407Skan break; 114117407Skan case 1: 115117407Skan#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 116169706Skan mode = RW & ~umask(RW); 117169706Skan break; 118117407Skan case 0: 11990285Sobrien default: 12090285Sobrien usage(); 12190285Sobrien } 12290285Sobrien 12390285Sobrien av = argv; 124117407Skan 12518334Speter if (outfile != NULL) { 126169706Skan output = fopen(outfile, "w+"); 127169706Skan if (output == NULL) 12852295Sobrien err(1, "unable to open %s for output", outfile); 129132744Skan } else 130132744Skan output = stdout; 131132744Skan if (base64) 132132744Skan base64_encode(); 133219374Smm else 134132744Skan encode(); 135132744Skan if (ferror(output)) 136132744Skan errx(1, "write error"); 137132744Skan exit(0); 138132744Skan} 139169706Skan 140219374Smm/* ENC is the basic 1 character encoding function to make a char printing */ 141169706Skan#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') 142169706Skan 143169706Skan/* 144252080Spfg * Copy from in to out, encoding in base64 as you go along. 145132744Skan */ 146132744Skanvoid 14752295Sobrienbase64_encode(void) 14852295Sobrien{ 14990285Sobrien /* 15090285Sobrien * Output must fit into 80 columns, chunks come in 4, leave 1. 151169706Skan */ 152169706Skan#define GROUPS ((80 / 4) - 1) 15390285Sobrien unsigned char buf[3]; 154117407Skan char buf2[sizeof(buf) * 2 + 1]; 15590285Sobrien size_t n; 15690285Sobrien int rv, sequence; 15790285Sobrien 15890285Sobrien sequence = 0; 15990285Sobrien 16090285Sobrien fprintf(output, "begin-base64 %o %s\n", mode, *av); 161117407Skan while ((n = fread(buf, 1, sizeof(buf), stdin))) { 162169706Skan ++sequence; 163252080Spfg rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0]))); 164132744Skan if (rv == -1) 165169706Skan errx(1, "b64_ntop: error encoding base64"); 166169706Skan fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); 167169706Skan } 168252080Spfg if (sequence % GROUPS) 169169706Skan fprintf(output, "\n"); 170169706Skan fprintf(output, "====\n"); 171169706Skan} 172252080Spfg 17352295Sobrien/* 174132744Skan * Copy from in to out, encoding as you go along. 175132744Skan */ 176132744Skanvoid 177132744Skanencode(void) 178132744Skan{ 17990285Sobrien register int ch, n; 18090285Sobrien register char *p; 18190285Sobrien char buf[80]; 182169706Skan 183132744Skan (void)fprintf(output, "begin %o %s\n", mode, *av); 184132744Skan while ((n = fread(buf, 1, 45, stdin))) { 185132744Skan ch = ENC(n); 186132744Skan if (fputc(ch, output) == EOF) 187132744Skan break; 188132744Skan for (p = buf; n > 0; n -= 3, p += 3) { 189169706Skan /* Pad with nulls if not a multiple of 3. */ 190169706Skan if (n < 3) { 191169706Skan p[2] = '\0'; 192132744Skan if (n < 2) 193132744Skan p[1] = '\0'; 194132744Skan } 195132744Skan ch = *p >> 2; 196132744Skan ch = ENC(ch); 197132744Skan if (fputc(ch, output) == EOF) 198132744Skan break; 199132744Skan ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); 200132744Skan ch = ENC(ch); 201132744Skan if (fputc(ch, output) == EOF) 202132744Skan break; 203132744Skan ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); 204132744Skan ch = ENC(ch); 205132744Skan if (fputc(ch, output) == EOF) 206132744Skan break; 207132744Skan ch = p[2] & 077; 208132744Skan ch = ENC(ch); 209132744Skan if (fputc(ch, output) == EOF) 210132744Skan break; 211132744Skan } 212252080Spfg if (fputc('\n', output) == EOF) 213252080Spfg break; 214169706Skan } 215132744Skan if (ferror(stdin)) 216132744Skan errx(1, "read error"); 217132744Skan (void)fprintf(output, "%c\nend\n", ENC('\0')); 218132744Skan} 219132744Skan 22090285Sobrienstatic void 221132744Skanusage(void) 222132744Skan{ 223132744Skan (void)fprintf(stderr, 224132744Skan"usage: uuencode [-m] [-o outfile] [infile] remotefile\n" 225169706Skan" b64encode [-o outfile] [infile] remotefile\n"); 226169706Skan exit(1); 227169706Skan} 228169706Skan