1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * uuencode [-m] [input] decode_pathname 39 * 40 * Encode a file so it can be mailed to a remote system. 41 */ 42 #include <unistd.h> 43 #include <limits.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <stdio.h> 47 #include <locale.h> 48 #include <sys/types.h> 49 #include <sys/stat.h> 50 #include <errno.h> 51 #include <assert.h> 52 #include <signal.h> 53 54 /* 55 * (Size of TABLE_SIZE octal is large enough to convert a basic 6-bit 56 * data chunk.) 57 */ 58 #define TABLE_SIZE 0x40 59 60 61 static unsigned char base64_table_initializer[] = 62 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 63 "abcdefghijklmnopqrstuvwxyz0123456789+/"; 64 65 static unsigned char encode_table[TABLE_SIZE]; 66 67 /* ENC is the basic 1 character encoding function to make a char printing */ 68 #define ENC(c) encode_table[(c) & 077] 69 70 static void encode(FILE *, FILE *, int); 71 static char *prog; 72 73 int 74 main(int argc, char **argv) 75 { 76 FILE *in; 77 struct stat sbuf; 78 mode_t mode = 0; 79 int c, i; 80 int errflag = 0; 81 int base64flag = 0; 82 char oline[PATH_MAX + 20]; 83 84 prog = argv[0]; 85 (void) signal(SIGPIPE, SIG_DFL); 86 87 /* Set locale environment variables local definitions */ 88 (void) setlocale(LC_ALL, ""); 89 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 90 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 91 #endif 92 (void) textdomain(TEXT_DOMAIN); 93 94 while ((c = getopt(argc, argv, "m")) != EOF) 95 switch (c) { 96 case 'm': 97 base64flag++; 98 break; 99 default: 100 case '?': 101 errflag++; 102 } 103 104 argc -= optind; 105 argv = &argv[optind]; 106 107 /* optional 1st argument */ 108 if (argc > 1) { 109 if ((in = fopen(*argv, "r")) == NULL) { 110 perror(*argv); 111 exit(1); 112 } 113 argv++; argc--; 114 } else { 115 in = stdin; 116 mode = 0777; 117 } 118 119 if ((argc != 1) || errflag) { 120 (void) fprintf(stderr, 121 gettext("Usage: %s [-m] [infile] remotefile\n"), prog); 122 exit(2); 123 } 124 125 /* figure out the input file mode */ 126 errno = 0; 127 if (fstat(fileno(in), &sbuf) < 0 || !S_ISREG(sbuf.st_mode)) { 128 mode = 0666 & ~umask(0666); 129 } else { 130 mode = sbuf.st_mode & 0777; 131 } 132 133 /* 134 * encoding varies depending on whether we are 135 * using base64 encoding or the historical algorithm 136 */ 137 if (base64flag) { 138 (void) memcpy(encode_table, base64_table_initializer, 139 sizeof (base64_table_initializer)); 140 } else { 141 for (i = 0; i < TABLE_SIZE; i++) 142 encode_table[i] = (unsigned char)i + 0x20; 143 } 144 145 /* 146 * here's the meat of the whole thing 147 */ 148 if (base64flag) 149 (void) snprintf(oline, sizeof (oline), "begin-base64 %lo %s\n", 150 (long)mode, *argv); 151 else 152 (void) snprintf(oline, sizeof (oline), "begin %lo %s\n", 153 (long)mode, *argv); 154 155 if (printf("%s", oline) < 0) { 156 perror(prog); 157 exit(6); 158 } 159 160 encode(in, stdout, base64flag); 161 162 if (base64flag) 163 (void) snprintf(oline, sizeof (oline), "====\n"); 164 else 165 (void) snprintf(oline, sizeof (oline), "end\n"); 166 167 if (printf("%s", oline) < 0) { 168 perror(prog); 169 exit(6); 170 } 171 172 if (ferror(stdout) != 0 || fclose(stdout) != 0) { 173 perror(prog); 174 exit(6); 175 } 176 177 return (0); 178 } 179 180 /* 181 * copy from in to out, encoding as you go along. 182 */ 183 static void 184 encode(FILE *in, FILE *out, int base64) 185 { 186 unsigned char in_buf[80]; 187 unsigned char out_buf[112]; 188 unsigned char *iptr, *optr; 189 int i; 190 size_t n, opos; 191 192 if (! base64) { 193 /* historical algorithm */ 194 195 for (;;) { 196 iptr = in_buf; 197 optr = out_buf; 198 199 /* 1 (up to) 45 character line */ 200 n = fread(iptr, 1, 45, in); 201 202 *(optr++) = ENC(n); 203 204 for (i = 0; i < n; i += 3) { 205 *(optr++) = ENC(*iptr >> 2); 206 *(optr++) = ENC((*iptr << 4) & 060 | 207 (*(iptr + 1) >> 4) & 017); 208 *(optr++) = ENC((*(iptr + 1) << 2) & 074 | 209 (*(iptr + 2) >> 6) & 03); 210 *(optr++) = ENC(*(iptr + 2) & 077); 211 iptr += 3; 212 } 213 214 *(optr++) = '\n'; 215 216 /*LINTED*/ 217 (void) fwrite(out_buf, 1, (size_t)(optr - out_buf), 218 out); 219 220 if (ferror(out)) { 221 perror(prog); 222 exit(6); 223 } 224 225 if (n == 0) 226 break; 227 } 228 } else { 229 /* base64 algorithm */ 230 231 optr = out_buf; 232 /* 233 * read must be a multiple of 3 bytes for 234 * this algorithm to work, and also must 235 * be small enough that read_size * (4/3) 236 * will always be 76 bytes or less, since 237 * base64 lines can be no longer than that 238 */ 239 while ((n = fread(in_buf, 1, 51, in)) > 0) { 240 opos = 0; 241 iptr = in_buf; 242 for (i = 0; i < n / 3; i++) { 243 *(optr++) = ENC(*iptr >> 2); 244 *(optr++) = ENC((*iptr << 4) & 060 | 245 (*(iptr + 1) >> 4) & 017); 246 *(optr++) = ENC((*(iptr + 1) << 2) 247 & 074 | (*(iptr + 2) >> 6) & 03); 248 *(optr++) = ENC(*(iptr + 2) & 077); 249 iptr += 3; 250 opos += 3; 251 252 /* need output padding ? */ 253 if (n - opos < 3) 254 break; 255 256 (void) fwrite(out_buf, 1, 257 /*LINTED*/ 258 (size_t)(optr - out_buf), out); 259 260 if (ferror(out)) { 261 perror(prog); 262 exit(6); 263 } 264 265 optr = out_buf; 266 } 267 /* 268 * Take care of any output padding that is 269 * necessary. 270 */ 271 assert(n - opos < 3); 272 switch (n - opos) { 273 case 0: 274 /* no-op - 24 bits of data encoded */ 275 *(optr++) = '\n'; 276 break; 277 case 1: 278 /* 8 bits encoded - pad with 2 '=' */ 279 *(optr++) = ENC((*iptr & 0xFC) >> 2); 280 *(optr++) = ENC((*iptr & 0x03) << 4); 281 *(optr++) = '='; 282 *(optr++) = '='; 283 *(optr++) = '\n'; 284 break; 285 case 2: 286 /* 16 bits encoded - pad with 1 '=' */ 287 *(optr++) = ENC((*iptr & 0xFC) >> 2); 288 *(optr++) = ENC(((*iptr & 0x03) << 4) | 289 ((*(iptr + 1) & 0xF0) >> 4)); 290 *(optr++) = ENC((*(iptr + 1) & 0x0F) 291 << 2); 292 *(optr++) = '='; 293 *(optr++) = '\n'; 294 break; 295 default: 296 /* impossible */ 297 break; 298 } 299 (void) fwrite(out_buf, 1, 300 /*LINTED*/ 301 (size_t)(optr - out_buf), out); 302 303 if (ferror(out)) { 304 perror(prog); 305 exit(6); 306 } 307 308 optr = out_buf; 309 } 310 } 311 } 312