1*66660Sbostic /*-
262415Sbostic * Copyright (c) 1983, 1993
362415Sbostic * The Regents of the University of California. All rights reserved.
434953Sbostic *
542781Sbostic * %sccs.include.redist.c%
634953Sbostic */
734953Sbostic
813681Ssam #ifndef lint
9*66660Sbostic char copyright[] =
10*66660Sbostic "@(#) Copyright (c) 1983, 1993\n\
11*66660Sbostic The Regents of the University of California. All rights reserved.\n";
1234953Sbostic #endif /* not lint */
1313681Ssam
14*66660Sbostic #ifndef lint
15*66660Sbostic static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 04/02/94";
16*66660Sbostic #endif /* not lint */
17*66660Sbostic
1813681Ssam /*
1938475Sbostic * uudecode [file ...]
2013681Ssam *
2113681Ssam * create the specified file, decoding as you go.
2213681Ssam * used with uuencode.
2313681Ssam */
2438475Sbostic #include <sys/param.h>
2537845Sbostic #include <sys/stat.h>
26*66660Sbostic
2738475Sbostic #include <pwd.h>
2813681Ssam #include <stdio.h>
2942049Sbostic #include <string.h>
3013681Ssam
3138475Sbostic char *filename;
3213681Ssam
33*66660Sbostic int
main(argc,argv)3413681Ssam main(argc, argv)
3538475Sbostic int argc;
36*66660Sbostic char *argv[];
3713681Ssam {
3838475Sbostic extern int errno;
3938475Sbostic int rval;
4013681Ssam
4138475Sbostic if (*++argv) {
4238475Sbostic rval = 0;
4338475Sbostic do {
4438475Sbostic if (!freopen(filename = *argv, "r", stdin)) {
4538475Sbostic (void)fprintf(stderr, "uudecode: %s: %s\n",
4638475Sbostic *argv, strerror(errno));
4738475Sbostic rval = 1;
4838475Sbostic continue;
4938475Sbostic }
5038475Sbostic rval |= decode();
5138475Sbostic } while (*++argv);
5238475Sbostic } else {
5338475Sbostic filename = "stdin";
5438475Sbostic rval = decode();
5513681Ssam }
5638475Sbostic exit(rval);
5738475Sbostic }
5813681Ssam
decode()5938475Sbostic decode()
6038475Sbostic {
6138475Sbostic extern int errno;
6238475Sbostic struct passwd *pw;
6338475Sbostic register int n;
6438475Sbostic register char ch, *p;
6538475Sbostic int mode, n1;
6638475Sbostic char buf[MAXPATHLEN];
6738475Sbostic
6813681Ssam /* search for header line */
6938475Sbostic do {
7038475Sbostic if (!fgets(buf, sizeof(buf), stdin)) {
7138475Sbostic (void)fprintf(stderr,
7238475Sbostic "uudecode: %s: no \"begin\" line\n", filename);
7338475Sbostic return(1);
7413681Ssam }
7538475Sbostic } while (strncmp(buf, "begin ", 6));
7638475Sbostic (void)sscanf(buf, "begin %o %s", &mode, buf);
7713681Ssam
7813681Ssam /* handle ~user/file format */
7938475Sbostic if (buf[0] == '~') {
8038475Sbostic if (!(p = index(buf, '/'))) {
8138475Sbostic (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
8238475Sbostic filename);
8338475Sbostic return(1);
8413681Ssam }
8538475Sbostic *p++ = NULL;
8638475Sbostic if (!(pw = getpwnam(buf + 1))) {
8738475Sbostic (void)fprintf(stderr, "uudecode: %s: no user %s.\n",
8838475Sbostic filename, buf);
8938475Sbostic return(1);
9013681Ssam }
9138475Sbostic n = strlen(pw->pw_dir);
9238475Sbostic n1 = strlen(p);
9338475Sbostic if (n + n1 + 2 > MAXPATHLEN) {
9438475Sbostic (void)fprintf(stderr, "uudecode: %s: path too long.\n",
9538475Sbostic filename);
9638475Sbostic return(1);
9738475Sbostic }
9838475Sbostic bcopy(p, buf + n + 1, n1 + 1);
9938475Sbostic bcopy(pw->pw_dir, buf, n);
10038475Sbostic buf[n] = '/';
10113681Ssam }
10213681Ssam
10338475Sbostic /* create output file, set mode */
10438720Sbostic if (!freopen(buf, "w", stdout) ||
10538720Sbostic fchmod(fileno(stdout), mode&0666)) {
10638475Sbostic (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
10738475Sbostic filename, strerror(errno));
10838475Sbostic return(1);
10913681Ssam }
11013681Ssam
11138475Sbostic /* for each input line */
11213681Ssam for (;;) {
11338475Sbostic if (!fgets(p = buf, sizeof(buf), stdin)) {
11438475Sbostic (void)fprintf(stderr, "uudecode: %s: short file.\n",
11538475Sbostic filename);
11638475Sbostic return(1);
11713681Ssam }
11838475Sbostic #define DEC(c) (((c) - ' ') & 077) /* single character decode */
11938475Sbostic /*
12038475Sbostic * `n' is used to avoid writing out all the characters
12138475Sbostic * at the end of the file.
12238475Sbostic */
12338475Sbostic if ((n = DEC(*p)) <= 0)
12413681Ssam break;
12538475Sbostic for (++p; n > 0; p += 4, n -= 3)
12638475Sbostic if (n >= 3) {
12738475Sbostic ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
12838475Sbostic putchar(ch);
12938475Sbostic ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
13038475Sbostic putchar(ch);
13138475Sbostic ch = DEC(p[2]) << 6 | DEC(p[3]);
13238475Sbostic putchar(ch);
13338475Sbostic }
13438475Sbostic else {
13538475Sbostic if (n >= 1) {
13638475Sbostic ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
13738475Sbostic putchar(ch);
13838475Sbostic }
13938475Sbostic if (n >= 2) {
14038475Sbostic ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
14138475Sbostic putchar(ch);
14238475Sbostic }
14338475Sbostic if (n >= 3) {
14438475Sbostic ch = DEC(p[2]) << 6 | DEC(p[3]);
14538475Sbostic putchar(ch);
14638475Sbostic }
14738475Sbostic }
14813681Ssam }
14938475Sbostic if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
15038475Sbostic (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
15138475Sbostic filename);
15238475Sbostic return(1);
15338475Sbostic }
15438475Sbostic return(0);
15513681Ssam }
15613681Ssam
usage()15738475Sbostic usage()
15813681Ssam {
15938475Sbostic (void)fprintf(stderr, "usage: uudecode [file ...]\n");
16038475Sbostic exit(1);
16113681Ssam }
162