1 /* $NetBSD: uudecode.c,v 1.24 2008/11/29 22:36:57 dholland 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.24 2008/11/29 22:36:57 dholland Exp $");
49 * create the specified file, decoding as you go.
52 #include <sys/param.h>
66 #include <netinet/in.h>
70 static int decode(void);
71 static void usage(void);
72 static int checkend(const char *, const char *, const char *);
73 static int base64_decode(void);
74 int main(int, char *[]);
80 main(int argc
, char *argv
[])
84 setlocale(LC_ALL
, "");
88 while ((ch
= getopt(argc
, argv
, "mp")) != -1)
105 if (!freopen(filename
= *argv
, "r", stdin
)) {
128 char buf
[MAXPATHLEN
];
130 /* search for header line */
132 if (!fgets(buf
, sizeof(buf
), stdin
)) {
133 warnx("%s: no \"%s\" line", filename
, base64
?
134 "begin-base64" : "begin");
138 if (strncmp(p
, "begin-base64", 12) == 0) {
142 } else if (strncmp(p
, "begin", 5) == 0) {
149 /* must be followed by an octal mode and a space */
150 mode
= strtol(p
, &fn
, 8);
151 if (fn
== (p
) || !isspace((unsigned char)*fn
) || mode
==LONG_MIN
|| mode
==LONG_MAX
)
153 warnx("%s: invalid mode on \"%s\" line", filename
,
154 base64
? "begin-base64" : "begin");
157 /* skip whitespace for file name */
158 while (*fn
&& isspace((unsigned char)*fn
)) fn
++;
160 warnx("%s: no filename on \"%s\" line", filename
,
161 base64
? "begin-base64" : "begin");
165 for (p
= fn
; *p
&& *p
!= '\n'; p
++)
169 /* handle ~user/file format */
171 if (!(p
= strchr(fn
, '/'))) {
172 warnx("%s: illegal ~user.", filename
);
176 if (!(pw
= getpwnam(fn
+ 1))) {
177 warnx("%s: no user %s.", filename
, buf
);
180 n
= strlen(pw
->pw_dir
);
182 if (n
+ n1
+ 2 > MAXPATHLEN
) {
183 warnx("%s: path too long.", filename
);
186 /* make space at beginning of buf by moving end of pathname */
187 memmove(buf
+ n
+ 1, p
, n1
+ 1);
188 memmove(buf
, pw
->pw_dir
, n
);
193 /* create output file, set mode */
194 if (!pflag
&& (!freopen(fn
, "w", stdout
) ||
195 fchmod(fileno(stdout
), mode
& 0666))) {
196 warn("%s: %s", fn
, filename
);
201 return base64_decode();
203 /* for each input line */
205 if (!fgets(p
= buf
, sizeof(buf
), stdin
)) {
206 warnx("%s: short file.", filename
);
209 #define DEC(c) (((c) - ' ') & 077) /* single character decode */
211 * `n' is used to avoid writing out all the characters
212 * at the end of the file.
214 if ((n
= DEC(*p
)) <= 0)
216 for (++p
; n
> 0; p
+= 4, n
-= 3)
218 ch
= DEC(p
[0]) << 2 | DEC(p
[1]) >> 4;
220 ch
= DEC(p
[1]) << 4 | DEC(p
[2]) >> 2;
222 ch
= DEC(p
[2]) << 6 | DEC(p
[3]);
227 ch
= DEC(p
[0]) << 2 | DEC(p
[1]) >> 4;
231 ch
= DEC(p
[1]) << 4 | DEC(p
[2]) >> 2;
235 ch
= DEC(p
[2]) << 6 | DEC(p
[3]);
240 if (!fgets(buf
, sizeof(buf
), stdin
) || strcmp(buf
, "end\n")) {
241 warnx("%s: no \"end\" line.", filename
);
249 checkend(const char *ptr
, const char *end
, const char *msg
)
254 if (strncmp(ptr
, end
, n
) != 0 ||
255 strspn(ptr
+ n
, "\t\r\n") != strlen(ptr
+ n
)) {
266 char inbuf
[MAXPATHLEN
];
267 unsigned char outbuf
[MAXPATHLEN
* 4];
270 if (!fgets(inbuf
, sizeof(inbuf
), stdin
)) {
271 warnx("%s: short file.", filename
);
275 warnx("%s: base64 decoding is not supported", filename
);
278 n
= b64_pton(inbuf
, outbuf
, sizeof(outbuf
));
282 fwrite(outbuf
, 1, n
, stdout
);
284 return (checkend(inbuf
, "====",
285 "error decoding base64 input stream"));
291 (void)fprintf(stderr
, "usage: %s [-m | -p] [encoded-file ...]\n",