Create and populate OS/2 EMX port build directory:
  PC/os2emx/
    Makefile
    README.os2emx
    config.c
    dlfcn.c            // libdl emulation code for loadable extensions
    dlfcn.h
    dllentry.c         // DLL initialisation routine for Python DLL
    getpath.c
    pyconfig.h
    python23.def       // Python DLL symbol export definitions
    pythonpm.c         // console-less PM interpreter wrapper
diff --git a/PC/os2emx/pythonpm.c b/PC/os2emx/pythonpm.c
new file mode 100644
index 0000000..5accbbd
--- /dev/null
+++ b/PC/os2emx/pythonpm.c
@@ -0,0 +1,124 @@
+/* OS/2 PM main program - creates a hidden window, and starts Python
+ * interpreter in a separate thread, so that Python scripts can be
+ * run in PM process space without a console Window.  The interpreter
+ * is incorporated by linking in the Python DLL.
+ *
+ * As it stands, I don't think this is adequate for supporting Python
+ * GUI modules, as the Python thread doesn't have its own message
+ * queue - which is required of threads that want to create/use
+ * PM windows.
+ *
+ * This code owes a lot to "OS/2 Presentation Manager Programming", by
+ * Charles Petzold.
+ *
+ * Andrew MacIntyre <andymac@bullseye.apana.org.au>, August 2001.
+ * Released under the terms of the Python 2.1.1 licence - see the LICENCE
+ * file in the Python v2.1.1 (or later) source distribution.
+ * Copyright assigned to the Python Software Foundation, 2001.
+ */
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <process.h>
+
+#include "Python.h"
+
+/* use structure to pass command line to Python thread */
+typedef struct
+{
+	int argc;
+	char **argv;
+	HWND Frame;
+	int running;
+} arglist;
+
+/* make this a global to simplify access.
+ * it should only be set from the Python thread, or by the code that
+ * initiates the Python thread when the thread cannot be created.
+ */
+int PythonRC;
+
+extern DL_EXPORT(int) Py_Main(int, char **);
+void PythonThread(void *);
+
+int
+main(int argc, char **argv)
+{
+	ULONG FrameFlags = FCF_TITLEBAR |
+			   FCF_SYSMENU |
+			   FCF_SIZEBORDER |
+			   FCF_HIDEBUTTON |
+			   FCF_SHELLPOSITION |
+			   FCF_TASKLIST;
+	HAB hab;
+	HMQ hmq;
+	HWND Client;
+	QMSG qmsg;
+	arglist args;
+	int python_tid;
+
+	/* init PM and create message queue */
+	hab = WinInitialize(0);
+	hmq = WinCreateMsgQueue(hab, 0);
+
+	/* create a (hidden) Window to house the window procedure */
+	args.Frame = WinCreateStdWindow(HWND_DESKTOP,
+					0,
+					&FrameFlags,
+					NULL,
+					"PythonPM",
+					0L,
+					0,
+					0,
+					&Client);
+
+	/* run Python interpreter in a thread */
+	args.argc = argc;
+	args.argv = argv;
+	args.running = 0;
+	if (-1 == (python_tid = _beginthread(PythonThread, NULL, 1024 * 1024, &args)))
+	{
+		/* couldn't start thread */
+		WinAlarm(HWND_DESKTOP, WA_ERROR);
+		PythonRC = 1;
+	}
+	else
+	{
+		/* process PM messages, until Python exits */
+		while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
+			WinDispatchMsg(hab, &qmsg);
+		if (args.running > 0)
+			DosKillThread(python_tid);
+	}
+		
+	/* destroy window, shutdown message queue and PM */
+	WinDestroyWindow(args.Frame);
+	WinDestroyMsgQueue(hmq);
+	WinTerminate(hab);
+
+	return PythonRC;
+}
+
+void PythonThread(void *argl)
+{
+	HAB hab;
+	arglist *args;
+
+	/* PM initialisation */
+	hab = WinInitialize(0);
+
+	/* start Python */
+	args = (arglist *)argl;
+	args->running = 1;
+	PythonRC = Py_Main(args->argc, args->argv);
+
+	/* enter a critical section and send the termination message */
+	DosEnterCritSec();
+	args->running = 0;
+	WinPostMsg(args->Frame, WM_QUIT, NULL, NULL);
+
+	/* shutdown PM and terminate thread */
+	WinTerminate(hab);
+	_endthread();
+}