11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 30114594Sobrien#if 0 311590Srgrimes#ifndef lint 3228564Scharnierstatic const char copyright[] = 331590Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 341590Srgrimes The Regents of the University of California. All rights reserved.\n"; 351590Srgrimes#endif /* not lint */ 361590Srgrimes 371590Srgrimes#ifndef lint 381590Srgrimesstatic char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94"; 3996438Smike#endif /* not lint */ 4028564Scharnier#endif 4196438Smike#include <sys/cdefs.h> 4296438Smike__FBSDID("$FreeBSD$"); 4396438Smike 441590Srgrimes/* 451590Srgrimes * uuencode [input] output 461590Srgrimes * 471590Srgrimes * Encode a file so it can be mailed to a remote system. 481590Srgrimes */ 4991661Sjmallett#include <sys/param.h> 5091661Sjmallett#include <sys/socket.h> 511590Srgrimes#include <sys/stat.h> 521590Srgrimes 5391661Sjmallett#include <netinet/in.h> 5491661Sjmallett 5528564Scharnier#include <err.h> 56105519Sfanf#include <libgen.h> 5791661Sjmallett#include <resolv.h> 581590Srgrimes#include <stdio.h> 5978718Sdd#include <stdlib.h> 6091661Sjmallett#include <string.h> 6128564Scharnier#include <unistd.h> 621590Srgrimes 6392922Simpvoid encode(void); 6492922Simpvoid base64_encode(void); 6592922Simpstatic void usage(void); 6628564Scharnier 6791676SmikeFILE *output; 6891661Sjmallettint mode; 6991661Sjmallettchar **av; 7091661Sjmallett 711590Srgrimesint 7296386Salfredmain(int argc, char *argv[]) 731590Srgrimes{ 741590Srgrimes struct stat sb; 7591661Sjmallett int base64; 76124830Sgrehan int ch; 7791661Sjmallett char *outfile; 781590Srgrimes 7991661Sjmallett base64 = 0; 8091661Sjmallett outfile = NULL; 8191661Sjmallett 82105519Sfanf if (strcmp(basename(argv[0]), "b64encode") == 0) 8396942Sjmallett base64 = 1; 8496942Sjmallett 8591661Sjmallett while ((ch = getopt(argc, argv, "mo:")) != -1) { 8691661Sjmallett switch (ch) { 8791661Sjmallett case 'm': 8891661Sjmallett base64 = 1; 8991661Sjmallett break; 9091661Sjmallett case 'o': 9191661Sjmallett outfile = optarg; 9291661Sjmallett break; 9391661Sjmallett case '?': 9491661Sjmallett default: 9591661Sjmallett usage(); 9691661Sjmallett } 9791661Sjmallett } 981590Srgrimes argv += optind; 991590Srgrimes argc -= optind; 1001590Srgrimes 1011590Srgrimes switch(argc) { 1021590Srgrimes case 2: /* optional first argument is input file */ 10328564Scharnier if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb)) 10428564Scharnier err(1, "%s", *argv); 1051590Srgrimes#define RWX (S_IRWXU|S_IRWXG|S_IRWXO) 1061590Srgrimes mode = sb.st_mode & RWX; 1071590Srgrimes ++argv; 1081590Srgrimes break; 1091590Srgrimes case 1: 1101590Srgrimes#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 1111590Srgrimes mode = RW & ~umask(RW); 1121590Srgrimes break; 1131590Srgrimes case 0: 1141590Srgrimes default: 1151590Srgrimes usage(); 1161590Srgrimes } 1171590Srgrimes 11891661Sjmallett av = argv; 11991661Sjmallett 12091661Sjmallett if (outfile != NULL) { 12191661Sjmallett output = fopen(outfile, "w+"); 12291661Sjmallett if (output == NULL) 12391661Sjmallett err(1, "unable to open %s for output", outfile); 12491676Smike } else 12591676Smike output = stdout; 12691661Sjmallett if (base64) 12791661Sjmallett base64_encode(); 12891661Sjmallett else 12991661Sjmallett encode(); 13091661Sjmallett if (ferror(output)) 13128564Scharnier errx(1, "write error"); 1321590Srgrimes exit(0); 1331590Srgrimes} 1341590Srgrimes 1351590Srgrimes/* ENC is the basic 1 character encoding function to make a char printing */ 1361590Srgrimes#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') 1371590Srgrimes 1381590Srgrimes/* 13991661Sjmallett * Copy from in to out, encoding in base64 as you go along. 1401590Srgrimes */ 14128564Scharniervoid 14296438Smikebase64_encode(void) 14391661Sjmallett{ 14496810Sjmallett /* 14596810Sjmallett * Output must fit into 80 columns, chunks come in 4, leave 1. 14696810Sjmallett */ 14796810Sjmallett#define GROUPS ((80 / 4) - 1) 14896810Sjmallett unsigned char buf[3]; 14996810Sjmallett char buf2[sizeof(buf) * 2 + 1]; 15091661Sjmallett size_t n; 15191661Sjmallett int rv, sequence; 15291661Sjmallett 15391661Sjmallett sequence = 0; 15491661Sjmallett 15591661Sjmallett fprintf(output, "begin-base64 %o %s\n", mode, *av); 15691661Sjmallett while ((n = fread(buf, 1, sizeof(buf), stdin))) { 15791661Sjmallett ++sequence; 15891661Sjmallett rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0]))); 15991661Sjmallett if (rv == -1) 16091661Sjmallett errx(1, "b64_ntop: error encoding base64"); 16191661Sjmallett fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n"); 16291661Sjmallett } 16391661Sjmallett if (sequence % GROUPS) 16491661Sjmallett fprintf(output, "\n"); 16591661Sjmallett fprintf(output, "====\n"); 16691661Sjmallett} 16791661Sjmallett 16891661Sjmallett/* 16991661Sjmallett * Copy from in to out, encoding as you go along. 17091661Sjmallett */ 17191661Sjmallettvoid 17296438Smikeencode(void) 1731590Srgrimes{ 1741590Srgrimes register int ch, n; 1751590Srgrimes register char *p; 1761590Srgrimes char buf[80]; 1771590Srgrimes 17891661Sjmallett (void)fprintf(output, "begin %o %s\n", mode, *av); 17928564Scharnier while ((n = fread(buf, 1, 45, stdin))) { 1801590Srgrimes ch = ENC(n); 18191661Sjmallett if (fputc(ch, output) == EOF) 1821590Srgrimes break; 1831590Srgrimes for (p = buf; n > 0; n -= 3, p += 3) { 18484715Sru /* Pad with nulls if not a multiple of 3. */ 18584715Sru if (n < 3) { 18684715Sru p[2] = '\0'; 18784715Sru if (n < 2) 18884715Sru p[1] = '\0'; 18984715Sru } 1901590Srgrimes ch = *p >> 2; 1911590Srgrimes ch = ENC(ch); 19291661Sjmallett if (fputc(ch, output) == EOF) 1931590Srgrimes break; 19478387Sdd ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); 1951590Srgrimes ch = ENC(ch); 19691661Sjmallett if (fputc(ch, output) == EOF) 1971590Srgrimes break; 19878387Sdd ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); 1991590Srgrimes ch = ENC(ch); 20091661Sjmallett if (fputc(ch, output) == EOF) 2011590Srgrimes break; 2021590Srgrimes ch = p[2] & 077; 2031590Srgrimes ch = ENC(ch); 20491661Sjmallett if (fputc(ch, output) == EOF) 2051590Srgrimes break; 2061590Srgrimes } 20791661Sjmallett if (fputc('\n', output) == EOF) 2081590Srgrimes break; 2091590Srgrimes } 21028564Scharnier if (ferror(stdin)) 21128564Scharnier errx(1, "read error"); 21291661Sjmallett (void)fprintf(output, "%c\nend\n", ENC('\0')); 2131590Srgrimes} 2141590Srgrimes 21528564Scharnierstatic void 21696438Smikeusage(void) 2171590Srgrimes{ 21896943Sjmallett (void)fprintf(stderr, 21996943Sjmallett"usage: uuencode [-m] [-o outfile] [infile] remotefile\n" 22096943Sjmallett" b64encode [-o outfile] [infile] remotefile\n"); 2211590Srgrimes exit(1); 2221590Srgrimes} 223