1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)uudecode.c 5.5 (Berkeley) 07/06/88"; 20 #endif /* not lint */ 21 22 /* 23 * uudecode [input] 24 * 25 * create the specified file, decoding as you go. 26 * used with uuencode. 27 */ 28 #include <stdio.h> 29 #include <pwd.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 33 /* single character decode */ 34 #define DEC(c) (((c) - ' ') & 077) 35 36 main(argc, argv) 37 char **argv; 38 { 39 FILE *in, *out; 40 int mode; 41 char dest[128]; 42 char buf[80]; 43 44 /* optional input arg */ 45 if (argc > 1) { 46 if ((in = fopen(argv[1], "r")) == NULL) { 47 perror(argv[1]); 48 exit(1); 49 } 50 argv++; argc--; 51 } else 52 in = stdin; 53 54 if (argc != 1) { 55 printf("Usage: uudecode [infile]\n"); 56 exit(2); 57 } 58 59 /* search for header line */ 60 for (;;) { 61 if (fgets(buf, sizeof buf, in) == NULL) { 62 fprintf(stderr, "No begin line\n"); 63 exit(3); 64 } 65 if (strncmp(buf, "begin ", 6) == 0) 66 break; 67 } 68 (void)sscanf(buf, "begin %o %s", &mode, dest); 69 70 /* handle ~user/file format */ 71 if (dest[0] == '~') { 72 char *sl; 73 struct passwd *getpwnam(); 74 struct passwd *user; 75 char dnbuf[100], *index(), *strcat(), *strcpy(); 76 77 sl = index(dest, '/'); 78 if (sl == NULL) { 79 fprintf(stderr, "Illegal ~user\n"); 80 exit(3); 81 } 82 *sl++ = 0; 83 user = getpwnam(dest+1); 84 if (user == NULL) { 85 fprintf(stderr, "No such user as %s\n", dest); 86 exit(4); 87 } 88 strcpy(dnbuf, user->pw_dir); 89 strcat(dnbuf, "/"); 90 strcat(dnbuf, sl); 91 strcpy(dest, dnbuf); 92 } 93 94 /* create output file */ 95 out = fopen(dest, "w"); 96 if (out == NULL) { 97 perror(dest); 98 exit(4); 99 } 100 chmod(dest, mode); 101 102 decode(in, out); 103 104 if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { 105 fprintf(stderr, "No end line\n"); 106 exit(5); 107 } 108 exit(0); 109 } 110 111 /* 112 * copy from in to out, decoding as you go along. 113 */ 114 decode(in, out) 115 FILE *in; 116 FILE *out; 117 { 118 char buf[80]; 119 char *bp; 120 int n; 121 122 for (;;) { 123 /* for each input line */ 124 if (fgets(buf, sizeof buf, in) == NULL) { 125 printf("Short file\n"); 126 exit(10); 127 } 128 n = DEC(buf[0]); 129 if (n <= 0) 130 break; 131 132 bp = &buf[1]; 133 while (n > 0) { 134 outdec(bp, out, n); 135 bp += 4; 136 n -= 3; 137 } 138 } 139 } 140 141 /* 142 * output a group of 3 bytes (4 input characters). 143 * the input chars are pointed to by p, they are to 144 * be output to file f. n is used to tell us not to 145 * output all of them at the end of the file. 146 */ 147 outdec(p, f, n) 148 char *p; 149 FILE *f; 150 { 151 int c1, c2, c3; 152 153 c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; 154 c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 155 c3 = DEC(p[2]) << 6 | DEC(p[3]); 156 if (n >= 1) 157 putc(c1, f); 158 if (n >= 2) 159 putc(c2, f); 160 if (n >= 3) 161 putc(c3, f); 162 } 163