mtr: Fix #305 by implementing hsearch(3) (#1697)
authorKarol Baraniecki <karol@karcom.pl>
Fri, 3 Nov 2017 22:44:43 +0000 (23:44 +0100)
committerFredrik Fornwall <fredrik@fornwall.net>
Fri, 3 Nov 2017 22:44:43 +0000 (23:44 +0100)
This hsearch(3) implementation is (with very minor changes) taken
from FreeBSD 11.1.

Also fix compilation errors due to calls to index(). This should
probably be fixed upstream.

disabled-packages/mtr/build.sh
disabled-packages/mtr/hsearch.patch [new file with mode: 0644]
disabled-packages/mtr/hsearch/README.md [new file with mode: 0644]
disabled-packages/mtr/hsearch/hcreate.c [new file with mode: 0644]
disabled-packages/mtr/hsearch/hcreate_r.c [new file with mode: 0644]
disabled-packages/mtr/hsearch/hdestroy_r.c [new file with mode: 0644]
disabled-packages/mtr/hsearch/hsearch.h [new file with mode: 0644]
disabled-packages/mtr/hsearch/hsearch_r.c [new file with mode: 0644]
disabled-packages/mtr/hsearch/search.h [new file with mode: 0644]
disabled-packages/mtr/index_to_strchr.patch [new file with mode: 0644]

index 241a0c0..22e4e5b 100644 (file)
@@ -1,6 +1,3 @@
-# Status: Needs a working resolv.h.
-#         Perhaps add libres?
-#         http://dan.drown.org/android/src/libres/
 TERMUX_PKG_HOMEPAGE=https://github.com/traviscross/mtr
 TERMUX_PKG_DESCRIPTION="Network diagnostic tool"
 TERMUX_PKG_VERSION=0.92
@@ -10,6 +7,8 @@ TERMUX_PKG_DEPENDS="ncurses"
 TERMUX_PKG_EXTRA_CONFIGURE_ARGS="--without-gtk --disable-ipv6"
 
 termux_step_pre_configure() {
+       cp $TERMUX_PKG_BUILDER_DIR/hsearch/* $TERMUX_PKG_SRCDIR/portability
+
        cd $TERMUX_PKG_SRCDIR
        ./bootstrap.sh
 }
diff --git a/disabled-packages/mtr/hsearch.patch b/disabled-packages/mtr/hsearch.patch
new file mode 100644 (file)
index 0000000..529eb38
--- /dev/null
@@ -0,0 +1,27 @@
+--- mtr/ui/asn.c        2017-06-02 08:54:58.000000000 +0000
++++ ./ui/asn.c          2017-10-21 22:21:43.076825733 +0000
+@@ -41,7 +41,7 @@
+ #include <resolv.h>
+ #include <string.h>
+ #include <sys/socket.h>
+-#include <search.h>
++#include "portability/search.h"
+ #include "mtr.h"
+ #include "asn.h"
+--- mtr/Makefile.am     2017-06-02 08:54:58.000000000 +0000
++++ ./Makefile.am       2017-10-21 22:39:26.628914946 +0000
+@@ -59,6 +59,12 @@
+               img/mtr_icon.xpm \
+               ui/mtr-gtk.h
++mtr_SOURCES += \
++      portability/hcreate.c \
++      portability/hcreate_r.c \
++      portability/hsearch_r.c \
++      portability/hdestroy_r.c
++
+ if WITH_ERROR
+ mtr_SOURCES += \
+       portability/error.h \
+
diff --git a/disabled-packages/mtr/hsearch/README.md b/disabled-packages/mtr/hsearch/README.md
new file mode 100644 (file)
index 0000000..3fe4c2d
--- /dev/null
@@ -0,0 +1 @@
+This hsearch(3) implementation is mostly based on the one present in FreeBSD 11.1.
diff --git a/disabled-packages/mtr/hsearch/hcreate.c b/disabled-packages/mtr/hsearch/hcreate.c
new file mode 100644 (file)
index 0000000..2d1d00c
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include "search.h"
+#include <stdbool.h>
+#include <stddef.h>
+
+/*
+ * Thread unsafe interface: use a single process-wide hash table and
+ * forward calls to *_r() functions.
+ */
+
+static struct hsearch_data global_hashtable;
+static bool global_hashtable_initialized = false;
+
+int
+hcreate(size_t nel)
+{
+
+       return (1);
+}
+
+void
+hdestroy(void)
+{
+
+       /* Destroy global hash table if present. */
+       if (global_hashtable_initialized) {
+               hdestroy_r(&global_hashtable);
+               global_hashtable_initialized = false;
+       }
+}
+
+ENTRY *
+hsearch(ENTRY item, ACTION action)
+{
+       ENTRY *retval;
+
+       /* Create global hash table if needed. */
+       if (!global_hashtable_initialized) {
+               if (hcreate_r(0, &global_hashtable) == 0)
+                       return (NULL);
+               global_hashtable_initialized = true;
+       }
+       if (hsearch_r(item, action, &retval, &global_hashtable) == 0)
+               return (NULL);
+       return (retval);
+}
diff --git a/disabled-packages/mtr/hsearch/hcreate_r.c b/disabled-packages/mtr/hsearch/hcreate_r.c
new file mode 100644 (file)
index 0000000..4b77cb1
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD$");
+
+#include "search.h"
+#include <stdlib.h>
+
+#include "hsearch.h"
+
+int
+hcreate_r(size_t nel, struct hsearch_data *htab)
+{
+       struct __hsearch *hsearch;
+
+       /*
+        * Allocate a hash table object. Ignore the provided hint and start
+        * off with a table of sixteen entries. In most cases this hint is
+        * just a wild guess. Resizing the table dynamically if the use
+        * increases a threshold does not affect the worst-case running time.
+        */
+       hsearch = malloc(sizeof(*hsearch));
+       if (hsearch == NULL)
+               return 0;
+       hsearch->entries = calloc(16, sizeof(ENTRY));
+       if (hsearch->entries == NULL) {
+               free(hsearch);
+               return 0;
+       }
+
+       /*
+        * Pick a random initialization for the FNV-1a hashing. This makes it
+        * hard to come up with a fixed set of keys to force hash collisions.
+        */
+       arc4random_buf(&hsearch->offset_basis, sizeof(hsearch->offset_basis));
+       hsearch->index_mask = 0xf;
+       hsearch->entries_used = 0;
+       htab->__hsearch = hsearch;
+       return 1;
+}
diff --git a/disabled-packages/mtr/hsearch/hdestroy_r.c b/disabled-packages/mtr/hsearch/hdestroy_r.c
new file mode 100644 (file)
index 0000000..dcb29a5
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD$");
+
+#include "search.h"
+#include <stdlib.h>
+
+#include "hsearch.h"
+
+void
+hdestroy_r(struct hsearch_data *htab)
+{
+       struct __hsearch *hsearch;
+
+       /* Free hash table object and its entries. */
+       hsearch = htab->__hsearch;
+       free(hsearch->entries);
+       free(hsearch);
+}
diff --git a/disabled-packages/mtr/hsearch/hsearch.h b/disabled-packages/mtr/hsearch/hsearch.h
new file mode 100644 (file)
index 0000000..9fdc2b0
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef HSEARCH_H
+#define HSEARCH_H
+
+#include "search.h"
+
+struct __hsearch {
+       size_t offset_basis;    /* Initial value for FNV-1a hashing. */
+       size_t index_mask;      /* Bitmask for indexing the table. */
+       size_t entries_used;    /* Number of entries currently used. */
+       ENTRY *entries;         /* Hash table entries. */
+};
+
+#endif
diff --git a/disabled-packages/mtr/hsearch/hsearch_r.c b/disabled-packages/mtr/hsearch/hsearch_r.c
new file mode 100644 (file)
index 0000000..7e4aebd
--- /dev/null
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include "search.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hsearch.h"
+
+/*
+ * Look up an unused entry in the hash table for a given hash. For this
+ * implementation we use quadratic probing. Quadratic probing has the
+ * advantage of preventing primary clustering.
+ */
+static ENTRY *
+hsearch_lookup_free(struct __hsearch *hsearch, size_t hash)
+{
+       size_t index, i;
+
+       for (index = hash, i = 0;; index += ++i) {
+               ENTRY *entry = &hsearch->entries[index & hsearch->index_mask];
+               if (entry->key == NULL)
+                       return (entry);
+       }
+}
+
+/*
+ * Computes an FNV-1a hash of the key. Depending on the pointer size, this
+ * either uses the 32- or 64-bit FNV prime.
+ */
+static size_t
+hsearch_hash(size_t offset_basis, const char *str)
+{
+       size_t hash;
+
+       hash = offset_basis;
+       while (*str != '\0') {
+               hash ^= (uint8_t)*str++;
+               if (sizeof(size_t) * CHAR_BIT <= 32)
+                       hash *= UINT32_C(16777619);
+               else
+                       hash *= UINT64_C(1099511628211);
+       }
+       return (hash);
+}
+
+int
+hsearch_r(ENTRY item, ACTION action, ENTRY **retval, struct hsearch_data *htab)
+{
+       struct __hsearch *hsearch;
+       ENTRY *entry, *old_entries, *new_entries;
+       size_t hash, index, i, old_hash, old_count, new_count;
+
+       hsearch = htab->__hsearch;
+       hash = hsearch_hash(hsearch->offset_basis, item.key);
+
+       /*
+        * Search the hash table for an existing entry for this key.
+        * Stop searching if we run into an unused hash table entry.
+        */
+       for (index = hash, i = 0;; index += ++i) {
+               entry = &hsearch->entries[index & hsearch->index_mask];
+               if (entry->key == NULL)
+                       break;
+               if (strcmp(entry->key, item.key) == 0) {
+                       *retval = entry;
+                       return (1);
+               }
+       }
+
+       /* Only perform the insertion if action is set to ENTER. */
+       if (action == FIND) {
+               errno = ESRCH;
+               return (0);
+       }
+
+       if (hsearch->entries_used * 2 >= hsearch->index_mask) {
+               /* Preserve the old hash table entries. */
+               old_count = hsearch->index_mask + 1;
+               old_entries = hsearch->entries;
+
+               /*
+                * Allocate and install a new table if insertion would
+                * yield a hash table that is more than 50% used. By
+                * using 50% as a threshold, a lookup will only take up
+                * to two steps on average.
+                */
+               new_count = (hsearch->index_mask + 1) * 2;
+               new_entries = calloc(new_count, sizeof(ENTRY));
+               if (new_entries == NULL)
+                       return (0);
+               hsearch->entries = new_entries;
+               hsearch->index_mask = new_count - 1;
+
+               /* Copy over the entries from the old table to the new table. */
+               for (i = 0; i < old_count; ++i) {
+                       entry = &old_entries[i];
+                       if (entry->key != NULL) {
+                               old_hash = hsearch_hash(hsearch->offset_basis,
+                                   entry->key);
+                               *hsearch_lookup_free(hsearch, old_hash) =
+                                   *entry;
+                       }
+               }
+
+               /* Destroy the old hash table entries. */
+               free(old_entries);
+
+               /*
+                * Perform a new lookup for a free table entry, so that
+                * we insert the entry into the new hash table.
+                */
+               hsearch = htab->__hsearch;
+               entry = hsearch_lookup_free(hsearch, hash);
+       }
+
+       /* Insert the new entry into the hash table. */
+       *entry = item;
+       ++hsearch->entries_used;
+       *retval = entry;
+       return (1);
+}
diff --git a/disabled-packages/mtr/hsearch/search.h b/disabled-packages/mtr/hsearch/search.h
new file mode 100644 (file)
index 0000000..b191905
--- /dev/null
@@ -0,0 +1,86 @@
+/*-
+ * Written by J.T. Conklin <jtc@NetBSD.org>
+ * Public domain.
+ *
+ *     $NetBSD: search.h,v 1.16 2005/02/03 04:39:32 perry Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _SEARCH_H_
+#define _SEARCH_H_
+
+#include <stddef.h>
+//#include <sys/cdefs.h>
+//#include <sys/types.h>
+
+#ifndef _SIZE_T_DECLARED
+//typedef      __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+typedef        struct entry {
+       char    *key;
+       void    *data;
+} ENTRY;
+
+typedef        enum {
+       FIND, ENTER
+} ACTION;
+
+typedef        enum {
+       preorder,
+       postorder,
+       endorder,
+       leaf
+} VISIT;
+
+#ifdef _SEARCH_PRIVATE
+typedef struct __posix_tnode {
+       void                    *key;
+       struct __posix_tnode    *llink, *rlink;
+       signed char              balance;
+} posix_tnode;
+
+struct que_elem {
+       struct que_elem *next;
+       struct que_elem *prev;
+};
+#else
+typedef void posix_tnode;
+#endif
+
+//#if __BSD_VISIBLE
+struct hsearch_data {
+       struct __hsearch *__hsearch;
+};
+//#endif
+
+__BEGIN_DECLS
+int     hcreate(size_t);
+void    hdestroy(void);
+ENTRY  *hsearch(ENTRY, ACTION);
+void    insque(void *, void *);
+void   *lfind(const void *, const void *, size_t *, size_t,
+           int (*)(const void *, const void *));
+void   *lsearch(const void *, void *, size_t *, size_t,
+           int (*)(const void *, const void *));
+void    remque(void *);
+void   *tdelete(const void * __restrict, posix_tnode ** __restrict,
+           int (*)(const void *, const void *));
+posix_tnode *
+        tfind(const void *, posix_tnode * const *,
+           int (*)(const void *, const void *));
+posix_tnode *
+        tsearch(const void *, posix_tnode **,
+           int (*)(const void *, const void *));
+void    twalk(const posix_tnode *, void (*)(const posix_tnode *, VISIT, int));
+
+//#if __BSD_VISIBLE
+int     hcreate_r(size_t, struct hsearch_data *);
+void    hdestroy_r(struct hsearch_data *);
+int     hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *);
+//#endif
+
+__END_DECLS
+
+#endif /* !_SEARCH_H_ */
diff --git a/disabled-packages/mtr/index_to_strchr.patch b/disabled-packages/mtr/index_to_strchr.patch
new file mode 100644 (file)
index 0000000..a9be89a
--- /dev/null
@@ -0,0 +1,35 @@
+--- mtr/ui/curses.c       2017-06-02 08:54:58.000000000 +0000
++++ ./ui/curses.c         2017-10-21 22:47:23.221332133 +0000
+@@ -383,7 +383,7 @@
+     const char *format,
+     int n)
+ {
+-    if (index(format, 'N')) {
++    if (strchr(format, 'N')) {
+         *dst++ = ' ';
+         format_number(n, 5, dst);
+     } else if (strchr(format, 'f')) {
+
+--- mtr/ui/cmdpipe.c      2017-10-21 22:50:49.843505234 +0000
++++ ./ui/cmdpipe.c        2017-10-21 22:51:08.507344155 +0000
+@@ -736,7 +736,7 @@
+      */
+     while (true) {
+         /*  If no newline is found, our reply isn't yet complete  */
+-        end_of_reply = index(reply_start, '\n');
++        end_of_reply = strchr(reply_start, '\n');
+         if (end_of_reply == NULL) {
+             /*  No complete replies remaining  */
+             break;
+--- mtr/packet/command.c     2017-06-02 08:54:58.000000000 +0000
++++ ./packet/command.c       2017-10-21 22:55:13.321277161 +0000
+@@ -380,7 +380,7 @@
+         buffer->incoming_buffer[buffer->incoming_read_position] = 0;
+         /*  Find the next newline, which terminates command requests  */
+-        end_of_command = index(buffer->incoming_buffer, '\n');
++        end_of_command = strchr(buffer->incoming_buffer, '\n');
+         if (end_of_command == NULL) {
+             /*
+                No newlines found, so any data we've read so far is
+