mercurial/exewrapper.c
changeset 17732 93d97a212559
parent 17063 3fbc6e3abdbd
child 26662 d215def59c3b
equal deleted inserted replaced
17731:c85dbae29684 17732:93d97a212559
     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