1 /* $OpenBSD: uudecode.c,v 1.7 1998/09/15 15:59:44 millert Exp $ */ 2 /* $NetBSD: uudecode.c,v 1.6 1994/11/17 07:40:43 jtc Exp $ */ 3 4 /*- 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 char copyright[] = 38 "@(#) Copyright (c) 1983, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94"; 44 #endif 45 static char rcsid[] = "$OpenBSD: uudecode.c,v 1.7 1998/09/15 15:59:44 millert Exp $"; 46 #endif /* not lint */ 47 48 /* 49 * uudecode [-p] [file ...] 50 * 51 * create the specified file, decoding as you go. 52 * used with uuencode. 53 * 54 * Write to stdout if '-p' is specified. Use this option if you care about 55 * security at all. 56 */ 57 #include <stdio.h> 58 #include <string.h> 59 #include <locale.h> 60 #include <errno.h> 61 #include <sys/param.h> 62 #include <sys/stat.h> 63 64 #include <pwd.h> 65 #include <unistd.h> 66 67 static int decode(int); 68 static void usage(); 69 char *filename; 70 71 int 72 main(argc, argv) 73 int argc; 74 char *argv[]; 75 { 76 int rval; 77 int ch; 78 int tostdout = 0; 79 80 setlocale(LC_ALL, ""); 81 82 while ((ch = getopt(argc, argv, "p")) != -1) 83 switch((char)ch) { 84 case 'p': 85 tostdout++; 86 break; 87 case '?': 88 default: 89 usage(); 90 } 91 argc -= optind; 92 argv += optind; 93 94 if (*argv) { 95 rval = 0; 96 do { 97 if (!freopen(filename = *argv, "r", stdin)) { 98 (void)fprintf(stderr, "uudecode: %s: %s\n", 99 *argv, strerror(errno)); 100 rval = 1; 101 continue; 102 } 103 rval |= decode(tostdout); 104 } while (*++argv); 105 } else { 106 filename = "stdin"; 107 rval = decode(tostdout); 108 } 109 exit(rval); 110 } 111 112 static int 113 decode(int tostdout) 114 { 115 extern int errno; 116 struct passwd *pw; 117 register int n; 118 register char ch, *p; 119 int mode, n1; 120 char buf[MAXPATHLEN]; 121 122 /* search for header line */ 123 do { 124 if (!fgets(buf, sizeof(buf), stdin)) { 125 (void)fprintf(stderr, 126 "uudecode: %s: no \"begin\" line\n", filename); 127 return(1); 128 } 129 } while (strncmp(buf, "begin ", 6)); 130 (void)sscanf(buf, "begin %o %1023[^\n\r]", &mode, buf); 131 132 /* handle ~user/file format */ 133 if (buf[0] == '~') { 134 if (!(p = strchr(buf, '/'))) { 135 (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n", 136 filename); 137 return(1); 138 } 139 *p++ = NULL; 140 if (!(pw = getpwnam(buf + 1))) { 141 (void)fprintf(stderr, "uudecode: %s: no user %s.\n", 142 filename, buf); 143 return(1); 144 } 145 n = strlen(pw->pw_dir); 146 n1 = strlen(p); 147 if (n + n1 + 2 > MAXPATHLEN) { 148 (void)fprintf(stderr, "uudecode: %s: path too long.\n", 149 filename); 150 return(1); 151 } 152 bcopy(p, buf + n + 1, n1 + 1); 153 bcopy(pw->pw_dir, buf, n); 154 buf[n] = '/'; 155 } 156 157 if (!tostdout) { 158 /* create output file, set mode */ 159 if (!freopen(buf, "w", stdout) || 160 fchmod(fileno(stdout), mode&0666)) { 161 (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf, 162 filename, strerror(errno)); 163 return(1); 164 } 165 } 166 167 /* for each input line */ 168 for (;;) { 169 if (!fgets(p = buf, sizeof(buf), stdin)) { 170 (void)fprintf(stderr, "uudecode: %s: short file.\n", 171 filename); 172 return(1); 173 } 174 #define DEC(c) (((c) - ' ') & 077) /* single character decode */ 175 /* 176 * `n' is used to avoid writing out all the characters 177 * at the end of the file. 178 */ 179 if ((n = DEC(*p)) <= 0) 180 break; 181 for (++p; n > 0; p += 4, n -= 3) 182 if (n >= 3) { 183 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 184 putchar(ch); 185 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 186 putchar(ch); 187 ch = DEC(p[2]) << 6 | DEC(p[3]); 188 putchar(ch); 189 } 190 else { 191 if (n >= 1) { 192 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 193 putchar(ch); 194 } 195 if (n >= 2) { 196 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 197 putchar(ch); 198 } 199 if (n >= 3) { 200 ch = DEC(p[2]) << 6 | DEC(p[3]); 201 putchar(ch); 202 } 203 } 204 } 205 if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { 206 (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", 207 filename); 208 return(1); 209 } 210 return(0); 211 } 212 213 static void 214 usage() 215 { 216 (void)fprintf(stderr, "usage: uudecode [-p] [file ...]\n"); 217 exit(1); 218 } 219