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