diff -Paur --no-dereference -- python.upstream/config.sub python/config.sub
--- python.upstream/config.sub
+++ python/config.sub
@@ -1360,7 +1360,7 @@
 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
 	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* | -aros* \
+	      | -aos* | -aros* | -sortix* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
diff -Paur --no-dereference -- python.upstream/configure python/configure
--- python.upstream/configure
+++ python/configure
@@ -3253,6 +3253,9 @@
 	*-*-cygwin*)
 		ac_sys_system=Cygwin
 		;;
+	*-*-sortix*)
+		ac_sys_system=Sortix
+		;;
 	*)
 		# for now, limit cross builds to known configurations
 		MACHDEP="unknown"
@@ -3299,9 +3302,8 @@
 		_host_cpu=
 		;;
 	*)
-		# for now, limit cross builds to known configurations
-		MACHDEP="unknown"
-		as_fn_error $? "cross build not supported for $host" "$LINENO" 5
+		_host_cpu=$host_cpu
+		;;
 	esac
 	_PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}"
 fi
@@ -9279,7 +9281,9 @@
 	CYGWIN*)
 		LDSHARED="gcc -shared -Wl,--enable-auto-image-base"
 		LDCXXSHARED="g++ -shared -Wl,--enable-auto-image-base";;
-	*)	LDSHARED="ld";;
+	*)
+		LDSHARED='$(CC) -shared'
+		LDCXXSHARED='$(CXX) -shared';;
 	esac
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDSHARED" >&5
@@ -9619,6 +9623,50 @@
 						# pthread (first!) on Linux
 fi
 
+# check if we need libiconv for iconv functions
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv in -liconv" >&5
+$as_echo_n "checking for libiconv in -liconv... " >&6; }
+if ${ac_cv_lib_iconv_iconv+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-liconv  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char libiconv ();
+int
+main ()
+{
+return libiconv ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_iconv_libiconv=yes
+else
+  ac_cv_lib_iconv_libiconv=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv" >&5
+$as_echo "$ac_cv_lib_iconv_libiconv" >&6; }
+if test "x$ac_cv_lib_iconv_libiconv" = xyes; then :
+
+$as_echo "#define WITH_LIBICONV 1" >>confdefs.h
+
+        LIBS="-liconv $LIBS"
+fi
+
 # check if we need libintl for locale functions
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for textdomain in -lintl" >&5
 $as_echo_n "checking for textdomain in -lintl... " >&6; }
@@ -12709,7 +12757,7 @@
 if test "${enable_ipv6+set}" = set; then
   ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6"
 else
-  ac_cv_buggy_getaddrinfo=yes
+  ac_cv_buggy_getaddrinfo="no -- because you assume correctness when cross-compiling"
 fi
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -12808,7 +12856,7 @@
 if ac_fn_c_try_run "$LINENO"; then :
   ac_cv_buggy_getaddrinfo=no
 else
-  ac_cv_buggy_getaddrinfo=yes
+  ac_cv_buggy_getaddrinfo="no -- because you assume correctness when cross-compiling"
 fi
 rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
   conftest.$ac_objext conftest.beam conftest.$ac_ext
@@ -15712,7 +15760,7 @@
 
 # first curses header check
 ac_save_cppflags="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw"
+# PATCH: Removed cross-compilation unsafe include path addition.
 
 for ac_header in curses.h ncurses.h
 do :
@@ -15908,6 +15956,12 @@
 
 if test "x$cross_compiling" = xyes; then
   if test "${ac_cv_file__dev_ptmx+set}" != set; then
+    ac_cv_file__dev_ptmx=yes
+  fi
+  if test "${ac_cv_file__dev_ptc+set}" != set; then
+    ac_cv_file__dev_ptc=no
+  fi
+  if test "${ac_cv_file__dev_ptmx+set}" != set; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /dev/ptmx" >&5
 $as_echo_n "checking for /dev/ptmx... " >&6; }
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: not set" >&5
diff -Paur --no-dereference -- python.upstream/configure.ac python/configure.ac
--- python.upstream/configure.ac
+++ python/configure.ac
@@ -385,6 +385,9 @@
 	*-*-cygwin*)
 		ac_sys_system=Cygwin
 		;;
+	*-*-sortix*)
+		ac_sys_system=Sortix
+		;;
 	*)
 		# for now, limit cross builds to known configurations
 		MACHDEP="unknown"
@@ -431,9 +434,8 @@
 		_host_cpu=
 		;;
 	*)
-		# for now, limit cross builds to known configurations
-		MACHDEP="unknown"
-		AC_MSG_ERROR([cross build not supported for $host])
+		_host_cpu=$host_cpu
+		;;
 	esac
 	_PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}"
 fi
@@ -2535,7 +2537,9 @@
 	CYGWIN*)
 		LDSHARED="gcc -shared -Wl,--enable-auto-image-base"
 		LDCXXSHARED="g++ -shared -Wl,--enable-auto-image-base";;
-	*)	LDSHARED="ld";;
+	*)
+		LDSHARED='$(CC) -shared'
+		LDCXXSHARED='$(CXX) -shared';;
 	esac
 fi
 AC_MSG_RESULT($LDSHARED)
@@ -2679,6 +2683,12 @@
 						# pthread (first!) on Linux
 fi
 
+# check if we need libiconv for iconv functions
+AC_CHECK_LIB(iconv, libiconv,
+	[AC_DEFINE(WITH_ICONV, 1,
+	[Define to 1 if libiconv is needed for iconv functions.])
+        LIBS="-liconv $LIBS"])
+
 # check if we need libintl for locale functions
 AC_CHECK_LIB(intl, textdomain,
 	[AC_DEFINE(WITH_LIBINTL, 1,
@@ -3871,7 +3881,7 @@
 if test "${enable_ipv6+set}" = set; then
   ac_cv_buggy_getaddrinfo="no -- configured with --(en|dis)able-ipv6"
 else
-  ac_cv_buggy_getaddrinfo=yes
+  ac_cv_buggy_getaddrinfo="no -- because you assume correctness when cross-compiling"
 fi]))
 fi
 
@@ -4980,6 +4990,12 @@
 dnl NOTE: Inform user how to proceed with files when cross compiling.
 if test "x$cross_compiling" = xyes; then
   if test "${ac_cv_file__dev_ptmx+set}" != set; then
+    ac_cv_file__dev_ptmx=yes
+  fi
+  if test "${ac_cv_file__dev_ptc+set}" != set; then
+    ac_cv_file__dev_ptc=no
+  fi
+  if test "${ac_cv_file__dev_ptmx+set}" != set; then
     AC_MSG_CHECKING([for /dev/ptmx])
     AC_MSG_RESULT([not set])
     AC_MSG_ERROR([set ac_cv_file__dev_ptmx to yes/no in your CONFIG_SITE file when cross compiling])
diff -Paur --no-dereference -- python.upstream/Include/py_curses.h python/Include/py_curses.h
--- python.upstream/Include/py_curses.h
+++ python/Include/py_curses.h
@@ -48,18 +48,25 @@
 #include <ncurses.h>
 #else
 #include <curses.h>
+#endif
+/* PATCH: Some declarations are in term.h/termcap.h in Sortix's libcurses. */
 #ifdef HAVE_TERM_H
 /* for tigetstr, which is not declared in SysV curses */
 #include <term.h>
+#if __has_include(<termcap.h>)
+#include <termcap.h>
 #endif
 #endif
 
 #ifdef HAVE_NCURSES_H
 /* configure was checking <curses.h>, but we will
    use <ncurses.h>, which has all these features. */
+/* PATCH: Sortix's libcurses doesn't have a public _ISPAD */
+#ifdef _ISPAD
 #ifndef WINDOW_HAS_FLAGS
 #define WINDOW_HAS_FLAGS 1
 #endif
+#endif
 #ifndef MVWDELCH_IS_EXPRESSION
 #define MVWDELCH_IS_EXPRESSION 1
 #endif
diff -Paur --no-dereference -- python.upstream/Lib/ctypes/__init__.py python/Lib/ctypes/__init__.py
--- python.upstream/Lib/ctypes/__init__.py
+++ python/Lib/ctypes/__init__.py
@@ -429,7 +429,15 @@
 elif _sys.platform == "cygwin":
     pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
 else:
-    pythonapi = PyDLL(None)
+    # PATCH: Sortix doesn't have dynamic linking yet, but parts of ctypes are
+    # still useful without it, so ignore an error.
+    try:
+        pythonapi = PyDLL(None)
+    except OSError:
+        if _sys.platform == "sortix":
+            pythonapi = None
+        else:
+            raise
 
 
 if _os.name == "nt":
diff -Paur --no-dereference -- python.upstream/Makefile.pre.in python/Makefile.pre.in
--- python.upstream/Makefile.pre.in
+++ python/Makefile.pre.in
@@ -604,6 +604,7 @@
 	    *\ -s*|s*) quiet="-q";; \
 	    *) quiet="";; \
 	esac; \
+	test $(MACHDEP) = sortix || \
 	$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \
 		_TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \
 		$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
@@ -1145,20 +1146,25 @@
 	else true; \
 	fi
 	(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python3$(EXE))
+	-if test -f $(DESTDIR)$(BINDIR)/python$(EXE) -o -h $(DESTDIR)$(BINDIR)/python$(EXE); \
+	then rm -f $(DESTDIR)$(BINDIR)/python$(EXE); \
+	else true; \
+	fi
+	(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python$(EXE))
 	-if test "$(VERSION)" != "$(LDVERSION)"; then \
-		rm -f $(DESTDIR)$(BINDIR)/python$(VERSION)-config; \
-		(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(LDVERSION)-config python$(VERSION)-config); \
 		rm -f $(DESTDIR)$(LIBPC)/python-$(LDVERSION).pc; \
 		(cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python-$(LDVERSION).pc); \
 	fi
-	-rm -f $(DESTDIR)$(BINDIR)/python3-config
-	(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python3-config)
 	-rm -f $(DESTDIR)$(LIBPC)/python3.pc
 	(cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python3.pc)
 	-rm -f $(DESTDIR)$(BINDIR)/idle3
 	(cd $(DESTDIR)$(BINDIR); $(LN) -s idle$(VERSION) idle3)
+	-rm -f $(DESTDIR)$(BINDIR)/idle
+	(cd $(DESTDIR)$(BINDIR); $(LN) -s idle$(VERSION) idle)
 	-rm -f $(DESTDIR)$(BINDIR)/pydoc3
 	(cd $(DESTDIR)$(BINDIR); $(LN) -s pydoc$(VERSION) pydoc3)
+	-rm -f $(DESTDIR)$(BINDIR)/pydoc
+	(cd $(DESTDIR)$(BINDIR); $(LN) -s pydoc$(VERSION) pydoc)
 	-rm -f $(DESTDIR)$(BINDIR)/2to3
 	(cd $(DESTDIR)$(BINDIR); $(LN) -s 2to3-$(VERSION) 2to3)
 	-rm -f $(DESTDIR)$(BINDIR)/pyvenv
@@ -1411,7 +1417,6 @@
 	$(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup
 	$(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh
 	$(INSTALL_SCRIPT) python-config.py $(DESTDIR)$(LIBPL)/python-config.py
-	$(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(LDVERSION)-config
 	@if [ -s Modules/python.exp -a \
 		"`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \
 		echo; echo "Installing support files for building shared extension modules on AIX:"; \
@@ -1637,6 +1642,8 @@
 				     -o -name '*.orig' -o -name '*.rej' \
 				     -o -name '*.bak' ')' \
 				     -exec rm -f {} ';'
+	-rm -rf $(srcdir)/Lib/plat-sortix
+	-rm -f Misc/python-config.sh
 
 # Check for smelly exported symbols (not starting with Py/_Py)
 smelly: all
diff -Paur --no-dereference -- python.upstream/Modules/_cursesmodule.c python/Modules/_cursesmodule.c
--- python.upstream/Modules/_cursesmodule.c
+++ python/Modules/_cursesmodule.c
@@ -116,7 +116,7 @@
     #defines many common symbols (such as "lines") which breaks the
     curses module in other ways.  So the code will just specify
     explicit prototypes here. */
-extern int setupterm(char *,int,int *);
+/* PATCH: We use term.h now so let that header declare setupterm. */
 #ifdef __sgi
 #include <term.h>
 #endif
@@ -142,6 +142,14 @@
 
 #include "clinic/_cursesmodule.c.h"
 
+/* PATCH: Avoid conflict with <term.h> as described above now that we use it. */
+#ifdef lines
+#undef lines
+#endif
+#ifdef columns
+#undef columns
+#endif
+
 /* Definition of exception curses.error */
 
 static PyObject *PyCursesError;
@@ -475,7 +483,10 @@
 Window_NoArgNoReturnVoidFunction(wclear)
 
 Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)")
+/* PATCH: Sortix's libcurses doesn't have these declarations. */
+#ifndef __sortix__
 Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)")
+#endif
 Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay")
 
 Window_NoArg2TupleReturnFunction(getyx, int, "ii")
@@ -499,7 +510,9 @@
 Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)")
 Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)")
 Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines")
+#ifndef __sortix__
 Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)")
+#endif
 
 Window_TwoArgNoReturnFunction(mvwin, int, "ii;y,x")
 Window_TwoArgNoReturnFunction(mvderwin, int, "ii;y,x")
@@ -2024,7 +2037,9 @@
     {"hline",           (PyCFunction)PyCursesWindow_Hline, METH_VARARGS},
     {"idcok",           (PyCFunction)PyCursesWindow_idcok, METH_VARARGS},
     {"idlok",           (PyCFunction)PyCursesWindow_idlok, METH_VARARGS},
+#ifndef __sortix__
     {"immedok",         (PyCFunction)PyCursesWindow_immedok, METH_VARARGS},
+#endif
     {"inch",            (PyCFunction)PyCursesWindow_InCh, METH_VARARGS},
     {"insch",           (PyCFunction)PyCursesWindow_InsCh, METH_VARARGS},
     {"insdelln",        (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS},
@@ -2060,7 +2075,9 @@
     {"subpad",          (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS},
     {"subwin",          (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS},
     {"syncdown",        (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS},
+#ifndef __sortix__
     {"syncok",          (PyCFunction)PyCursesWindow_syncok, METH_VARARGS},
+#endif
     {"syncup",          (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS},
     {"timeout",         (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS},
     {"touchline",       (PyCFunction)PyCursesWindow_TouchLine, METH_VARARGS},
@@ -2152,6 +2169,7 @@
 NoArgNoReturnVoidFunction(flushinp)
 NoArgNoReturnVoidFunction(noqiflush)
 
+#ifndef __sortix__
 static PyObject *
 PyCurses_filter(PyObject *self)
 {
@@ -2161,6 +2179,7 @@
     Py_INCREF(Py_None);
     return Py_None;
 }
+#endif
 
 static PyObject *
 PyCurses_Color_Content(PyObject *self, PyObject *args)
@@ -2232,6 +2251,7 @@
     return PyBytes_FromStringAndSize(&ch, 1);
 }
 
+#ifndef __sortix__
 static PyObject *
 PyCurses_getsyx(PyObject *self)
 {
@@ -2244,6 +2264,7 @@
 
     return Py_BuildValue("(ii)", y, x);
 }
+#endif
 
 #ifdef NCURSES_MOUSE_VERSION
 static PyObject *
@@ -2355,6 +2376,7 @@
 }
 
 #ifndef STRICT_SYSV_CURSES
+#ifndef __sortix__
 /* No has_key! */
 static PyObject * PyCurses_has_key(PyObject *self, PyObject *args)
 {
@@ -2371,6 +2393,7 @@
     Py_INCREF(Py_True);
     return Py_True;
 }
+#endif
 #endif /* STRICT_SYSV_CURSES */
 
 static PyObject *
@@ -2938,6 +2961,7 @@
 }
 #endif /* HAVE_CURSES_RESIZE_TERM */
 
+#ifndef __sortix__
 static PyObject *
 PyCurses_setsyx(PyObject *self, PyObject *args)
 {
@@ -2957,6 +2981,7 @@
     Py_INCREF(Py_None);
     return Py_None;
 }
+#endif
 
 static PyObject *
 PyCurses_Start_Color(PyObject *self)
@@ -3055,6 +3080,7 @@
     return PyBytes_FromString(result);
 }
 
+#ifndef __sortix__
 static PyObject *
 PyCurses_TypeAhead(PyObject *self, PyObject *args)
 {
@@ -3066,6 +3092,7 @@
 
     return PyCursesCheckERR(typeahead( fd ), "typeahead");
 }
+#endif
 
 static PyObject *
 PyCurses_UnCtrl(PyObject *self, PyObject *args)
@@ -3165,6 +3192,7 @@
 }
 #endif
 
+#ifndef __sortix__
 static PyObject *
 PyCurses_Use_Env(PyObject *self, PyObject *args)
 {
@@ -3183,6 +3211,7 @@
     Py_INCREF(Py_None);
     return Py_None;
 }
+#endif
 
 #ifndef STRICT_SYSV_CURSES
 static PyObject *
@@ -3221,21 +3250,27 @@
     {"echo",                (PyCFunction)PyCurses_echo, METH_VARARGS},
     {"endwin",              (PyCFunction)PyCurses_endwin, METH_NOARGS},
     {"erasechar",           (PyCFunction)PyCurses_EraseChar, METH_NOARGS},
+#ifndef __sortix__
     {"filter",              (PyCFunction)PyCurses_filter, METH_NOARGS},
+#endif
     {"flash",               (PyCFunction)PyCurses_flash, METH_NOARGS},
     {"flushinp",            (PyCFunction)PyCurses_flushinp, METH_NOARGS},
 #ifdef NCURSES_MOUSE_VERSION
     {"getmouse",            (PyCFunction)PyCurses_GetMouse, METH_NOARGS},
     {"ungetmouse",          (PyCFunction)PyCurses_UngetMouse, METH_VARARGS},
 #endif
+#ifndef __sortix__
     {"getsyx",              (PyCFunction)PyCurses_getsyx, METH_NOARGS},
+#endif
     {"getwin",              (PyCFunction)PyCurses_GetWin, METH_O},
     {"has_colors",          (PyCFunction)PyCurses_has_colors, METH_NOARGS},
     {"has_ic",              (PyCFunction)PyCurses_has_ic, METH_NOARGS},
     {"has_il",              (PyCFunction)PyCurses_has_il, METH_NOARGS},
+#ifndef __sortix__
 #ifndef STRICT_SYSV_CURSES
     {"has_key",             (PyCFunction)PyCurses_has_key, METH_VARARGS},
 #endif
+#endif
     {"halfdelay",           (PyCFunction)PyCurses_HalfDelay, METH_VARARGS},
     {"init_color",          (PyCFunction)PyCurses_Init_Color, METH_VARARGS},
     {"init_pair",           (PyCFunction)PyCurses_Init_Pair, METH_VARARGS},
@@ -3279,7 +3314,9 @@
     {"resize_term",         (PyCFunction)PyCurses_Resize_Term, METH_VARARGS},
 #endif
     {"savetty",             (PyCFunction)PyCurses_savetty, METH_NOARGS},
+#ifndef __sortix__
     {"setsyx",              (PyCFunction)PyCurses_setsyx, METH_VARARGS},
+#endif
     {"setupterm",           (PyCFunction)PyCurses_setupterm,
      METH_VARARGS|METH_KEYWORDS},
     {"start_color",         (PyCFunction)PyCurses_Start_Color, METH_NOARGS},
@@ -3289,7 +3326,9 @@
     {"tigetnum",            (PyCFunction)PyCurses_tigetnum, METH_VARARGS},
     {"tigetstr",            (PyCFunction)PyCurses_tigetstr, METH_VARARGS},
     {"tparm",               (PyCFunction)PyCurses_tparm, METH_VARARGS},
+#ifndef __sortix__
     {"typeahead",           (PyCFunction)PyCurses_TypeAhead, METH_VARARGS},
+#endif
     {"unctrl",              (PyCFunction)PyCurses_UnCtrl, METH_VARARGS},
     {"ungetch",             (PyCFunction)PyCurses_UngetCh, METH_VARARGS},
 #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)
@@ -3298,7 +3337,9 @@
 #ifdef HAVE_NCURSESW
     {"unget_wch",           (PyCFunction)PyCurses_Unget_Wch, METH_VARARGS},
 #endif
+#ifndef __sortix__
     {"use_env",             (PyCFunction)PyCurses_Use_Env, METH_VARARGS},
+#endif
 #ifndef STRICT_SYSV_CURSES
     {"use_default_colors",  (PyCFunction)PyCurses_Use_Default_Colors, METH_NOARGS},
 #endif
diff -Paur --no-dereference -- python.upstream/Modules/expat/xmlparse.c python/Modules/expat/xmlparse.c
--- python.upstream/Modules/expat/xmlparse.c
+++ python/Modules/expat/xmlparse.c
@@ -693,9 +693,15 @@
 static unsigned long
 generate_hash_secret_salt(void)
 {
+#if defined(__sortix__)
+  unsigned long result;
+  arc4random_buf(&result, sizeof(result));
+  return result;
+#else
   unsigned int seed = time(NULL) % UINT_MAX;
   srand(seed);
   return rand();
+#endif
 }
 
 static XML_Bool  /* only valid for root parser */
diff -Paur --no-dereference -- python.upstream/Modules/faulthandler.c python/Modules/faulthandler.c
--- python.upstream/Modules/faulthandler.c
+++ python/Modules/faulthandler.c
@@ -14,6 +14,10 @@
 #  include <sys/resource.h>
 #endif
 
+#if defined(__sortix__) && !defined(SIGSTKSZ)
+#define SIGSTKSZ (64 * 1024) /* just some value */
+#endif
+
 /* Allocate at maximum 100 MB of the stack to raise the stack overflow */
 #define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
 
diff -Paur --no-dereference -- python.upstream/Modules/fcntlmodule.c python/Modules/fcntlmodule.c
--- python.upstream/Modules/fcntlmodule.c
+++ python/Modules/fcntlmodule.c
@@ -288,6 +288,10 @@
     Py_BEGIN_ALLOW_THREADS
     ret = flock(fd, code);
     Py_END_ALLOW_THREADS
+#elif defined(__sortix__)
+    errno = ENOSYS;
+    PyErr_SetFromErrno(PyExc_IOError);
+    return NULL;
 #else
 
 #ifndef LOCK_SH
@@ -371,6 +375,11 @@
 #define LOCK_UN         8       /* unlock */
 #endif  /* LOCK_SH */
     {
+#if defined(__sortix__)
+        errno = ENOSYS;
+        PyErr_SetFromErrno(PyExc_IOError);
+        return NULL;
+#else
         struct flock l;
         if (code == LOCK_UN)
             l.l_type = F_UNLCK;
@@ -410,6 +419,7 @@
         Py_BEGIN_ALLOW_THREADS
         ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
         Py_END_ALLOW_THREADS
+#endif
     }
     if (ret < 0) {
         PyErr_SetFromErrno(PyExc_IOError);
diff -Paur --no-dereference -- python.upstream/Modules/getpath.c python/Modules/getpath.c
--- python.upstream/Modules/getpath.c
+++ python/Modules/getpath.c
@@ -131,6 +131,11 @@
     return err;
 }
 
+static const char* fix_empty_prefix(const char* path)
+{
+    return path[0] ? path : "/";
+}
+
 static void
 reduce(wchar_t *dir)
 {
@@ -492,8 +497,8 @@
     wchar_t *lib_python;
 
     _pythonpath = Py_DecodeLocale(PYTHONPATH, NULL);
-    _prefix = Py_DecodeLocale(PREFIX, NULL);
-    _exec_prefix = Py_DecodeLocale(EXEC_PREFIX, NULL);
+    _prefix = Py_DecodeLocale(fix_empty_prefix(PREFIX), NULL);
+    _exec_prefix = Py_DecodeLocale(fix_empty_prefix(EXEC_PREFIX), NULL);
     lib_python = Py_DecodeLocale("lib/python" VERSION, NULL);
 
     if (!_pythonpath || !_prefix || !_exec_prefix || !lib_python) {
diff -Paur --no-dereference -- python.upstream/Modules/mmapmodule.c python/Modules/mmapmodule.c
--- python.upstream/Modules/mmapmodule.c
+++ python/Modules/mmapmodule.c
@@ -599,7 +599,7 @@
 
 #ifdef MS_WINDOWS
     return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
-#elif defined(UNIX)
+#elif defined(UNIX) && !defined(__sortix__)
     /* XXX semantics of return value? */
     /* XXX flags for msync? */
     if (-1 == msync(self->data + offset, size, MS_SYNC)) {
diff -Paur --no-dereference -- python.upstream/Modules/posixmodule.c python/Modules/posixmodule.c
--- python.upstream/Modules/posixmodule.c
+++ python/Modules/posixmodule.c
@@ -5734,15 +5734,6 @@
 #endif /* HAVE_SCHED_H */
 
 
-/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
-/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
-#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
-#define DEV_PTY_FILE "/dev/ptc"
-#define HAVE_DEV_PTMX
-#else
-#define DEV_PTY_FILE "/dev/ptmx"
-#endif
-
 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
 #ifdef HAVE_PTY_H
 #include <pty.h>
@@ -5807,7 +5798,7 @@
         goto error;
 
 #else
-    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
+    master_fd = posix_openpt(O_RDWR | O_NOCTTY); /* open master */
     if (master_fd < 0)
         goto posix_error;
 
@@ -8925,6 +8916,7 @@
         return posix_error();
 #endif
 
+#ifdef HAVE_PUTENV
     /* Remove the key from posix_putenv_garbage;
      * this will cause it to be collected.  This has to
      * happen after the real unsetenv() call because the
@@ -8934,6 +8926,7 @@
         /* really not much we can do; just leak */
         PyErr_Clear();
     }
+#endif
     Py_RETURN_NONE;
 }
 #endif /* HAVE_UNSETENV */
diff -Paur --no-dereference -- python.upstream/Modules/resource.c python/Modules/resource.c
--- python.upstream/Modules/resource.c
+++ python/Modules/resource.c
@@ -9,6 +9,10 @@
 #include <unistd.h>
 #endif
 
+#if defined(__sortix__) && !defined(RLIM_NLIMITS)
+#define RLIM_NLIMITS __RLIMIT_NUM_DECLARED
+#endif
+
 /* On some systems, these aren't in any header file.
    On others they are, with inconsistent prototypes.
    We declare the (default) return type, to shut up gcc -Wall;
@@ -83,6 +87,7 @@
                     PyFloat_FromDouble(doubletime(ru.ru_utime)));
     PyStructSequence_SET_ITEM(result, 1,
                     PyFloat_FromDouble(doubletime(ru.ru_stime)));
+#if !defined(__sortix__)
     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));
@@ -97,6 +102,7 @@
     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));
+#endif
 
     if (PyErr_Occurred()) {
         Py_DECREF(result);
diff -Paur --no-dereference -- python.upstream/Modules/Setup.dist python/Modules/Setup.dist
--- python.upstream/Modules/Setup.dist
+++ python/Modules/Setup.dist
@@ -97,6 +97,8 @@
 COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)
 PYTHONPATH=$(COREPYTHONPATH)
 
+# PATCH: Build all the modules into the python binary rather than shared libs.
+
 
 # The modules listed here can't be built as shared libraries for
 # various reasons; therefore they are listed here instead of in the
@@ -164,45 +166,44 @@
 # it, depending on your system -- see the GNU readline instructions.
 # It's okay for this to be a shared library, too.
 
-#readline readline.c -lreadline -ltermcap
+readline readline.c -lreadline -ltermcap
 
 
 # Modules that should always be present (non UNIX dependent):
 
-#array arraymodule.c	# array objects
-#cmath cmathmodule.c _math.c # -lm # complex math library functions
-#math mathmodule.c _math.c # -lm # math library functions, e.g. sin()
-#_struct _struct.c	# binary structure packing/unpacking
-#_weakref _weakref.c	# basic weak reference support
+array arraymodule.c	# array objects
+cmath cmathmodule.c	# -lm # complex math library functions
+math mathmodule.c _math.c # -lm # math library functions, e.g. sin()
+_struct _struct.c	# binary structure packing/unpacking
 #_testcapi _testcapimodule.c    # Python C API test module
-#_random _randommodule.c	# Random number generator
-#_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c	# elementtree accelerator
-#_pickle _pickle.c	# pickle accelerator
-#_datetime _datetimemodule.c	# datetime accelerator
-#_bisect _bisectmodule.c	# Bisection algorithms
-#_heapq _heapqmodule.c	# Heap queue algorithm
-#_asyncio _asynciomodule.c  # Fast asyncio Future
+_random _randommodule.c	# Random number generator
+_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c	# elementtree accelerator
+_pickle _pickle.c	# pickle accelerator
+_datetime _datetimemodule.c	# datetime accelerator
+_bisect _bisectmodule.c	# Bisection algorithms
+_heapq _heapqmodule.c	# Heap queue algorithm
+_asyncio _asynciomodule.c  # Fast asyncio Future
 
-#unicodedata unicodedata.c    # static Unicode character database
+unicodedata unicodedata.c    # static Unicode character database
 
 
 # Modules with some UNIX dependencies -- on by default:
 # (If you have a really backward UNIX, select and socket may not be
 # supported...)
 
-#fcntl fcntlmodule.c	# fcntl(2) and ioctl(2)
+fcntl fcntlmodule.c	# fcntl(2) and ioctl(2)
 #spwd spwdmodule.c		# spwd(3)
-#grp grpmodule.c		# grp(3)
-#select selectmodule.c	# select(2); not on ancient System V
+grp grpmodule.c		# grp(3)
+select selectmodule.c	# select(2); not on ancient System V
 
 # Memory-mapped files (also works on Win32).
-#mmap mmapmodule.c
+mmap mmapmodule.c
 
 # CSV file helper
-#_csv _csv.c
+_csv _csv.c
 
 # Socket module helper for socket(2)
-#_socket socketmodule.c
+_socket socketmodule.c
 
 # Socket module helper for SSL support; you must comment out the other
 # socket line above, and possibly edit the SSL variable:
@@ -210,6 +211,7 @@
 #_ssl _ssl.c \
 #	-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
 #	-L$(SSL)/lib -lssl -lcrypto
+_ssl _ssl.c -DUSE_SSL -lssl -lcrypto
 
 # The crypt module is now disabled by default because it breaks builds
 # on many systems (where -lcrypt is needed), e.g. Linux (I believe).
@@ -223,10 +225,10 @@
 # are not supported by all UNIX systems:
 
 #nis nismodule.c -lnsl	# Sun yellow pages -- not everywhere
-#termios termios.c	# Steen Lumholt's termios module
-#resource resource.c	# Jeremy Hylton's rlimit interface
+termios termios.c	# Steen Lumholt's termios module
+resource resource.c	# Jeremy Hylton's rlimit interface
 
-#_posixsubprocess _posixsubprocess.c  # POSIX subprocess module helper
+_posixsubprocess _posixsubprocess.c  # POSIX subprocess module helper
 
 # Multimedia modules -- off by default.
 # These don't work for 64-bit platforms!!!
@@ -242,17 +244,18 @@
 # The _md5 module implements the RSA Data Security, Inc. MD5
 # Message-Digest Algorithm, described in RFC 1321.
 
-#_md5 md5module.c
+_md5 md5module.c
 
 
 # The _sha module implements the SHA checksum algorithms.
 # (NIST's Secure Hash Algorithms.)
-#_sha1 sha1module.c
-#_sha256 sha256module.c
-#_sha512 sha512module.c
+_sha1 sha1module.c
+_sha256 sha256module.c
+_sha512 sha512module.c
+_sha3 _sha3/sha3module.c
 
 # _blake module
-#_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c
+_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c
 
 # The _tkinter module.
 #
@@ -298,7 +301,7 @@
 #	-lX11
 
 # Lance Ellinghaus's syslog module
-#syslog syslogmodule.c		# syslog daemon interface
+syslog syslogmodule.c		# syslog daemon interface
 
 
 # Curses support, requiring the System V version of curses, often
@@ -307,9 +310,9 @@
 #
 # First, look at Setup.config; configure may have set this for you.
 
-#_curses _cursesmodule.c -lcurses -ltermcap
+_curses _cursesmodule.c -lcurses -ltermcap
 # Wrapper for the panel library that's part of ncurses and SYSV curses.
-#_curses_panel _curses_panel.c -lpanel -lncurses
+_curses_panel _curses_panel.c -lpanel -lncurses
 
 
 # Modules that provide persistent dictionary-like semantics.  You will
@@ -336,10 +339,10 @@
 
 
 # Helper module for various ascii-encoders
-#binascii binascii.c
+binascii binascii.c
 
 # Fred Drake's interface to the Python parser
-#parser parsermodule.c
+parser parsermodule.c
 
 
 # Lee Busby's SIGFPE modules.
@@ -357,12 +360,12 @@
 #fpectl fpectlmodule.c ...
 
 # Test module for fpectl.  No extra libraries needed.
-#fpetest fpetestmodule.c
+fpetest fpetestmodule.c
 
 # Andrew Kuchling's zlib module.
 # This require zlib 1.1.3 (or later).
 # See http://www.gzip.org/zlib/
-#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz
+zlib zlibmodule.c -lz
 
 # Interface to the Expat XML parser
 #
@@ -375,22 +378,29 @@
 #
 # More information on Expat can be found at www.libexpat.org.
 #
-#pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI
+pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI
 
 # Hye-Shik Chang's CJKCodecs
 
 # multibytecodec is required for all the other CJK codec modules
-#_multibytecodec cjkcodecs/multibytecodec.c
+_multibytecodec cjkcodecs/multibytecodec.c
 
-#_codecs_cn cjkcodecs/_codecs_cn.c
-#_codecs_hk cjkcodecs/_codecs_hk.c
-#_codecs_iso2022 cjkcodecs/_codecs_iso2022.c
-#_codecs_jp cjkcodecs/_codecs_jp.c
-#_codecs_kr cjkcodecs/_codecs_kr.c
-#_codecs_tw cjkcodecs/_codecs_tw.c
+_codecs_cn cjkcodecs/_codecs_cn.c
+_codecs_hk cjkcodecs/_codecs_hk.c
+_codecs_iso2022 cjkcodecs/_codecs_iso2022.c
+_codecs_jp cjkcodecs/_codecs_jp.c
+_codecs_kr cjkcodecs/_codecs_kr.c
+_codecs_tw cjkcodecs/_codecs_tw.c
 
 # Example -- included for reference only:
 # xx xxmodule.c
 
 # Another example -- the 'xxsubtype' module shows C-level subtyping in action
 xxsubtype xxsubtype.c
+
+# PATCH: The rest of the modules that weren't mentioned in this file.
+_bz2 _bz2module.c -lbz2
+_ctypes _ctypes/callbacks.c _ctypes/callproc.c _ctypes/cfield.c _ctypes/_ctypes.c _ctypes/_ctypes_test.c _ctypes/malloc_closure.c _ctypes/stgdict.c -lffi
+_lsprof _lsprof.c rotatingtree.c
+_lzma _lzmamodule.c -llzma
+_opcode _opcode.c
diff -Paur --no-dereference -- python.upstream/Modules/socketmodule.c python/Modules/socketmodule.c
--- python.upstream/Modules/socketmodule.c
+++ python/Modules/socketmodule.c
@@ -83,6 +83,17 @@
 
 */
 
+#if defined(__sortix__)
+struct hostent
+{
+	char   *h_name;
+	char  **h_aliases;
+	int     h_addrtype;
+	int     h_length;
+	char  **h_addr_list;
+};
+#endif
+
 #ifdef __APPLE__
 #include <AvailabilityMacros.h>
 /* for getaddrinfo thread safety test on old versions of OS X */
@@ -479,6 +490,12 @@
 #define INADDR_NONE (-1)
 #endif
 
+#if defined(__sortix__)
+#define h_errno 0
+#define gethostbyname(a) ((void) (a), (struct hostent*) NULL)
+#define gethostbyaddr(a, b, c) ((void) (a), (void) (b), (void) (c), (struct hostent*) NULL)
+#endif
+
 /* XXX There's a problem here: *static* functions are not supposed to have
    a Py prefix (or use CapitalizedWords).  Later... */
 
@@ -5628,6 +5645,10 @@
 static PyObject*
 socket_inet_aton(PyObject *self, PyObject *args)
 {
+/* PATCH: Sortix only has the modern inet_pton. */
+#if defined(HAVE_INET_PTON) && !defined(HAVE_INET_ATON) && !defined(HAVE_INET_ADDR)
+    struct in_addr buf;
+#else
 #ifdef HAVE_INET_ATON
     struct in_addr buf;
 #endif
@@ -5639,11 +5660,21 @@
     /* Have to use inet_addr() instead */
     unsigned int packed_addr;
 #endif
+#endif
     char *ip_addr;
 
     if (!PyArg_ParseTuple(args, "s:inet_aton", &ip_addr))
         return NULL;
 
+#if defined(HAVE_INET_PTON) && !defined(HAVE_INET_ATON) && !defined(HAVE_INET_ADDR)
+    if (inet_pton(AF_INET, ip_addr, &buf))
+        return PyBytes_FromStringAndSize((char *)(&buf),
+                                          sizeof(buf));
+
+    PyErr_SetString(PyExc_OSError,
+                    "illegal IP address string passed to inet_aton");
+    return NULL;
+#else
 
 #ifdef HAVE_INET_ATON
 
@@ -5688,6 +5719,8 @@
 #endif
 
 #endif
+
+#endif
 }
 
 PyDoc_STRVAR(inet_ntoa_doc,
@@ -5700,6 +5733,7 @@
 {
     Py_buffer packed_ip;
     struct in_addr packed_addr;
+    char addr[INET_ADDRSTRLEN];
 
     if (!PyArg_ParseTuple(args, "y*:inet_ntoa", &packed_ip)) {
         return NULL;
@@ -5715,7 +5749,9 @@
     memcpy(&packed_addr, packed_ip.buf, packed_ip.len);
     PyBuffer_Release(&packed_ip);
 
-    return PyUnicode_FromString(inet_ntoa(packed_addr));
+    /* PATCH: Sortix only has the modern inet_ntop. */
+    inet_ntop(AF_INET, &packed_addr, addr, sizeof(addr));
+    return PyUnicode_FromString(addr);
 }
 
 #if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
diff -Paur --no-dereference -- python.upstream/Modules/_ssl.c python/Modules/_ssl.c
--- python.upstream/Modules/_ssl.c
+++ python/Modules/_ssl.c
@@ -101,6 +101,9 @@
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
 #  define OPENSSL_VERSION_1_1 1
+/* PATCH: The libressl shipped with Sortix is new enough.*/
+#elif !defined(OPENSSL_VERSION_1_1) && defined(LIBRESSL_VERSION_NUMBER) && 0x3000200fL <= LIBRESSL_VERSION_NUMBER
+#  define OPENSSL_VERSION_1_1 1
 #endif
 
 /* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1
diff -Paur --no-dereference -- python.upstream/Modules/timemodule.c python/Modules/timemodule.c
--- python.upstream/Modules/timemodule.c
+++ python/Modules/timemodule.c
@@ -1198,13 +1198,25 @@
 #if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__)
     PyObject *otz0, *otz1;
     tzset();
+#if defined(__sortix__) && !defined(__SORTIX_HAS_TIMEZONE__)
+    PyModule_AddIntConstant(m, "timezone", 0);
+#else
     PyModule_AddIntConstant(m, "timezone", timezone);
+#endif
 #ifdef HAVE_ALTZONE
     PyModule_AddIntConstant(m, "altzone", altzone);
 #else
+#if defined(__sortix__) && !defined(__SORTIX_HAS_ALTZONE__)
+    PyModule_AddIntConstant(m, "altzone", 0);
+#else
     PyModule_AddIntConstant(m, "altzone", timezone-3600);
 #endif
+#endif
+#if defined(__sortix__) && !defined(__SORTIX_HAS_DAYLIGHT__)
+    PyModule_AddIntConstant(m, "daylight", 0);
+#else
     PyModule_AddIntConstant(m, "daylight", daylight);
+#endif
     otz0 = PyUnicode_DecodeLocale(tzname[0], "surrogateescape");
     otz1 = PyUnicode_DecodeLocale(tzname[1], "surrogateescape");
     PyModule_AddObject(m, "tzname", Py_BuildValue("(NN)", otz0, otz1));
diff -Paur --no-dereference -- python.upstream/Python/fileutils.c python/Python/fileutils.c
--- python.upstream/Python/fileutils.c
+++ python/Python/fileutils.c
@@ -1387,7 +1387,9 @@
               wchar_t *resolved_path, size_t resolved_path_size)
 {
     char *cpath;
+#if !defined(__sortix__)
     char cresolved_path[MAXPATHLEN];
+#endif
     wchar_t *wresolved_path;
     char *res;
     size_t r;
@@ -1396,12 +1398,21 @@
         errno = EINVAL;
         return NULL;
     }
+#if defined(__sortix__)
+    res = realpath(cpath, NULL);
+#else
     res = realpath(cpath, cresolved_path);
+#endif
     PyMem_Free(cpath);
     if (res == NULL)
         return NULL;
 
+#if defined(__sortix__)
+    wresolved_path = Py_DecodeLocale(res, &r);
+    free(res);
+#else
     wresolved_path = Py_DecodeLocale(cresolved_path, &r);
+#endif
     if (wresolved_path == NULL) {
         errno = EINVAL;
         return NULL;
@@ -1411,7 +1422,11 @@
         errno = EINVAL;
         return NULL;
     }
+#if defined(__sortix__)
+    wcslcpy(resolved_path, wresolved_path, resolved_path_size);
+#else
     wcsncpy(resolved_path, wresolved_path, resolved_path_size);
+#endif
     PyMem_RawFree(wresolved_path);
     return resolved_path;
 }
diff -Paur --no-dereference -- python.upstream/Python/random.c python/Python/random.c
--- python.upstream/Python/random.c
+++ python/Python/random.c
@@ -1,9 +1,15 @@
+#if defined(__sortix__)
+#define HAVE_ARC4RANDOM
+#endif
+
 #include "Python.h"
 #ifdef MS_WINDOWS
 #  include <windows.h>
 /* All sample MSDN wincrypt programs include the header below. It is at least
  * required with Min GW. */
 #  include <wincrypt.h>
+#elif defined(HAVE_ARC4RANDOM)
+#  include <stdlib.h>
 #else
 #  include <fcntl.h>
 #  ifdef HAVE_SYS_STAT_H
@@ -26,6 +32,7 @@
 static int _Py_HashSecret_Initialized = 0;
 #endif
 
+#ifndef HAVE_ARC4RANDOM
 #ifdef MS_WINDOWS
 static HCRYPTPROV hCryptProv = 0;
 
@@ -351,6 +358,7 @@
 }
 
 #endif
+#endif /* !defined(HAVE_ARC4RANDOM) */
 
 /* Fill buffer with pseudo-random bytes generated by a linear congruent
    generator (LCG):
@@ -373,6 +381,7 @@
     }
 }
 
+#if !defined(HAVE_ARC4RANDOM)
 /* If raise is zero:
    - Don't raise exceptions on error
    - Don't call PyErr_CheckSignals() on EINTR (retry directly the interrupted
@@ -401,6 +410,7 @@
     return dev_urandom(buffer, size, blocking, raise);
 #endif
 }
+#endif /* !defined(HAVE_ARC4RANDOM) */
 
 /* Fill buffer with size pseudo-random bytes from the operating system random
    number generator (RNG). It is suitable for most cryptographic purposes
@@ -414,7 +424,12 @@
 int
 _PyOS_URandom(void *buffer, Py_ssize_t size)
 {
+#ifdef HAVE_ARC4RANDOM
+    arc4random_buf(buffer, size);
+    return 0;
+#else
     return pyurandom(buffer, size, 1, 1);
+#endif
 }
 
 /* Fill buffer with size pseudo-random bytes from the operating system random
@@ -428,7 +443,12 @@
 int
 _PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
 {
+#ifdef HAVE_ARC4RANDOM
+    arc4random_buf(buffer, size);
+    return 0;
+#else
     return pyurandom(buffer, size, 0, 1);
+#endif
 }
 
 void
@@ -469,6 +489,7 @@
         }
     }
     else {
+#ifndef HAVE_ARC4RANDOM
         int res;
 
         /* _PyRandom_Init() is called very early in the Python initialization
@@ -480,6 +501,9 @@
         if (res < 0) {
             Py_FatalError("failed to get random numbers to initialize Python");
         }
+#else
+        arc4random_buf(secret, secret_size);
+#endif
     }
 }
 
@@ -491,7 +515,7 @@
         CryptReleaseContext(hCryptProv, 0);
         hCryptProv = 0;
     }
-#elif defined(PY_GETENTROPY)
+#elif defined(HAVE_ARC4RANDOM) || defined(PY_GETENTROPY)
     /* nothing to clean */
 #else
     dev_urandom_close();
