Attached: updated uuencode/uudecode toys, and tests for both.
/* uudecode.c - uudecode / base64 decode * * Copyright 2013 Erich Plondke <[email protected]> * * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html
USE_UUENCODE(NEWTOY(uudecode, ">2o:", TOYFLAG_USR|TOYFLAG_BIN))
config UUDECODE
bool "uudecode"
default n
help
usage: uudecode [-o outfile] [file]
Uudecode or base64-decode stdin or [file], sending output to outfile or
filename specified by input.
*/
#define FOR_uudecode
#include "toys.h"
GLOBALS(
char *o;
)
/*
* Turn a character back into a value.
* The smallest valid character is 0x2B ('+')
* The biggest valid character is 0x7A ('z')
* We can make a table of 16*5 entries to cover 0x2B - 0x7A
*/
static inline int startswith(const char *a, const char *b)
{
return (0==strncmp(a,b,strlen(b)));
}
static inline signed char uudecode_b64_1byte(char in)
{
char ret;
static const signed char table[16*5] = {
/* '+' (0x2B) is 62, '/'(0x2F) is 63, rest invalid */
62, -1, -1, -1, 63,
/* '0'-'9' are values 52-61, rest of 0x3A - 0x3F is invalid, = is special... */
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
/* '@' is invalid, 'A'-'Z' are values 0-25, 0x5b - 0x5F are invalid */
-1, 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, -1, -1, -1, -1, -1,
/* '`' is invalid, 'a'-'z' are values 26-51, 0x7B - 0x7F are invalid */
-1, 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
};
in &= 0x7f;
if (in < '+') return -1;
if (in > 'z') return -1;
in -= '+';
ret = table[in];
return ret;
};
/* Returns length put in out */
static int uudecode_b64_4bytes(char *out, const char *in)
{
unsigned int i,x=0;
signed char b0,b1,b2,b3;
int len = 3;
b0 = uudecode_b64_1byte(in[0]);
b1 = uudecode_b64_1byte(in[1]);
b2 = uudecode_b64_1byte(in[2]);
b3 = uudecode_b64_1byte(in[3]);
if ((b1 < 0) || (b0 < 0)) return 0;
if (b3 < 0) len--;
if (b2 < 0) len--;
x = ((b0 & 0x3f)<<18) | ((b1 & 0x3f)<<12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
for (i = 0; i < len; i++) {
*out++ = (x>>(8*(2-i))) & 0x0ff;
}
return len;
}
static void uudecode_b64_line(int ofd, const char *in, int ilen)
{
int olen;
char out[4];
while (ilen >= 4) {
olen = uudecode_b64_4bytes(out,in);
xwrite(ofd,out,olen);
in += 4;
ilen -= 4;
};
}
static void uudecode_b64(int ifd, int ofd)
{
int len;
char *line;
while ((line = get_line(ifd)) != NULL) {
if (startswith(line,"====")) return;
if ((len = strlen(line)) < 4) continue; // skip empty lines
uudecode_b64_line(ofd,line,len);
free(line);
}
}
static void uudecode_uu_4bytes(char *out, const char *in, int len)
{
unsigned int i,x=0;
for (i = 0; i < 4; i++) {
x |= ((in[i] - 32) & 0x03f) << (6*(3-i));
}
for (i = 0; i < (min(3,len)); i++) {
*out++ = x >> (8*(2-i));
}
}
static void uudecode_uu_line(int ofd, const char *in)
{
int olen = in[0] - 32;
char buf[4];
in++;
while (olen > 0) {
uudecode_uu_4bytes(buf,in,olen);
xwrite(ofd,buf,min(olen,3));
olen -= 3;
in += 4;
}
}
static void uudecode_uu(int ifd, int ofd)
{
char *line = NULL;
while ((line = get_line(ifd)) != NULL) {
if (line[0] == '`') break;
if (startswith(line,"end")) break;
if (strlen(line) < 1) break;
uudecode_uu_line(ofd,line);
free(line);
}
}
void uudecode_main(void)
{
char *out_filename = NULL;
int ifd = 0; /* STDIN */
int ofd = 1; /* STDOUT */
char *line;
char *p,*p2;
void (*decoder)(int ifd, int ofd) = NULL;
long mode = 0744;
if (toys.optc == 1) {
ifd = xopen(toys.optargs[0],O_RDONLY); // dies if error
}
do {
if ((line = get_line(ifd)) == NULL) perror_exit("empty file");
} while (strlen(line) == 0); /* skip over empty lines */
if (startswith(line,"begin ")) decoder = uudecode_uu;
else if (startswith(line,"begin-base64 ")) decoder = uudecode_b64;
else perror_exit("not a valid uu- or base64-encoded file");
for (p = line; !isspace(*p); p++) /* skip first part */;
for (; isspace(*p); p++) /* skip spaces */;
mode = strtoul(p,&p2,8);
p = p2 + 1; /* skip space */
if (toys.optflags & FLAG_o) {
out_filename = TT.o;
} else {
out_filename = p;
}
ofd = xcreate(out_filename,O_WRONLY|O_CREAT|O_TRUNC,mode);
free(line);
decoder(ifd,ofd);
xclose(ofd);
}
/* uuencode.c - uuencode / base64 encode * * Copyright 2013 Erich Plondke <[email protected]> * * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uuencode.html USE_UUENCODE(NEWTOY(uuencode, "<1>2m", TOYFLAG_USR|TOYFLAG_BIN)) config UUENCODE bool "uuencode" default n help usage: uuencode [-m] [file] encode-filename Uuencode or (with -m option) base64-encode stdin or [file], with encode-filename in the output, which is sent to stdout. */ #define FOR_uuencode #include "toys.h" static void uuencode_b64_3bytes(char *out, const char *in, int bytes) { static const char *table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; unsigned int i,x=0; for (i = 0; i < bytes; i++) { x |= (in[i] & 0x0ff) << (8*(2-i)); } out[0] = table[(x>>(3*6)) & 0x3f]; out[1] = table[(x>>(2*6)) & 0x3f]; out[2] = table[(x>>(1*6)) & 0x3f]; out[3] = table[(x>>(0*6)) & 0x3f]; if (bytes <= 1) out[2] = '='; if (bytes <= 2) out[3] = '='; } static void uuencode_b64_line(char *out, const char *in, int len) { while (len > 0) { uuencode_b64_3bytes(out,in,min(3,len)); xprintf("%c%c%c%c",out[0],out[1],out[2],out[3]); in += 3; len -= 3; }; xprintf("\n"); } static void uuencode_b64(int fd, const char *name) { int len; char *inbuf = toybuf; char *outbuf = toybuf+64; xprintf("begin-base64 744 %s\n",name); do { len = xread(fd,inbuf,48); if (len > 0) uuencode_b64_line(outbuf,inbuf,len); } while (len > 0); xprintf("====\n"); } static void uuencode_uu_3bytes(char *out, const char *in) { unsigned int i,x=0; for (i = 0; i <= 2; i++) { x |= (in[i] & 0x0ff) << (8*(2-i)); } for (i = 0; i <= 3; i++) { out[i] = 32 + ((x >> (6*(3-i))) & 0x3f); } } static void uuencode_uu_line(char *out, const char *in, int len) { int i; if (len == 0) { xprintf("`\n"); return; } xprintf("%c",len+32); for (i = 0; i < len; i += 3) { uuencode_uu_3bytes(out,in+i); xprintf("%c%c%c%c",out[0],out[1],out[2],out[3]); } xprintf("\n"); } static void uuencode_uu(int fd, const char *name) { int len; char *inbuf = toybuf; char *outbuf = toybuf+64; xprintf("begin 744 %s\n",name); do { len = xread(fd,inbuf,45); uuencode_uu_line(outbuf,inbuf,len); } while (len > 0); xprintf("end\n"); } void uuencode_main(void) { char *encode_filename = toys.optargs[0]; int fd = 0; /* STDIN */ if (toys.optc == 2) { fd = xopen(toys.optargs[0],O_RDONLY); // dies if error encode_filename = toys.optargs[1]; } if (toys.optflags & FLAG_m) uuencode_b64(fd,encode_filename); else uuencode_uu(fd,encode_filename); }
uudecode.test
Description: Binary data
uuencode.test
Description: Binary data
_______________________________________________ Toybox mailing list [email protected] http://lists.landley.net/listinfo.cgi/toybox-landley.net
