diff options
| -rw-r--r-- | toys/pending/uudecode.c | 174 | ||||
| -rw-r--r-- | toys/pending/uuencode.c | 116 | 
2 files changed, 290 insertions, 0 deletions
| diff --git a/toys/pending/uudecode.c b/toys/pending/uudecode.c new file mode 100644 index 00000000..71774ea2 --- /dev/null +++ b/toys/pending/uudecode.c @@ -0,0 +1,174 @@ +/* uudecode.c - uudecode / base64 decode + * + * Copyright 2013 Erich Plondke <toybox@erich.wreck.org> + * + * 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)); +  } +  if (len > 3) len = 3; +  for (i = 0; i < 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,olen < 3 ? 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); +} diff --git a/toys/pending/uuencode.c b/toys/pending/uuencode.c new file mode 100644 index 00000000..d6cc5ad2 --- /dev/null +++ b/toys/pending/uuencode.c @@ -0,0 +1,116 @@ +/* uuencode.c - uuencode / base64 encode + * + * Copyright 2013 Erich Plondke <toybox@erich.wreck.org> + * + * 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,len < 3 ? len : 3); +    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); +    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); +} | 
