Annotation of src/usr.bin/uuencode/uuencode.c, Revision 1.15
1.15 ! schwarze 1: /* $OpenBSD: uuencode.c,v 1.14 2018/12/31 09:23:08 kn 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:
33: /*
34: * Encode a file so it can be mailed to a remote system.
35: */
1.7 millert 36:
37: #include <sys/stat.h>
38:
39: #include <netinet/in.h>
40:
41: #include <err.h>
42: #include <resolv.h>
1.1 deraadt 43: #include <stdio.h>
44: #include <stdlib.h>
45: #include <string.h>
46: #include <unistd.h>
47:
1.7 millert 48: void encode(void);
49: void base64_encode(void);
1.15 ! schwarze 50: static void __dead usage(void);
1.7 millert 51:
52: FILE *output;
53: int mode;
54: char **av;
1.1 deraadt 55:
1.9 sobrado 56: enum program_mode {
57: MODE_ENCODE,
58: MODE_B64ENCODE
59: } pmode;
1.8 sobrado 60:
1.1 deraadt 61: int
1.6 deraadt 62: main(int argc, char *argv[])
1.1 deraadt 63: {
64: struct stat sb;
1.9 sobrado 65: int base64, ch;
1.7 millert 66: char *outfile;
67: extern char *__progname;
1.8 sobrado 68: static const char *optstr[2] = {
69: "mo:",
70: "o:"
71: };
1.7 millert 72:
1.9 sobrado 73: base64 = 0;
1.7 millert 74: outfile = NULL;
75:
1.9 sobrado 76: pmode = MODE_ENCODE;
1.8 sobrado 77: if (strcmp(__progname, "b64encode") == 0) {
1.7 millert 78: base64 = 1;
1.9 sobrado 79: pmode = MODE_B64ENCODE;
1.8 sobrado 80: }
1.1 deraadt 81:
1.9 sobrado 82: while ((ch = getopt(argc, argv, optstr[pmode])) != -1) {
1.7 millert 83: switch (ch) {
84: case 'm':
85: base64 = 1;
86: break;
87: case 'o':
88: outfile = optarg;
89: break;
90: default:
1.9 sobrado 91: usage();
1.7 millert 92: }
93: }
1.1 deraadt 94: argv += optind;
95: argc -= optind;
1.12 deraadt 96:
97: if (argc == 2 || outfile) {
1.13 deraadt 98: if (pledge("stdio rpath wpath cpath", NULL) == -1)
99: err(1, "pledge");
1.12 deraadt 100: } else {
1.13 deraadt 101: if (pledge("stdio", NULL) == -1)
102: err(1, "pledge");
1.12 deraadt 103: }
1.1 deraadt 104:
105: switch(argc) {
106: case 2: /* optional first argument is input file */
1.7 millert 107: if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
108: err(1, "%s", *argv);
1.1 deraadt 109: #define RWX (S_IRWXU|S_IRWXG|S_IRWXO)
110: mode = sb.st_mode & RWX;
111: ++argv;
112: break;
113: case 1:
114: #define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
115: mode = RW & ~umask(RW);
116: break;
117: default:
1.9 sobrado 118: usage();
1.1 deraadt 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.15 ! schwarze 135: return 0;
1.1 deraadt 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:
1.15 ! schwarze 218: static void __dead
1.9 sobrado 219: usage(void)
1.1 deraadt 220: {
1.9 sobrado 221: switch (pmode) {
1.8 sobrado 222: case MODE_ENCODE:
223: (void)fprintf(stderr,
224: "usage: uuencode [-m] [-o output_file] [file] name\n");
225: break;
226: case MODE_B64ENCODE:
227: (void)fprintf(stderr,
228: "usage: b64encode [-o output_file] [file] name\n");
229: break;
230: }
1.1 deraadt 231: exit(1);
232: }