uudecode.c revision 1590
1169689Skan/*- 2169689Skan * Copyright (c) 1983, 1993 3169689Skan * The Regents of the University of California. All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions and the following disclaimer. 10169689Skan * 2. Redistributions in binary form must reproduce the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer in the 12169689Skan * documentation and/or other materials provided with the distribution. 13169689Skan * 3. All advertising materials mentioning features or use of this software 14169689Skan * must display the following acknowledgement: 15169689Skan * This product includes software developed by the University of 16169689Skan * California, Berkeley and its contributors. 17169689Skan * 4. Neither the name of the University nor the names of its contributors 18169689Skan * may be used to endorse or promote products derived from this software 19169689Skan * without specific prior written permission. 20169689Skan * 21169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31169689Skan * SUCH DAMAGE. 32169689Skan */ 33169689Skan 34169689Skan#ifndef lint 35169689Skanchar copyright[] = 36169689Skan"@(#) Copyright (c) 1983, 1993\n\ 37169689Skan The Regents of the University of California. All rights reserved.\n"; 38169689Skan#endif /* not lint */ 39169689Skan 40169689Skan#ifndef lint 41169689Skanstatic char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94"; 42169689Skan#endif /* not lint */ 43169689Skan 44169689Skan/* 45169689Skan * uudecode [file ...] 46169689Skan * 47169689Skan * create the specified file, decoding as you go. 48169689Skan * used with uuencode. 49169689Skan */ 50169689Skan#include <sys/param.h> 51169689Skan#include <sys/stat.h> 52169689Skan 53169689Skan#include <pwd.h> 54169689Skan#include <stdio.h> 55169689Skan#include <string.h> 56169689Skan 57169689Skanchar *filename; 58169689Skan 59169689Skanint 60169689Skanmain(argc, argv) 61169689Skan int argc; 62169689Skan char *argv[]; 63169689Skan{ 64169689Skan extern int errno; 65169689Skan int rval; 66169689Skan 67169689Skan if (*++argv) { 68169689Skan rval = 0; 69169689Skan do { 70169689Skan if (!freopen(filename = *argv, "r", stdin)) { 71169689Skan (void)fprintf(stderr, "uudecode: %s: %s\n", 72169689Skan *argv, strerror(errno)); 73169689Skan rval = 1; 74169689Skan continue; 75169689Skan } 76169689Skan rval |= decode(); 77169689Skan } while (*++argv); 78169689Skan } else { 79169689Skan filename = "stdin"; 80169689Skan rval = decode(); 81169689Skan } 82169689Skan exit(rval); 83169689Skan} 84169689Skan 85169689Skandecode() 86169689Skan{ 87169689Skan extern int errno; 88169689Skan struct passwd *pw; 89169689Skan register int n; 90169689Skan register char ch, *p; 91169689Skan int mode, n1; 92169689Skan char buf[MAXPATHLEN]; 93169689Skan 94169689Skan /* search for header line */ 95169689Skan do { 96169689Skan if (!fgets(buf, sizeof(buf), stdin)) { 97169689Skan (void)fprintf(stderr, 98169689Skan "uudecode: %s: no \"begin\" line\n", filename); 99169689Skan return(1); 100169689Skan } 101169689Skan } while (strncmp(buf, "begin ", 6)); 102169689Skan (void)sscanf(buf, "begin %o %s", &mode, buf); 103169689Skan 104169689Skan /* handle ~user/file format */ 105169689Skan if (buf[0] == '~') { 106169689Skan if (!(p = index(buf, '/'))) { 107169689Skan (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n", 108169689Skan filename); 109169689Skan return(1); 110169689Skan } 111169689Skan *p++ = NULL; 112169689Skan if (!(pw = getpwnam(buf + 1))) { 113169689Skan (void)fprintf(stderr, "uudecode: %s: no user %s.\n", 114169689Skan filename, buf); 115169689Skan return(1); 116169689Skan } 117169689Skan n = strlen(pw->pw_dir); 118169689Skan n1 = strlen(p); 119169689Skan if (n + n1 + 2 > MAXPATHLEN) { 120169689Skan (void)fprintf(stderr, "uudecode: %s: path too long.\n", 121169689Skan filename); 122169689Skan return(1); 123169689Skan } 124169689Skan bcopy(p, buf + n + 1, n1 + 1); 125169689Skan bcopy(pw->pw_dir, buf, n); 126169689Skan buf[n] = '/'; 127169689Skan } 128169689Skan 129169689Skan /* create output file, set mode */ 130169689Skan if (!freopen(buf, "w", stdout) || 131169689Skan fchmod(fileno(stdout), mode&0666)) { 132169689Skan (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf, 133169689Skan filename, strerror(errno)); 134169689Skan return(1); 135169689Skan } 136169689Skan 137169689Skan /* for each input line */ 138169689Skan for (;;) { 139169689Skan if (!fgets(p = buf, sizeof(buf), stdin)) { 140169689Skan (void)fprintf(stderr, "uudecode: %s: short file.\n", 141169689Skan filename); 142169689Skan return(1); 143169689Skan } 144169689Skan#define DEC(c) (((c) - ' ') & 077) /* single character decode */ 145169689Skan /* 146169689Skan * `n' is used to avoid writing out all the characters 147169689Skan * at the end of the file. 148169689Skan */ 149169689Skan if ((n = DEC(*p)) <= 0) 150169689Skan break; 151169689Skan for (++p; n > 0; p += 4, n -= 3) 152169689Skan if (n >= 3) { 153169689Skan ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 154169689Skan putchar(ch); 155169689Skan ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 156169689Skan putchar(ch); 157169689Skan ch = DEC(p[2]) << 6 | DEC(p[3]); 158169689Skan putchar(ch); 159169689Skan } 160169689Skan else { 161169689Skan if (n >= 1) { 162169689Skan ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 163169689Skan putchar(ch); 164169689Skan } 165169689Skan if (n >= 2) { 166169689Skan ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 167169689Skan putchar(ch); 168169689Skan } 169169689Skan if (n >= 3) { 170169689Skan ch = DEC(p[2]) << 6 | DEC(p[3]); 171169689Skan putchar(ch); 172169689Skan } 173169689Skan } 174169689Skan } 175169689Skan if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) { 176169689Skan (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n", 177169689Skan filename); 178169689Skan return(1); 179169689Skan } 180169689Skan return(0); 181169689Skan} 182169689Skan 183169689Skanusage() 184169689Skan{ 185169689Skan (void)fprintf(stderr, "usage: uudecode [file ...]\n"); 186169689Skan exit(1); 187169689Skan} 188169689Skan