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