Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.bin/bintrans/uuencode.c
34680 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1983, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. Neither the name of the University nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
/*
33
* uuencode [input] output
34
*
35
* Encode a file so it can be mailed to a remote system.
36
*/
37
#include <sys/param.h>
38
#include <sys/socket.h>
39
#include <sys/stat.h>
40
41
#include <netinet/in.h>
42
43
#include <err.h>
44
#include <errno.h>
45
#include <libgen.h>
46
#include <resolv.h>
47
#include <stdio.h>
48
#include <stdbool.h>
49
#include <stdlib.h>
50
#include <string.h>
51
#include <unistd.h>
52
53
extern int main_encode(int, char *[]);
54
extern int main_base64_encode(const char *, const char *);
55
56
static void encode(void);
57
static void base64_encode(void);
58
static int arg_to_col(const char *);
59
static void usage(void) __dead2;
60
61
static FILE *output;
62
static int mode;
63
static bool raw;
64
static char **av;
65
static int columns = 76;
66
67
int
68
main_base64_encode(const char *in, const char *w)
69
{
70
raw = 1;
71
if (in != NULL && freopen(in, "r", stdin) == NULL)
72
err(1, "%s", in);
73
output = stdout;
74
if (w != NULL)
75
columns = arg_to_col(w);
76
base64_encode();
77
if (fflush(output) != 0)
78
errx(1, "write error");
79
exit(0);
80
}
81
82
int
83
main_encode(int argc, char *argv[])
84
{
85
struct stat sb;
86
bool base64;
87
int ch;
88
const char *outfile;
89
90
base64 = false;
91
outfile = NULL;
92
93
if (strcmp(basename(argv[0]), "b64encode") == 0)
94
base64 = 1;
95
96
while ((ch = getopt(argc, argv, "mo:rw:")) != -1) {
97
switch (ch) {
98
case 'm':
99
base64 = true;
100
break;
101
case 'o':
102
outfile = optarg;
103
break;
104
case 'r':
105
raw = true;
106
break;
107
case 'w':
108
columns = arg_to_col(optarg);
109
break;
110
case '?':
111
default:
112
usage();
113
}
114
}
115
argv += optind;
116
argc -= optind;
117
118
switch (argc) {
119
case 2: /* optional first argument is input file */
120
if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
121
err(1, "%s", *argv);
122
#define RWX (S_IRWXU|S_IRWXG|S_IRWXO)
123
mode = sb.st_mode & RWX;
124
++argv;
125
break;
126
case 1:
127
#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
128
mode = RW & ~umask(RW);
129
break;
130
case 0:
131
default:
132
usage();
133
}
134
135
av = argv;
136
137
if (outfile != NULL) {
138
output = fopen(outfile, "w+");
139
if (output == NULL)
140
err(1, "unable to open %s for output", outfile);
141
} else
142
output = stdout;
143
if (base64)
144
base64_encode();
145
else
146
encode();
147
if (fflush(output) != 0)
148
errx(1, "write error");
149
exit(0);
150
}
151
152
/* ENC is the basic 1 character encoding function to make a char printing */
153
#define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
154
155
/*
156
* Copy from in to out, encoding in base64 as you go along.
157
*/
158
static void
159
base64_encode(void)
160
{
161
/*
162
* This buffer's length should be a multiple of 24 bits to avoid "="
163
* padding. Once it reached ~1 KB, further expansion didn't improve
164
* performance for me.
165
*/
166
unsigned char buf[1023];
167
char buf2[sizeof(buf) * 2 + 1];
168
size_t n;
169
unsigned carry = 0;
170
int rv, written;
171
172
if (!raw)
173
fprintf(output, "begin-base64 %o %s\n", mode, *av);
174
while ((n = fread(buf, 1, sizeof(buf), stdin))) {
175
rv = b64_ntop(buf, n, buf2, nitems(buf2));
176
if (rv == -1)
177
errx(1, "b64_ntop: error encoding base64");
178
if (columns == 0) {
179
fputs(buf2, output);
180
continue;
181
}
182
for (int i = 0; i < rv; i += written) {
183
written = fprintf(output, "%.*s", columns - carry,
184
&buf2[i]);
185
186
carry = (carry + written) % columns;
187
if (carry == 0)
188
fputc('\n', output);
189
}
190
}
191
if (columns == 0 || carry != 0)
192
fputc('\n', output);
193
if (!raw)
194
fprintf(output, "====\n");
195
}
196
197
/*
198
* Copy from in to out, encoding as you go along.
199
*/
200
static void
201
encode(void)
202
{
203
int ch, n;
204
char *p;
205
char buf[80];
206
207
if (!raw)
208
(void)fprintf(output, "begin %o %s\n", mode, *av);
209
while ((n = fread(buf, 1, 45, stdin))) {
210
ch = ENC(n);
211
if (fputc(ch, output) == EOF)
212
break;
213
for (p = buf; n > 0; n -= 3, p += 3) {
214
/* Pad with nulls if not a multiple of 3. */
215
if (n < 3) {
216
p[2] = '\0';
217
if (n < 2)
218
p[1] = '\0';
219
}
220
ch = *p >> 2;
221
ch = ENC(ch);
222
if (fputc(ch, output) == EOF)
223
break;
224
ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
225
ch = ENC(ch);
226
if (fputc(ch, output) == EOF)
227
break;
228
ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
229
ch = ENC(ch);
230
if (fputc(ch, output) == EOF)
231
break;
232
ch = p[2] & 077;
233
ch = ENC(ch);
234
if (fputc(ch, output) == EOF)
235
break;
236
}
237
if (fputc('\n', output) == EOF)
238
break;
239
}
240
if (ferror(stdin))
241
errx(1, "read error");
242
if (!raw)
243
(void)fprintf(output, "%c\nend\n", ENC('\0'));
244
}
245
246
static int
247
arg_to_col(const char *w)
248
{
249
char *ep;
250
long option;
251
252
errno = 0;
253
option = strtol(w, &ep, 10);
254
if (option > INT_MAX)
255
errno = ERANGE;
256
else if (ep[0] != '\0')
257
errno = EINVAL;
258
if (errno != 0)
259
err(2, NULL);
260
261
if (option < 0) {
262
errno = EINVAL;
263
err(2, "columns argument must be non-negative");
264
}
265
return (option);
266
}
267
268
static void
269
usage(void)
270
{
271
(void)fprintf(stderr,
272
"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"
273
" b64encode [-o outfile] [infile] remotefile\n");
274
exit(1);
275
}
276
277