Annotation of src/usr.bin/uuencode/uuencode.c, Revision 1.7
1.7 ! millert 1: /* $OpenBSD: uuencode.c,v 1.6 2003/06/10 22:20:53 deraadt Exp $ */
! 2: /* $FreeBSD: uuencode.c,v 1.18 2004/01/22 07:23:35 grehan Exp $ */
1.1 deraadt 3:
4: /*-
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.5 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.7 ! millert 33: #ifndef lint
! 34: static const char copyright[] =
1.1 deraadt 35: "@(#) Copyright (c) 1983, 1993\n\
36: The Regents of the University of California. All rights reserved.\n";
1.7 ! millert 37: #endif /* not lint */
1.1 deraadt 38:
39: #ifndef lint
40: #if 0
1.7 ! millert 41: static const char sccsid[] = "@(#)uuencode.c 8.2 (Berkeley) 4/2/94";
1.1 deraadt 42: #endif
1.7 ! millert 43: static const char rcsid[] = "$OpenBSD: uuencode.c,v 1.6 2003/06/10 22:20:53 deraadt Exp $";
1.1 deraadt 44: #endif /* not lint */
45:
46: /*
47: * Encode a file so it can be mailed to a remote system.
48: */
1.7 ! millert 49:
! 50: #include <sys/param.h>
! 51: #include <sys/socket.h>
! 52: #include <sys/stat.h>
! 53:
! 54: #include <netinet/in.h>
! 55:
! 56: #include <err.h>
! 57: #include <locale.h>
! 58: #include <resolv.h>
1.1 deraadt 59: #include <stdio.h>
60: #include <stdlib.h>
61: #include <string.h>
62: #include <unistd.h>
63:
1.7 ! millert 64: void encode(void);
! 65: void base64_encode(void);
! 66: static void usage(void);
! 67:
! 68: FILE *output;
! 69: int mode;
! 70: char **av;
1.1 deraadt 71:
72: int
1.6 deraadt 73: main(int argc, char *argv[])
1.1 deraadt 74: {
75: struct stat sb;
1.7 ! millert 76: int base64;
! 77: int ch;
! 78: char *outfile;
! 79: extern char *__progname;
! 80:
! 81: base64 = 0;
! 82: outfile = NULL;
! 83:
! 84: if (strcmp(__progname, "b64encode") == 0)
! 85: base64 = 1;
1.1 deraadt 86:
87: setlocale(LC_ALL, "");
1.7 ! millert 88: while ((ch = getopt(argc, argv, "mo:")) != -1) {
! 89: switch (ch) {
! 90: case 'm':
! 91: base64 = 1;
! 92: break;
! 93: case 'o':
! 94: outfile = optarg;
! 95: break;
! 96: case '?':
! 97: default:
! 98: usage();
! 99: }
! 100: }
1.1 deraadt 101: argv += optind;
102: argc -= optind;
103:
104: switch(argc) {
105: case 2: /* optional first argument is input file */
1.7 ! millert 106: if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
! 107: err(1, "%s", *argv);
1.1 deraadt 108: #define RWX (S_IRWXU|S_IRWXG|S_IRWXO)
109: mode = sb.st_mode & RWX;
110: ++argv;
111: break;
112: case 1:
113: #define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
114: mode = RW & ~umask(RW);
115: break;
116: case 0:
117: default:
118: usage();
119: }
120:
1.7 ! millert 121: av = argv;
! 122:
! 123: if (outfile != NULL) {
! 124: output = fopen(outfile, "w+");
! 125: if (output == NULL)
! 126: err(1, "unable to open %s for output", outfile);
! 127: } else
! 128: output = stdout;
! 129: if (base64)
! 130: base64_encode();
! 131: else
! 132: encode();
! 133: if (ferror(output))
! 134: errx(1, "write error");
1.1 deraadt 135: exit(0);
136: }
137:
138: /* ENC is the basic 1 character encoding function to make a char printing */
139: #define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
140:
141: /*
1.7 ! millert 142: * Copy from in to out, encoding in base64 as you go along.
! 143: */
! 144: void
! 145: base64_encode(void)
! 146: {
! 147: /*
! 148: * Output must fit into 80 columns, chunks come in 4, leave 1.
! 149: */
! 150: #define GROUPS ((80 / 4) - 1)
! 151: unsigned char buf[3];
! 152: char buf2[sizeof(buf) * 2 + 1];
! 153: size_t n;
! 154: int rv, sequence;
! 155:
! 156: sequence = 0;
! 157:
! 158: fprintf(output, "begin-base64 %o %s\n", mode, *av);
! 159: while ((n = fread(buf, 1, sizeof(buf), stdin))) {
! 160: ++sequence;
! 161: rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0])));
! 162: if (rv == -1)
! 163: errx(1, "b64_ntop: error encoding base64");
! 164: fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
! 165: }
! 166: if (sequence % GROUPS)
! 167: fprintf(output, "\n");
! 168: fprintf(output, "====\n");
! 169: }
! 170:
! 171: /*
! 172: * Copy from in to out, encoding as you go along.
1.1 deraadt 173: */
1.7 ! millert 174: void
1.6 deraadt 175: encode(void)
1.1 deraadt 176: {
1.4 mpech 177: int ch, n;
178: char *p;
1.1 deraadt 179: char buf[80];
180:
1.7 ! millert 181: (void)fprintf(output, "begin %o %s\n", mode, *av);
1.3 deraadt 182: while ((n = fread(buf, 1, 45, stdin))) {
1.1 deraadt 183: ch = ENC(n);
1.7 ! millert 184: if (fputc(ch, output) == EOF)
1.1 deraadt 185: break;
186: for (p = buf; n > 0; n -= 3, p += 3) {
1.7 ! millert 187: /* Pad with nulls if not a multiple of 3. */
! 188: if (n < 3) {
! 189: p[2] = '\0';
! 190: if (n < 2)
! 191: p[1] = '\0';
! 192: }
1.1 deraadt 193: ch = *p >> 2;
194: ch = ENC(ch);
1.7 ! millert 195: if (fputc(ch, output) == EOF)
1.1 deraadt 196: break;
1.7 ! millert 197: ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
1.1 deraadt 198: ch = ENC(ch);
1.7 ! millert 199: if (fputc(ch, output) == EOF)
1.1 deraadt 200: break;
1.7 ! millert 201: ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
1.1 deraadt 202: ch = ENC(ch);
1.7 ! millert 203: if (fputc(ch, output) == EOF)
1.1 deraadt 204: break;
205: ch = p[2] & 077;
206: ch = ENC(ch);
1.7 ! millert 207: if (fputc(ch, output) == EOF)
1.1 deraadt 208: break;
209: }
1.7 ! millert 210: if (fputc('\n', output) == EOF)
1.1 deraadt 211: break;
212: }
1.7 ! millert 213: if (ferror(stdin))
! 214: errx(1, "read error");
! 215: (void)fprintf(output, "%c\nend\n", ENC('\0'));
1.1 deraadt 216: }
217:
218: static void
1.6 deraadt 219: usage(void)
1.1 deraadt 220: {
1.7 ! millert 221: (void)fprintf(stderr,
! 222: "usage: uuencode [-m] [-o outfile] [infile] remotefile\n"
! 223: " b64encode [-o outfile] [infile] remotefile\n");
1.1 deraadt 224: exit(1);
225: }