1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)uudecode.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 /* 13 * uudecode [file ...] 14 * 15 * create the specified file, decoding as you go. 16 * used with uuencode. 17 */ 18 #include <sys/param.h> 19 #include <sys/stat.h> 20 #include <pwd.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 char *filename; 25 26 /* ARGSUSED */ 27 main(argc, argv) 28 int argc; 29 char **argv; 30 { 31 extern int errno; 32 int rval; 33 34 if (*++argv) { 35 rval = 0; 36 do { 37 if (!freopen(filename = *argv, "r", stdin)) { 38 (void)fprintf(stderr, "uudecode: %s: %s\n", 39 *argv, strerror(errno)); 40 rval = 1; 41 continue; 42 } 43 rval |= decode(); 44 } while (*++argv); 45 } else { 46 filename = "stdin"; 47 rval = decode(); 48 } 49 exit(rval); 50 } 51 52 decode() 53 { 54 extern int errno; 55 struct passwd *pw; 56 register int n; 57 register char ch, *p; 58 int mode, n1; 59 char buf[MAXPATHLEN]; 60 61 /* search for header line */ 62 do { 63 if (!fgets(buf, sizeof(buf), stdin)) { 64 (void)fprintf(stderr, 65 "uudecode: %s: no \"begin\" line\n", filename); 66 return(1); 67 } 68 } while (strncmp(buf, "begin ", 6)); 69 (void)sscanf(buf, "begin %o %s", &mode, buf); 70 71 /* handle ~user/file format */ 72 if (buf[0] == '~') { 73 if (!(p = index(buf, '/'))) { 74 (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n", 75 filename); 76 return(1); 77 } 78 *p++ = NULL; 79 if (!(pw = getpwnam(buf + 1))) { 80 (void)fprintf(stderr, "uudecode: %s: no user %s.\n", 81 filename, buf); 82 return(1); 83 } 84 n = strlen(pw->pw_dir); 85 n1 = strlen(p); 86 if (n + n1 + 2 > MAXPATHLEN) { 87 (void)fprintf(stderr, "uudecode: %s: path too long.\n", 88 filename); 89 return(1); 90 } 91 bcopy(p, buf + n + 1, n1 + 1); 92 bcopy(pw->pw_dir, buf, n); 93 buf[n] = '/'; 94 } 95 96 /* create output file, set mode */ 97 if (!freopen(buf, "w", stdout) || 98 fchmod(fileno(stdout), mode&0666)) { 99 (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf, 100 filename, strerror(errno)); 101 return(1); 102 } 103 104 /* for each input line */ 105 for (;;) { 106 if (!fgets(p = buf, sizeof(buf), stdin)) { 107 (void)fprintf(stderr, "uudecode: %s: short file.\n", 108 filename); 109 return(1); 110 } 111 #define DEC(c) (((c) - ' ') & 077) /* single character decode */ 112 /* 113 * `n' is used to avoid writing out all the characters 114 * at the end of the file. 115 */ 116 if ((n = DEC(*p)) <= 0) 117 break; 118 for (++p; n > 0; p += 4, n -= 3) 119 if (n >= 3) { 120 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 121 putchar(ch); 122 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 123 putchar(ch); 124 ch = DEC(p[2]) << 6 | DEC(p[3]); 125 putchar(ch); 126 } 127 else { 128 if (n >= 1) { 129 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 130 putchar(ch); 131 } 132 if (n >= 2) { 133 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 134 putchar(ch); 135 } 136 if (n >= 3) { 137 ch = DEC(p[2]) << 6 | DEC(p[3]); 138 putchar(ch); 139 } 140 } 141 } 142 if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { 143 (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", 144 filename); 145 return(1); 146 } 147 return(0); 148 } 149 150 usage() 151 { 152 (void)fprintf(stderr, "usage: uudecode [file ...]\n"); 153 exit(1); 154 } 155