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.4 (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 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 char *index(); 75 struct passwd *user; 76 char dnbuf[100]; 77 78 sl = index(dest, '/'); 79 if (sl == NULL) { 80 fprintf(stderr, "Illegal ~user\n"); 81 exit(3); 82 } 83 *sl++ = 0; 84 user = getpwnam(dest+1); 85 if (user == NULL) { 86 fprintf(stderr, "No such user as %s\n", dest); 87 exit(4); 88 } 89 strcpy(dnbuf, user->pw_dir); 90 strcat(dnbuf, "/"); 91 strcat(dnbuf, sl); 92 strcpy(dest, dnbuf); 93 } 94 95 /* create output file */ 96 out = fopen(dest, "w"); 97 if (out == NULL) { 98 perror(dest); 99 exit(4); 100 } 101 chmod(dest, mode); 102 103 decode(in, out); 104 105 if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { 106 fprintf(stderr, "No end line\n"); 107 exit(5); 108 } 109 exit(0); 110 } 111 112 /* 113 * copy from in to out, decoding as you go along. 114 */ 115 decode(in, out) 116 FILE *in; 117 FILE *out; 118 { 119 char buf[80]; 120 char *bp; 121 int n; 122 123 for (;;) { 124 /* for each input line */ 125 if (fgets(buf, sizeof buf, in) == NULL) { 126 printf("Short file\n"); 127 exit(10); 128 } 129 n = DEC(buf[0]); 130 if (n <= 0) 131 break; 132 133 bp = &buf[1]; 134 while (n > 0) { 135 outdec(bp, out, n); 136 bp += 4; 137 n -= 3; 138 } 139 } 140 } 141 142 /* 143 * output a group of 3 bytes (4 input characters). 144 * the input chars are pointed to by p, they are to 145 * be output to file f. n is used to tell us not to 146 * output all of them at the end of the file. 147 */ 148 outdec(p, f, n) 149 char *p; 150 FILE *f; 151 { 152 int c1, c2, c3; 153 154 c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; 155 c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 156 c3 = DEC(p[2]) << 6 | DEC(p[3]); 157 if (n >= 1) 158 putc(c1, f); 159 if (n >= 2) 160 putc(c2, f); 161 if (n >= 3) 162 putc(c3, f); 163 } 164 165 166 /* fr: like read but stdio */ 167 int 168 fr(fd, buf, cnt) 169 FILE *fd; 170 char *buf; 171 int cnt; 172 { 173 int c, i; 174 175 for (i=0; i<cnt; i++) { 176 c = getc(fd); 177 if (c == EOF) 178 return(i); 179 buf[i] = c; 180 } 181 return (cnt); 182 } 183 184 /* 185 * Return the ptr in sp at which the character c appears; 186 * NULL if not found 187 */ 188 189 #define NULL 0 190 191 char * 192 index(sp, c) 193 register char *sp, c; 194 { 195 do { 196 if (*sp == c) 197 return(sp); 198 } while (*sp++); 199 return(NULL); 200 } 201