comparison bin/parpg.c.in @ 6:dd4ed4945411

Ported binary launcher to Windows. * Reorganized the parpg executable source so that it now compiles with the MSVC compiler (tested with MSVC Express 2010). * Cleaned up the launcher source by adding a bunch of const statements and removing the superfluous NULL_TERMINATE macro. * Fixed a few memory leaks in the launcher source by freeing malloced/calloced pointers; * Added a new SubstfileEscape builder to the SConstruct script used to escape certain sequences when substituting a template file. This is used to escape backslashes ("\") in c strings in the bin/parpg.c.in template for Windows paths. * Fixed the PY_LIB_DIR_DEFAULT for Windows so that it now correctly points to the default Python installation path. * Modified the SConstruct script to support compiling the launcher executable with debugging symbols in Windows with the DEBUG flag.
author M. George Hansen
date Sun, 22 May 2011 00:53:59 -0700
parents 33684971cdb1
children
comparison
equal deleted inserted replaced
5:33684971cdb1 6:dd4ed4945411
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <stdio.h> 2 #include <stdio.h>
3 #include <string.h> 3 #include <string.h>
4 #ifdef _MSC_VER 4 #ifdef _WIN32
5 # include <process.h> 5 # include <process.h>
6 #else 6 #else
7 # include <sys/types.h> 7 # include <sys/types.h>
8 # include <sys/wait.h> 8 # include <sys/wait.h>
9 #endif 9 #endif
10 10
11 #define CONCAT_ARRAYS(TYPE, ARRAY_A, SIZE_A, ARRAY_B, SIZE_B) \
12 (TYPE*)concatArrays((const void**)(ARRAY_A), (SIZE_A), \
13 (const void**)(ARRAY_B), (SIZE_B), sizeof(TYPE))
14
15 #define NULL_TERMINATE(TYPE, ARRAY, SIZE) \
16 (TYPE*)realloc(ARRAY, sizeof(TYPE) * (SIZE + 1))
17
18 #define ARRAY_LEN(ARRAY) (sizeof(ARRAY) / sizeof *(ARRAY)) 11 #define ARRAY_LEN(ARRAY) (sizeof(ARRAY) / sizeof *(ARRAY))
19 12
13 #define CONCAT_ARRAYS(TYPE, ARRAY_A, ARRAY_B) \
14 (TYPE*)concatArrays((const void** const)(ARRAY_A), \
15 ARRAY_LEN(ARRAY_A) * sizeof(TYPE), (const void** const)(ARRAY_B), \
16 ARRAY_LEN(ARRAY_B) * sizeof(TYPE), sizeof(TYPE))
17
20 void* 18 void*
21 concatArrays(const void* arrayA, size_t sizeA, 19 concatArrays(const void* const arrayA, const size_t sizeA,
22 const void* arrayB, size_t sizeB, size_t sizeType) { 20 const void* const arrayB, const size_t sizeB, const size_t sizeType) {
23 char* concatenatedArray = malloc(sizeType * (sizeA + sizeB)); 21 char* const concatenatedArray = malloc(sizeType * (sizeA + sizeB));
24 memcpy(concatenatedArray, arrayA, sizeA * sizeType); 22 memcpy(concatenatedArray, arrayA, sizeA * sizeType);
25 memcpy(concatenatedArray + sizeA * sizeType, arrayB, sizeB * sizeType); 23 memcpy(concatenatedArray + sizeA * sizeType, arrayB, sizeB * sizeType);
26 return concatenatedArray; 24 return concatenatedArray;
27 } 25 }
28 26
29 char* 27 char*
30 joinStr(char* strA, char* strB, char* separator) { 28 joinStr(const char* const strA, const char* const strB,
31 int lenA = strlen(strA); 29 const char* const separator) {
32 int lenB = strlen(strB); 30 const int lenA = strlen(strA);
33 int lenSeparator = strlen(separator); 31 const int lenB = strlen(strB);
34 char* concatenatedStr = malloc(lenA + lenB + lenSeparator + 1); 32 const int lenSeparator = strlen(separator);
33 char* const concatenatedStr = malloc(lenA + lenB + lenSeparator + 1);
35 memcpy(concatenatedStr, strA, lenA); 34 memcpy(concatenatedStr, strA, lenA);
36 memcpy(concatenatedStr + lenA, separator, lenSeparator); 35 memcpy(concatenatedStr + lenA, separator, lenSeparator);
37 memcpy(concatenatedStr + lenA + lenSeparator, strB, lenB + 1); 36 memcpy(concatenatedStr + lenA + lenSeparator, strB, lenB + 1);
38 return concatenatedStr; 37 return concatenatedStr;
39 } 38 }
40 39
41 int 40 int
42 spawnParpgProcess(char* pythonExecutable, char* configDir, int argc, 41 spawnParpgProcess(char* const pythonExecutable, char* const configDir,
43 char* argv[]) { 42 const int argc, char* const argv[]) {
44 char* baseArgs[] = {pythonExecutable, "-m", "parpg.main", configDir}; 43 const int sizeCharPtr = sizeof(char*);
45 int nBaseArgs = ARRAY_LEN(baseArgs); 44 const int nBaseArgs = 4;
46 int nAdditionalArgs = argc - 1; 45 char** const baseArgs = malloc(nBaseArgs * sizeCharPtr);
47 char* additionalArgs[nAdditionalArgs]; 46 const int nAdditionalArgs = argc - 1;
47 char** const additionalArgs =
48 (char**)malloc(nAdditionalArgs * sizeCharPtr);
49 const int nArgs = nBaseArgs + nAdditionalArgs;
50 char* const oldPythonPath = getenv("PYTHONPATH");
51 char* newPythonPath;
52 // Use calloc so that the last element is NULL.
53 char** const env = calloc(2, sizeCharPtr);
54 int exitStatus;
55 // Use calloc so that the last element is NULL.
56 char** const args = (char**)calloc(nArgs + 1, sizeCharPtr);
48 int i; 57 int i;
49 for (i = 1; i < argc; i++) { 58
50 additionalArgs[i - 1] = argv[i]; 59 baseArgs[0] = pythonExecutable;
60 baseArgs[1] = "-m";
61 baseArgs[2] = "parpg.main";
62 baseArgs[3] = configDir;
63 if (nAdditionalArgs > 0) {
64 for (i = 1; i < argc; i++) {
65 additionalArgs[i - 1] = argv[i];
66 }
67 memcpy(args, CONCAT_ARRAYS(char*, baseArgs, additionalArgs),
68 nArgs * sizeCharPtr);
69 } else {
70 // Use memcpy so that the last NULL element in args is preserved.
71 memcpy(args, baseArgs, nArgs * sizeCharPtr);
51 } 72 }
52 int nArgs = nBaseArgs + nAdditionalArgs; 73 if (oldPythonPath != 0) {
53 char** args = NULL_TERMINATE(char*, CONCAT_ARRAYS(char*, baseArgs, 74 newPythonPath = joinStr(oldPythonPath, "@PY_PACKAGES_DIR@", ":");
54 nBaseArgs, additionalArgs, nAdditionalArgs), nArgs); 75 } else {
55 char* oldPythonPath = getenv("PYTHONPATH"); 76 newPythonPath = "@PY_PACKAGES_DIR@";
56 char* newPythonPath = joinStr(oldPythonPath, "@PY_PACKAGES_DIR@", ":"); 77 }
57 int exitStatus; 78 env[0] = joinStr("PYTHONPATH=", newPythonPath, "");
58 char* env[2] = {joinStr("PYTHONPATH=", newPythonPath, ""), (char*)(0)}; 79 #ifdef _WIN32
59 #ifdef _MSC_VER 80 # ifdef _MSC_VER // MSVC deprecated POSIX spawn functions.
81 exitStatus = _spawnve(_P_WAIT, pythonExecutable, args, env);
82 # else
60 exitStatus = spawnve(P_WAIT, pythonExecutable, args, env); 83 exitStatus = spawnve(P_WAIT, pythonExecutable, args, env);
84 # endif
61 #else 85 #else
62 exitStatus = execve(pythonExecutable, args, env); 86 exitStatus = execve(pythonExecutable, args, env);
63 #endif 87 #endif
88 free(baseArgs);
89 free(additionalArgs);
90 free(env);
91 free(args);
64 return exitStatus; 92 return exitStatus;
65 } 93 }
66 94
67 int 95 int
68 main(int argc, char* argv[]) { 96 main(int argc, char* argv[]) {
69 int exitStatus = spawnParpgProcess("@PYTHON@", "@SYS_CONF_DIR@", argc, 97 const int exitStatus = spawnParpgProcess("@PYTHON@", "@SYS_CONF_DIR@",
70 argv); 98 argc, argv);
71 if (exitStatus) { 99 if (exitStatus < 0) {
72 perror("parpg exited with error"); 100 perror("failed to execute subprocess");
101 exit(EXIT_FAILURE);
102 } else {
103 exit(EXIT_SUCCESS);
73 } 104 }
74 return exitStatus;
75 } 105 }
76 106