Change command line processing API to use wchar_t.
Fixes #2128.
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index d45e2d4..33efaff 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -3012,7 +3012,7 @@
 PyMODINIT_FUNC
 init_tkinter(void)
 {
-	PyObject *m, *d;
+	PyObject *m, *d, *uexe, *cexe;
 
 	Py_TYPE(&Tkapp_Type) = &PyType_Type;
 
@@ -3065,7 +3065,16 @@
 
 	/* This helps the dynamic loader; in Unicode aware Tcl versions
 	   it also helps Tcl find its encodings. */
-	Tcl_FindExecutable(Py_GetProgramName());
+	uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
+	if (uexe) {
+		cexe = PyUnicode_AsEncodedString(uexe, 
+						 Py_FileSystemDefaultEncoding, 
+						 NULL);
+		if (cexe)
+			Tcl_FindExecutable(PyString_AsString(cexe));
+		Py_XDECREF(cexe);
+		Py_DECREF(uexe);
+	}
 
 	if (PyErr_Occurred())
 		return;
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 09fbe10..f752a7f 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -122,19 +122,81 @@
 #endif
 
 #ifndef LANDMARK
-#define LANDMARK "os.py"
+#define LANDMARK L"os.py"
 #endif
 
-static char prefix[MAXPATHLEN+1];
-static char exec_prefix[MAXPATHLEN+1];
-static char progpath[MAXPATHLEN+1];
-static char *module_search_path = NULL;
-static char lib_python[] = "lib/python" VERSION;
+static wchar_t prefix[MAXPATHLEN+1];
+static wchar_t exec_prefix[MAXPATHLEN+1];
+static wchar_t progpath[MAXPATHLEN+1];
+static wchar_t *module_search_path = NULL;
+static wchar_t lib_python[] = L"lib/python" VERSION;
+
+/* In principle, this should use HAVE__WSTAT, and _wstat
+   should be detected by autoconf. However, no current
+   POSIX system provides that function, so testing for
+   it is pointless. */
+#ifndef MS_WINDOWS
+static int
+_wstat(const wchar_t* path, struct stat *buf)
+{
+    char fname[PATH_MAX];
+    size_t res = wcstombs(fname, path, sizeof(fname));
+    if (res == (size_t)-1) {
+	errno = EINVAL;
+	return -1;
+    }
+    return stat(fname, buf);
+}
+#endif
+
+#ifndef MS_WINDOWS
+static wchar_t*
+_wgetcwd(wchar_t *buf, size_t size)
+{
+    char fname[PATH_MAX];
+    if (getcwd(fname, PATH_MAX) == NULL)
+	return NULL;
+    if (mbstowcs(buf, fname, size) >= size) {
+	errno = ERANGE;
+	return NULL;
+    }
+    return buf;
+}
+#endif
+
+#ifdef HAVE_READLINK
+int 
+_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
+{
+    char cbuf[PATH_MAX];
+    char cpath[PATH_MAX];
+    int res;
+    size_t r1 = wcstombs(cpath, path, PATH_MAX);
+    if (r1 == (size_t)-1 || r1 >= PATH_MAX) {
+	errno = EINVAL;
+	return -1;
+    }
+    res = (int)readlink(cpath, cbuf, PATH_MAX);
+    if (res == -1)
+	return -1;
+    if (res == PATH_MAX) {
+	errno = EINVAL;
+	return -1;
+    }
+    r1 = mbstowcs(buf, cbuf, bufsiz);
+    if (r1 == -1) {
+	errno = EINVAL;
+	return -1;
+    }
+    return (int)r1;
+    
+}
+#endif
 
 static void
-reduce(char *dir)
+reduce(wchar_t *dir)
 {
-    size_t i = strlen(dir);
+    size_t i = wcslen(dir);
     while (i > 0 && dir[i] != SEP)
         --i;
     dir[i] = '\0';
@@ -142,10 +204,10 @@
 
 
 static int
-isfile(char *filename)          /* Is file, not directory */
+isfile(wchar_t *filename)          /* Is file, not directory */
 {
     struct stat buf;
-    if (stat(filename, &buf) != 0)
+    if (_wstat(filename, &buf) != 0)
         return 0;
     if (!S_ISREG(buf.st_mode))
         return 0;
@@ -154,14 +216,14 @@
 
 
 static int
-ismodule(char *filename)        /* Is module -- check for .pyc/.pyo too */
+ismodule(wchar_t *filename)        /* Is module -- check for .pyc/.pyo too */
 {
     if (isfile(filename))
         return 1;
 
     /* Check for the compiled version of prefix. */
-    if (strlen(filename) < MAXPATHLEN) {
-        strcat(filename, Py_OptimizeFlag ? "o" : "c");
+    if (wcslen(filename) < MAXPATHLEN) {
+        wcscat(filename, Py_OptimizeFlag ? L"o" : L"c");
         if (isfile(filename))
             return 1;
     }
@@ -170,10 +232,10 @@
 
 
 static int
-isxfile(char *filename)         /* Is executable file */
+isxfile(wchar_t *filename)         /* Is executable file */
 {
     struct stat buf;
-    if (stat(filename, &buf) != 0)
+    if (_wstat(filename, &buf) != 0)
         return 0;
     if (!S_ISREG(buf.st_mode))
         return 0;
@@ -184,10 +246,10 @@
 
 
 static int
-isdir(char *filename)                   /* Is directory */
+isdir(wchar_t *filename)                   /* Is directory */
 {
     struct stat buf;
-    if (stat(filename, &buf) != 0)
+    if (_wstat(filename, &buf) != 0)
         return 0;
     if (!S_ISDIR(buf.st_mode))
         return 0;
@@ -205,34 +267,34 @@
    stuff as fits will be appended.
 */
 static void
-joinpath(char *buffer, char *stuff)
+joinpath(wchar_t *buffer, wchar_t *stuff)
 {
     size_t n, k;
     if (stuff[0] == SEP)
         n = 0;
     else {
-        n = strlen(buffer);
+        n = wcslen(buffer);
         if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN)
             buffer[n++] = SEP;
     }
     if (n > MAXPATHLEN)
     	Py_FatalError("buffer overflow in getpath.c's joinpath()");
-    k = strlen(stuff);
+    k = wcslen(stuff);
     if (n + k > MAXPATHLEN)
         k = MAXPATHLEN - n;
-    strncpy(buffer+n, stuff, k);
+    wcsncpy(buffer+n, stuff, k);
     buffer[n+k] = '\0';
 }
 
 /* copy_absolute requires that path be allocated at least
    MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */
 static void
-copy_absolute(char *path, char *p)
+copy_absolute(wchar_t *path, wchar_t *p)
 {
     if (p[0] == SEP)
-        strcpy(path, p);
+        wcscpy(path, p);
     else {
-        getcwd(path, MAXPATHLEN);
+        _wgetcwd(path, MAXPATHLEN);
         if (p[0] == '.' && p[1] == SEP)
             p += 2;
         joinpath(path, p);
@@ -241,46 +303,46 @@
 
 /* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */
 static void
-absolutize(char *path)
+absolutize(wchar_t *path)
 {
-    char buffer[MAXPATHLEN + 1];
+    wchar_t buffer[MAXPATHLEN + 1];
 
     if (path[0] == SEP)
         return;
     copy_absolute(buffer, path);
-    strcpy(path, buffer);
+    wcscpy(path, buffer);
 }
 
 /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
    bytes long.
 */
 static int
-search_for_prefix(char *argv0_path, char *home)
+search_for_prefix(wchar_t *argv0_path, wchar_t *home)
 {
     size_t n;
-    char *vpath;
+    wchar_t *vpath;
 
     /* If PYTHONHOME is set, we believe it unconditionally */
     if (home) {
-        char *delim;
-        strncpy(prefix, home, MAXPATHLEN);
-        delim = strchr(prefix, DELIM);
+        wchar_t *delim;
+        wcsncpy(prefix, home, MAXPATHLEN);
+        delim = wcschr(prefix, DELIM);
         if (delim)
-            *delim = '\0';
+            *delim = L'\0';
         joinpath(prefix, lib_python);
         joinpath(prefix, LANDMARK);
         return 1;
     }
 
     /* Check to see if argv[0] is in the build directory */
-    strcpy(prefix, argv0_path);
-    joinpath(prefix, "Modules/Setup");
+    wcscpy(prefix, argv0_path);
+    joinpath(prefix, L"Modules/Setup");
     if (isfile(prefix)) {
         /* Check VPATH to see if argv0_path is in the build directory. */
-        vpath = VPATH;
-        strcpy(prefix, argv0_path);
+        vpath = L"" VPATH;
+        wcscpy(prefix, argv0_path);
         joinpath(prefix, vpath);
-        joinpath(prefix, "Lib");
+        joinpath(prefix, L"Lib");
         joinpath(prefix, LANDMARK);
         if (ismodule(prefix))
             return -1;
@@ -289,17 +351,17 @@
     /* Search from argv0_path, until root is found */
     copy_absolute(prefix, argv0_path);
     do {
-        n = strlen(prefix);
+        n = wcslen(prefix);
         joinpath(prefix, lib_python);
         joinpath(prefix, LANDMARK);
         if (ismodule(prefix))
             return 1;
-        prefix[n] = '\0';
+        prefix[n] = L'\0';
         reduce(prefix);
     } while (prefix[0]);
 
     /* Look at configure's PREFIX */
-    strncpy(prefix, PREFIX, MAXPATHLEN);
+    wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
     joinpath(prefix, lib_python);
     joinpath(prefix, LANDMARK);
     if (ismodule(prefix))
@@ -314,26 +376,26 @@
    MAXPATHLEN bytes long.
 */
 static int
-search_for_exec_prefix(char *argv0_path, char *home)
+search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home)
 {
     size_t n;
 
     /* If PYTHONHOME is set, we believe it unconditionally */
     if (home) {
-        char *delim;
-        delim = strchr(home, DELIM);
+        wchar_t *delim;
+        delim = wcschr(home, DELIM);
         if (delim)
-            strncpy(exec_prefix, delim+1, MAXPATHLEN);
+            wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
         else
-            strncpy(exec_prefix, home, MAXPATHLEN);
+            wcsncpy(exec_prefix, home, MAXPATHLEN);
         joinpath(exec_prefix, lib_python);
-        joinpath(exec_prefix, "lib-dynload");
+        joinpath(exec_prefix, L"lib-dynload");
         return 1;
     }
 
     /* Check to see if argv[0] is in the build directory */
-    strcpy(exec_prefix, argv0_path);
-    joinpath(exec_prefix, "Modules/Setup");
+    wcscpy(exec_prefix, argv0_path);
+    joinpath(exec_prefix, L"Modules/Setup");
     if (isfile(exec_prefix)) {
         reduce(exec_prefix);
         return -1;
@@ -342,19 +404,19 @@
     /* Search from argv0_path, until root is found */
     copy_absolute(exec_prefix, argv0_path);
     do {
-        n = strlen(exec_prefix);
+        n = wcslen(exec_prefix);
         joinpath(exec_prefix, lib_python);
-        joinpath(exec_prefix, "lib-dynload");
+        joinpath(exec_prefix, L"lib-dynload");
         if (isdir(exec_prefix))
             return 1;
-        exec_prefix[n] = '\0';
+        exec_prefix[n] = L'\0';
         reduce(exec_prefix);
     } while (exec_prefix[0]);
 
     /* Look at configure's EXEC_PREFIX */
-    strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
+    wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
     joinpath(exec_prefix, lib_python);
-    joinpath(exec_prefix, "lib-dynload");
+    joinpath(exec_prefix, L"lib-dynload");
     if (isdir(exec_prefix))
         return 1;
 
@@ -366,22 +428,25 @@
 static void
 calculate_path(void)
 {
-    extern char *Py_GetProgramName(void);
+    extern wchar_t *Py_GetProgramName(void);
 
-    static char delimiter[2] = {DELIM, '\0'};
-    static char separator[2] = {SEP, '\0'};
-    char *pythonpath = PYTHONPATH;
-    char *rtpypath = Py_GETENV("PYTHONPATH");
-    char *home = Py_GetPythonHome();
-    char *path = getenv("PATH");
-    char *prog = Py_GetProgramName();
-    char argv0_path[MAXPATHLEN+1];
-    char zip_path[MAXPATHLEN+1];
+    static wchar_t delimiter[2] = {DELIM, '\0'};
+    static wchar_t separator[2] = {SEP, '\0'};
+    wchar_t *pythonpath = L"" PYTHONPATH;
+    char *_rtpypath = Py_GETENV("PYTHONPATH"); /* XXX use wide version on Windows */
+    wchar_t rtpypath[MAXPATHLEN+1];
+    wchar_t *home = Py_GetPythonHome();
+    char *_path = getenv("PATH");
+    wchar_t wpath[MAXPATHLEN+1];
+    wchar_t *path = NULL;
+    wchar_t *prog = Py_GetProgramName();
+    wchar_t argv0_path[MAXPATHLEN+1];
+    wchar_t zip_path[MAXPATHLEN+1];
     int pfound, efound; /* 1 if found; -1 if found build directory */
-    char *buf;
+    wchar_t *buf;
     size_t bufsz;
     size_t prefixsz;
-    char *defpath = pythonpath;
+    wchar_t *defpath = pythonpath;
 #ifdef WITH_NEXT_FRAMEWORK
     NSModule pythonModule;
 #endif
@@ -393,13 +458,22 @@
 #endif
 #endif
 
+    if (_path) {
+	    size_t r = mbstowcs(wpath, _path, MAXPATHLEN+1);
+	    path = wpath;
+	    if (r == (size_t)-1 || r > MAXPATHLEN) {
+		    /* Could not convert PATH, or it's too long. */
+		    path = NULL;
+	    }
+    }
+
 	/* If there is no slash in the argv0 path, then we have to
 	 * assume python is on the user's $PATH, since there's no
 	 * other way to find a directory to start the search from.  If
 	 * $PATH isn't exported, you lose.
 	 */
-	if (strchr(prog, SEP))
-		strncpy(progpath, prog, MAXPATHLEN);
+	if (wcschr(prog, SEP))
+		wcsncpy(progpath, prog, MAXPATHLEN);
 #ifdef __APPLE__
      /* On Mac OS X, if a script uses an interpreter of the form
       * "#!/opt/python2.3/bin/python", the kernel only passes "python"
@@ -416,24 +490,24 @@
 #endif /* __APPLE__ */
 	else if (path) {
 		while (1) {
-			char *delim = strchr(path, DELIM);
+			wchar_t *delim = wcschr(path, DELIM);
 
 			if (delim) {
 				size_t len = delim - path;
 				if (len > MAXPATHLEN)
 					len = MAXPATHLEN;
-				strncpy(progpath, path, len);
+				wcsncpy(progpath, path, len);
 				*(progpath + len) = '\0';
 			}
 			else
-				strncpy(progpath, path, MAXPATHLEN);
+				wcsncpy(progpath, path, MAXPATHLEN);
 
 			joinpath(progpath, prog);
 			if (isxfile(progpath))
 				break;
 
 			if (!delim) {
-				progpath[0] = '\0';
+				progpath[0] = L'\0';
 				break;
 			}
 			path = delim + 1;
@@ -443,7 +517,7 @@
 		progpath[0] = '\0';
 	if (progpath[0] != SEP)
 		absolutize(progpath);
-	strncpy(argv0_path, progpath, MAXPATHLEN);
+	wcsncpy(argv0_path, progpath, MAXPATHLEN);
 	argv0_path[MAXPATHLEN] = '\0';
 
 #ifdef WITH_NEXT_FRAMEWORK
@@ -454,7 +528,7 @@
 	*/
     pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
     /* Use dylib functions to find out where the framework was loaded from */
-    buf = (char *)NSLibraryNameForModule(pythonModule);
+    buf = (wchar_t *)NSLibraryNameForModule(pythonModule);
     if (buf != NULL) {
         /* We're in a framework. */
         /* See if we might be in the build directory. The framework in the
@@ -464,39 +538,39 @@
         ** be running the interpreter in the build directory, so we use the
         ** build-directory-specific logic to find Lib and such.
         */
-        strncpy(argv0_path, buf, MAXPATHLEN);
+        wcsncpy(argv0_path, buf, MAXPATHLEN);
         reduce(argv0_path);
         joinpath(argv0_path, lib_python);
         joinpath(argv0_path, LANDMARK);
         if (!ismodule(argv0_path)) {
                 /* We are in the build directory so use the name of the
                    executable - we know that the absolute path is passed */
-                strncpy(argv0_path, prog, MAXPATHLEN);
+                wcsncpy(argv0_path, prog, MAXPATHLEN);
         }
         else {
                 /* Use the location of the library as the progpath */
-                strncpy(argv0_path, buf, MAXPATHLEN);
+                wcsncpy(argv0_path, buf, MAXPATHLEN);
         }
     }
 #endif
 
 #if HAVE_READLINK
     {
-        char tmpbuffer[MAXPATHLEN+1];
-        int linklen = readlink(progpath, tmpbuffer, MAXPATHLEN);
+        wchar_t tmpbuffer[MAXPATHLEN+1];
+        int linklen = _Py_wreadlink(progpath, tmpbuffer, MAXPATHLEN);
         while (linklen != -1) {
             /* It's not null terminated! */
             tmpbuffer[linklen] = '\0';
             if (tmpbuffer[0] == SEP)
                 /* tmpbuffer should never be longer than MAXPATHLEN,
                    but extra check does not hurt */
-                strncpy(argv0_path, tmpbuffer, MAXPATHLEN);
+                wcsncpy(argv0_path, tmpbuffer, MAXPATHLEN);
             else {
                 /* Interpret relative to progpath */
                 reduce(argv0_path);
                 joinpath(argv0_path, tmpbuffer);
             }
-            linklen = readlink(argv0_path, tmpbuffer, MAXPATHLEN);
+            linklen = _Py_wreadlink(argv0_path, tmpbuffer, MAXPATHLEN);
         }
     }
 #endif /* HAVE_READLINK */
@@ -510,22 +584,22 @@
         if (!Py_FrozenFlag)
             fprintf(stderr,
                 "Could not find platform independent libraries <prefix>\n");
-        strncpy(prefix, PREFIX, MAXPATHLEN);
+        wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
         joinpath(prefix, lib_python);
     }
     else
         reduce(prefix);
 
-    strncpy(zip_path, prefix, MAXPATHLEN);
-    zip_path[MAXPATHLEN] = '\0';
+    wcsncpy(zip_path, prefix, MAXPATHLEN);
+    zip_path[MAXPATHLEN] = L'\0';
     if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
         reduce(zip_path);
         reduce(zip_path);
     }
     else
-        strncpy(zip_path, PREFIX, MAXPATHLEN);
-    joinpath(zip_path, "lib/python00.zip");
-    bufsz = strlen(zip_path);	/* Replace "00" with version */
+        wcsncpy(zip_path, L"" PREFIX, MAXPATHLEN);
+    joinpath(zip_path, L"lib/python00.zip");
+    bufsz = wcslen(zip_path);	/* Replace "00" with version */
     zip_path[bufsz - 6] = VERSION[0];
     zip_path[bufsz - 5] = VERSION[2];
 
@@ -533,8 +607,8 @@
         if (!Py_FrozenFlag)
             fprintf(stderr,
                 "Could not find platform dependent libraries <exec_prefix>\n");
-        strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
-        joinpath(exec_prefix, "lib/lib-dynload");
+        wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
+        joinpath(exec_prefix, L"lib/lib-dynload");
     }
     /* If we found EXEC_PREFIX do *not* reduce it!  (Yet.) */
 
@@ -546,13 +620,19 @@
      */
     bufsz = 0;
 
-    if (rtpypath)
-        bufsz += strlen(rtpypath) + 1;
+    if (_rtpypath) {
+	size_t s = mbstowcs(rtpypath, _rtpypath, sizeof(rtpypath)/sizeof(wchar_t));
+	if (s == (size_t)-1 || s >=sizeof(rtpypath))
+	    /* XXX deal with errors more gracefully */
+	    _rtpypath = NULL;
+	if (_rtpypath)
+	    bufsz += wcslen(rtpypath) + 1;
+    }
 
-    prefixsz = strlen(prefix) + 1;
+    prefixsz = wcslen(prefix) + 1;
 
     while (1) {
-        char *delim = strchr(defpath, DELIM);
+        wchar_t *delim = wcschr(defpath, DELIM);
 
         if (defpath[0] != SEP)
             /* Paths are relative to prefix */
@@ -561,65 +641,65 @@
         if (delim)
             bufsz += delim - defpath + 1;
         else {
-            bufsz += strlen(defpath) + 1;
+            bufsz += wcslen(defpath) + 1;
             break;
         }
         defpath = delim + 1;
     }
 
-    bufsz += strlen(zip_path) + 1;
-    bufsz += strlen(exec_prefix) + 1;
+    bufsz += wcslen(zip_path) + 1;
+    bufsz += wcslen(exec_prefix) + 1;
 
     /* This is the only malloc call in this file */
-    buf = (char *)PyMem_Malloc(bufsz);
+    buf = (wchar_t *)PyMem_Malloc(bufsz*sizeof(wchar_t));
 
     if (buf == NULL) {
         /* We can't exit, so print a warning and limp along */
         fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
         fprintf(stderr, "Using default static PYTHONPATH.\n");
-        module_search_path = PYTHONPATH;
+        module_search_path = L"" PYTHONPATH;
     }
     else {
         /* Run-time value of $PYTHONPATH goes first */
-        if (rtpypath) {
-            strcpy(buf, rtpypath);
-            strcat(buf, delimiter);
+        if (_rtpypath) {
+            wcscpy(buf, rtpypath);
+            wcscat(buf, delimiter);
         }
         else
             buf[0] = '\0';
 
         /* Next is the default zip path */
-        strcat(buf, zip_path);
-        strcat(buf, delimiter);
+        wcscat(buf, zip_path);
+        wcscat(buf, delimiter);
 
         /* Next goes merge of compile-time $PYTHONPATH with
          * dynamically located prefix.
          */
         defpath = pythonpath;
         while (1) {
-            char *delim = strchr(defpath, DELIM);
+            wchar_t *delim = wcschr(defpath, DELIM);
 
             if (defpath[0] != SEP) {
-                strcat(buf, prefix);
-                strcat(buf, separator);
+                wcscat(buf, prefix);
+                wcscat(buf, separator);
             }
 
             if (delim) {
                 size_t len = delim - defpath + 1;
-                size_t end = strlen(buf) + len;
-                strncat(buf, defpath, len);
+                size_t end = wcslen(buf) + len;
+                wcsncat(buf, defpath, len);
                 *(buf + end) = '\0';
             }
             else {
-                strcat(buf, defpath);
+                wcscat(buf, defpath);
                 break;
             }
             defpath = delim + 1;
         }
-        strcat(buf, delimiter);
+        wcscat(buf, delimiter);
 
         /* Finally, on goes the directory for dynamic-load modules */
-        strcat(buf, exec_prefix);
+        wcscat(buf, exec_prefix);
 
         /* And publish the results */
         module_search_path = buf;
@@ -636,26 +716,26 @@
 	/* The prefix is the root directory, but reduce() chopped
 	 * off the "/". */
 	if (!prefix[0])
-		strcpy(prefix, separator);
+		wcscpy(prefix, separator);
     }
     else
-        strncpy(prefix, PREFIX, MAXPATHLEN);
+        wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
 
     if (efound > 0) {
         reduce(exec_prefix);
         reduce(exec_prefix);
         reduce(exec_prefix);
 	if (!exec_prefix[0])
-		strcpy(exec_prefix, separator);
+		wcscpy(exec_prefix, separator);
     }
     else
-        strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
+        wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
 }
 
 
 /* External interface */
 
-char *
+wchar_t *
 Py_GetPath(void)
 {
     if (!module_search_path)
@@ -663,7 +743,7 @@
     return module_search_path;
 }
 
-char *
+wchar_t *
 Py_GetPrefix(void)
 {
     if (!module_search_path)
@@ -671,7 +751,7 @@
     return prefix;
 }
 
-char *
+wchar_t *
 Py_GetExecPrefix(void)
 {
     if (!module_search_path)
@@ -679,7 +759,7 @@
     return exec_prefix;
 }
 
-char *
+wchar_t *
 Py_GetProgramFullPath(void)
 {
     if (!module_search_path)
diff --git a/Modules/main.c b/Modules/main.c
index 9f0b01c..81a3d46 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -12,6 +12,7 @@
 #include <windows.h>
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
+#define PATH_MAX MAXPATHLEN
 #endif
 #endif
 
@@ -40,17 +41,17 @@
 #endif
 
 /* For Py_GetArgcArgv(); set by main() */
-static char **orig_argv;
+static wchar_t **orig_argv;
 static int  orig_argc;
 
 /* command line options */
-#define BASE_OPTS "bBc:dEhim:OStuvVW:xX?"
+#define BASE_OPTS L"bBc:dEhim:OStuvVW:xX?"
 
 #define PROGRAM_OPTS BASE_OPTS
 
 /* Short usage message (with %s for argv0) */
 static char *usage_line =
-"usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
+"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
 
 /* Long usage message, split into parts < 512 bytes */
 static char *usage_1 = "\
@@ -96,9 +97,30 @@
 PYTHONCASEOK : ignore case in 'import' statements (Windows).\n\
 ";
 
+#ifndef MS_WINDOWS
+static FILE*
+_wfopen(const wchar_t *path, const wchar_t *mode)
+{
+	char cpath[PATH_MAX];
+	char cmode[10];
+	size_t r;
+	r = wcstombs(cpath, path, PATH_MAX);
+	if (r == (size_t)-1 || r >= PATH_MAX) {
+		errno = EINVAL;
+		return NULL;
+	}
+	r = wcstombs(cmode, mode, 10);
+	if (r == (size_t)-1 || r >= 10) {
+		errno = EINVAL;
+		return NULL;
+	}
+	return fopen(cpath, cmode);
+}
+#endif
+
 
 static int
-usage(int exitcode, char* program)
+usage(int exitcode, wchar_t* program)
 {
 	FILE *f = exitcode ? stderr : stdout;
 
@@ -187,11 +209,11 @@
 	return 0;
 }
 
-static int RunMainFromImporter(char *filename)
+static int RunMainFromImporter(wchar_t *filename)
 {
 	PyObject *argv0 = NULL, *importer = NULL;
 
-	if ((argv0 = PyUnicode_DecodeFSDefault(filename)) &&
+	if ((argv0 = PyUnicode_FromWideChar(filename,wcslen(filename))) &&
 	    (importer = PyImport_GetImporter(argv0)) &&
 	    (importer->ob_type != &PyNullImporter_Type))
 	{
@@ -249,12 +271,12 @@
 /* Main program */
 
 int
-Py_Main(int argc, char **argv)
+Py_Main(int argc, wchar_t **argv)
 {
 	int c;
 	int sts;
 	char *command = NULL;
-	char *filename = NULL;
+	wchar_t *filename = NULL;
 	char *module = NULL;
 	FILE *fp = stdin;
 	char *p;
@@ -275,14 +297,19 @@
 
 	while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
 		if (c == 'c') {
+			size_t r1 = wcslen(_PyOS_optarg) + 2;
+			size_t r2;
 			/* -c is the last option; following arguments
 			   that look like options are left for the
 			   command to interpret. */
-			command = (char *)malloc(strlen(_PyOS_optarg) + 2);
+			command = (char *)malloc(r1);
 			if (command == NULL)
 				Py_FatalError(
 				   "not enough memory to copy -c argument");
-			strcpy(command, _PyOS_optarg);
+			r2 = wcstombs(command, _PyOS_optarg, r1);
+			if (r2 > r1-2)
+				Py_FatalError(
+				    "not enough memory to copy -c argument");
 			strcat(command, "\n");
 			break;
 		}
@@ -291,11 +318,16 @@
 			/* -m is the last option; following arguments
 			   that look like options are left for the
 			   module to interpret. */
-			module = (char *)malloc(strlen(_PyOS_optarg) + 2);
+			size_t r1 = wcslen(_PyOS_optarg) + 1;
+			size_t r2;
+			module = (char *)malloc(r1);
 			if (module == NULL)
 				Py_FatalError(
 				   "not enough memory to copy -m argument");
-			strcpy(module, _PyOS_optarg);
+			r2 = wcstombs(module, _PyOS_optarg, r1);
+			if (r2 >= r1)
+				Py_FatalError(
+				   "not enough memory to copy -m argument");
 			break;
 		}
 
@@ -355,7 +387,7 @@
 			version++;
 			break;
 
-		case 'W':
+		case 'W': 
 			PySys_AddWarnOption(_PyOS_optarg);
 			break;
 
@@ -384,7 +416,7 @@
 		unbuffered = 1;
 
 	if (command == NULL && module == NULL && _PyOS_optind < argc &&
-	    strcmp(argv[_PyOS_optind], "-") != 0)
+	    wcscmp(argv[_PyOS_optind], L"-") != 0)
 	{
 #ifdef __VMS
 		filename = decc$translate_vms(argv[_PyOS_optind]);
@@ -462,14 +494,14 @@
 	if (command != NULL) {
 		/* Backup _PyOS_optind and force sys.argv[0] = '-c' */
 		_PyOS_optind--;
-		argv[_PyOS_optind] = "-c";
+		argv[_PyOS_optind] = L"-c";
 	}
 
 	if (module != NULL) {
 		/* Backup _PyOS_optind and force sys.argv[0] = '-c'
 		   so that PySys_SetArgv correctly sets sys.path[0] to ''*/
 		_PyOS_optind--;
-		argv[_PyOS_optind] = "-c";
+		argv[_PyOS_optind] = L"-c";
 	}
 
 	PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
@@ -506,8 +538,8 @@
 		}
 
 		if (sts==-1 && filename!=NULL) {
-			if ((fp = fopen(filename, "r")) == NULL) {
-				fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
+			if ((fp = _wfopen(filename, L"r")) == NULL) {
+				fprintf(stderr, "%s: can't open file '%ls': [Errno %d] %s\n",
 					argv[0], filename, errno, strerror(errno));
 
 				return 2;
@@ -528,7 +560,7 @@
 				struct stat sb;
 				if (fstat(fileno(fp), &sb) == 0 &&
 				    S_ISDIR(sb.st_mode)) {
-					fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
+					fprintf(stderr, "%ls: '%ls' is a directory, cannot continue\n", argv[0], filename);
 					fclose(fp);
 					return 1;
 				}
@@ -536,9 +568,17 @@
 		}
 
 		if (sts==-1) {
+			char cfilename[PATH_MAX];
+			char *p_cfilename = "<stdin>";
+			if (filename) {
+				size_t r = wcstombs(cfilename, filename, PATH_MAX);
+				p_cfilename = cfilename;
+				if (r == (size_t)-1 || r >= PATH_MAX)
+					p_cfilename = "<decoding error>";
+			}
 			sts = PyRun_AnyFileExFlags(
 				fp,
-				filename == NULL ? "<stdin>" : filename,
+				p_cfilename,
 				filename != NULL, &cf) != 0;
 		}
 		
@@ -589,7 +629,7 @@
    This is rare, but it is needed by the secureware extension. */
 
 void
-Py_GetArgcArgv(int *argc, char ***argv)
+Py_GetArgcArgv(int *argc, wchar_t ***argv)
 {
 	*argc = orig_argc;
 	*argv = orig_argv;
diff --git a/Modules/python.c b/Modules/python.c
index 2739b8b..c1de64a 100644
--- a/Modules/python.c
+++ b/Modules/python.c
@@ -1,14 +1,27 @@
 /* Minimal main program -- everything is loaded from the library */
 
 #include "Python.h"
+#include <locale.h>
 
 #ifdef __FreeBSD__
 #include <floatingpoint.h>
 #endif
 
+#ifdef MS_WINDOWS
+int
+wmain(int argc, wchar_t **argv)
+{
+	return Py_Main(argc, argv);
+}
+#else
 int
 main(int argc, char **argv)
 {
+	wchar_t **argv_copy = PyMem_Malloc(sizeof(wchar_t*)*argc);
+	/* We need a second copies, as Python might modify the first one. */
+	wchar_t **argv_copy2 = PyMem_Malloc(sizeof(wchar_t*)*argc);
+	int i, res;
+	char *oldloc;
 	/* 754 requires that FP exceptions run in "no stop" mode by default,
 	 * and until C vendors implement C99's ways to control FP exceptions,
 	 * Python requires non-stop mode.  Alas, some platforms enable FP
@@ -20,5 +33,33 @@
 	m = fpgetmask();
 	fpsetmask(m & ~FP_X_OFL);
 #endif
-	return Py_Main(argc, argv);
+	if (!argv_copy || !argv_copy2) {
+		fprintf(stderr, "out of memory");
+		return 1;
+	}
+	oldloc = setlocale(LC_ALL, NULL);
+	setlocale(LC_ALL, "");
+	for (i = 0; i < argc; i++) {
+		size_t argsize = mbstowcs(NULL, argv[i], 0);
+		if (argsize == (size_t)-1) {
+			fprintf(stderr, "Could not convert argument %d to string", i);
+			return 1;
+		}
+		argv_copy[i] = PyMem_Malloc((argsize+1)*sizeof(wchar_t));
+		argv_copy2[i] = argv_copy[i];
+		if (!argv_copy[i]) {
+			fprintf(stderr, "out of memory");
+			return 1;
+		}
+		mbstowcs(argv_copy[i], argv[i], argsize+1);
+	}
+	setlocale(LC_ALL, oldloc);
+	res = Py_Main(argc, argv_copy);
+	for (i = 0; i < argc; i++) {
+		PyMem_Free(argv_copy2[i]);
+	}
+	PyMem_Free(argv_copy);
+	PyMem_Free(argv_copy2);
+	return res;
 }
+#endif