1 /* $NetBSD: uudecode.c,v 1.28 2013/01/28 19:50:30 apb Exp $ */
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/cdefs.h>
38 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
39 The Regents of the University of California. All rights reserved.");
41 static char sccsid
[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94";
43 __RCSID("$NetBSD: uudecode.c,v 1.28 2013/01/28 19:50:30 apb Exp $");
49 * create the specified file, decoding as you go.
52 #include <sys/param.h>
66 #include <netinet/in.h>
70 static int decode(char *);
71 __dead
static void usage(void);
72 static int checkend(const char *, const char *, const char *);
73 static int base64_decode(void);
76 static const char *inputname
;
79 main(int argc
, char *argv
[])
82 char *outputname
= NULL
;
84 setlocale(LC_ALL
, "");
87 while ((ch
= getopt(argc
, argv
, "mo:p")) != -1)
96 outputname
= __UNCONST("/dev/stdout");
107 if (!freopen(inputname
= *argv
, "r", stdin
)) {
112 rval
|= decode(outputname
);
116 rval
= decode(outputname
);
122 * Decode one file from stdin. If outputname is not NULL
123 * then it overrides the file name embedded in the input data.
126 decode(char *outputname
)
134 char buf
[MAXPATHLEN
];
136 /* search for header line */
138 if (!fgets(buf
, sizeof(buf
), stdin
)) {
139 warnx("%s: no \"%s\" line", inputname
, base64
?
140 "begin-base64" : "begin");
144 if (strncmp(p
, "begin-base64", 12) == 0) {
148 } else if (strncmp(p
, "begin", 5) == 0) {
155 /* must be followed by an octal mode and a space */
156 mode
= strtol(p
, &fn
, 8);
157 if (fn
== (p
) || !isspace((unsigned char)*fn
) || mode
==LONG_MIN
|| mode
==LONG_MAX
)
159 warnx("%s: invalid mode on \"%s\" line", inputname
,
160 base64
? "begin-base64" : "begin");
163 /* skip whitespace for file name */
164 while (*fn
&& isspace((unsigned char)*fn
)) fn
++;
166 warnx("%s: no filename on \"%s\" line", inputname
,
167 base64
? "begin-base64" : "begin");
171 for (p
= fn
; *p
&& *p
!= '\n'; p
++)
175 /* outputname overrides fn */
179 /* handle ~user/file format */
181 if (!(p
= strchr(fn
, '/'))) {
182 warnx("%s: illegal ~user.", inputname
);
186 if (!(pw
= getpwnam(fn
+ 1))) {
187 warnx("%s: no user %s.", inputname
, buf
);
190 n
= strlen(pw
->pw_dir
);
192 if (n
+ n1
+ 2 > MAXPATHLEN
) {
193 warnx("%s: path too long.", inputname
);
196 /* make space at beginning of buf by moving end of pathname */
197 memmove(buf
+ n
+ 1, p
, n1
+ 1);
198 memmove(buf
, pw
->pw_dir
, n
);
203 if (strcmp(fn
, "/dev/stdout") == 0 || strcmp(fn
, "-") == 0) {
205 * POSIX.1-2008 says that both "-" and "/dev/stdout"
206 * refer to standard output when they appear in the file
207 * header, but only "/dev/stdout" refers to standard
208 * output when it appears as the argument to the "-o"
209 * command line option.
211 * We handle both special names, regardless of whether
212 * they came from the "-o" option or from the header of
217 * Create output file, and set its mode. POSIX.1-2008
218 * requires the mode to be used exactly, ignoring the
219 * umask and anything else, but we mask it with 0666.
221 if (freopen(fn
, "w", stdout
) == NULL
||
222 fchmod(fileno(stdout
), mode
& 0666) != 0) {
223 warn("%s: %s", fn
, inputname
);
229 return base64_decode();
231 /* for each input line */
233 if (!fgets(p
= buf
, sizeof(buf
), stdin
)) {
234 warnx("%s: short file.", inputname
);
237 #define DEC(c) (((c) - ' ') & 077) /* single character decode */
239 * `n' is used to avoid writing out all the characters
240 * at the end of the file.
242 if ((n
= DEC(*p
)) <= 0)
244 for (++p
; n
> 0; p
+= 4, n
-= 3)
246 ch
= DEC(p
[0]) << 2 | DEC(p
[1]) >> 4;
248 ch
= DEC(p
[1]) << 4 | DEC(p
[2]) >> 2;
250 ch
= DEC(p
[2]) << 6 | DEC(p
[3]);
255 ch
= DEC(p
[0]) << 2 | DEC(p
[1]) >> 4;
259 ch
= DEC(p
[1]) << 4 | DEC(p
[2]) >> 2;
263 ch
= DEC(p
[2]) << 6 | DEC(p
[3]);
268 if (!fgets(buf
, sizeof(buf
), stdin
) || strcmp(buf
, "end\n")) {
269 warnx("%s: no \"end\" line.", inputname
);
277 checkend(const char *ptr
, const char *end
, const char *msg
)
282 if (strncmp(ptr
, end
, n
) != 0 ||
283 strspn(ptr
+ n
, "\t\r\n") != strlen(ptr
+ n
)) {
294 char inbuf
[MAXPATHLEN
];
295 unsigned char outbuf
[MAXPATHLEN
* 4];
298 if (!fgets(inbuf
, sizeof(inbuf
), stdin
)) {
299 warnx("%s: short file.", inputname
);
303 warnx("%s: base64 decoding is not supported", inputname
);
306 n
= b64_pton(inbuf
, outbuf
, sizeof(outbuf
));
310 fwrite(outbuf
, 1, n
, stdout
);
312 return (checkend(inbuf
, "====",
313 "error decoding base64 input stream"));
319 (void)fprintf(stderr
,
320 "usage: %s [-m] [-p | -o outfile] [encoded-file ...]\n",