summaryrefslogtreecommitdiff
path: root/net/echoping/files/extra-patch-idn2-echoping.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/echoping/files/extra-patch-idn2-echoping.c')
-rw-r--r--net/echoping/files/extra-patch-idn2-echoping.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/net/echoping/files/extra-patch-idn2-echoping.c b/net/echoping/files/extra-patch-idn2-echoping.c
new file mode 100644
index 000000000000..e5a3ed3e1ffa
--- /dev/null
+++ b/net/echoping/files/extra-patch-idn2-echoping.c
@@ -0,0 +1,219 @@
+--- echoping.c.orig 2025-05-05 00:28:45.988741000 +0700
++++ echoping.c 2025-05-05 01:44:14.970048000 +0700
+@@ -9,6 +9,12 @@
+ *
+ * */
+
++#include <iconv.h>
++#include <langinfo.h>
++#include <limits.h>
++#include <stdint.h>
++#include <strings.h>
++
+ char *progname;
+
+ #include "echoping.h"
+@@ -54,6 +60,188 @@ static terminate_f plugin_terminate;
+ struct timeval null_timeval;
+ static struct timeval max_timeval;
+
++#ifdef LIBIDN
++/* Basically stolen from libidn with small modifications */
++
++static char * _str_cd_iconv (const char *src, iconv_t cd);
++static char * _str_iconv (const char *src, const char *from_codeset, const char *to_codeset);
++
++static char *
++_str_cd_iconv (const char *src, iconv_t cd)
++{
++ char *result;
++ size_t result_size;
++ size_t length;
++ const char *inptr = src;
++ size_t inbytes_remaining = strlen (src);
++
++ /* Make a guess for the worst-case output size, in order to avoid a
++ realloc. It's OK if the guess is wrong as long as it is not zero and
++ doesn't lead to an integer overflow. */
++ result_size = inbytes_remaining;
++ {
++ size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2);
++ if (result_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX)
++ result_size *= MB_LEN_MAX;
++ }
++ result_size += 1; /* for the terminating NUL */
++
++ result = (char *) malloc (result_size);
++ if (result == NULL)
++ {
++ errno = ENOMEM;
++ return NULL;
++ }
++
++ /* Set to the initial state. */
++ iconv (cd, NULL, NULL, NULL, NULL);
++
++ /* Do the conversion. */
++ {
++ char *outptr = result;
++ size_t outbytes_remaining = result_size - 1;
++
++ for (;;)
++ {
++ /* Here inptr + inbytes_remaining = src + strlen (src),
++ outptr + outbytes_remaining = result + result_size - 1. */
++ size_t res = iconv (cd,
++ &inptr, &inbytes_remaining,
++ &outptr, &outbytes_remaining);
++
++ if (res == (size_t)(-1))
++ {
++ if (errno == EINVAL)
++ break;
++ else if (errno == E2BIG)
++ {
++ size_t used = outptr - result;
++ size_t newsize = result_size * 2;
++ char *newresult;
++
++ if (!(newsize > result_size))
++ {
++ errno = ENOMEM;
++ goto failed;
++ }
++ newresult = (char *) realloc (result, newsize);
++ if (newresult == NULL)
++ {
++ errno = ENOMEM;
++ goto failed;
++ }
++ result = newresult;
++ result_size = newsize;
++ outptr = result + used;
++ outbytes_remaining = result_size - 1 - used;
++ }
++ else
++ goto failed;
++ }
++ else
++ break;
++ }
++ for (;;)
++ {
++ /* Here outptr + outbytes_remaining = result + result_size - 1. */
++ size_t res = iconv (cd, NULL, NULL, &outptr, &outbytes_remaining);
++
++ if (res == (size_t)(-1))
++ {
++ if (errno == E2BIG)
++ {
++ size_t used = outptr - result;
++ size_t newsize = result_size * 2;
++ char *newresult;
++
++ if (!(newsize > result_size))
++ {
++ errno = ENOMEM;
++ goto failed;
++ }
++ newresult = (char *) realloc (result, newsize);
++ if (newresult == NULL)
++ {
++ errno = ENOMEM;
++ goto failed;
++ }
++ result = newresult;
++ result_size = newsize;
++ outptr = result + used;
++ outbytes_remaining = result_size - 1 - used;
++ }
++ else
++ goto failed;
++ }
++ else
++ break;
++ }
++
++ /* Add the terminating NUL byte. */
++ *outptr++ = '\0';
++
++ length = outptr - result;
++ }
++
++ /* Give away unused memory. */
++ if (length < result_size)
++ {
++ char *smaller_result = (char *) realloc (result, length);
++
++ if (smaller_result != NULL)
++ result = smaller_result;
++ }
++
++ return result;
++
++ failed:
++ free (result);
++ return NULL;
++}
++
++static char *
++_str_iconv (const char *src, const char *from_codeset, const char *to_codeset)
++{
++ if (*src == '\0' || strcasecmp (from_codeset, to_codeset) == 0)
++ {
++ char *result = strdup (src);
++
++ if (result == NULL)
++ errno = ENOMEM;
++ return result;
++ }
++ else
++ {
++ iconv_t cd;
++ char *result;
++
++ cd = iconv_open (to_codeset, from_codeset);
++ if (cd == (iconv_t) -1)
++ return NULL;
++
++ result = _str_cd_iconv (src, cd);
++
++ if (result == NULL)
++ {
++ /* Close cd, but preserve the errno from str_cd_iconv. */
++ int saved_errno = errno;
++ iconv_close (cd);
++ errno = saved_errno;
++ }
++ else
++ {
++ if (iconv_close (cd) < 0)
++ {
++ free (result);
++ return NULL;
++ }
++ }
++ return result;
++ }
++}
++
++#endif
++
+ int
+ main(argc, argv)
+ int argc;
+@@ -561,12 +749,12 @@ main(argc, argv)
+ server = leftover[0];
+ #ifdef LIBIDN
+ locale_server = server;
+- utf8_server = stringprep_locale_to_utf8(server);
++ utf8_server = _str_iconv(server, nl_langinfo(CODESET), "UTF-8");
+ if (utf8_server)
+ server = utf8_server;
+ else
+ err_quit("Cannot convert %s to UTF-8 encoding: wrong locale (%s)?",
+- server, stringprep_locale_charset());
++ server, nl_langinfo(CODESET));
+ #endif
+ if (!http && !icp) {
+ for (p = server; *p && (*p != ':'); p++) {