xref: /original-bsd/usr.bin/uudecode/uudecode.c (revision f1324ba5)
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.5 (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 	(void)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 		struct passwd *user;
75 		char dnbuf[100], *index(), *strcat(), *strcpy();
76 
77 		sl = index(dest, '/');
78 		if (sl == NULL) {
79 			fprintf(stderr, "Illegal ~user\n");
80 			exit(3);
81 		}
82 		*sl++ = 0;
83 		user = getpwnam(dest+1);
84 		if (user == NULL) {
85 			fprintf(stderr, "No such user as %s\n", dest);
86 			exit(4);
87 		}
88 		strcpy(dnbuf, user->pw_dir);
89 		strcat(dnbuf, "/");
90 		strcat(dnbuf, sl);
91 		strcpy(dest, dnbuf);
92 	}
93 
94 	/* create output file */
95 	out = fopen(dest, "w");
96 	if (out == NULL) {
97 		perror(dest);
98 		exit(4);
99 	}
100 	chmod(dest, mode);
101 
102 	decode(in, out);
103 
104 	if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
105 		fprintf(stderr, "No end line\n");
106 		exit(5);
107 	}
108 	exit(0);
109 }
110 
111 /*
112  * copy from in to out, decoding as you go along.
113  */
114 decode(in, out)
115 FILE *in;
116 FILE *out;
117 {
118 	char buf[80];
119 	char *bp;
120 	int n;
121 
122 	for (;;) {
123 		/* for each input line */
124 		if (fgets(buf, sizeof buf, in) == NULL) {
125 			printf("Short file\n");
126 			exit(10);
127 		}
128 		n = DEC(buf[0]);
129 		if (n <= 0)
130 			break;
131 
132 		bp = &buf[1];
133 		while (n > 0) {
134 			outdec(bp, out, n);
135 			bp += 4;
136 			n -= 3;
137 		}
138 	}
139 }
140 
141 /*
142  * output a group of 3 bytes (4 input characters).
143  * the input chars are pointed to by p, they are to
144  * be output to file f.  n is used to tell us not to
145  * output all of them at the end of the file.
146  */
147 outdec(p, f, n)
148 char *p;
149 FILE *f;
150 {
151 	int c1, c2, c3;
152 
153 	c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
154 	c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
155 	c3 = DEC(p[2]) << 6 | DEC(p[3]);
156 	if (n >= 1)
157 		putc(c1, f);
158 	if (n >= 2)
159 		putc(c2, f);
160 	if (n >= 3)
161 		putc(c3, f);
162 }
163