Must distinguish between "ambiguous" and "unknown" commands.
[unix-history] / usr / src / usr.bin / uudecode / uudecode.c
CommitLineData
4c7e459f 1#ifndef lint
1a85e9d2 2static char sccsid[] = "@(#)uudecode.c 5.3 (Berkeley) %G%";
4c7e459f
SL
3#endif
4
5/*
6 * uudecode [input]
7 *
8 * create the specified file, decoding as you go.
9 * used with uuencode.
10 */
11#include <stdio.h>
12#include <pwd.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15
16/* single character decode */
17#define DEC(c) (((c) - ' ') & 077)
18
19main(argc, argv)
20char **argv;
21{
22 FILE *in, *out;
4c7e459f
SL
23 int mode;
24 char dest[128];
25 char buf[80];
26
27 /* optional input arg */
28 if (argc > 1) {
29 if ((in = fopen(argv[1], "r")) == NULL) {
30 perror(argv[1]);
31 exit(1);
32 }
33 argv++; argc--;
34 } else
35 in = stdin;
36
37 if (argc != 1) {
38 printf("Usage: uudecode [infile]\n");
39 exit(2);
40 }
41
42 /* search for header line */
43 for (;;) {
44 if (fgets(buf, sizeof buf, in) == NULL) {
45 fprintf(stderr, "No begin line\n");
46 exit(3);
47 }
48 if (strncmp(buf, "begin ", 6) == 0)
49 break;
50 }
51 sscanf(buf, "begin %o %s", &mode, dest);
52
53 /* handle ~user/file format */
54 if (dest[0] == '~') {
55 char *sl;
56 struct passwd *getpwnam();
57 char *index();
58 struct passwd *user;
59 char dnbuf[100];
60
61 sl = index(dest, '/');
62 if (sl == NULL) {
63 fprintf(stderr, "Illegal ~user\n");
64 exit(3);
65 }
66 *sl++ = 0;
67 user = getpwnam(dest+1);
68 if (user == NULL) {
69 fprintf(stderr, "No such user as %s\n", dest);
70 exit(4);
71 }
72 strcpy(dnbuf, user->pw_dir);
73 strcat(dnbuf, "/");
74 strcat(dnbuf, sl);
75 strcpy(dest, dnbuf);
76 }
77
78 /* create output file */
79 out = fopen(dest, "w");
80 if (out == NULL) {
81 perror(dest);
82 exit(4);
83 }
84 chmod(dest, mode);
85
86 decode(in, out);
87
88 if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
89 fprintf(stderr, "No end line\n");
90 exit(5);
91 }
92 exit(0);
93}
94
95/*
96 * copy from in to out, decoding as you go along.
97 */
98decode(in, out)
99FILE *in;
100FILE *out;
101{
102 char buf[80];
103 char *bp;
104 int n;
105
106 for (;;) {
107 /* for each input line */
108 if (fgets(buf, sizeof buf, in) == NULL) {
109 printf("Short file\n");
110 exit(10);
111 }
112 n = DEC(buf[0]);
113 if (n <= 0)
114 break;
115
116 bp = &buf[1];
117 while (n > 0) {
118 outdec(bp, out, n);
119 bp += 4;
120 n -= 3;
121 }
122 }
123}
124
125/*
126 * output a group of 3 bytes (4 input characters).
127 * the input chars are pointed to by p, they are to
128 * be output to file f. n is used to tell us not to
129 * output all of them at the end of the file.
130 */
131outdec(p, f, n)
132char *p;
133FILE *f;
134{
135 int c1, c2, c3;
136
137 c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
138 c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
139 c3 = DEC(p[2]) << 6 | DEC(p[3]);
140 if (n >= 1)
141 putc(c1, f);
142 if (n >= 2)
143 putc(c2, f);
144 if (n >= 3)
145 putc(c3, f);
146}
147
148
149/* fr: like read but stdio */
150int
151fr(fd, buf, cnt)
152FILE *fd;
153char *buf;
154int cnt;
155{
156 int c, i;
157
158 for (i=0; i<cnt; i++) {
159 c = getc(fd);
160 if (c == EOF)
161 return(i);
162 buf[i] = c;
163 }
164 return (cnt);
165}
166
167/*
168 * Return the ptr in sp at which the character c appears;
169 * NULL if not found
170 */
171
172#define NULL 0
173
174char *
175index(sp, c)
176register char *sp, c;
177{
178 do {
179 if (*sp == c)
180 return(sp);
181 } while (*sp++);
182 return(NULL);
183}