/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
* 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, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright 2004 Sun Microsystems, Inc. All rights reserved. */
/* Use is subject to license terms. */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* uudecode [-o outfile | -p] [input]
*
* create the specified file, decoding as you go.
* used with uuencode.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <string.h>
#include <strings.h>
#include <locale.h>
#include <nl_types.h>
#include <langinfo.h>
#include <iconv.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <stdarg.h>
/*
* base64 decoding table
*/
/* BEGIN CSTYLED */
static char base64tab[] = {
'\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
'\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
'\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
'\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
'\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
'\377', '\377', '\377', 62, '\377', '\377', '\377', 63,
52, 53, 54, 55, 56, 57, 58, 59,
60, 61, '\377', '\377', '\377', '\377', '\377', '\377',
'\377', 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, '\377', '\377', '\377', '\377', '\377',
'\377', 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, '\377', '\377', '\377', '\377', '\377'
};
/* END CSTYLED */
/* DEC is the basic 1 character decoding function (historical algorithm) */
/* true if the character is in the base64 encoding table */
('a' <= (c) && (c) <= 'z') || \
('0' <= (c) && (c) <= '9') || \
(c) == '+' || (c) == '/')
static int outdec(unsigned char *, unsigned char *, int);
static int outdec64(unsigned char *, unsigned char *, int);
static char *prog;
int
{
int pipeout = 0;
int oflag = 0;
int i;
int c, errflag = 0;
int base64flag = 0;
outfile[0] = '\0';
/* Set locale environment variables local definitions */
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case 'o':
oflag++;
break;
case 'p':
pipeout++;
break;
default:
case '?':
errflag++;
break;
}
}
/* optional input arg */
if (argc > 0) {
exit(1);
}
} else {
errno = 0;
perror("stdin");
exit(1);
}
}
exit(2);
}
/* search for header line */
for (;;) {
/* suppress message if we printed a mode error */
if (mode_err == 0)
gettext("No begin line\n"));
exit(3);
}
/*
* the check for begin-base64 obviously needs to come
* first, since both algorithms' begin strings start
* with 'begin'. Also verify that there is a valid
* octal or symbolic file mode.
*/
base64flag = 1;
mode_err = 0;
break;
base64flag = 0;
mode_err = 0;
break;
}
}
/*
* Now that we know the type of encoding used, we can
* initialize the decode table.
*/
if (base64flag == 0) {
for (i = 0; i <= TABLE_SIZE; i++)
decode_table[(unsigned char)i + 0x20] =
(unsigned char)i & 0x3F;
} else
/*
* Filename specified on the command line with -o
* overrides filename in the encoded file.
*/
if (outfile[0] != '\0')
if (pipeout ||
} else {
if (dest[0] == '~') {
char *sl;
gettext("Illegal ~user\n"));
exit(3);
}
*sl++ = 0;
exit(4);
}
}
}
/* if not using stdout, create file */
if (dest[0] != '\0') {
exit(4);
}
}
exit(6);
}
return (0);
}
/*
* copy from in to out, decoding as you go along.
*/
static void
{
if (! base64) { /* use historical algorithm */
warned = 0;
/* for each input line */
gettext("No end line\n"));
exit(5);
}
/* Is line == 'end\n'? */
break;
}
if (n < 0)
continue;
/*
* Decode data lines.
*
* character set for encoded data and the portable
* character set characters must be represented in
* a single byte. We use this knowledge to reuse
* buffer space while decoding.
*/
octets = n;
while (octets > 0) {
!= 0x20) {
/* invalid characters where detected */
if (!warned) {
warned = 1;
gettext("Invalid character"
" (0x%x) on line"
}
break;
}
ibp += 4;
obp += 3;
octets -= 3;
}
/*
* Only write out uncorrupted lines
*/
if (octets <= 0) {
}
}
} else { /* use base64 algorithm */
endseen = numbase64chars = 0;
/* process an input line */
/* decode chars */
endseen++;
if (validbase64(curchr))
/*
* if we've gathered 4 base64 octets
* we need to decode and output them
*/
if (numbase64chars == 4) {
/*LINTED*/
/*LINTED*/
1, out);
exit(6);
}
}
numbase64chars = 0;
}
}
/*
* handle any remaining base64 octets at end
*/
if (endseen && numbase64chars > 0) {
numbase64chars = 0;
}
}
/*
* if we have generated any additional output
* in the buffer, write it out
*/
/*LINTED*/
1, out);
exit(6);
}
}
if (endseen == 0) {
exit(5);
}
}
}
/*
* historical algorithm
*
* output a group of 3 bytes (4 input characters).
* the input chars are pointed to by p, they are to
* be output to file f. n is used to tell us not to
* output all of them at the end of the file.
*/
static int
{
return (*(in-3));
}
return (*(in-2));
}
if (n >= 2) {
return (*(in - 1));
}
if (n >= 3) {
return (*in);
}
}
}
return (0x20); /* a know good value */
}
/*
* base64 algorithm
*
* Takes a pointer to the current position in the output buffer,
* a pointer to the (up to) 4 byte base64 input buffer and a
* count of the number of valid input bytes.
*
* Return the number of bytes placed in the output buffer
*/
static int
{
int rc = 0;
switch (num) {
case 0:
case 1: /* these are impossible */
default:
break;
case 2: /* 2 base64 bytes == 1 decoded byte */
rc = 1;
break;
case 3: /* 3 base64 bytes == 2 decoded bytes */
rc = 2;
break;
case 4: /* 4 base64 bytes == 3 decoded bytes */
(char4 & 0x3F);
rc = 3;
break;
}
return (rc);
}
/*
* error message routine called by newmode.
*
* The severity and code are ignored here. If this routine gets
* called, we set a global flag (which can be tested after return
* from here) which tells us whether or not a valid mode has been
* parsed or if we printed an error message.
*/
/*ARGSUSED*/
void
{
mode_err = 1;
}