iconv_t iconv_open(const char *out, const char *in) { int ret; struct _citrus_iconv *handle; ret = _citrus_iconv_open(&handle, _PATH_ICONV, in, out); if (ret) { errno = ret == ENOENT? EINVAL : ret; return ((iconv_t)-1); } return ((iconv_t)(void *)handle); }
iconv_t _iconv_open(const char *out, const char *in, struct _citrus_iconv *handle) { const char *out_slashes; char *out_noslashes; int ret; /* * Remove anything following a //, as these are options (like * //ignore, //translate, etc) and we just don't handle them. * This is for compatibility with software that uses these * blindly. */ out_slashes = strstr(out, "//"); if (out_slashes != NULL) { out_noslashes = strndup(out, out_slashes - out); if (out_noslashes == NULL) { errno = ENOMEM; return ((iconv_t)-1); } ret = _citrus_iconv_open(&handle, in, out_noslashes); free(out_noslashes); } else { ret = _citrus_iconv_open(&handle, in, out); } if (ret) { errno = ret == ENOENT ? EINVAL : ret; return ((iconv_t)-1); } handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE"); handle->cv_shared->ci_ilseq_invalid = false; handle->cv_shared->ci_hooks = NULL; return ((iconv_t)(void *)handle); }