/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Portions of this source code were derived from Berkeley 4.3 BSD * under license from the Regents of the University of California. */ /* * uuencode [-m] [input] decode_pathname * * Encode a file so it can be mailed to a remote system. */ #include #include #include #include #include #include #include #include #include #include #include /* * (Size of TABLE_SIZE octal is large enough to convert a basic 6-bit * data chunk.) */ #define TABLE_SIZE 0x40 static unsigned char base64_table_initializer[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz0123456789+/"; static unsigned char encode_table[TABLE_SIZE]; /* ENC is the basic 1 character encoding function to make a char printing */ #define ENC(c) encode_table[(c) & 077] static void encode(FILE *, FILE *, int); static char *prog; int main(int argc, char **argv) { FILE *in; struct stat sbuf; mode_t mode = 0; int c, i; int errflag = 0; int base64flag = 0; char oline[PATH_MAX + 20]; prog = argv[0]; (void) signal(SIGPIPE, SIG_DFL); /* Set locale environment variables local definitions */ (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ #endif (void) textdomain(TEXT_DOMAIN); while ((c = getopt(argc, argv, "m")) != EOF) switch (c) { case 'm': base64flag++; break; default: case '?': errflag++; } argc -= optind; argv = &argv[optind]; /* optional 1st argument */ if (argc > 1) { if ((in = fopen(*argv, "r")) == NULL) { perror(*argv); exit(1); } argv++; argc--; } else { in = stdin; mode = 0777; } if ((argc != 1) || errflag) { (void) fprintf(stderr, gettext("Usage: %s [-m] [infile] remotefile\n"), prog); exit(2); } /* figure out the input file mode */ errno = 0; if (fstat(fileno(in), &sbuf) < 0 || !S_ISREG(sbuf.st_mode)) { mode = 0666 & ~umask(0666); } else { mode = sbuf.st_mode & 0777; } /* * encoding varies depending on whether we are * using base64 encoding or the historical algorithm */ if (base64flag) { (void) memcpy(encode_table, base64_table_initializer, sizeof (encode_table)); } else { for (i = 0; i < TABLE_SIZE; i++) encode_table[i] = (unsigned char)i + 0x20; } /* * here's the meat of the whole thing */ if (base64flag) (void) snprintf(oline, sizeof (oline), "begin-base64 %lo %s\n", (long)mode, *argv); else (void) snprintf(oline, sizeof (oline), "begin %lo %s\n", (long)mode, *argv); if (printf("%s", oline) < 0) { perror(prog); exit(6); } encode(in, stdout, base64flag); if (base64flag) (void) snprintf(oline, sizeof (oline), "====\n"); else (void) snprintf(oline, sizeof (oline), "end\n"); if (printf("%s", oline) < 0) { perror(prog); exit(6); } if (ferror(stdout) != 0 || fclose(stdout) != 0) { perror(prog); exit(6); } return (0); } /* * copy from in to out, encoding as you go along. */ static void encode(FILE *in, FILE *out, int base64) { unsigned char in_buf[80]; unsigned char out_buf[112]; unsigned char *iptr, *optr; int i; size_t n, opos; if (! base64) { /* historical algorithm */ for (;;) { iptr = in_buf; optr = out_buf; /* 1 (up to) 45 character line */ n = fread(iptr, 1, 45, in); *(optr++) = ENC(n); for (i = 0; i < n; i += 3) { *(optr++) = ENC(*iptr >> 2); *(optr++) = ENC((*iptr << 4) & 060 | (*(iptr + 1) >> 4) & 017); *(optr++) = ENC((*(iptr + 1) << 2) & 074 | (*(iptr + 2) >> 6) & 03); *(optr++) = ENC(*(iptr + 2) & 077); iptr += 3; } *(optr++) = '\n'; /*LINTED*/ (void) fwrite(out_buf, 1, (size_t)(optr - out_buf), out); if (ferror(out)) { perror(prog); exit(6); } if (n == 0) break; } } else { /* base64 algorithm */ optr = out_buf; /* * read must be a multiple of 3 bytes for * this algorithm to work, and also must * be small enough that read_size * (4/3) * will always be 76 bytes or less, since * base64 lines can be no longer than that */ while ((n = fread(in_buf, 1, 51, in)) > 0) { opos = 0; iptr = in_buf; for (i = 0; i < n / 3; i++) { *(optr++) = ENC(*iptr >> 2); *(optr++) = ENC((*iptr << 4) & 060 | (*(iptr + 1) >> 4) & 017); *(optr++) = ENC((*(iptr + 1) << 2) & 074 | (*(iptr + 2) >> 6) & 03); *(optr++) = ENC(*(iptr + 2) & 077); iptr += 3; opos += 3; /* need output padding ? */ if (n - opos < 3) break; (void) fwrite(out_buf, 1, /*LINTED*/ (size_t)(optr - out_buf), out); if (ferror(out)) { perror(prog); exit(6); } optr = out_buf; } /* * Take care of any output padding that is * necessary. */ assert(n - opos < 3); switch (n - opos) { case 0: /* no-op - 24 bits of data encoded */ *(optr++) = '\n'; break; case 1: /* 8 bits encoded - pad with 2 '=' */ *(optr++) = ENC((*iptr & 0xFC) >> 2); *(optr++) = ENC((*iptr & 0x03) << 4); *(optr++) = '='; *(optr++) = '='; *(optr++) = '\n'; break; case 2: /* 16 bits encoded - pad with 1 '=' */ *(optr++) = ENC((*iptr & 0xFC) >> 2); *(optr++) = ENC(((*iptr & 0x03) << 4) | ((*(iptr + 1) & 0xF0) >> 4)); *(optr++) = ENC((*(iptr + 1) & 0x0F) << 2); *(optr++) = '='; *(optr++) = '\n'; break; default: /* impossible */ break; } (void) fwrite(out_buf, 1, /*LINTED*/ (size_t)(optr - out_buf), out); if (ferror(out)) { perror(prog); exit(6); } optr = out_buf; } } }