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*38475Sbostic static char sccsid[] = "@(#)uudecode.c 5.7 (Berkeley) 07/19/89"; 2034953Sbostic #endif /* not lint */ 2113681Ssam 2213681Ssam /* 23*38475Sbostic * uudecode [file ...] 2413681Ssam * 2513681Ssam * create the specified file, decoding as you go. 2613681Ssam * used with uuencode. 2713681Ssam */ 28*38475Sbostic #include <sys/param.h> 2937845Sbostic #include <sys/stat.h> 30*38475Sbostic #include <pwd.h> 3113681Ssam #include <stdio.h> 32*38475Sbostic #include <strings.h> 3313681Ssam 34*38475Sbostic char *filename; 3513681Ssam 36*38475Sbostic /* ARGSUSED */ 3713681Ssam main(argc, argv) 38*38475Sbostic int argc; 39*38475Sbostic char **argv; 4013681Ssam { 41*38475Sbostic extern int errno; 42*38475Sbostic int rval; 4313681Ssam 44*38475Sbostic if (*++argv) { 45*38475Sbostic rval = 0; 46*38475Sbostic do { 47*38475Sbostic if (!freopen(filename = *argv, "r", stdin)) { 48*38475Sbostic (void)fprintf(stderr, "uudecode: %s: %s\n", 49*38475Sbostic *argv, strerror(errno)); 50*38475Sbostic rval = 1; 51*38475Sbostic continue; 52*38475Sbostic } 53*38475Sbostic rval |= decode(); 54*38475Sbostic } while (*++argv); 55*38475Sbostic } else { 56*38475Sbostic filename = "stdin"; 57*38475Sbostic rval = decode(); 5813681Ssam } 59*38475Sbostic exit(rval); 60*38475Sbostic } 6113681Ssam 62*38475Sbostic decode() 63*38475Sbostic { 64*38475Sbostic extern int errno; 65*38475Sbostic struct passwd *pw; 66*38475Sbostic register int n; 67*38475Sbostic register char ch, *p; 68*38475Sbostic int mode, n1; 69*38475Sbostic char buf[MAXPATHLEN]; 70*38475Sbostic 7113681Ssam /* search for header line */ 72*38475Sbostic do { 73*38475Sbostic if (!fgets(buf, sizeof(buf), stdin)) { 74*38475Sbostic (void)fprintf(stderr, 75*38475Sbostic "uudecode: %s: no \"begin\" line\n", filename); 76*38475Sbostic return(1); 7713681Ssam } 78*38475Sbostic } while (strncmp(buf, "begin ", 6)); 79*38475Sbostic (void)sscanf(buf, "begin %o %s", &mode, buf); 8013681Ssam 8113681Ssam /* handle ~user/file format */ 82*38475Sbostic if (buf[0] == '~') { 83*38475Sbostic if (!(p = index(buf, '/'))) { 84*38475Sbostic (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n", 85*38475Sbostic filename); 86*38475Sbostic return(1); 8713681Ssam } 88*38475Sbostic *p++ = NULL; 89*38475Sbostic if (!(pw = getpwnam(buf + 1))) { 90*38475Sbostic (void)fprintf(stderr, "uudecode: %s: no user %s.\n", 91*38475Sbostic filename, buf); 92*38475Sbostic return(1); 9313681Ssam } 94*38475Sbostic n = strlen(pw->pw_dir); 95*38475Sbostic n1 = strlen(p); 96*38475Sbostic if (n + n1 + 2 > MAXPATHLEN) { 97*38475Sbostic (void)fprintf(stderr, "uudecode: %s: path too long.\n", 98*38475Sbostic filename); 99*38475Sbostic return(1); 100*38475Sbostic } 101*38475Sbostic bcopy(p, buf + n + 1, n1 + 1); 102*38475Sbostic bcopy(pw->pw_dir, buf, n); 103*38475Sbostic buf[n] = '/'; 10413681Ssam } 10513681Ssam 106*38475Sbostic /* create output file, set mode */ 107*38475Sbostic if (!freopen(buf, "w", stdout) || fchmod(fileno(stdout), mode)) { 108*38475Sbostic (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf, 109*38475Sbostic filename, strerror(errno)); 110*38475Sbostic return(1); 11113681Ssam } 11213681Ssam 113*38475Sbostic /* for each input line */ 11413681Ssam for (;;) { 115*38475Sbostic if (!fgets(p = buf, sizeof(buf), stdin)) { 116*38475Sbostic (void)fprintf(stderr, "uudecode: %s: short file.\n", 117*38475Sbostic filename); 118*38475Sbostic return(1); 11913681Ssam } 120*38475Sbostic #define DEC(c) (((c) - ' ') & 077) /* single character decode */ 121*38475Sbostic /* 122*38475Sbostic * `n' is used to avoid writing out all the characters 123*38475Sbostic * at the end of the file. 124*38475Sbostic */ 125*38475Sbostic if ((n = DEC(*p)) <= 0) 12613681Ssam break; 127*38475Sbostic for (++p; n > 0; p += 4, n -= 3) 128*38475Sbostic if (n >= 3) { 129*38475Sbostic ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 130*38475Sbostic putchar(ch); 131*38475Sbostic ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 132*38475Sbostic putchar(ch); 133*38475Sbostic ch = DEC(p[2]) << 6 | DEC(p[3]); 134*38475Sbostic putchar(ch); 135*38475Sbostic } 136*38475Sbostic else { 137*38475Sbostic if (n >= 1) { 138*38475Sbostic ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 139*38475Sbostic putchar(ch); 140*38475Sbostic } 141*38475Sbostic if (n >= 2) { 142*38475Sbostic ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 143*38475Sbostic putchar(ch); 144*38475Sbostic } 145*38475Sbostic if (n >= 3) { 146*38475Sbostic ch = DEC(p[2]) << 6 | DEC(p[3]); 147*38475Sbostic putchar(ch); 148*38475Sbostic } 149*38475Sbostic } 15013681Ssam } 151*38475Sbostic if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { 152*38475Sbostic (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", 153*38475Sbostic filename); 154*38475Sbostic return(1); 155*38475Sbostic } 156*38475Sbostic return(0); 15713681Ssam } 15813681Ssam 159*38475Sbostic usage() 16013681Ssam { 161*38475Sbostic (void)fprintf(stderr, "usage: uudecode [file ...]\n"); 162*38475Sbostic exit(1); 16313681Ssam } 164