1 /* $OpenBSD: uudecode.c,v 1.9 2001/11/19 19:02:17 mpech 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.9 2001/11/19 19:02:17 mpech 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 struct passwd *pw; 116 int n; 117 char ch, *p; 118 int mode, n1; 119 char buf[MAXPATHLEN]; 120 121 /* search for header line */ 122 do { 123 if (!fgets(buf, sizeof(buf), stdin)) { 124 (void)fprintf(stderr, 125 "uudecode: %s: no \"begin\" line\n", filename); 126 return(1); 127 } 128 } while (strncmp(buf, "begin ", 6)); 129 (void)sscanf(buf, "begin %o %1023[^\n\r]", &mode, buf); 130 131 /* handle ~user/file format */ 132 if (buf[0] == '~') { 133 if (!(p = strchr(buf, '/'))) { 134 (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n", 135 filename); 136 return(1); 137 } 138 *p++ = NULL; 139 if (!(pw = getpwnam(buf + 1))) { 140 (void)fprintf(stderr, "uudecode: %s: no user %s.\n", 141 filename, buf); 142 return(1); 143 } 144 n = strlen(pw->pw_dir); 145 n1 = strlen(p); 146 if (n + n1 + 2 > MAXPATHLEN) { 147 (void)fprintf(stderr, "uudecode: %s: path too long.\n", 148 filename); 149 return(1); 150 } 151 bcopy(p, buf + n + 1, n1 + 1); 152 bcopy(pw->pw_dir, buf, n); 153 buf[n] = '/'; 154 } 155 156 if (!tostdout) { 157 /* create output file, set mode */ 158 if (!freopen(buf, "w", stdout) || 159 fchmod(fileno(stdout), mode&0666)) { 160 (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf, 161 filename, strerror(errno)); 162 return(1); 163 } 164 } 165 166 /* for each input line */ 167 for (;;) { 168 if (!fgets(p = buf, sizeof(buf), stdin)) { 169 (void)fprintf(stderr, "uudecode: %s: short file.\n", 170 filename); 171 return(1); 172 } 173 #define DEC(c) (((c) - ' ') & 077) /* single character decode */ 174 /* 175 * `n' is used to avoid writing out all the characters 176 * at the end of the file. 177 */ 178 if ((n = DEC(*p)) <= 0) 179 break; 180 for (++p; n > 0; p += 4, n -= 3) 181 if (n >= 3) { 182 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 183 putchar(ch); 184 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 185 putchar(ch); 186 ch = DEC(p[2]) << 6 | DEC(p[3]); 187 putchar(ch); 188 } 189 else { 190 if (n >= 1) { 191 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 192 putchar(ch); 193 } 194 if (n >= 2) { 195 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 196 putchar(ch); 197 } 198 if (n >= 3) { 199 ch = DEC(p[2]) << 6 | DEC(p[3]); 200 putchar(ch); 201 } 202 } 203 } 204 if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { 205 (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", 206 filename); 207 return(1); 208 } 209 return(0); 210 } 211 212 static void 213 usage() 214 { 215 (void)fprintf(stderr, "usage: uudecode [-p] [file ...]\n"); 216 exit(1); 217 } 218