xref: /csrg-svn/usr.bin/uudecode/uudecode.c (revision 34953)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)uudecode.c	5.4 (Berkeley) 07/06/88";
20 #endif /* not lint */
21 
22 /*
23  * uudecode [input]
24  *
25  * create the specified file, decoding as you go.
26  * used with uuencode.
27  */
28 #include <stdio.h>
29 #include <pwd.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 
33 /* single character decode */
34 #define DEC(c)	(((c) - ' ') & 077)
35 
36 main(argc, argv)
37 char **argv;
38 {
39 	FILE *in, *out;
40 	int mode;
41 	char dest[128];
42 	char buf[80];
43 
44 	/* optional input arg */
45 	if (argc > 1) {
46 		if ((in = fopen(argv[1], "r")) == NULL) {
47 			perror(argv[1]);
48 			exit(1);
49 		}
50 		argv++; argc--;
51 	} else
52 		in = stdin;
53 
54 	if (argc != 1) {
55 		printf("Usage: uudecode [infile]\n");
56 		exit(2);
57 	}
58 
59 	/* search for header line */
60 	for (;;) {
61 		if (fgets(buf, sizeof buf, in) == NULL) {
62 			fprintf(stderr, "No begin line\n");
63 			exit(3);
64 		}
65 		if (strncmp(buf, "begin ", 6) == 0)
66 			break;
67 	}
68 	sscanf(buf, "begin %o %s", &mode, dest);
69 
70 	/* handle ~user/file format */
71 	if (dest[0] == '~') {
72 		char *sl;
73 		struct passwd *getpwnam();
74 		char *index();
75 		struct passwd *user;
76 		char dnbuf[100];
77 
78 		sl = index(dest, '/');
79 		if (sl == NULL) {
80 			fprintf(stderr, "Illegal ~user\n");
81 			exit(3);
82 		}
83 		*sl++ = 0;
84 		user = getpwnam(dest+1);
85 		if (user == NULL) {
86 			fprintf(stderr, "No such user as %s\n", dest);
87 			exit(4);
88 		}
89 		strcpy(dnbuf, user->pw_dir);
90 		strcat(dnbuf, "/");
91 		strcat(dnbuf, sl);
92 		strcpy(dest, dnbuf);
93 	}
94 
95 	/* create output file */
96 	out = fopen(dest, "w");
97 	if (out == NULL) {
98 		perror(dest);
99 		exit(4);
100 	}
101 	chmod(dest, mode);
102 
103 	decode(in, out);
104 
105 	if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
106 		fprintf(stderr, "No end line\n");
107 		exit(5);
108 	}
109 	exit(0);
110 }
111 
112 /*
113  * copy from in to out, decoding as you go along.
114  */
115 decode(in, out)
116 FILE *in;
117 FILE *out;
118 {
119 	char buf[80];
120 	char *bp;
121 	int n;
122 
123 	for (;;) {
124 		/* for each input line */
125 		if (fgets(buf, sizeof buf, in) == NULL) {
126 			printf("Short file\n");
127 			exit(10);
128 		}
129 		n = DEC(buf[0]);
130 		if (n <= 0)
131 			break;
132 
133 		bp = &buf[1];
134 		while (n > 0) {
135 			outdec(bp, out, n);
136 			bp += 4;
137 			n -= 3;
138 		}
139 	}
140 }
141 
142 /*
143  * output a group of 3 bytes (4 input characters).
144  * the input chars are pointed to by p, they are to
145  * be output to file f.  n is used to tell us not to
146  * output all of them at the end of the file.
147  */
148 outdec(p, f, n)
149 char *p;
150 FILE *f;
151 {
152 	int c1, c2, c3;
153 
154 	c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
155 	c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
156 	c3 = DEC(p[2]) << 6 | DEC(p[3]);
157 	if (n >= 1)
158 		putc(c1, f);
159 	if (n >= 2)
160 		putc(c2, f);
161 	if (n >= 3)
162 		putc(c3, f);
163 }
164 
165 
166 /* fr: like read but stdio */
167 int
168 fr(fd, buf, cnt)
169 FILE *fd;
170 char *buf;
171 int cnt;
172 {
173 	int c, i;
174 
175 	for (i=0; i<cnt; i++) {
176 		c = getc(fd);
177 		if (c == EOF)
178 			return(i);
179 		buf[i] = c;
180 	}
181 	return (cnt);
182 }
183 
184 /*
185  * Return the ptr in sp at which the character c appears;
186  * NULL if not found
187  */
188 
189 #define	NULL	0
190 
191 char *
192 index(sp, c)
193 register char *sp, c;
194 {
195 	do {
196 		if (*sp == c)
197 			return(sp);
198 	} while (*sp++);
199 	return(NULL);
200 }
201