apr_ssize_t iconv_bwrite(void *handle, const void *buf, apr_size_t insize) { #define stream ((iconv_stream *)handle) apr_ssize_t res = 0; apr_size_t left, size = insize; if (!buf) return iconv_write(handle, NULL, 0); if (stream->buffer && stream->buf_ptr > stream->buffer) { do { left = stream->buffer + buf_size - stream->buf_ptr; if (!left) { errno = E2BIG; return -1; } if (left > size) left = size; memcpy(stream->buf_ptr, buf, left); buf = ((const char *)buf) + left; size -= left; stream->buf_ptr += left; res = iconv_write(handle, stream->buffer, stream->buf_ptr - stream->buffer); if (res < 0) { if (errno != EINVAL) return -1; res = 0; } left = stream->buf_ptr - (stream->buffer + res); if (!res) break; if (left > 0) memmove(stream->buffer, stream->buffer + res, left); stream->buf_ptr -= res; } while (size && left); if (!size) return insize; } do { res = iconv_write(handle, buf, size); if (res <= 0) { if (errno != EINVAL) return -1; res = 0; } buf = ((const char *)buf) + res; size -= res; } while (size && res); if (!size) return insize; if (size > buf_size) return -1; if (!stream->buffer) { if (!(stream->buffer = malloc(buf_size))) return -1; } memcpy(stream->buffer, buf, size); stream->buf_ptr = stream->buffer + size; return insize; #undef stream }
int main(int argc, const char **argv) { apr_iconv_t cd; iconv_stream *is; const char *from = NULL, *to = NULL, *input = NULL; char opt; apr_pool_t *ctx; apr_status_t status; apr_getopt_t *options; const char *opt_arg; /* Initialize APR */ apr_initialize(); atexit(closeapr); if (apr_pool_create(&ctx, NULL) != APR_SUCCESS) { fprintf(stderr, "Couldn't allocate context.\n"); exit(-1); } apr_getopt_init(&options, ctx, argc, argv); status = apr_getopt(options, "f:s:t:v", &opt, &opt_arg); while (status == APR_SUCCESS) { switch (opt) { case 'f': from = opt_arg; break; case 't': to = opt_arg; break; case 's': input = opt_arg; break; case 'v': fprintf(stderr, "APR-iconv version " API_VERSION_STRING "\n"); exit(0); default: fprintf(stderr, "Usage: iconv -f <name> -t <name> [-s <input>]\n"); exit(3); } status = apr_getopt(options, "f:s:t:v",&opt, &opt_arg); } if (status == APR_BADCH || status == APR_BADARG) { fprintf(stderr, "Usage: iconv -f <name> -t <name> [-s <input>]\n"); exit(3); } if (from == NULL) { fprintf(stderr, "missing source charset (-f <name>)\n"); exit(4); } if (to == NULL) { fprintf(stderr, "missing destination charset (-t <name>)\n"); exit(5); } /* Use it */ status = apr_iconv_open(to, from, ctx, &cd); if (status) { fprintf(stderr, "unable to open specified converter\n"); exit(6); } if (!(is = iconv_ostream_fopen(cd, stdout))) { apr_iconv_close(cd,ctx); exit(7); } if (input) { if (iconv_bwrite(is, input, strlen(input)) <= 0) exit(8); } else if (optind < argc) { for (opt = optind; opt < argc; opt ++) convert_file(argv[opt], is); } else convert_file("-", is); if (iconv_write(is, NULL, 0) < 0) exit(9); iconv_stream_close(is); apr_iconv_close(cd,ctx); return 0; }