uudecode.c revision 15381
1255801Sdes/*-
2255801Sdes * Copyright (c) 1983, 1993
3255801Sdes *	The Regents of the University of California.  All rights reserved.
4255801Sdes *
5255801Sdes * Redistribution and use in source and binary forms, with or without
6255801Sdes * modification, are permitted provided that the following conditions
7255801Sdes * are met:
8255801Sdes * 1. Redistributions of source code must retain the above copyright
9255801Sdes *    notice, this list of conditions and the following disclaimer.
10255801Sdes * 2. Redistributions in binary form must reproduce the above copyright
11255801Sdes *    notice, this list of conditions and the following disclaimer in the
12255801Sdes *    documentation and/or other materials provided with the distribution.
13255801Sdes * 3. All advertising materials mentioning features or use of this software
14255801Sdes *    must display the following acknowledgement:
15255801Sdes *	This product includes software developed by the University of
16255801Sdes *	California, Berkeley and its contributors.
17255801Sdes * 4. Neither the name of the University nor the names of its contributors
18255801Sdes *    may be used to endorse or promote products derived from this software
19255801Sdes *    without specific prior written permission.
20255801Sdes *
21255801Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22255801Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23255801Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24255801Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25255801Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26255801Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27255801Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28255801Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29255801Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30255801Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31255801Sdes * SUCH DAMAGE.
32255801Sdes */
33255801Sdes
34255801Sdes#ifndef lint
35255801Sdeschar copyright[] =
36255801Sdes"@(#) Copyright (c) 1983, 1993\n\
37255801Sdes	The Regents of the University of California.  All rights reserved.\n";
38255801Sdes#endif /* not lint */
39255801Sdes
40255801Sdes#ifndef lint
41255801Sdesstatic char sccsid[] = "@(#)uudecode.c	8.2 (Berkeley) 4/2/94";
42255801Sdes#endif /* not lint */
43255801Sdes
44255801Sdes/*
45255801Sdes * uudecode [file ...]
46255801Sdes *
47255801Sdes * create the specified file, decoding as you go.
48255801Sdes * used with uuencode.
49255801Sdes */
50255801Sdes#include <sys/param.h>
51255801Sdes#include <sys/stat.h>
52255801Sdes
53255801Sdes#include <pwd.h>
54255801Sdes#include <stdio.h>
55255801Sdes#include <string.h>
56255801Sdes
57255801Sdeschar *filename;
58255801Sdes
59255801Sdesint
60255801Sdesmain(argc, argv)
61255801Sdes	int argc;
62255801Sdes	char *argv[];
63255801Sdes{
64255801Sdes	extern int errno;
65255801Sdes	int rval;
66255801Sdes
67255801Sdes	if (*++argv) {
68255801Sdes		rval = 0;
69255801Sdes		do {
70255801Sdes			if (!freopen(filename = *argv, "r", stdin)) {
71255801Sdes				(void)fprintf(stderr, "uudecode: %s: %s\n",
72255801Sdes				    *argv, strerror(errno));
73255801Sdes				rval = 1;
74255801Sdes				continue;
75255801Sdes			}
76255801Sdes			rval |= decode();
77255801Sdes		} while (*++argv);
78255801Sdes	} else {
79255801Sdes		filename = "stdin";
80255801Sdes		rval = decode();
81255801Sdes	}
82255801Sdes	exit(rval);
83255801Sdes}
84255801Sdes
85255801Sdesdecode()
86255801Sdes{
87255801Sdes	extern int errno;
88255801Sdes	struct passwd *pw;
89255801Sdes	register int n;
90255801Sdes	register char ch, *p;
91255801Sdes	int mode, n1;
92255801Sdes	char buf[MAXPATHLEN];
93255801Sdes
94255801Sdes	/* search for header line */
95255801Sdes	do {
96255801Sdes		if (!fgets(buf, sizeof(buf), stdin)) {
97255801Sdes			(void)fprintf(stderr,
98255801Sdes			    "uudecode: %s: no \"begin\" line\n", filename);
99255801Sdes			return(1);
100255801Sdes		}
101255801Sdes	} while (strncmp(buf, "begin ", 6));
102255801Sdes	(void)sscanf(buf, "begin %o %s", &mode, buf);
103255801Sdes
104255801Sdes	/* handle ~user/file format */
105255801Sdes	if (buf[0] == '~') {
106255801Sdes		if (!(p = index(buf, '/'))) {
107255801Sdes			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
108255801Sdes			    filename);
109255801Sdes			return(1);
110255801Sdes		}
111255801Sdes		*p++ = NULL;
112255801Sdes		if (!(pw = getpwnam(buf + 1))) {
113255801Sdes			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
114255801Sdes			    filename, buf);
115255801Sdes			return(1);
116255801Sdes		}
117255801Sdes		n = strlen(pw->pw_dir);
118255801Sdes		n1 = strlen(p);
119255801Sdes		if (n + n1 + 2 > MAXPATHLEN) {
120255801Sdes			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
121255801Sdes			    filename);
122255801Sdes			return(1);
123255801Sdes		}
124255801Sdes		bcopy(p, buf + n + 1, n1 + 1);
125285206Sdes		bcopy(pw->pw_dir, buf, n);
126255801Sdes		buf[n] = '/';
127255801Sdes	}
128255801Sdes
129255801Sdes	/* create output file, set mode */
130255801Sdes	if (!freopen(buf, "w", stdout) ||
131255801Sdes	    fchmod(fileno(stdout), mode&0666)) {
132255801Sdes		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
133255801Sdes		    filename, strerror(errno));
134285206Sdes		return(1);
135255801Sdes	}
136255801Sdes
137255801Sdes	/* for each input line */
138255801Sdes	for (;;) {
139255801Sdes		if (!fgets(p = buf, sizeof(buf), stdin)) {
140255801Sdes			(void)fprintf(stderr, "uudecode: %s: short file.\n",
141255801Sdes			    filename);
142255801Sdes			return(1);
143255801Sdes		}
144255801Sdes#define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
145255801Sdes		/*
146255801Sdes		 * `n' is used to avoid writing out all the characters
147255801Sdes		 * at the end of the file.
148255801Sdes		 */
149255801Sdes		if ((n = DEC(*p)) <= 0)
150255801Sdes			break;
151255801Sdes		for (++p; n > 0; p += 4, n -= 3)
152255801Sdes			if (n >= 3) {
153255801Sdes				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
154255801Sdes				putchar(ch);
155255801Sdes				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
156255801Sdes				putchar(ch);
157255801Sdes				ch = DEC(p[2]) << 6 | DEC(p[3]);
158255801Sdes				putchar(ch);
159255801Sdes			}
160255801Sdes			else {
161255801Sdes				if (n >= 1) {
162255801Sdes					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
163255801Sdes					putchar(ch);
164255801Sdes				}
165255801Sdes				if (n >= 2) {
166255801Sdes					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
167255801Sdes					putchar(ch);
168255801Sdes				}
169255801Sdes				if (n >= 3) {
170255801Sdes					ch = DEC(p[2]) << 6 | DEC(p[3]);
171255801Sdes					putchar(ch);
172255801Sdes				}
173255801Sdes			}
174255801Sdes	}
175255801Sdes	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end") || (buf[3] && buf[3] != '\n')) {
176255801Sdes		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
177255801Sdes		    filename);
178255801Sdes		return(1);
179255801Sdes	}
180255801Sdes	return(0);
181255801Sdes}
182255801Sdes
183255801Sdesusage()
184255801Sdes{
185255801Sdes	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
186255801Sdes	exit(1);
187255801Sdes}
188255801Sdes