5 |
5 |
6 This software may be used and distributed according to the terms of the |
6 This software may be used and distributed according to the terms of the |
7 GNU General Public License version 2 or any later version. |
7 GNU General Public License version 2 or any later version. |
8 */ |
8 */ |
9 |
9 |
10 #include <Python.h> |
10 #include <stdio.h> |
11 #include <windows.h> |
11 #include <windows.h> |
12 |
12 |
|
13 #include "hgpythonlib.h" |
13 |
14 |
14 #ifdef __GNUC__ |
15 #ifdef __GNUC__ |
15 int strcat_s(char *d, size_t n, const char *s) |
16 int strcat_s(char *d, size_t n, const char *s) |
16 { |
17 { |
17 return !strncat(d, s, n); |
18 return !strncat(d, s, n); |
18 } |
19 } |
|
20 int strcpy_s(char *d, size_t n, const char *s) |
|
21 { |
|
22 return !strncpy(d, s, n); |
|
23 } |
19 #endif |
24 #endif |
20 |
25 |
21 |
26 |
22 static char pyscript[MAX_PATH + 10]; |
27 static char pyscript[MAX_PATH + 10]; |
|
28 static char pyhome[MAX_PATH + 10]; |
|
29 static char envpyhome[MAX_PATH + 10]; |
|
30 static char pydllfile[MAX_PATH + 10]; |
23 |
31 |
24 int main(int argc, char *argv[]) |
32 int main(int argc, char *argv[]) |
25 { |
33 { |
26 char *dot; |
34 char *p; |
27 int ret; |
35 int ret; |
28 int i; |
36 int i; |
29 int n; |
37 int n; |
30 char **pyargv; |
38 char **pyargv; |
31 WIN32_FIND_DATA fdata; |
39 WIN32_FIND_DATA fdata; |
32 HANDLE hfind; |
40 HANDLE hfind; |
33 const char *err; |
41 const char *err; |
|
42 HMODULE pydll; |
|
43 void (__cdecl *Py_SetPythonHome)(char *home); |
|
44 int (__cdecl *Py_Main)(int argc, char *argv[]); |
34 |
45 |
35 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0) |
46 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0) |
36 { |
47 { |
37 err = "GetModuleFileName failed"; |
48 err = "GetModuleFileName failed"; |
38 goto bail; |
49 goto bail; |
39 } |
50 } |
40 |
51 |
41 dot = strrchr(pyscript, '.'); |
52 p = strrchr(pyscript, '.'); |
42 if (dot == NULL) { |
53 if (p == NULL) { |
43 err = "malformed module filename"; |
54 err = "malformed module filename"; |
44 goto bail; |
55 goto bail; |
45 } |
56 } |
46 *dot = 0; /* cut trailing ".exe" */ |
57 *p = 0; /* cut trailing ".exe" */ |
|
58 strcpy_s(pyhome, sizeof(pyhome), pyscript); |
47 |
59 |
48 hfind = FindFirstFile(pyscript, &fdata); |
60 hfind = FindFirstFile(pyscript, &fdata); |
49 if (hfind != INVALID_HANDLE_VALUE) { |
61 if (hfind != INVALID_HANDLE_VALUE) { |
50 /* pyscript exists, close handle */ |
62 /* pyscript exists, close handle */ |
51 FindClose(hfind); |
63 FindClose(hfind); |
52 } else { |
64 } else { |
53 /* file pyscript isn't there, take <pyscript>exe.py */ |
65 /* file pyscript isn't there, take <pyscript>exe.py */ |
54 strcat_s(pyscript, sizeof(pyscript), "exe.py"); |
66 strcat_s(pyscript, sizeof(pyscript), "exe.py"); |
|
67 } |
|
68 |
|
69 pydll = NULL; |
|
70 if (GetEnvironmentVariable("PYTHONHOME", envpyhome, |
|
71 sizeof(envpyhome)) == 0) |
|
72 { |
|
73 /* environment var PYTHONHOME is not set */ |
|
74 |
|
75 p = strrchr(pyhome, '\\'); |
|
76 if (p == NULL) { |
|
77 err = "can't find backslash in module filename"; |
|
78 goto bail; |
|
79 } |
|
80 *p = 0; /* cut at directory */ |
|
81 |
|
82 /* check for private Python of HackableMercurial */ |
|
83 strcat_s(pyhome, sizeof(pyhome), "\\hg-python"); |
|
84 |
|
85 hfind = FindFirstFile(pyhome, &fdata); |
|
86 if (hfind != INVALID_HANDLE_VALUE) { |
|
87 /* path pyhome exists, let's use it */ |
|
88 FindClose(hfind); |
|
89 strcpy_s(pydllfile, sizeof(pydllfile), pyhome); |
|
90 strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB); |
|
91 pydll = LoadLibrary(pydllfile); |
|
92 if (pydll == NULL) { |
|
93 err = "failed to load private Python DLL"; |
|
94 goto bail; |
|
95 } |
|
96 Py_SetPythonHome = (void*)GetProcAddress(pydll, |
|
97 "Py_SetPythonHome"); |
|
98 if (Py_SetPythonHome == NULL) { |
|
99 err = "failed to get Py_SetPythonHome"; |
|
100 goto bail; |
|
101 } |
|
102 Py_SetPythonHome(pyhome); |
|
103 } |
|
104 } |
|
105 |
|
106 if (pydll == NULL) { |
|
107 pydll = LoadLibrary(HGPYTHONLIB); |
|
108 if (pydll == NULL) { |
|
109 err = "failed to load Python DLL"; |
|
110 goto bail; |
|
111 } |
|
112 } |
|
113 |
|
114 Py_Main = (void*)GetProcAddress(pydll, "Py_Main"); |
|
115 if (Py_Main == NULL) { |
|
116 err = "failed to get Py_Main"; |
|
117 goto bail; |
55 } |
118 } |
56 |
119 |
57 /* |
120 /* |
58 Only add the pyscript to the args, if it's not already there. It may |
121 Only add the pyscript to the args, if it's not already there. It may |
59 already be there, if the script spawned a child process of itself, in |
122 already be there, if the script spawned a child process of itself, in |