Home | History | Annotate | Download | only in pending
      1 /* iconv.c - Convert character encoding
      2  *
      3  * Copyright 2014 Felix Janda <felix.janda (at) posteo.de>
      4  *
      5  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/iconv.html
      6 
      7 USE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN))
      8 
      9 config ICONV
     10   bool "iconv"
     11   default n
     12   depends on TOYBOX_ICONV
     13   help
     14     usage: iconv [-f FROM] [-t TO] [FILE...]
     15 
     16     Convert character encoding of files.
     17 
     18     -f  convert from (default utf8)
     19     -t  convert to   (default utf8)
     20 */
     21 
     22 #define FOR_iconv
     23 #include "toys.h"
     24 #include <iconv.h>
     25 
     26 GLOBALS(
     27   char *from;
     28   char *to;
     29 
     30   void *ic;
     31 )
     32 
     33 static void do_iconv(int fd, char *name)
     34 {
     35   char *outstart = toybuf+2048;
     36   size_t inleft = 0;
     37   int len = 1;
     38 
     39   do {
     40     size_t outleft = 2048;
     41     char *in = toybuf+inleft, *out = outstart;
     42 
     43     len = read(fd, in, 2048-inleft);
     44 
     45     if (len < 0) {
     46       perror_msg("read '%s'");
     47       return;
     48     }
     49     inleft += len;
     50 
     51     do {
     52       if (iconv(TT.ic, &in, &inleft, &out, &outleft) == -1
     53           && (errno == EILSEQ || (in == toybuf+inleft-len && errno == EINVAL)))
     54       {
     55         if (outleft) {
     56           // Skip first byte of illegal sequence to avoid endless loops
     57           *(out++) = *(in++);
     58           inleft--;
     59         }
     60       }
     61       xwrite(1, outstart, out-outstart);
     62       // Top off input buffer
     63       memmove(in, toybuf, inleft);
     64     } while (len < 1 && inleft);
     65   } while (len > 0);
     66 }
     67 
     68 void iconv_main(void)
     69 {
     70   TT.ic = iconv_open(TT.to ? TT.to : "utf8", TT.from ? TT.from : "utf8");
     71   if (TT.ic == (iconv_t)-1) error_exit("bad encoding");
     72   loopfiles(toys.optargs, do_iconv);
     73   if (CFG_TOYBOX_FREE) iconv_close(TT.ic);
     74 }
     75