10f66f451Sopenharmony_ci/* iconv.c - Convert character encoding 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2014 Felix Janda <felix.janda@posteo.de> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/iconv.html 60f66f451Sopenharmony_ci * 70f66f451Sopenharmony_ci * Deviations from posix: no idea how to implement -l 80f66f451Sopenharmony_ci 90f66f451Sopenharmony_ciUSE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN)) 100f66f451Sopenharmony_ci 110f66f451Sopenharmony_ciconfig ICONV 120f66f451Sopenharmony_ci bool "iconv" 130f66f451Sopenharmony_ci default y 140f66f451Sopenharmony_ci depends on TOYBOX_ICONV 150f66f451Sopenharmony_ci help 160f66f451Sopenharmony_ci usage: iconv [-f FROM] [-t TO] [FILE...] 170f66f451Sopenharmony_ci 180f66f451Sopenharmony_ci Convert character encoding of files. 190f66f451Sopenharmony_ci 200f66f451Sopenharmony_ci -c Omit invalid chars 210f66f451Sopenharmony_ci -f Convert from (default UTF-8) 220f66f451Sopenharmony_ci -t Convert to (default UTF-8) 230f66f451Sopenharmony_ci*/ 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci#define FOR_iconv 260f66f451Sopenharmony_ci#include "toys.h" 270f66f451Sopenharmony_ci#include <iconv.h> 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ciGLOBALS( 300f66f451Sopenharmony_ci char *f, *t; 310f66f451Sopenharmony_ci 320f66f451Sopenharmony_ci void *ic; 330f66f451Sopenharmony_ci) 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_cistatic void do_iconv(int fd, char *name) 360f66f451Sopenharmony_ci{ 370f66f451Sopenharmony_ci char *outstart = toybuf+2048; 380f66f451Sopenharmony_ci size_t outlen, inlen = 0; 390f66f451Sopenharmony_ci int readlen = 1; 400f66f451Sopenharmony_ci 410f66f451Sopenharmony_ci for (;;) { 420f66f451Sopenharmony_ci char *in = toybuf, *out = outstart; 430f66f451Sopenharmony_ci 440f66f451Sopenharmony_ci if (readlen && 0>(readlen = read(fd, in+inlen, 2048-inlen))) { 450f66f451Sopenharmony_ci perror_msg("read '%s'", name); 460f66f451Sopenharmony_ci return; 470f66f451Sopenharmony_ci } 480f66f451Sopenharmony_ci inlen += readlen; 490f66f451Sopenharmony_ci if (!inlen) break; 500f66f451Sopenharmony_ci 510f66f451Sopenharmony_ci outlen = 2048; 520f66f451Sopenharmony_ci iconv(TT.ic, &in, &inlen, &out, &outlen); 530f66f451Sopenharmony_ci if (in == toybuf) { 540f66f451Sopenharmony_ci // Skip first byte of illegal sequence to avoid endless loops 550f66f451Sopenharmony_ci if (toys.optflags & FLAG_c) in++; 560f66f451Sopenharmony_ci else *(out++) = *(in++); 570f66f451Sopenharmony_ci inlen--; 580f66f451Sopenharmony_ci } 590f66f451Sopenharmony_ci if (out != outstart) xwrite(1, outstart, out-outstart); 600f66f451Sopenharmony_ci memmove(toybuf, in, inlen); 610f66f451Sopenharmony_ci } 620f66f451Sopenharmony_ci} 630f66f451Sopenharmony_ci 640f66f451Sopenharmony_civoid iconv_main(void) 650f66f451Sopenharmony_ci{ 660f66f451Sopenharmony_ci if (!TT.t) TT.t = "UTF-8"; 670f66f451Sopenharmony_ci if (!TT.f) TT.f = "UTF-8"; 680f66f451Sopenharmony_ci 690f66f451Sopenharmony_ci if ((iconv_t)-1 == (TT.ic = iconv_open(TT.t, TT.f))) 700f66f451Sopenharmony_ci perror_exit("%s/%s", TT.t, TT.f); 710f66f451Sopenharmony_ci loopfiles(toys.optargs, do_iconv); 720f66f451Sopenharmony_ci if (CFG_TOYBOX_FREE) iconv_close(TT.ic); 730f66f451Sopenharmony_ci} 74