##// END OF EJS Templates
exewrapper: report name of failed private DLL in error message...
Adrian Buehlmann -
r26663:fa6858be default
parent child Browse files
Show More
@@ -1,164 +1,165 b''
1 /*
1 /*
2 exewrapper.c - wrapper for calling a python script on Windows
2 exewrapper.c - wrapper for calling a python script on Windows
3
3
4 Copyright 2012 Adrian Buehlmann <adrian@cadifra.com> and others
4 Copyright 2012 Adrian Buehlmann <adrian@cadifra.com> and others
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 <stdio.h>
10 #include <stdio.h>
11 #include <windows.h>
11 #include <windows.h>
12
12
13 #include "hgpythonlib.h"
13 #include "hgpythonlib.h"
14
14
15 #ifdef __GNUC__
15 #ifdef __GNUC__
16 int strcat_s(char *d, size_t n, const char *s)
16 int strcat_s(char *d, size_t n, const char *s)
17 {
17 {
18 return !strncat(d, s, n);
18 return !strncat(d, s, n);
19 }
19 }
20 int strcpy_s(char *d, size_t n, const char *s)
20 int strcpy_s(char *d, size_t n, const char *s)
21 {
21 {
22 return !strncpy(d, s, n);
22 return !strncpy(d, s, n);
23 }
23 }
24 #endif
24 #endif
25
25
26
26
27 static char pyscript[MAX_PATH + 10];
27 static char pyscript[MAX_PATH + 10];
28 static char pyhome[MAX_PATH + 10];
28 static char pyhome[MAX_PATH + 10];
29 static char envpyhome[MAX_PATH + 10];
29 static char envpyhome[MAX_PATH + 10];
30 static char pydllfile[MAX_PATH + 10];
30 static char pydllfile[MAX_PATH + 10];
31
31
32 int main(int argc, char *argv[])
32 int main(int argc, char *argv[])
33 {
33 {
34 char *p;
34 char *p;
35 int ret;
35 int ret;
36 int i;
36 int i;
37 int n;
37 int n;
38 char **pyargv;
38 char **pyargv;
39 WIN32_FIND_DATA fdata;
39 WIN32_FIND_DATA fdata;
40 HANDLE hfind;
40 HANDLE hfind;
41 const char *err;
41 const char *err;
42 HMODULE pydll;
42 HMODULE pydll;
43 void (__cdecl *Py_SetPythonHome)(char *home);
43 void (__cdecl *Py_SetPythonHome)(char *home);
44 int (__cdecl *Py_Main)(int argc, char *argv[]);
44 int (__cdecl *Py_Main)(int argc, char *argv[]);
45
45
46 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
46 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
47 {
47 {
48 err = "GetModuleFileName failed";
48 err = "GetModuleFileName failed";
49 goto bail;
49 goto bail;
50 }
50 }
51
51
52 p = strrchr(pyscript, '.');
52 p = strrchr(pyscript, '.');
53 if (p == NULL) {
53 if (p == NULL) {
54 err = "malformed module filename";
54 err = "malformed module filename";
55 goto bail;
55 goto bail;
56 }
56 }
57 *p = 0; /* cut trailing ".exe" */
57 *p = 0; /* cut trailing ".exe" */
58 strcpy_s(pyhome, sizeof(pyhome), pyscript);
58 strcpy_s(pyhome, sizeof(pyhome), pyscript);
59
59
60 hfind = FindFirstFile(pyscript, &fdata);
60 hfind = FindFirstFile(pyscript, &fdata);
61 if (hfind != INVALID_HANDLE_VALUE) {
61 if (hfind != INVALID_HANDLE_VALUE) {
62 /* pyscript exists, close handle */
62 /* pyscript exists, close handle */
63 FindClose(hfind);
63 FindClose(hfind);
64 } else {
64 } else {
65 /* file pyscript isn't there, take <pyscript>exe.py */
65 /* file pyscript isn't there, take <pyscript>exe.py */
66 strcat_s(pyscript, sizeof(pyscript), "exe.py");
66 strcat_s(pyscript, sizeof(pyscript), "exe.py");
67 }
67 }
68
68
69 pydll = NULL;
69 pydll = NULL;
70 if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
70 if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
71 sizeof(envpyhome)) == 0)
71 sizeof(envpyhome)) == 0)
72 {
72 {
73 /* environment var PYTHONHOME is not set */
73 /* environment var PYTHONHOME is not set */
74
74
75 p = strrchr(pyhome, '\\');
75 p = strrchr(pyhome, '\\');
76 if (p == NULL) {
76 if (p == NULL) {
77 err = "can't find backslash in module filename";
77 err = "can't find backslash in module filename";
78 goto bail;
78 goto bail;
79 }
79 }
80 *p = 0; /* cut at directory */
80 *p = 0; /* cut at directory */
81
81
82 /* check for private Python of HackableMercurial */
82 /* check for private Python of HackableMercurial */
83 strcat_s(pyhome, sizeof(pyhome), "\\hg-python");
83 strcat_s(pyhome, sizeof(pyhome), "\\hg-python");
84
84
85 hfind = FindFirstFile(pyhome, &fdata);
85 hfind = FindFirstFile(pyhome, &fdata);
86 if (hfind != INVALID_HANDLE_VALUE) {
86 if (hfind != INVALID_HANDLE_VALUE) {
87 /* path pyhome exists, let's use it */
87 /* path pyhome exists, let's use it */
88 FindClose(hfind);
88 FindClose(hfind);
89 strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
89 strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
90 strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB);
90 strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB);
91 pydll = LoadLibrary(pydllfile);
91 pydll = LoadLibrary(pydllfile);
92 if (pydll == NULL) {
92 if (pydll == NULL) {
93 err = "failed to load private Python DLL";
93 err = "failed to load private Python DLL "
94 HGPYTHONLIB ".dll";
94 goto bail;
95 goto bail;
95 }
96 }
96 Py_SetPythonHome = (void*)GetProcAddress(pydll,
97 Py_SetPythonHome = (void*)GetProcAddress(pydll,
97 "Py_SetPythonHome");
98 "Py_SetPythonHome");
98 if (Py_SetPythonHome == NULL) {
99 if (Py_SetPythonHome == NULL) {
99 err = "failed to get Py_SetPythonHome";
100 err = "failed to get Py_SetPythonHome";
100 goto bail;
101 goto bail;
101 }
102 }
102 Py_SetPythonHome(pyhome);
103 Py_SetPythonHome(pyhome);
103 }
104 }
104 }
105 }
105
106
106 if (pydll == NULL) {
107 if (pydll == NULL) {
107 pydll = LoadLibrary(HGPYTHONLIB);
108 pydll = LoadLibrary(HGPYTHONLIB);
108 if (pydll == NULL) {
109 if (pydll == NULL) {
109 err = "failed to load Python DLL " HGPYTHONLIB ".dll";
110 err = "failed to load Python DLL " HGPYTHONLIB ".dll";
110 goto bail;
111 goto bail;
111 }
112 }
112 }
113 }
113
114
114 Py_Main = (void*)GetProcAddress(pydll, "Py_Main");
115 Py_Main = (void*)GetProcAddress(pydll, "Py_Main");
115 if (Py_Main == NULL) {
116 if (Py_Main == NULL) {
116 err = "failed to get Py_Main";
117 err = "failed to get Py_Main";
117 goto bail;
118 goto bail;
118 }
119 }
119
120
120 /*
121 /*
121 Only add the pyscript to the args, if it's not already there. It may
122 Only add the pyscript to the args, if it's not already there. It may
122 already be there, if the script spawned a child process of itself, in
123 already be there, if the script spawned a child process of itself, in
123 the same way as it got called, that is, with the pyscript already in
124 the same way as it got called, that is, with the pyscript already in
124 place. So we optionally accept the pyscript as the first argument
125 place. So we optionally accept the pyscript as the first argument
125 (argv[1]), letting our exe taking the role of the python interpreter.
126 (argv[1]), letting our exe taking the role of the python interpreter.
126 */
127 */
127 if (argc >= 2 && strcmp(argv[1], pyscript) == 0) {
128 if (argc >= 2 && strcmp(argv[1], pyscript) == 0) {
128 /*
129 /*
129 pyscript is already in the args, so there is no need to copy
130 pyscript is already in the args, so there is no need to copy
130 the args and we can directly call the python interpreter with
131 the args and we can directly call the python interpreter with
131 the original args.
132 the original args.
132 */
133 */
133 return Py_Main(argc, argv);
134 return Py_Main(argc, argv);
134 }
135 }
135
136
136 /*
137 /*
137 Start assembling the args for the Python interpreter call. We put the
138 Start assembling the args for the Python interpreter call. We put the
138 name of our exe (argv[0]) in the position where the python.exe
139 name of our exe (argv[0]) in the position where the python.exe
139 canonically is, and insert the pyscript next.
140 canonically is, and insert the pyscript next.
140 */
141 */
141 pyargv = malloc((argc + 5) * sizeof(char*));
142 pyargv = malloc((argc + 5) * sizeof(char*));
142 if (pyargv == NULL) {
143 if (pyargv == NULL) {
143 err = "not enough memory";
144 err = "not enough memory";
144 goto bail;
145 goto bail;
145 }
146 }
146 n = 0;
147 n = 0;
147 pyargv[n++] = argv[0];
148 pyargv[n++] = argv[0];
148 pyargv[n++] = pyscript;
149 pyargv[n++] = pyscript;
149
150
150 /* copy remaining args from the command line */
151 /* copy remaining args from the command line */
151 for (i = 1; i < argc; i++)
152 for (i = 1; i < argc; i++)
152 pyargv[n++] = argv[i];
153 pyargv[n++] = argv[i];
153 /* argv[argc] is guaranteed to be NULL, so we forward that guarantee */
154 /* argv[argc] is guaranteed to be NULL, so we forward that guarantee */
154 pyargv[n] = NULL;
155 pyargv[n] = NULL;
155
156
156 ret = Py_Main(n, pyargv); /* The Python interpreter call */
157 ret = Py_Main(n, pyargv); /* The Python interpreter call */
157
158
158 free(pyargv);
159 free(pyargv);
159 return ret;
160 return ret;
160
161
161 bail:
162 bail:
162 fprintf(stderr, "abort: %s\n", err);
163 fprintf(stderr, "abort: %s\n", err);
163 return 255;
164 return 255;
164 }
165 }
General Comments 0
You need to be logged in to leave comments. Login now