134953Sbostic /* 234953Sbostic * Copyright (c) 1983 Regents of the University of California. 334953Sbostic * All rights reserved. 434953Sbostic * 534953Sbostic * Redistribution and use in source and binary forms are permitted 634953Sbostic * provided that the above copyright notice and this paragraph are 734953Sbostic * duplicated in all such forms and that any documentation, 834953Sbostic * advertising materials, and other materials related to such 934953Sbostic * distribution and use acknowledge that the software was developed 1034953Sbostic * by the University of California, Berkeley. The name of the 1134953Sbostic * University may not be used to endorse or promote products derived 1234953Sbostic * from this software without specific prior written permission. 1334953Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434953Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534953Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1634953Sbostic */ 1734953Sbostic 1813681Ssam #ifndef lint 19*42049Sbostic static char sccsid[] = "@(#)uudecode.c 5.9 (Berkeley) 05/15/90"; 2034953Sbostic #endif /* not lint */ 2113681Ssam 2213681Ssam /* 2338475Sbostic * uudecode [file ...] 2413681Ssam * 2513681Ssam * create the specified file, decoding as you go. 2613681Ssam * used with uuencode. 2713681Ssam */ 2838475Sbostic #include <sys/param.h> 2937845Sbostic #include <sys/stat.h> 3038475Sbostic #include <pwd.h> 3113681Ssam #include <stdio.h> 32*42049Sbostic #include <string.h> 3313681Ssam 3438475Sbostic char *filename; 3513681Ssam 3638475Sbostic /* ARGSUSED */ 3713681Ssam main(argc, argv) 3838475Sbostic int argc; 3938475Sbostic char **argv; 4013681Ssam { 4138475Sbostic extern int errno; 4238475Sbostic int rval; 4313681Ssam 4438475Sbostic if (*++argv) { 4538475Sbostic rval = 0; 4638475Sbostic do { 4738475Sbostic if (!freopen(filename = *argv, "r", stdin)) { 4838475Sbostic (void)fprintf(stderr, "uudecode: %s: %s\n", 4938475Sbostic *argv, strerror(errno)); 5038475Sbostic rval = 1; 5138475Sbostic continue; 5238475Sbostic } 5338475Sbostic rval |= decode(); 5438475Sbostic } while (*++argv); 5538475Sbostic } else { 5638475Sbostic filename = "stdin"; 5738475Sbostic rval = decode(); 5813681Ssam } 5938475Sbostic exit(rval); 6038475Sbostic } 6113681Ssam 6238475Sbostic decode() 6338475Sbostic { 6438475Sbostic extern int errno; 6538475Sbostic struct passwd *pw; 6638475Sbostic register int n; 6738475Sbostic register char ch, *p; 6838475Sbostic int mode, n1; 6938475Sbostic char buf[MAXPATHLEN]; 7038475Sbostic 7113681Ssam /* search for header line */ 7238475Sbostic do { 7338475Sbostic if (!fgets(buf, sizeof(buf), stdin)) { 7438475Sbostic (void)fprintf(stderr, 7538475Sbostic "uudecode: %s: no \"begin\" line\n", filename); 7638475Sbostic return(1); 7713681Ssam } 7838475Sbostic } while (strncmp(buf, "begin ", 6)); 7938475Sbostic (void)sscanf(buf, "begin %o %s", &mode, buf); 8013681Ssam 8113681Ssam /* handle ~user/file format */ 8238475Sbostic if (buf[0] == '~') { 8338475Sbostic if (!(p = index(buf, '/'))) { 8438475Sbostic (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n", 8538475Sbostic filename); 8638475Sbostic return(1); 8713681Ssam } 8838475Sbostic *p++ = NULL; 8938475Sbostic if (!(pw = getpwnam(buf + 1))) { 9038475Sbostic (void)fprintf(stderr, "uudecode: %s: no user %s.\n", 9138475Sbostic filename, buf); 9238475Sbostic return(1); 9313681Ssam } 9438475Sbostic n = strlen(pw->pw_dir); 9538475Sbostic n1 = strlen(p); 9638475Sbostic if (n + n1 + 2 > MAXPATHLEN) { 9738475Sbostic (void)fprintf(stderr, "uudecode: %s: path too long.\n", 9838475Sbostic filename); 9938475Sbostic return(1); 10038475Sbostic } 10138475Sbostic bcopy(p, buf + n + 1, n1 + 1); 10238475Sbostic bcopy(pw->pw_dir, buf, n); 10338475Sbostic buf[n] = '/'; 10413681Ssam } 10513681Ssam 10638475Sbostic /* create output file, set mode */ 10738720Sbostic if (!freopen(buf, "w", stdout) || 10838720Sbostic fchmod(fileno(stdout), mode&0666)) { 10938475Sbostic (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf, 11038475Sbostic filename, strerror(errno)); 11138475Sbostic return(1); 11213681Ssam } 11313681Ssam 11438475Sbostic /* for each input line */ 11513681Ssam for (;;) { 11638475Sbostic if (!fgets(p = buf, sizeof(buf), stdin)) { 11738475Sbostic (void)fprintf(stderr, "uudecode: %s: short file.\n", 11838475Sbostic filename); 11938475Sbostic return(1); 12013681Ssam } 12138475Sbostic #define DEC(c) (((c) - ' ') & 077) /* single character decode */ 12238475Sbostic /* 12338475Sbostic * `n' is used to avoid writing out all the characters 12438475Sbostic * at the end of the file. 12538475Sbostic */ 12638475Sbostic if ((n = DEC(*p)) <= 0) 12713681Ssam break; 12838475Sbostic for (++p; n > 0; p += 4, n -= 3) 12938475Sbostic if (n >= 3) { 13038475Sbostic ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 13138475Sbostic putchar(ch); 13238475Sbostic ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 13338475Sbostic putchar(ch); 13438475Sbostic ch = DEC(p[2]) << 6 | DEC(p[3]); 13538475Sbostic putchar(ch); 13638475Sbostic } 13738475Sbostic else { 13838475Sbostic if (n >= 1) { 13938475Sbostic ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 14038475Sbostic putchar(ch); 14138475Sbostic } 14238475Sbostic if (n >= 2) { 14338475Sbostic ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 14438475Sbostic putchar(ch); 14538475Sbostic } 14638475Sbostic if (n >= 3) { 14738475Sbostic ch = DEC(p[2]) << 6 | DEC(p[3]); 14838475Sbostic putchar(ch); 14938475Sbostic } 15038475Sbostic } 15113681Ssam } 15238475Sbostic if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { 15338475Sbostic (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", 15438475Sbostic filename); 15538475Sbostic return(1); 15638475Sbostic } 15738475Sbostic return(0); 15813681Ssam } 15913681Ssam 16038475Sbostic usage() 16113681Ssam { 16238475Sbostic (void)fprintf(stderr, "usage: uudecode [file ...]\n"); 16338475Sbostic exit(1); 16413681Ssam } 165