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*37845Sbostic static char sccsid[] = "@(#)uudecode.c 5.6 (Berkeley) 05/10/89"; 2034953Sbostic #endif /* not lint */ 2113681Ssam 2213681Ssam /* 2313681Ssam * uudecode [input] 2413681Ssam * 2513681Ssam * create the specified file, decoding as you go. 2613681Ssam * used with uuencode. 2713681Ssam */ 28*37845Sbostic #include <sys/types.h> 29*37845Sbostic #include <sys/stat.h> 3013681Ssam #include <stdio.h> 3113681Ssam #include <pwd.h> 3213681Ssam 3313681Ssam /* single character decode */ 3413681Ssam #define DEC(c) (((c) - ' ') & 077) 3513681Ssam 3613681Ssam main(argc, argv) 3713681Ssam char **argv; 3813681Ssam { 3913681Ssam FILE *in, *out; 4013681Ssam int mode; 4113681Ssam char dest[128]; 4213681Ssam char buf[80]; 4313681Ssam 4413681Ssam /* optional input arg */ 4513681Ssam if (argc > 1) { 4613681Ssam if ((in = fopen(argv[1], "r")) == NULL) { 4713681Ssam perror(argv[1]); 4813681Ssam exit(1); 4913681Ssam } 5013681Ssam argv++; argc--; 5113681Ssam } else 5213681Ssam in = stdin; 5313681Ssam 5413681Ssam if (argc != 1) { 5513681Ssam printf("Usage: uudecode [infile]\n"); 5613681Ssam exit(2); 5713681Ssam } 5813681Ssam 5913681Ssam /* search for header line */ 6013681Ssam for (;;) { 6113681Ssam if (fgets(buf, sizeof buf, in) == NULL) { 6213681Ssam fprintf(stderr, "No begin line\n"); 6313681Ssam exit(3); 6413681Ssam } 6513681Ssam if (strncmp(buf, "begin ", 6) == 0) 6613681Ssam break; 6713681Ssam } 6834956Sbostic (void)sscanf(buf, "begin %o %s", &mode, dest); 6913681Ssam 7013681Ssam /* handle ~user/file format */ 7113681Ssam if (dest[0] == '~') { 7213681Ssam char *sl; 7313681Ssam struct passwd *getpwnam(); 7413681Ssam struct passwd *user; 7534956Sbostic char dnbuf[100], *index(), *strcat(), *strcpy(); 7613681Ssam 7713681Ssam sl = index(dest, '/'); 7813681Ssam if (sl == NULL) { 7913681Ssam fprintf(stderr, "Illegal ~user\n"); 8013681Ssam exit(3); 8113681Ssam } 8213681Ssam *sl++ = 0; 8313681Ssam user = getpwnam(dest+1); 8413681Ssam if (user == NULL) { 8513681Ssam fprintf(stderr, "No such user as %s\n", dest); 8613681Ssam exit(4); 8713681Ssam } 8813681Ssam strcpy(dnbuf, user->pw_dir); 8913681Ssam strcat(dnbuf, "/"); 9013681Ssam strcat(dnbuf, sl); 9113681Ssam strcpy(dest, dnbuf); 9213681Ssam } 9313681Ssam 9413681Ssam /* create output file */ 9513681Ssam out = fopen(dest, "w"); 9613681Ssam if (out == NULL) { 9713681Ssam perror(dest); 9813681Ssam exit(4); 9913681Ssam } 10013681Ssam chmod(dest, mode); 10113681Ssam 10213681Ssam decode(in, out); 10313681Ssam 10413681Ssam if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { 10513681Ssam fprintf(stderr, "No end line\n"); 10613681Ssam exit(5); 10713681Ssam } 10813681Ssam exit(0); 10913681Ssam } 11013681Ssam 11113681Ssam /* 11213681Ssam * copy from in to out, decoding as you go along. 11313681Ssam */ 11413681Ssam decode(in, out) 11513681Ssam FILE *in; 11613681Ssam FILE *out; 11713681Ssam { 11813681Ssam char buf[80]; 11913681Ssam char *bp; 12013681Ssam int n; 12113681Ssam 12213681Ssam for (;;) { 12313681Ssam /* for each input line */ 12413681Ssam if (fgets(buf, sizeof buf, in) == NULL) { 12513681Ssam printf("Short file\n"); 12613681Ssam exit(10); 12713681Ssam } 12813681Ssam n = DEC(buf[0]); 12913681Ssam if (n <= 0) 13013681Ssam break; 13113681Ssam 13213681Ssam bp = &buf[1]; 13313681Ssam while (n > 0) { 13413681Ssam outdec(bp, out, n); 13513681Ssam bp += 4; 13613681Ssam n -= 3; 13713681Ssam } 13813681Ssam } 13913681Ssam } 14013681Ssam 14113681Ssam /* 14213681Ssam * output a group of 3 bytes (4 input characters). 14313681Ssam * the input chars are pointed to by p, they are to 14413681Ssam * be output to file f. n is used to tell us not to 14513681Ssam * output all of them at the end of the file. 14613681Ssam */ 14713681Ssam outdec(p, f, n) 14813681Ssam char *p; 14913681Ssam FILE *f; 15013681Ssam { 15113681Ssam int c1, c2, c3; 15213681Ssam 15313681Ssam c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; 15413681Ssam c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 15513681Ssam c3 = DEC(p[2]) << 6 | DEC(p[3]); 15613681Ssam if (n >= 1) 15713681Ssam putc(c1, f); 15813681Ssam if (n >= 2) 15913681Ssam putc(c2, f); 16013681Ssam if (n >= 3) 16113681Ssam putc(c3, f); 16213681Ssam } 163