Annotation of src/usr.bin/uuencode/uuencode.c, Revision 1.8
1.8 ! sobrado 1: /* $OpenBSD: uuencode.c,v 1.7 2004/04/09 22:54:02 millert Exp $ */
1.7 millert 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.8 ! sobrado 43: static const char rcsid[] = "$OpenBSD: uuencode.c,v 1.7 2004/04/09 22:54:02 millert 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);
1.8 ! sobrado 66: static void usage(int);
1.7 millert 67:
68: FILE *output;
69: int mode;
70: char **av;
1.1 deraadt 71:
1.8 ! sobrado 72: /*
! 73: * program modes
! 74: */
! 75: #define MODE_ENCODE 0
! 76: #define MODE_B64ENCODE 1
! 77:
1.1 deraadt 78: int
1.6 deraadt 79: main(int argc, char *argv[])
1.1 deraadt 80: {
81: struct stat sb;
1.8 ! sobrado 82: int base64, ch, mode;
1.7 millert 83: char *outfile;
84: extern char *__progname;
1.8 ! sobrado 85: static const char *optstr[2] = {
! 86: "mo:",
! 87: "o:"
! 88: };
1.7 millert 89:
1.8 ! sobrado 90: base64 = mode = 0;
1.7 millert 91: outfile = NULL;
92:
1.8 ! sobrado 93: if (strcmp(__progname, "b64encode") == 0) {
1.7 millert 94: base64 = 1;
1.8 ! sobrado 95: mode = MODE_B64ENCODE;
! 96: }
1.1 deraadt 97:
98: setlocale(LC_ALL, "");
1.8 ! sobrado 99: while ((ch = getopt(argc, argv, optstr[mode])) != -1) {
1.7 millert 100: switch (ch) {
101: case 'm':
102: base64 = 1;
103: break;
104: case 'o':
105: outfile = optarg;
106: break;
107: case '?':
108: default:
1.8 ! sobrado 109: usage(mode);
1.7 millert 110: }
111: }
1.1 deraadt 112: argv += optind;
113: argc -= optind;
114:
115: switch(argc) {
116: case 2: /* optional first argument is input file */
1.7 millert 117: if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
118: err(1, "%s", *argv);
1.1 deraadt 119: #define RWX (S_IRWXU|S_IRWXG|S_IRWXO)
120: mode = sb.st_mode & RWX;
121: ++argv;
122: break;
123: case 1:
124: #define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
125: mode = RW & ~umask(RW);
126: break;
127: case 0:
128: default:
1.8 ! sobrado 129: usage(mode);
1.1 deraadt 130: }
131:
1.7 millert 132: av = argv;
133:
134: if (outfile != NULL) {
135: output = fopen(outfile, "w+");
136: if (output == NULL)
137: err(1, "unable to open %s for output", outfile);
138: } else
139: output = stdout;
140: if (base64)
141: base64_encode();
142: else
143: encode();
144: if (ferror(output))
145: errx(1, "write error");
1.1 deraadt 146: exit(0);
147: }
148:
149: /* ENC is the basic 1 character encoding function to make a char printing */
150: #define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
151:
152: /*
1.7 millert 153: * Copy from in to out, encoding in base64 as you go along.
154: */
155: void
156: base64_encode(void)
157: {
158: /*
159: * Output must fit into 80 columns, chunks come in 4, leave 1.
160: */
161: #define GROUPS ((80 / 4) - 1)
162: unsigned char buf[3];
163: char buf2[sizeof(buf) * 2 + 1];
164: size_t n;
165: int rv, sequence;
166:
167: sequence = 0;
168:
169: fprintf(output, "begin-base64 %o %s\n", mode, *av);
170: while ((n = fread(buf, 1, sizeof(buf), stdin))) {
171: ++sequence;
172: rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0])));
173: if (rv == -1)
174: errx(1, "b64_ntop: error encoding base64");
175: fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
176: }
177: if (sequence % GROUPS)
178: fprintf(output, "\n");
179: fprintf(output, "====\n");
180: }
181:
182: /*
183: * Copy from in to out, encoding as you go along.
1.1 deraadt 184: */
1.7 millert 185: void
1.6 deraadt 186: encode(void)
1.1 deraadt 187: {
1.4 mpech 188: int ch, n;
189: char *p;
1.1 deraadt 190: char buf[80];
191:
1.7 millert 192: (void)fprintf(output, "begin %o %s\n", mode, *av);
1.3 deraadt 193: while ((n = fread(buf, 1, 45, stdin))) {
1.1 deraadt 194: ch = ENC(n);
1.7 millert 195: if (fputc(ch, output) == EOF)
1.1 deraadt 196: break;
197: for (p = buf; n > 0; n -= 3, p += 3) {
1.7 millert 198: /* Pad with nulls if not a multiple of 3. */
199: if (n < 3) {
200: p[2] = '\0';
201: if (n < 2)
202: p[1] = '\0';
203: }
1.1 deraadt 204: ch = *p >> 2;
205: ch = ENC(ch);
1.7 millert 206: if (fputc(ch, output) == EOF)
1.1 deraadt 207: break;
1.7 millert 208: ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
1.1 deraadt 209: ch = ENC(ch);
1.7 millert 210: if (fputc(ch, output) == EOF)
1.1 deraadt 211: break;
1.7 millert 212: ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
1.1 deraadt 213: ch = ENC(ch);
1.7 millert 214: if (fputc(ch, output) == EOF)
1.1 deraadt 215: break;
216: ch = p[2] & 077;
217: ch = ENC(ch);
1.7 millert 218: if (fputc(ch, output) == EOF)
1.1 deraadt 219: break;
220: }
1.7 millert 221: if (fputc('\n', output) == EOF)
1.1 deraadt 222: break;
223: }
1.7 millert 224: if (ferror(stdin))
225: errx(1, "read error");
226: (void)fprintf(output, "%c\nend\n", ENC('\0'));
1.1 deraadt 227: }
228:
229: static void
1.8 ! sobrado 230: usage(int mode)
1.1 deraadt 231: {
1.8 ! sobrado 232: switch (mode) {
! 233: case MODE_ENCODE:
! 234: (void)fprintf(stderr,
! 235: "usage: uuencode [-m] [-o output_file] [file] name\n");
! 236: break;
! 237: case MODE_B64ENCODE:
! 238: (void)fprintf(stderr,
! 239: "usage: b64encode [-o output_file] [file] name\n");
! 240: break;
! 241: }
1.1 deraadt 242: exit(1);
243: }