iconv.c - randomcrap - random crap programs of varying quality
 (HTM) git clone git://git.codemadness.org/randomcrap
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       iconv.c (2586B)
       ---
            1 /*
            2  * iconv.c
            3  * Implementation of SUSv4 XCU iconv utility
            4  * Copyright © 2011 Rich Felker
            5  * Licensed under the terms of the GNU General Public License, v2 or later
            6  */
            7 
            8 #include <stdlib.h>
            9 #include <stdio.h>
           10 #include <iconv.h>
           11 #include <locale.h>
           12 #include <langinfo.h>
           13 #include <unistd.h>
           14 #include <errno.h>
           15 #include <string.h>
           16 
           17 int main(int argc, char **argv)
           18 {
           19         const char *from=0, *to=0;
           20         int b;
           21         iconv_t cd;
           22         char buf[BUFSIZ];
           23         char outbuf[BUFSIZ*4];
           24         char *in, *out;
           25         size_t inb;
           26         size_t l;
           27         size_t unitsize=0;
           28         int err=0;
           29         FILE *f;
           30 
           31         while ((b = getopt(argc, argv, "f:t:csl")) != EOF) switch(b) {
           32         case 'l':
           33                 puts("UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF32-LE, UCS-2BE, UCS-2LE, WCHAR_T,\n"
           34                         "US_ASCII, ISO8859-1, ISO8859-2, ISO8859-3, ISO8859-4, ISO8859-5,\n"
           35                         "ISO8859-6, ISO8859-7, ...");
           36                 exit(0);
           37         case 'c': case 's': break;
           38         case 'f': from=optarg; break;
           39         case 't': to=optarg; break;
           40         default: exit(1);
           41         }
           42 
           43         if (!from || !to) {
           44                 setlocale(LC_CTYPE, "");
           45                 if (!to) to = nl_langinfo(CODESET);
           46                 if (!from) from = nl_langinfo(CODESET);
           47         }
           48         cd = iconv_open(to, from);
           49         if (cd == (iconv_t)-1) {
           50                 if (iconv_open(to, "WCHAR_T") == (iconv_t)-1)
           51                         fprintf(stderr, "iconv: destination charset %s", to);
           52                 else
           53                         fprintf(stderr, "iconv: source charset %s", from);
           54                 perror("");
           55                 exit(1);
           56         }
           57         if (optind == argc) argv[argc++] = "-";
           58 
           59         for (; optind < argc; optind++) {
           60                 if (argv[optind][0]=='-' && !argv[optind][1]) {
           61                         f = stdin;
           62                         argv[optind] = "(stdin)";
           63                 } else if (!(f = fopen(argv[optind], "rb"))) {
           64                         fprintf(stderr, "iconv: %s", argv[optind]);
           65                         perror("");
           66                         err = 1;
           67                         continue;
           68                 }
           69                 inb = 0;
           70                 for (;;) {
           71                         in = buf;
           72                         out = outbuf;
           73                         l = fread(buf+inb, 1, sizeof(buf)-inb, f);
           74                         inb += l;
           75                         if (!inb) break;
           76                         if (iconv(cd, &in, &inb, &out, (size_t [1]){sizeof outbuf})==-1
           77                          && errno == EILSEQ) {
           78                                  if (!unitsize) {
           79                                          wchar_t wc='0';
           80                                          char dummy[4], *dummyp=dummy;
           81                                          iconv_t cd2 = iconv_open(from, "WCHAR_T");
           82                                          if (cd == (iconv_t)-1) {
           83                                                  unitsize = 1;
           84                                          } else {
           85                                                  iconv(cd2,
           86                                                          (char *[1]){(char *)&wc},
           87                                                          (size_t[1]){1},
           88                                                          &dummyp, (size_t[1]){4});
           89                                                  unitsize = dummyp-dummy;
           90                                                  if (!unitsize) unitsize=1;
           91                                          }
           92                                  }
           93                                  inb-=unitsize;
           94                                  in+=unitsize;
           95                         }
           96                         if (inb && !l && errno==EINVAL) break;
           97                         if (out>outbuf && !fwrite(outbuf, out-outbuf, 1, stdout)) {
           98                                 perror("iconv: write error");
           99                                 exit(1);
          100                         }
          101                         if (inb) memmove(buf, in, inb);
          102                 }
          103                 if (ferror(f)) {
          104                         fprintf(stderr, "iconv: %s", argv[optind]);
          105                         perror("");
          106                         err = 1;
          107                 }
          108         }
          109         return err;
          110 }