From 5c4b11a81a6defd12a01f2123e4fcb783d28c2fe Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Thu, 10 Apr 2014 16:03:33 +0000
Subject: initial Haiku patch


diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
index 0258d3d..aaec6e6 100644
--- a/Lib/distutils/command/install.py
+++ b/Lib/distutils/command/install.py
@@ -43,6 +43,27 @@ INSTALL_SCHEMES = {
         'data'   : '$base',
         },
     'nt': WINDOWS_SCHEME,
+    'haiku': {
+        'purelib': '$base/non-packaged/lib/python$py_version_short/site-packages',
+        'platlib': '$platbase/non-packaged/lib/python$py_version_short/site-packages',
+        'headers': '$base/non-packaged/develop/headers/python$py_version_short/$dist_name',
+        'scripts': '$base/non-packaged/bin',
+        'data'   : '$base/non-packaged',
+        },
+    'haiku_vendor': {
+        'purelib': '$base/lib/python$py_version_short/vendor-packages',
+        'platlib': '$platbase/lib/python$py_version_short/vendor-packages',
+        'headers': '$base/develop/headers/python$py_version_short/$dist_name',
+        'scripts': '$base/bin',
+        'data'   : '$base',
+        },
+    'haiku_home': {
+        'purelib': '$base/lib/python',
+        'platlib': '$base/lib/python',
+        'headers': '$base/develop/headers/python/$dist_name',
+        'scripts': '$base/bin',
+        'data'   : '$base',
+        },
     }
 
 # user site schemes
@@ -64,6 +85,14 @@ if HAS_USER_SITE:
         'data'   : '$userbase',
         }
 
+    INSTALL_SCHEMES['haiku_user'] = {
+        'purelib': '$usersite',
+        'platlib': '$usersite',
+        'headers': '$userbase/develop/headers/python$py_version_short/$dist_name',
+        'scripts': '$userbase/bin',
+        'data'   : '$userbase',
+        }
+
 # The keys to an installation scheme; if any new types of files are to be
 # installed, be sure to add an entry to every installation scheme above,
 # and to SCHEME_KEYS here.
@@ -408,10 +437,16 @@ class install(Command):
                 raise DistutilsPlatformError(
                     "User base directory is not specified")
             self.install_base = self.install_platbase = self.install_userbase
-            self.select_scheme("unix_user")
+            if sys.platform.startswith('haiku'):
+                self.select_scheme("haiku_user")
+            else:
+                self.select_scheme("unix_user")
         elif self.home is not None:
             self.install_base = self.install_platbase = self.home
-            self.select_scheme("unix_home")
+            if sys.platform.startswith('haiku'):
+                self.select_scheme("haiku_home")
+            else:
+                self.select_scheme("unix_home")
         else:
             if self.prefix is None:
                 if self.exec_prefix is not None:
@@ -427,7 +462,13 @@ class install(Command):
 
             self.install_base = self.prefix
             self.install_platbase = self.exec_prefix
-            self.select_scheme("unix_prefix")
+            if sys.platform.startswith('haiku'):
+                if os.environ.get('HAIKU_USE_VENDOR_DIRECTORIES') == '1':
+                    self.select_scheme("haiku_vendor")
+                else:
+                    self.select_scheme("haiku")
+            else:
+                self.select_scheme("unix_prefix")
 
     def finalize_other(self):
         """Finalizes options for non-posix platforms"""
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 0a034ee..db37eeb 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -112,7 +112,8 @@ def get_python_inc(plat_specific=0, prefix=None):
                 incdir = os.path.join(get_config_var('srcdir'), 'Include')
                 return os.path.normpath(incdir)
         python_dir = 'python' + get_python_version() + build_flags
-        return os.path.join(prefix, "include", python_dir)
+        inc_dir = "include" if sys.platform != "haiku1" else "develop/headers"
+        return os.path.join(prefix, inc_dir, python_dir)
     elif os.name == "nt":
         if python_build:
             # Include both the include and PC dir to ensure we can find
@@ -147,12 +148,20 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
             prefix = plat_specific and EXEC_PREFIX or PREFIX
 
     if os.name == "posix":
-        libpython = os.path.join(prefix,
-                                 "lib", "python" + get_python_version())
-        if standard_lib:
-            return libpython
+        if sys.platform.startswith('haiku'):
+            if standard_lib:
+                return os.path.join(prefix,
+                                    "lib", "python" + get_python_version())
+            return os.path.join(prefix, "non-packaged",
+                                "lib", "python" + get_python_version(),
+                                "site-packages")
         else:
-            return os.path.join(libpython, "site-packages")
+	        libpython = os.path.join(prefix,
+	                                 "lib", "python" + get_python_version())
+	        if standard_lib:
+	            return libpython
+	        else:
+	            return os.path.join(libpython, "site-packages")
     elif os.name == "nt":
         if standard_lib:
             return os.path.join(prefix, "Lib")
diff --git a/Lib/plat-haiku1/regen b/Lib/plat-haiku1/regen
new file mode 100644
index 0000000..4372ee2
--- /dev/null
+++ b/Lib/plat-haiku1/regen
@@ -0,0 +1,4 @@
+#! /bin/sh
+HEADERS=/boot/develop/headers
+set -v
+eval $PYTHON_FOR_BUILD ../../Tools/scripts/h2py.py -i "'(u_long)'" $HEADERS/posix/netinet/in.h
diff --git a/Lib/site.py b/Lib/site.py
index 8786588..ffd717f 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -258,6 +258,14 @@ def _getuserbase():
         return joinuser("~", "Library", sys._framework,
                         "%d.%d" % sys.version_info[:2])
 
+    if sys.platform.startswith('haiku'):
+        try:
+            import subprocess
+            return subprocess.run(['finddir', 'B_USER_NONPACKAGED_DIRECTORY'],
+                stdout=subprocess.PIPE, check=True).stdout.rstrip().decode('utf-8')
+        except:
+            pass
+
     return joinuser("~", ".local")
 
 
@@ -333,7 +341,14 @@ def getsitepackages(prefixes=None):
             continue
         seen.add(prefix)
 
-        if os.sep == '/':
+        if sys.platform.startswith('haiku'):
+           sitepackages.append(os.path.join(prefix, "non-packaged", "lib",
+                                       "python" + sys.version[:3],
+                                       "site-packages"))
+           sitepackages.append(os.path.join(prefix, "lib",
+                                       "python" + sys.version[:3],
+                                       "vendor-packages"))
+        elif os.sep == '/':
             sitepackages.append(os.path.join(prefix, "lib",
                                         "python%d.%d" % sys.version_info[:2],
                                         "site-packages"))
@@ -433,8 +448,16 @@ def enablerlcompleter():
             # each interpreter exit when readline was already configured
             # through a PYTHONSTARTUP hook, see:
             # http://bugs.python.org/issue5845#msg198636
-            history = os.path.join(os.path.expanduser('~'),
-                                   '.python_history')
+            import subprocess
+            try:
+                history = os.path.join(subprocess.run(['finddir', 'B_USER_VAR_DIRECTORY'],
+                            check=True, stdout=subprocess.PIPE).stdout.rstrip().decode('utf-8'),
+                            'python', 'history')
+                if not os.path.exists(os.path.dirname(history)):
+                    os.makedirs(os.path.dirname(history))
+            except subprocess.CalledProcessError:
+                history = os.path.join(os.path.expanduser('~'),
+                                       '.python_history')
             try:
                 readline.read_history_file(history)
             except OSError:
diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py
index 57a0265..ea316a7 100644
--- a/Lib/test/test_fileio.py
+++ b/Lib/test/test_fileio.py
@@ -384,6 +384,7 @@ class OtherFileTests:
                     self.assertEqual(f.writable(), True)
                     if sys.platform != "darwin" and \
                        'bsd' not in sys.platform and \
+                       'haiku' not in sys.platform and \
                        not sys.platform.startswith(('sunos', 'aix')):
                         # Somehow /dev/tty appears seekable on some BSDs
                         self.assertEqual(f.seekable(), False)
diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
index 1cd9e56..893cf1f 100644
--- a/Lib/test/test_posix.py
+++ b/Lib/test/test_posix.py
@@ -1174,7 +1174,7 @@ class PosixTester(unittest.TestCase):
             posix.close(f)
             support.rmtree(support.TESTFN + 'dir')
 
-    @unittest.skipUnless((os.mknod in os.supports_dir_fd) and hasattr(stat, 'S_IFIFO'),
+    @unittest.skipUnless(hasattr(os, 'mknod') and (os.mknod in os.supports_dir_fd) and hasattr(stat, 'S_IFIFO'),
                          "test requires both stat.S_IFIFO and dir_fd support for os.mknod()")
     def test_mknod_dir_fd(self):
         # Test using mknodat() to create a FIFO (the only use specified
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 35ca1a8..d316694 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -143,7 +143,7 @@ BINDIR=		@bindir@
 LIBDIR=		@libdir@
 MANDIR=		@mandir@
 INCLUDEDIR=	@includedir@
-CONFINCLUDEDIR=	$(exec_prefix)/include
+CONFINCLUDEDIR=	$(INCLUDEDIR)
 SCRIPTDIR=	$(prefix)/lib
 ABIFLAGS=	@ABIFLAGS@
 
diff --git a/Modules/resource.c b/Modules/resource.c
index e59280f..f1aaef9 100644
--- a/Modules/resource.c
+++ b/Modules/resource.c
@@ -102,6 +102,7 @@ resource_getrusage_impl(PyObject *module, int who)
                     PyFloat_FromDouble(doubletime(ru.ru_utime)));
     PyStructSequence_SET_ITEM(result, 1,
                     PyFloat_FromDouble(doubletime(ru.ru_stime)));
+#ifndef __HAIKU__
     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
@@ -116,7 +117,22 @@ resource_getrusage_impl(PyObject *module, int who)
     PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
     PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
     PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
-
+#else
+    PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(0));
+#endif
     if (PyErr_Occurred()) {
         Py_DECREF(result);
         return NULL;
@@ -369,19 +385,19 @@ PyInit_resource(void)
                        (PyObject*) &StructRUsageType);
 
     /* insert constants */
-#ifdef RLIMIT_CPU
+#if !defined(__HAIKU__) && defined(RLIMIT_CPU)
     PyModule_AddIntMacro(m, RLIMIT_CPU);
 #endif
 
-#ifdef RLIMIT_FSIZE
+#if !defined(__HAIKU__) && defined(RLIMIT_FSIZE)
     PyModule_AddIntMacro(m, RLIMIT_FSIZE);
 #endif
 
-#ifdef RLIMIT_DATA
+#if !defined(__HAIKU__) && defined(RLIMIT_DATA)
     PyModule_AddIntMacro(m, RLIMIT_DATA);
 #endif
 
-#ifdef RLIMIT_STACK
+#if !defined(__HAIKU__) && defined(RLIMIT_STACK)
     PyModule_AddIntMacro(m, RLIMIT_STACK);
 #endif
 
@@ -393,31 +409,31 @@ PyInit_resource(void)
     PyModule_AddIntMacro(m, RLIMIT_NOFILE);
 #endif
 
-#ifdef RLIMIT_OFILE
+#if !defined(__HAIKU__) && defined(RLIMIT_OFILE)
     PyModule_AddIntMacro(m, RLIMIT_OFILE);
 #endif
 
-#ifdef RLIMIT_VMEM
+#if !defined(__HAIKU__) && defined(RLIMIT_VMEM)
     PyModule_AddIntMacro(m, RLIMIT_VMEM);
 #endif
 
-#ifdef RLIMIT_AS
+#if !defined(__HAIKU__) && defined(RLIMIT_AS)
     PyModule_AddIntMacro(m, RLIMIT_AS);
 #endif
 
-#ifdef RLIMIT_RSS
+#if !defined(__HAIKU__) && defined(RLIMIT_RSS)
     PyModule_AddIntMacro(m, RLIMIT_RSS);
 #endif
 
-#ifdef RLIMIT_NPROC
+#if !defined(__HAIKU__) && defined(RLIMIT_NPROC)
     PyModule_AddIntMacro(m, RLIMIT_NPROC);
 #endif
 
-#ifdef RLIMIT_MEMLOCK
+#if !defined(__HAIKU__) && defined(RLIMIT_MEMLOCK)
     PyModule_AddIntMacro(m, RLIMIT_MEMLOCK);
 #endif
 
-#ifdef RLIMIT_SBSIZE
+#if !defined(__HAIKU__) && defined(RLIMIT_SBSIZE)
     PyModule_AddIntMacro(m, RLIMIT_SBSIZE);
 #endif
 
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index a9ef7e2..3173b3b 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -7153,7 +7153,9 @@ PyInit__socket(void)
     /* SOCK_RAW is marked as optional in the POSIX specification */
     PyModule_AddIntMacro(m, SOCK_RAW);
 #endif
+#ifndef __HAIKU__
     PyModule_AddIntMacro(m, SOCK_SEQPACKET);
+#endif
 #if defined(SOCK_RDM)
     PyModule_AddIntMacro(m, SOCK_RDM);
 #endif
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 0b2edc1..1ee4fdd 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -54,6 +54,10 @@ typedef int socklen_t;
 #  undef AF_NETLINK
 #endif
 
+#if defined(__HAIKU__)
+#undef HAVE_BLUETOOTH_BLUETOOTH_H
+#endif
+
 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/rfcomm.h>
diff --git a/Modules/spwdmodule.c b/Modules/spwdmodule.c
index 1601ec0..4c98fe8 100644
--- a/Modules/spwdmodule.c
+++ b/Modules/spwdmodule.c
@@ -9,6 +9,7 @@
 #ifdef HAVE_SHADOW_H
 #include <shadow.h>
 #endif
+#include <errno.h>
 
 #include "clinic/spwdmodule.c.h"
 
@@ -138,7 +139,12 @@ spwd_getspnam_impl(PyObject *module, PyObject *arg)
     if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
         goto out;
     if ((p = getspnam(name)) == NULL) {
+// Haiku sets ENOENT if invalid user is specified. Ignore it to make KeyError is set.
+#ifdef __HAIKU__
+        if (errno != 0 && errno != ENOENT)
+#else
         if (errno != 0)
+#endif
             PyErr_SetFromErrno(PyExc_OSError);
         else
             PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 12def95..6521bd6 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -17,7 +17,7 @@
    Don't forget to modify PyUnicode_DecodeFSDefault() if you touch any of the
    values for Py_FileSystemDefaultEncoding!
 */
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__HAIKU__)
 const char *Py_FileSystemDefaultEncoding = "utf-8";
 int Py_HasFileSystemDefaultEncoding = 1;
 #elif defined(MS_WINDOWS)
diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py
index 4363c0c..40994b0 100755
--- a/Tools/scripts/h2py.py
+++ b/Tools/scripts/h2py.py
@@ -49,12 +49,15 @@ except KeyError:
     try:
         searchdirs=os.environ['INCLUDE'].split(';')
     except KeyError:
-        searchdirs=['/usr/include']
-        try:
-            searchdirs.insert(0, os.path.join('/usr/include',
+        if sys.platform.find("beos") == 0 or sys.platform.find("haiku1") == 0:
+            searchdirs=os.environ['BEINCLUDES'].split(';')
+        else:
+            searchdirs=['/usr/include']
+            try:
+                searchdirs.insert(0, os.path.join('/usr/include',
                                               os.environ['MULTIARCH']))
-        except KeyError:
-            pass
+            except KeyError:
+                pass
 
 def main():
     global filedict
diff --git a/configure.ac b/configure.ac
index f1cc8e9..b0cca04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1151,6 +1151,16 @@ if test $enable_shared = "yes"; then
 	      PY3LIBRARY=libpython3.so
 	  fi
 	  ;;
+    Haiku*)
+	  LDLIBRARY='libpython$(LDVERSION).so'
+	  BLDLIBRARY='-L. -lpython$(LDVERSION)'
+	  RUNSHARED=LIBRARY_PATH=`pwd`${LIBRARY_PATH:+:${LIBRARY_PATH}}
+	  INSTSONAME="$LDLIBRARY".$SOVERSION
+	  if test "$with_pydebug" != yes
+          then
+	      PY3LIBRARY=libpython3.so
+	  fi
+	  ;;
     hp*|HP*)
 	  case `uname -m` in
 		ia64)
@@ -1226,6 +1236,7 @@ AC_PROG_MKDIR_P
 AC_SUBST(LN)
 if test -z "$LN" ; then
 	case $ac_sys_system in
+		Haiku*) LN="ln -s";;
 		CYGWIN*) LN="ln -s";;
 		*) LN=ln;;
 	esac
@@ -2614,7 +2625,7 @@ then
 			BLDSHARED="$LDSHARED"
 		fi
 		;;
-	Linux*|GNU*|QNX*)
+	Linux*|GNU*|QNX*|Haiku*)
 		LDSHARED='$(CC) -shared'
 		LDCXXSHARED='$(CXX) -shared';;
 	FreeBSD*)
@@ -2681,7 +2692,7 @@ then
 		 else CCSHARED="+z";
 		 fi;;
 	Linux-android*) ;;
-	Linux*|GNU*) CCSHARED="-fPIC";;
+	Linux*|GNU*|Haiku*) CCSHARED="-fPIC";;
 	FreeBSD*|NetBSD*|OpenBSD*|DragonFly*) CCSHARED="-fPIC";;
 	OpenUNIX*|UnixWare*)
 		if test "$GCC" = "yes"
@@ -2707,7 +2718,7 @@ then
 	    LINKFORSHARED="-Wl,-E -Wl,+s";;
 #	    LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
 	Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
-	Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
+	Linux*|GNU*|Haiku*) LINKFORSHARED="-Xlinker -export-dynamic";;
 	# -u libsys_s pulls in all symbols in libsys
 	Darwin/*)
 		LINKFORSHARED="$extra_undefs -framework CoreFoundation"
@@ -2952,6 +2963,12 @@ LDFLAGS="-fsanitize=undefined $LDFLAGS"
 AC_CHECK_LIB(nsl, t_open, [LIBS="-lnsl $LIBS"]) # SVR4
 AC_CHECK_LIB(socket, socket, [LIBS="-lsocket $LIBS"], [], $LIBS) # SVR4 sockets
 
+# Haiku's sockets are stashed in libnetwork.
+case "$ac_sys_system" in
+	Haiku*)
+		AC_CHECK_LIB(network, socket, [LIBS="-lnetwork $LIBS"], [], $LIBS);;
+esac
+
 AC_MSG_CHECKING(for --with-libs)
 AC_ARG_WITH(libs,
             AS_HELP_STRING([--with-libs='lib1 ...'], [link against additional libs]),
@@ -4314,6 +4331,7 @@ AC_CHECK_FUNC(__fpu_control,
 AC_SUBST(LIBM)
 case $ac_sys_system in
 Darwin) ;;
+Haiku) ;;
 *) LIBM=-lm
 esac
 AC_MSG_CHECKING(for --with-libm=STRING)
diff --git a/setup.py b/setup.py
index bf90600..397acca 100644
--- a/setup.py
+++ b/setup.py
@@ -664,6 +664,11 @@ class PyBuildExt(build_ext):
 
         srcdir = sysconfig.get_config_var('srcdir')
 
+        # Haiku-specific library locations
+        if host_platform == 'haiku1':
+            inc_dirs += ['/boot/develop/headers/posix',
+                         '/boot/system/develop/headers']
+            lib_dirs += ['/boot/system/develop/lib']
         # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
         if host_platform in ['osf1', 'unixware7', 'openunix8']:
             lib_dirs += ['/usr/ccs/lib']
@@ -706,12 +711,12 @@ class PyBuildExt(build_ext):
         exts.append( Extension('cmath', ['cmathmodule.c'],
                                extra_objects=[shared_math],
                                depends=['_math.h', shared_math],
-                               libraries=['m']) )
+                               libraries=[]) )
         # math library functions, e.g. sin()
         exts.append( Extension('math',  ['mathmodule.c'],
                                extra_objects=[shared_math],
                                depends=['_math.h', shared_math],
-                               libraries=['m']) )
+                               libraries=[]) )
 
         # time libraries: librt may be needed for clock_gettime()
         time_libs = []
@@ -725,7 +730,7 @@ class PyBuildExt(build_ext):
         # libm is needed by delta_new() that uses round() and by accum() that
         # uses modf().
         exts.append( Extension('_datetime', ['_datetimemodule.c'],
-                               libraries=['m']) )
+                               libraries=[]) )
         # random number generator implemented in C
         exts.append( Extension("_random", ["_randommodule.c"]) )
         # bisect
@@ -816,7 +821,7 @@ class PyBuildExt(build_ext):
         #
         # audioop needs libm for floor() in multiple functions.
         exts.append( Extension('audioop', ['audioop.c'],
-                               libraries=['m']) )
+                               libraries=[]) )
 
         # readline
         do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
@@ -2015,7 +2020,7 @@ class PyBuildExt(build_ext):
         # function my_sqrt() needs libm for sqrt()
         ext_test = Extension('_ctypes_test',
                      sources=['_ctypes/_ctypes_test.c'],
-                     libraries=['m'])
+                     libraries=[])
         self.extensions.extend([ext, ext_test])
 
         if host_platform == 'darwin':
@@ -2063,7 +2068,7 @@ class PyBuildExt(build_ext):
                                                          'Modules',
                                                          '_decimal',
                                                          'libmpdec'))]
-            libraries = ['m']
+            libraries = []
             sources = [
               '_decimal/_decimal.c',
               '_decimal/libmpdec/basearith.c',
@@ -2226,7 +2231,7 @@ class PyBuildExt(build_ext):
         return ssl_ext, hashlib_ext
 
     def _detect_nis(self, inc_dirs, lib_dirs):
-        if host_platform in {'win32', 'cygwin', 'qnx6'}:
+        if host_platform in {'win32', 'cygwin', 'qnx6', 'haiku1'}:
             return None
 
         libs = []
-- 
2.28.0


From 3b0375cba65c406f43a1669837c737920b233d73 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Sun, 16 Apr 2017 10:05:42 +0200
Subject: fix for negative errnos


diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 3f99be5..7114840 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1537,6 +1537,8 @@ class Popen(object):
                         SubprocessError)
                 if issubclass(child_exception_type, OSError) and hex_errno:
                     errno_num = int(hex_errno, 16)
+                    if sys.platform.startswith('haiku'):
+                        errno_num = -errno_num;
                     child_exec_never_called = (err_msg == "noexec")
                     if child_exec_never_called:
                         err_msg = ""
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index 3cf0683..adf3608 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -534,6 +534,10 @@ error:
         char *cur;
         _Py_write_noraise(errpipe_write, "OSError:", 8);
         cur = hex_errno + sizeof(hex_errno);
+#ifdef __HAIKU__
+        if (saved_errno < 0)
+            saved_errno = -saved_errno;
+#endif
         while (saved_errno != 0 && cur != hex_errno) {
             *--cur = Py_hexdigits[saved_errno % 16];
             saved_errno /= 16;
-- 
2.28.0


From a261fb454a9c843fea23936d23eca4e4e95ff694 Mon Sep 17 00:00:00 2001
From: Philippe Houdoin <philippe.houdoin@gmail.com>
Date: Wed, 24 May 2017 11:09:43 +0000
Subject: Implement CTypes's find_library for Haiku


diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index 97973bc..b2e4095 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -252,6 +252,56 @@ elif os.name == "posix":
         def find_library(name, is64 = False):
             return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name))
 
+    elif sys.platform.startswith("haiku"):
+
+        def _num_version(libname):
+            # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
+            parts = libname.split('.')
+            nums = []
+            try:
+                while parts:
+                    nums.insert(0, int(parts.pop()))
+            except ValueError:
+                pass
+            return nums or [sys.maxint]
+
+        def find_library(name):
+            if name in ('c', 'm'):
+                return find_library('root')
+            for directory in os.environ['LIBRARY_PATH'].split(os.pathsep):
+                if directory.startswith("%A/"):
+                    directory = directory.replace('%A',
+                        os.path.dirname(os.path.abspath(sys.argv[0] or os.getcwd())))
+
+                if not os.path.isdir(directory):
+                    continue
+
+                # try direct match
+                fname = os.path.join(directory, name)
+                if os.path.isfile(fname):
+                    return fname
+
+                fname = os.path.join(directory, 'lib%s.so' % name)
+                if os.path.isfile(fname):
+                    return fname
+
+                # no exact matching in this directroy
+                # collect versioned candidates, if any
+                candidates = []
+                pattern = re.compile(r'lib%s\.so\.\S+' % re.escape(name))
+                for entry in os.listdir(directory):
+                    if not os.path.isfile(os.path.join(directory, entry)):
+                        continue
+
+                    if re.match(pattern, entry):
+                        candidates.append(os.path.join(directory, entry))
+
+                if candidates:
+                    # return latest version found
+                    candidates.sort(key=_num_version)
+                    return candidates[-1]
+
+            return None
     else:
 
         def _findSoname_ldconfig(name):
@@ -349,6 +399,12 @@ def test():
             print(f"crypt\t:: {cdll.LoadLibrary(find_library('crypt'))}")
             print(f"crypto\t:: {find_library('crypto')}")
             print(f"crypto\t:: {cdll.LoadLibrary(find_library('crypto'))}")
+        elif sys.platform.startswith("haiku"):
+            print(find_library("libbz2.so.1.0"))
+            print(find_library("tracker"))
+            print(find_library("media"))
+            print(cdll.LoadLibrary(find_library("tracker")))
+            print(cdll.LoadLibrary("libmedia.so"))
         else:
             print(cdll.LoadLibrary("libm.so"))
             print(cdll.LoadLibrary("libcrypt.so"))
-- 
2.28.0


From ff662b9d4cb680ec9f960565d6d6ccb446433b5b Mon Sep 17 00:00:00 2001
From: Philipp Wolfer <phil@parolu.io>
Date: Mon, 23 Sep 2019 09:14:58 +0200
Subject: webbrowser: Support for default browsers on Haiku


diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
index b04ec7b..c59cdee 100755
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -538,6 +538,11 @@ def register_standard_browsers():
                         "netscape", "opera", iexplore):
             if shutil.which(browser):
                 register(browser, None, BackgroundBrowser(browser))
+    elif sys.platform[:5] == "haiku":
+        # First try to use the default configured browser
+        register("haiku-default", None, GenericBrowser("open"))
+        # Fall back to WebPositive as the standard browser of Haiku
+        register("webpositive", None, BackgroundBrowser("WebPositive"))
     else:
         # Prefer X browsers if present
         if os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"):
-- 
2.28.0


From 79a8f791905b604c31b52a8e005dacec09529228 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Sat, 30 Nov 2019 23:26:57 +0100
Subject: don't reinit locks on fork.


diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index b596f80..431f750 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -228,7 +228,7 @@ def _releaseLock():
 
 # Prevent a held logging lock from blocking a child from logging.
 
-if not hasattr(os, 'register_at_fork'):  # Windows and friends.
+if sys.platform.startswith('haiku') or not hasattr(os, 'register_at_fork'):  # Windows and friends.
     def _register_at_fork_reinit_lock(instance):
         pass  # no-op when os.register_at_fork does not exist.
 else:
-- 
2.28.0


From 8c7414695d2ff888f56b3027425476acdf0ec68f Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Fri, 15 May 2020 15:20:57 +0200
Subject: handle errors returned by internal_connect()

upstream bug #40628 by Ryan C. Gordon

diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 3173b3b..88b66ed 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -3101,7 +3101,7 @@ sock_connect(PySocketSockObject *s, PyObject *addro)
         return NULL;
 
     res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1);
-    if (res < 0)
+    if (res == -1)
         return NULL;
 
     Py_RETURN_NONE;
@@ -3127,7 +3127,7 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro)
         return NULL;
 
     res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0);
-    if (res < 0)
+    if (res == -1)
         return NULL;
 
     return PyLong_FromLong((long) res);
-- 
2.28.0

