diff --git a/simple_recode.c b/simple_recode.c index 0ddbbaa..a2b057c 100644 --- a/simple_recode.c +++ b/simple_recode.c @@ -139,7 +139,7 @@ char *simple_recode(const iconv_t handle, const char *str) * Like fputs(3), but transparently recodes s using the global variable * simple_recode_input_charset as the input charset and the current locale * as the output charset. - * If simple_recode_input_charset is NULL it just calls fputs(3). + * Terminal control characters are replaced before output. * Exits with an error if iconv(3) or iconv_open(3) fail. * * Assumes that setlocale(3) has already been called. @@ -153,7 +153,7 @@ int recode_fputs(const char *s, FILE *stream) int result; if (simple_recode_input_charset == NULL) /* no conversion is needed */ - return fputs(s, stream); + return fputs_sanitized(s, stream); if (simple_recode_iconv_handle == NULL) { simple_recode_iconv_handle = iconv_open(nl_langinfo(CODESET), @@ -165,7 +165,7 @@ int recode_fputs(const char *s, FILE *stream) out = simple_recode(simple_recode_iconv_handle, s); if (!out) err_sys("iconv"); - result = fputs(out, stream); + result = fputs_sanitized(out, stream); free(out); return result; @@ -180,4 +180,3 @@ void simple_recode_iconv_close(void) simple_recode_iconv_handle = NULL; simple_recode_input_charset = NULL; } - diff --git a/utils.c b/utils.c index a018694..ac4af68 100644 --- a/utils.c +++ b/utils.c @@ -73,6 +73,22 @@ char **merge_args(char *args, char *argv[], int *argc) return newargs; } +/* Like fputs(3), but replace terminal control characters with '?'. */ +int fputs_sanitized(const char *s, FILE *stream) +{ + const unsigned char *p; + + for (p = (const unsigned char *) s; *p; p++) { + if ((*p < 0x20 && *p != '\t') || *p == 0x7f) { + if (fputc('?', stream) == EOF) + return EOF; + } else if (fputc(*p, stream) == EOF) + return EOF; + } + + return 0; +} + /* Error routines */ void NORETURN err_sys(const char *fmt, ...) { @@ -95,4 +111,3 @@ void NORETURN err_quit(const char *fmt, ...) va_end(ap); exit(2); } - diff --git a/utils.h b/utils.h index ee2880f..2f747f6 100644 --- a/utils.h +++ b/utils.h @@ -2,6 +2,8 @@ #ifndef WHOIS_UTILS_H #define WHOIS_UTILS_H +#include + /* Convenience macros */ #define streq(a, b) (strcmp(a, b) == 0) #define strcaseeq(a, b) (strcasecmp(a, b) == 0) @@ -68,6 +70,8 @@ void *MALLOC_FREE NONNULL do_nofail(void *ptr, const char *file, const int line) ; char **merge_args(char *args, char *argv[], int *argc); +int fputs_sanitized(const char *s, FILE *stream); + void NORETURN err_quit(const char *fmt, ...); void NORETURN err_sys(const char *fmt, ...); diff --git a/whois.c b/whois.c index d93500d..d143233 100644 --- a/whois.c +++ b/whois.c @@ -64,7 +64,7 @@ static void find_referral_server_verisign(char **, const char *); #ifdef HAVE_ICONV #include "simple_recode.h" #else -#define recode_fputs(a, b) fputs(a, b) +#define recode_fputs(a, b) fputs_sanitized(a, b) #endif /* hack */ @@ -430,7 +430,9 @@ int handle_query(const char *hserver, const char *hport, /* recursion is fun */ if (!no_recursion && new_server && !strchr(query, ' ')) { - printf(_("\n\nFound a referral to %s.\n\n"), new_server); + fputs(_("\n\nFound a referral to "), stdout); + fputs_sanitized(new_server, stdout); + fputs(_(".\n\n"), stdout); handle_query(new_server, NULL, query, flags); free(new_server); } @@ -968,6 +970,17 @@ static void find_referral_server_verisign(char **referral_server, const char *bu } } +static int has_terminal_control(const char *s) +{ + const unsigned char *p; + + for (p = (const unsigned char *) s; *p; p++) + if (*p < 0x20 || *p == 0x7f) + return 1; + + return 0; +} + /* returns a string which should be freed by the caller, or NULL */ char *query_server(const char *server, const char *port, const char *query) { @@ -1033,6 +1046,10 @@ char *query_server(const char *server, const char *port, const char *query) free(referral_server); referral_server = NULL; } + if (referral_server && has_terminal_control(referral_server)) { + free(referral_server); + referral_server = NULL; + } return referral_server; } @@ -1616,4 +1633,3 @@ void NORETURN usage(int error) )); exit(error); } -