xref: /aoo42x/main/pyuno/zipcore/python.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include <cstddef>
29*cdf0e10cSrcweir #include <stdlib.h>
30*cdf0e10cSrcweir #include <wchar.h>
31*cdf0e10cSrcweir 
32*cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
33*cdf0e10cSrcweir #if defined _MSC_VER
34*cdf0e10cSrcweir #pragma warning(push, 1)
35*cdf0e10cSrcweir #endif
36*cdf0e10cSrcweir #include <windows.h>
37*cdf0e10cSrcweir #if defined _MSC_VER
38*cdf0e10cSrcweir #pragma warning(pop)
39*cdf0e10cSrcweir #endif
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "tools/pathutils.hxx"
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #include "pyversion.hxx"
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
46*cdf0e10cSrcweir #define MY_STRING(s) (s), MY_LENGTH(s)
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir wchar_t * encode(wchar_t * buffer, wchar_t const * text) {
49*cdf0e10cSrcweir     *buffer++ = L'"';
50*cdf0e10cSrcweir     std::size_t n = 0;
51*cdf0e10cSrcweir     for (;;) {
52*cdf0e10cSrcweir         wchar_t c = *text++;
53*cdf0e10cSrcweir         if (c == L'\0') {
54*cdf0e10cSrcweir             break;
55*cdf0e10cSrcweir         } else if (c == L'"') {
56*cdf0e10cSrcweir             // Double any preceding backslashes as required by Windows:
57*cdf0e10cSrcweir             for (std::size_t i = 0; i < n; ++i) {
58*cdf0e10cSrcweir                 *buffer++ = L'\\';
59*cdf0e10cSrcweir             }
60*cdf0e10cSrcweir             *buffer++ = L'\\';
61*cdf0e10cSrcweir             *buffer++ = L'"';
62*cdf0e10cSrcweir             n = 0;
63*cdf0e10cSrcweir         } else if (c == L'\\') {
64*cdf0e10cSrcweir             *buffer++ = L'\\';
65*cdf0e10cSrcweir             ++n;
66*cdf0e10cSrcweir         } else {
67*cdf0e10cSrcweir             *buffer++ = c;
68*cdf0e10cSrcweir             n = 0;
69*cdf0e10cSrcweir         }
70*cdf0e10cSrcweir     }
71*cdf0e10cSrcweir     // The command line will continue with a double quote, so double any
72*cdf0e10cSrcweir     // preceding backslashes as required by Windows:
73*cdf0e10cSrcweir     for (std::size_t i = 0; i < n; ++i) {
74*cdf0e10cSrcweir         *buffer++ = L'\\';
75*cdf0e10cSrcweir     }
76*cdf0e10cSrcweir     *buffer++ = L'"';
77*cdf0e10cSrcweir     return buffer;
78*cdf0e10cSrcweir }
79*cdf0e10cSrcweir 
80*cdf0e10cSrcweir #ifdef __MINGW32__
81*cdf0e10cSrcweir int main(int argc, char ** argv, char **) {
82*cdf0e10cSrcweir #else
83*cdf0e10cSrcweir int wmain(int argc, wchar_t ** argv, wchar_t **) {
84*cdf0e10cSrcweir #endif
85*cdf0e10cSrcweir     wchar_t path[MAX_PATH];
86*cdf0e10cSrcweir     DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH);
87*cdf0e10cSrcweir     if (n == 0 || n >= MAX_PATH) {
88*cdf0e10cSrcweir         exit(EXIT_FAILURE);
89*cdf0e10cSrcweir     }
90*cdf0e10cSrcweir     wchar_t * pathEnd = tools::filename(path);
91*cdf0e10cSrcweir     *pathEnd = L'\0';
92*cdf0e10cSrcweir     n = GetEnvironmentVariableW(L"UNO_PATH", NULL, 0);
93*cdf0e10cSrcweir     if (n == 0) {
94*cdf0e10cSrcweir         if (GetLastError() != ERROR_ENVVAR_NOT_FOUND ||
95*cdf0e10cSrcweir             !SetEnvironmentVariableW(L"UNO_PATH", path))
96*cdf0e10cSrcweir         {
97*cdf0e10cSrcweir             exit(EXIT_FAILURE);
98*cdf0e10cSrcweir         }
99*cdf0e10cSrcweir     }
100*cdf0e10cSrcweir     wchar_t bootstrap[MY_LENGTH(L"vnd.sun.star.pathname:") + MAX_PATH] =
101*cdf0e10cSrcweir         L"vnd.sun.star.pathname:"; //TODO: overflow
102*cdf0e10cSrcweir     wchar_t * bootstrapEnd = tools::buildPath(
103*cdf0e10cSrcweir         bootstrap + MY_LENGTH(L"vnd.sun.star.pathname:"), path, pathEnd,
104*cdf0e10cSrcweir         MY_STRING(L"fundamental.ini"));
105*cdf0e10cSrcweir     if (bootstrapEnd == NULL ||
106*cdf0e10cSrcweir         (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link"))
107*cdf0e10cSrcweir          == NULL))
108*cdf0e10cSrcweir     {
109*cdf0e10cSrcweir         exit(EXIT_FAILURE);
110*cdf0e10cSrcweir     }
111*cdf0e10cSrcweir     pathEnd = tools::resolveLink(path);
112*cdf0e10cSrcweir     wchar_t path1[MAX_PATH];
113*cdf0e10cSrcweir     wchar_t * path1End = tools::buildPath(
114*cdf0e10cSrcweir         path1, path, pathEnd, MY_STRING(L"\\program"));
115*cdf0e10cSrcweir     if (path1End == NULL) {
116*cdf0e10cSrcweir         exit(EXIT_FAILURE);
117*cdf0e10cSrcweir     }
118*cdf0e10cSrcweir     wchar_t pythonpath2[MAX_PATH];
119*cdf0e10cSrcweir     wchar_t * pythonpath2End = tools::buildPath(
120*cdf0e10cSrcweir         pythonpath2, path, pathEnd,
121*cdf0e10cSrcweir         MY_STRING(L"\\program\\python-core-" MY_PYVERSION L"\\lib"));
122*cdf0e10cSrcweir     if (pythonpath2End == NULL) {
123*cdf0e10cSrcweir         exit(EXIT_FAILURE);
124*cdf0e10cSrcweir     }
125*cdf0e10cSrcweir     wchar_t pythonpath3[MAX_PATH];
126*cdf0e10cSrcweir     wchar_t * pythonpath3End = tools::buildPath(
127*cdf0e10cSrcweir         pythonpath3, path, pathEnd,
128*cdf0e10cSrcweir         MY_STRING(
129*cdf0e10cSrcweir             L"\\program\\python-core-" MY_PYVERSION L"\\lib\\site-packages"));
130*cdf0e10cSrcweir     if (pythonpath3End == NULL) {
131*cdf0e10cSrcweir         exit(EXIT_FAILURE);
132*cdf0e10cSrcweir     }
133*cdf0e10cSrcweir #ifdef __MINGW32__
134*cdf0e10cSrcweir     wchar_t pythonpath4[MAX_PATH];
135*cdf0e10cSrcweir     wchar_t * pythonpath4End = tools::buildPath(
136*cdf0e10cSrcweir         pythonpath4, path, pathEnd,
137*cdf0e10cSrcweir         MY_STRING(L"\\program\\python-core-" MY_PYVERSION L"\\lib\\lib-dynload"));
138*cdf0e10cSrcweir     if (pythonpath4End == NULL) {
139*cdf0e10cSrcweir         exit(EXIT_FAILURE);
140*cdf0e10cSrcweir     }
141*cdf0e10cSrcweir     wchar_t pythonpath5[MAX_PATH];
142*cdf0e10cSrcweir     wchar_t * pythonpath5End = tools::buildPath(
143*cdf0e10cSrcweir         pythonpath5, path, pathEnd,
144*cdf0e10cSrcweir         MY_STRING(L"\\program\\python-core-" MY_PYVERSION L"\\lib\\lib-dynload"));
145*cdf0e10cSrcweir     if (pythonpath5End == NULL) {
146*cdf0e10cSrcweir         exit(EXIT_FAILURE);
147*cdf0e10cSrcweir     }
148*cdf0e10cSrcweir #endif
149*cdf0e10cSrcweir     wchar_t pythonhome[MAX_PATH];
150*cdf0e10cSrcweir     wchar_t * pythonhomeEnd = tools::buildPath(
151*cdf0e10cSrcweir         pythonhome, path, pathEnd,
152*cdf0e10cSrcweir         MY_STRING(L"\\program\\python-core-" MY_PYVERSION));
153*cdf0e10cSrcweir     if (pythonhomeEnd == NULL) {
154*cdf0e10cSrcweir         exit(EXIT_FAILURE);
155*cdf0e10cSrcweir     }
156*cdf0e10cSrcweir     wchar_t pythonexe[MAX_PATH];
157*cdf0e10cSrcweir     wchar_t * pythonexeEnd = tools::buildPath(
158*cdf0e10cSrcweir         pythonexe, path, pathEnd,
159*cdf0e10cSrcweir #ifdef __MINGW32__
160*cdf0e10cSrcweir         MY_STRING(
161*cdf0e10cSrcweir             L"\\program\\python-core-" MY_PYVERSION L"\\bin\\python.bin"));
162*cdf0e10cSrcweir #else
163*cdf0e10cSrcweir         MY_STRING(
164*cdf0e10cSrcweir             L"\\program\\python-core-" MY_PYVERSION L"\\bin\\python.exe"));
165*cdf0e10cSrcweir #endif
166*cdf0e10cSrcweir     if (pythonexeEnd == NULL) {
167*cdf0e10cSrcweir         exit(EXIT_FAILURE);
168*cdf0e10cSrcweir     }
169*cdf0e10cSrcweir     if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL)
170*cdf0e10cSrcweir     {
171*cdf0e10cSrcweir         exit(EXIT_FAILURE);
172*cdf0e10cSrcweir     }
173*cdf0e10cSrcweir     pathEnd = tools::resolveLink(path);
174*cdf0e10cSrcweir     if (pathEnd == NULL) {
175*cdf0e10cSrcweir         exit(EXIT_FAILURE);
176*cdf0e10cSrcweir     }
177*cdf0e10cSrcweir     pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin"));
178*cdf0e10cSrcweir     if (pathEnd == NULL) {
179*cdf0e10cSrcweir         exit(EXIT_FAILURE);
180*cdf0e10cSrcweir     }
181*cdf0e10cSrcweir     std::size_t clSize = MY_LENGTH(L"\"") + 4 * (pythonexeEnd - pythonexe) +
182*cdf0e10cSrcweir         MY_LENGTH(L"\"\0"); //TODO: overflow
183*cdf0e10cSrcweir         // 4 * len: each char preceded by backslash, each trailing backslash
184*cdf0e10cSrcweir         // doubled
185*cdf0e10cSrcweir     for (int i = 1; i < argc; ++i) {
186*cdf0e10cSrcweir #ifdef __MINGW32__
187*cdf0e10cSrcweir         clSize += MY_LENGTH(L" \"") + 4 * strlen(argv[i]) +
188*cdf0e10cSrcweir #else
189*cdf0e10cSrcweir         clSize += MY_LENGTH(L" \"") + 4 * wcslen(argv[i]) +
190*cdf0e10cSrcweir #endif
191*cdf0e10cSrcweir             MY_LENGTH(L"\""); //TODO: overflow
192*cdf0e10cSrcweir     }
193*cdf0e10cSrcweir     wchar_t * cl = new wchar_t[clSize];
194*cdf0e10cSrcweir     if (cl == NULL) {
195*cdf0e10cSrcweir         exit(EXIT_FAILURE);
196*cdf0e10cSrcweir     }
197*cdf0e10cSrcweir     wchar_t * cp = encode(cl, pythonhome);
198*cdf0e10cSrcweir     for (int i = 1; i < argc; ++i) {
199*cdf0e10cSrcweir         *cp++ = L' ';
200*cdf0e10cSrcweir #ifdef __MINGW32__
201*cdf0e10cSrcweir         int nNeededWStrBuffSize = MultiByteToWideChar(CP_ACP, 0, argv[i], -1, NULL, 0);
202*cdf0e10cSrcweir         WCHAR *buff = new WCHAR[nNeededWStrBuffSize+1];
203*cdf0e10cSrcweir         MultiByteToWideChar(CP_ACP, 0, argv[i], -1, buff, nNeededWStrBuffSize);
204*cdf0e10cSrcweir         buff[nNeededWStrBuffSize] = 0;
205*cdf0e10cSrcweir         cp = encode(cp, buff);
206*cdf0e10cSrcweir         delete [] buff;
207*cdf0e10cSrcweir #else
208*cdf0e10cSrcweir         cp = encode(cp, argv[i]);
209*cdf0e10cSrcweir #endif
210*cdf0e10cSrcweir     }
211*cdf0e10cSrcweir     *cp = L'\0';
212*cdf0e10cSrcweir     n = GetEnvironmentVariableW(L"PATH", NULL, 0);
213*cdf0e10cSrcweir     wchar_t * orig;
214*cdf0e10cSrcweir     if (n == 0) {
215*cdf0e10cSrcweir         if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
216*cdf0e10cSrcweir             exit(EXIT_FAILURE);
217*cdf0e10cSrcweir         }
218*cdf0e10cSrcweir         orig = L"";
219*cdf0e10cSrcweir     } else {
220*cdf0e10cSrcweir         orig = new wchar_t[n];
221*cdf0e10cSrcweir         if (orig == NULL ||
222*cdf0e10cSrcweir             GetEnvironmentVariableW(L"PATH", orig, n) != n - 1)
223*cdf0e10cSrcweir         {
224*cdf0e10cSrcweir             exit(EXIT_FAILURE);
225*cdf0e10cSrcweir         }
226*cdf0e10cSrcweir     }
227*cdf0e10cSrcweir     wchar_t * value = new wchar_t[
228*cdf0e10cSrcweir         (pathEnd - path) + MY_LENGTH(L";") + (path1End - path1) +
229*cdf0e10cSrcweir         (n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1]; //TODO: overflow
230*cdf0e10cSrcweir     wsprintfW(value, L"%s;%s%s%s", path, path1, n == 0 ? L"" : L";", orig);
231*cdf0e10cSrcweir     if (!SetEnvironmentVariableW(L"PATH", value)) {
232*cdf0e10cSrcweir         exit(EXIT_FAILURE);
233*cdf0e10cSrcweir     }
234*cdf0e10cSrcweir     if (n != 0) {
235*cdf0e10cSrcweir         delete [] orig;
236*cdf0e10cSrcweir     }
237*cdf0e10cSrcweir     delete [] value;
238*cdf0e10cSrcweir     n = GetEnvironmentVariableW(L"PYTHONPATH", NULL, 0);
239*cdf0e10cSrcweir     if (n == 0) {
240*cdf0e10cSrcweir         if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
241*cdf0e10cSrcweir             exit(EXIT_FAILURE);
242*cdf0e10cSrcweir         }
243*cdf0e10cSrcweir         orig = L"";
244*cdf0e10cSrcweir     } else {
245*cdf0e10cSrcweir         orig = new wchar_t[n];
246*cdf0e10cSrcweir         if (orig == NULL ||
247*cdf0e10cSrcweir             GetEnvironmentVariableW(L"PYTHONPATH", orig, n) != n - 1)
248*cdf0e10cSrcweir         {
249*cdf0e10cSrcweir             exit(EXIT_FAILURE);
250*cdf0e10cSrcweir         }
251*cdf0e10cSrcweir     }
252*cdf0e10cSrcweir #ifdef __MINGW32__
253*cdf0e10cSrcweir     value = new wchar_t[
254*cdf0e10cSrcweir         (path1End - path1) + MY_LENGTH(L";") + (pythonpath2End - pythonpath2) +
255*cdf0e10cSrcweir         MY_LENGTH(L";") + (pythonpath4End - pythonpath4) +
256*cdf0e10cSrcweir         MY_LENGTH(L";") + (pythonpath5End - pythonpath5) +
257*cdf0e10cSrcweir         MY_LENGTH(L";") + (pythonpath3End - pythonpath3) +
258*cdf0e10cSrcweir         (n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1]; //TODO: overflow
259*cdf0e10cSrcweir     wsprintfW(
260*cdf0e10cSrcweir         value, L"%s;%s;%s;%s;%s%s%s", path1, pythonpath2, pythonpath4,
261*cdf0e10cSrcweir         pythonpath5, pythonpath3,
262*cdf0e10cSrcweir         n == 0 ? L"" : L";", orig);
263*cdf0e10cSrcweir #else
264*cdf0e10cSrcweir     value = new wchar_t[
265*cdf0e10cSrcweir         (path1End - path1) + MY_LENGTH(L";") + (pythonpath2End - pythonpath2) +
266*cdf0e10cSrcweir         MY_LENGTH(L";") + (pythonpath3End - pythonpath3) +
267*cdf0e10cSrcweir         (n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1]; //TODO: overflow
268*cdf0e10cSrcweir     wsprintfW(
269*cdf0e10cSrcweir         value, L"%s;%s;%s%s%s", path1, pythonpath2, pythonpath3,
270*cdf0e10cSrcweir         n == 0 ? L"" : L";", orig);
271*cdf0e10cSrcweir #endif
272*cdf0e10cSrcweir     if (!SetEnvironmentVariableW(L"PYTHONPATH", value)) {
273*cdf0e10cSrcweir         exit(EXIT_FAILURE);
274*cdf0e10cSrcweir     }
275*cdf0e10cSrcweir     if (n != 0) {
276*cdf0e10cSrcweir         delete [] orig;
277*cdf0e10cSrcweir     }
278*cdf0e10cSrcweir     delete [] value;
279*cdf0e10cSrcweir     if (!SetEnvironmentVariableW(L"PYTHONHOME", pythonhome)) {
280*cdf0e10cSrcweir         exit(EXIT_FAILURE);
281*cdf0e10cSrcweir     }
282*cdf0e10cSrcweir     n = GetEnvironmentVariableW(L"URE_BOOTSTRAP", NULL, 0);
283*cdf0e10cSrcweir     if (n == 0) {
284*cdf0e10cSrcweir         if (GetLastError() != ERROR_ENVVAR_NOT_FOUND ||
285*cdf0e10cSrcweir             !SetEnvironmentVariableW(L"URE_BOOTSTRAP", bootstrap))
286*cdf0e10cSrcweir         {
287*cdf0e10cSrcweir             exit(EXIT_FAILURE);
288*cdf0e10cSrcweir         }
289*cdf0e10cSrcweir     }
290*cdf0e10cSrcweir     STARTUPINFOW startinfo;
291*cdf0e10cSrcweir     ZeroMemory(&startinfo, sizeof (STARTUPINFOW));
292*cdf0e10cSrcweir     startinfo.cb = sizeof (STARTUPINFOW);
293*cdf0e10cSrcweir     PROCESS_INFORMATION procinfo;
294*cdf0e10cSrcweir     if (!CreateProcessW(
295*cdf0e10cSrcweir             pythonexe, cl, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, NULL,
296*cdf0e10cSrcweir             NULL, &startinfo, &procinfo)) {
297*cdf0e10cSrcweir         exit(EXIT_FAILURE);
298*cdf0e10cSrcweir     }
299*cdf0e10cSrcweir     WaitForSingleObject(procinfo.hProcess,INFINITE);
300*cdf0e10cSrcweir     DWORD exitStatus;
301*cdf0e10cSrcweir     GetExitCodeProcess(procinfo.hProcess,&exitStatus);
302*cdf0e10cSrcweir     exit(exitStatus);
303*cdf0e10cSrcweir }
304