Index: head/usr.bin/iconv/iconv.c =================================================================== --- head/usr.bin/iconv/iconv.c +++ head/usr.bin/iconv/iconv.c @@ -28,7 +28,9 @@ */ #include +#include +#include #include #include #include @@ -41,7 +43,7 @@ #include #include -static int do_conv(FILE *, const char *, const char *, bool, bool); +static int do_conv(FILE *, iconv_t, bool, bool); static int do_list(unsigned int, const char * const *, void *); static void usage(void) __dead2; @@ -67,23 +69,16 @@ #define INBUFSIZE 1024 #define OUTBUFSIZE (INBUFSIZE * 2) static int -do_conv(FILE *fp, const char *from, const char *to, bool silent, - bool hide_invalid) +do_conv(FILE *fp, iconv_t cd, bool silent, bool hide_invalid) { - iconv_t cd; char inbuf[INBUFSIZE], outbuf[OUTBUFSIZE], *in, *out; unsigned long long invalids; size_t inbytes, outbytes, ret; - if ((cd = iconv_open(to, from)) == (iconv_t)-1) - err(EXIT_FAILURE, "iconv_open(%s, %s)", to, from); - - if (hide_invalid) { - int arg = 1; + int arg = (int)hide_invalid; + if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&arg) == -1) + err(EXIT_FAILURE, "iconvctl(DISCARD_ILSEQ, %d)", arg); - if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&arg) == -1) - err(EXIT_FAILURE, NULL); - } invalids = 0; while ((inbytes = fread(inbuf, 1, INBUFSIZE, fp)) > 0) { in = inbuf; @@ -133,7 +128,6 @@ if (invalids > 0 && !silent) warnx("warning: invalid characters: %llu", invalids); - iconv_close(cd); return (invalids > 0); } @@ -155,6 +149,7 @@ int main(int argc, char **argv) { + iconv_t cd; FILE *fp; const char *opt_f, *opt_t; int ch, i, res; @@ -201,9 +196,28 @@ argv += optind; if ((strcmp(opt_f, "") == 0) && (strcmp(opt_t, "") == 0)) usage(); - if (argc == 0) - res = do_conv(stdin, opt_f, opt_t, opt_s, opt_c); - else { + + if (caph_limit_stdio() < 0) + err(EXIT_FAILURE, "capsicum"); + + /* + * Cache NLS data, for strerror, for err(3), before entering capability + * mode. + */ + caph_cache_catpages(); + + /* + * Cache iconv conversion handle before entering sandbox. + */ + cd = iconv_open(opt_t, opt_f); + if (cd == (iconv_t)-1) + err(EXIT_FAILURE, "iconv_open(%s, %s)", opt_t, opt_f); + + if (argc == 0) { + if (cap_enter() < 0 && errno != ENOSYS) + err(EXIT_FAILURE, "unable to enter capability mode"); + res = do_conv(stdin, cd, opt_s, opt_c); + } else { res = 0; for (i = 0; i < argc; i++) { fp = (strcmp(argv[i], "-") != 0) ? @@ -211,9 +225,17 @@ if (fp == NULL) err(EXIT_FAILURE, "Cannot open `%s'", argv[i]); - res |= do_conv(fp, opt_f, opt_t, opt_s, opt_c); + /* Enter Capsicum sandbox for final input file. */ + if (i + 1 == argc && cap_enter() < 0 && errno != ENOSYS) + err(EXIT_FAILURE, + "unable to enter capability mode"); + res |= do_conv(fp, cd, opt_s, opt_c); (void)fclose(fp); + + /* Reset iconv descriptor state. */ + (void)iconv(cd, NULL, NULL, NULL, NULL); } } + iconv_close(cd); return (res == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }