#include <stdio.h>
#include <errno.h>
#include <string.h> 
#include <iconv.h> 
#include <stdlib.h>

#define OUT_BUF_LEN 256
#define IN_BUF_LEN 1024 
/*
* For state-dependent encodings, changes the state of the
* conversion descriptor to initial shift state.  Also, outputs
* the byte sequence to change the state to initial state.
* This code is assuming the iconv call for initializing the
* state will not fail due to lack of space in the output buffer.
*/
#define INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft) \
	{ \
		fptr = NULL; \
		ileft = 0; \
		tptr = to; \
		oleft = OUT_BUF_LEN; \
		(void) iconv(cd, &fptr, &ileft, &tptr, &oleft); \
		(void) fwrite(to, 1, OUT_BUF_LEN - oleft, stdout); \
	}

int main(int argc, char **argv)
{
	iconv_t cd;
	char from[IN_BUF_LEN],to[OUT_BUF_LEN];
	char    *from_code, *to_code;
	char    *tptr;
	const char  *fptr;
	size_t  ileft, oleft, num, ret;

	if (argc != 3) {
		(void) fprintf(stderr,
			"Usage: %s from_codeset to_codeset\n", argv[0]);
		return (1);
	}

	from_code = argv[1];
	to_code = argv[2];

	cd = iconv_open((const char *)to_code, (const char *)from_code);
	if (cd == (iconv_t)-1) {
              /*
               * iconv_open failed
               */
		(void) fprintf(stderr,
			"iconv_open(%s, %s) failed\n", to_code, from_code);
		return (1);
	}

	ileft = 0;
	while ((ileft +=
              (num = fread(from + ileft, 1, IN_BUF_LEN - ileft, stdin))) > 0) {
              if (num == 0) {
                  /*
                   * Input buffer still contains incomplete character
                   * or sequence.  However, no more input character.
                   */

                  /*
                   * Initializes the conversion descriptor and outputs
                   * the sequence to change the state to initial state.
                   */
                  INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
                  (void) iconv_close(cd);

                  (void) fprintf(stderr, "Conversion error\n");
                  return (1);
              }
              fptr = from;
              for (;;) {
                  tptr = to;
                  oleft = OUT_BUF_LEN;

                  ret = iconv(cd, &fptr, &ileft, &tptr, &oleft);
                  printf( "\n\niconv ret is %d, errno is %d\n", ret, errno);
                  if (ret != (size_t)-1) {
                      /*
                       * iconv succeeded
                       */

                      /*
                       * Outputs converted characters
                       */
                      (void) fwrite(to, 1, 256 - oleft, stdout);
                      break;
                  }
					/*
                   * iconv failed
                   */
                  if (errno == EINVAL) {
                      /*
                     * Incomplete character or shift sequence
                       */

                      /*
                       * Outputs converted characters
                       */
                      (void) fwrite(to, 1, OUT_BUF_LEN - oleft, stdout);
                      /*
                       * Copies remaining characters in input buffer
                       * to the top of the input buffer.
                       */
                      (void) memmove(from, fptr, ileft);
                      /*
                       * Tries to fill input buffer from stdin
                       */
                      break;
                  } else if (errno == E2BIG) {

						/*
						* Lack of space in output buffer
                       */

                      /*
                       * Outputs converted characters
                       */
                      (void) fwrite(to, 1, OUT_BUF_LEN - oleft, stdout);
                      /*
                       * Tries to convert remaining characters in
                       * input buffer with emptied output buffer
                       */
                      continue;
                  } else if (errno == EILSEQ) {
                      /*
                       * Illegal character or shift sequence
                       */

                      /*
                       * Outputs converted characters
                       */
					(void) fwrite(to, 1, OUT_BUF_LEN - oleft, stdout);
                      /*
                       * Initializes the conversion descriptor and
                      * Initializes the conversion descriptor and
                       * outputs the sequence to change the state to
                       * initial state.
                       */
					INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
					(void) iconv_close(cd);

					(void) fprintf(stderr,
					 "Illegal character or sequence\\n");
					return (1);
				} else if (errno == EBADF) {
					/*
				 	 * Invalid conversion descriptor.
					 * Actually, this shouldn't happen here.
					 */
					(void) fprintf(stderr, "Conversion error\\n");
					return (1);
				} else {
				/*
				 * This errno is not defined
				 */
				(void) fprintf(stderr, "iconv error\\n");
				return (1);
			}
		}
	}

	/*
	 * Initializes the conversion descriptor and outputs
	 * the sequence to change the state to initial state.
	 */
	INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);

	(void) iconv_close(cd);
	return (0);
}

