Issue #7518: Move substitute definitions of C99 math functions from
[python.git] / PC / os2vacpp / getpathp.c
blob607f2a192a56a327d16d317f187132081fa9e3f3
2 /* Return the initial module search path. */
3 /* Used by DOS, OS/2, Windows 3.1. Works on NT too. */
5 #include "Python.h"
6 #include "osdefs.h"
8 #ifdef MS_WIN32
9 #include <windows.h>
10 extern BOOL PyWin_IsWin32s(void);
11 #endif
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <string.h>
17 #if HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif /* HAVE_UNISTD_H */
21 /* Search in some common locations for the associated Python libraries.
23 * Two directories must be found, the platform independent directory
24 * (prefix), containing the common .py and .pyc files, and the platform
25 * dependent directory (exec_prefix), containing the shared library
26 * modules. Note that prefix and exec_prefix can be the same directory,
27 * but for some installations, they are different.
29 * Py_GetPath() tries to return a sensible Python module search path.
31 * First, we look to see if the executable is in a subdirectory of
32 * the Python build directory. We calculate the full path of the
33 * directory containing the executable as progpath. We work backwards
34 * along progpath and look for $dir/Modules/Setup.in, a distinctive
35 * landmark. If found, we use $dir/Lib as $root. The returned
36 * Python path is the compiled #define PYTHONPATH with all the initial
37 * "./lib" replaced by $root.
39 * Otherwise, if there is a PYTHONPATH environment variable, we return that.
41 * Otherwise we try to find $progpath/lib/os.py, and if found, then
42 * root is $progpath/lib, and we return Python path as compiled PYTHONPATH
43 * with all "./lib" replaced by $root (as above).
47 #ifndef LANDMARK
48 #define LANDMARK "lib\\os.py"
49 #endif
51 static char prefix[MAXPATHLEN+1];
52 static char exec_prefix[MAXPATHLEN+1];
53 static char progpath[MAXPATHLEN+1];
54 static char *module_search_path = NULL;
57 static int
58 is_sep(char ch) /* determine if "ch" is a separator character */
60 #ifdef ALTSEP
61 return ch == SEP || ch == ALTSEP;
62 #else
63 return ch == SEP;
64 #endif
68 static void
69 reduce(char *dir)
71 int i = strlen(dir);
72 while (i > 0 && !is_sep(dir[i]))
73 --i;
74 dir[i] = '\0';
78 static int
79 exists(char *filename)
81 struct stat buf;
82 return stat(filename, &buf) == 0;
86 /* Add a path component, by appending stuff to buffer.
87 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
88 NUL-terminated string with no more than MAXPATHLEN characters (not counting
89 the trailing NUL). It's a fatal error if it contains a string longer than
90 that (callers must be careful!). If these requirements are met, it's
91 guaranteed that buffer will still be a NUL-terminated string with no more
92 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
93 stuff as fits will be appended.
95 static void
96 join(char *buffer, char *stuff)
98 int n, k;
99 if (is_sep(stuff[0]))
100 n = 0;
101 else {
102 n = strlen(buffer);
103 if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
104 buffer[n++] = SEP;
106 if (n > MAXPATHLEN)
107 Py_FatalError("buffer overflow in getpathp.c's joinpath()");
108 k = strlen(stuff);
109 if (n + k > MAXPATHLEN)
110 k = MAXPATHLEN - n;
111 strncpy(buffer+n, stuff, k);
112 buffer[n+k] = '\0';
116 static int
117 search_for_prefix(char *argv0_path, char *landmark)
119 int n;
121 /* Search from argv0_path, until root is found */
122 strcpy(prefix, argv0_path);
123 do {
124 n = strlen(prefix);
125 join(prefix, landmark);
126 if (exists(prefix)) {
127 prefix[n] = '\0';
128 return 1;
130 prefix[n] = '\0';
131 reduce(prefix);
132 } while (prefix[0]);
133 return 0;
136 #ifdef MS_WIN32
137 #include "malloc.h" // for alloca - see comments below!
138 extern const char *PyWin_DLLVersionString; // a string loaded from the DLL at startup.
141 /* Load a PYTHONPATH value from the registry.
142 Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
144 Returns NULL, or a pointer that should be freed.
147 static char *
148 getpythonregpath(HKEY keyBase, BOOL bWin32s)
150 HKEY newKey = 0;
151 DWORD nameSize = 0;
152 DWORD dataSize = 0;
153 DWORD numEntries = 0;
154 LONG rc;
155 char *retval = NULL;
156 char *dataBuf;
157 const char keyPrefix[] = "Software\\Python\\PythonCore\\";
158 const char keySuffix[] = "\\PythonPath";
159 int versionLen;
160 char *keyBuf;
162 // Tried to use sysget("winver") but here is too early :-(
163 versionLen = strlen(PyWin_DLLVersionString);
164 // alloca == no free required, but memory only local to fn.
165 // also no heap fragmentation! Am I being silly?
166 keyBuf = alloca(sizeof(keyPrefix)-1 + versionLen + sizeof(keySuffix)); // chars only, plus 1 NULL.
167 // lots of constants here for the compiler to optimize away :-)
168 memcpy(keyBuf, keyPrefix, sizeof(keyPrefix)-1);
169 memcpy(keyBuf+sizeof(keyPrefix)-1, PyWin_DLLVersionString, versionLen);
170 memcpy(keyBuf+sizeof(keyPrefix)-1+versionLen, keySuffix, sizeof(keySuffix)); // NULL comes with this one!
172 rc=RegOpenKey(keyBase,
173 keyBuf,
174 &newKey);
175 if (rc==ERROR_SUCCESS) {
176 RegQueryInfoKey(newKey, NULL, NULL, NULL, NULL, NULL, NULL,
177 &numEntries, &nameSize, &dataSize, NULL, NULL);
179 if (bWin32s && numEntries==0 && dataSize==0) {
180 /* must hardcode for Win32s */
181 numEntries = 1;
182 dataSize = 511;
184 if (numEntries) {
185 /* Loop over all subkeys. */
186 /* Win32s doesnt know how many subkeys, so we do
187 it twice */
188 char keyBuf[MAX_PATH+1];
189 int index = 0;
190 int off = 0;
191 for(index=0;;index++) {
192 long reqdSize = 0;
193 DWORD rc = RegEnumKey(newKey,
194 index, keyBuf, MAX_PATH+1);
195 if (rc) break;
196 rc = RegQueryValue(newKey, keyBuf, NULL, &reqdSize);
197 if (rc) break;
198 if (bWin32s && reqdSize==0) reqdSize = 512;
199 dataSize += reqdSize + 1; /* 1 for the ";" */
201 dataBuf = malloc(dataSize+1);
202 if (dataBuf==NULL)
203 return NULL; /* pretty serious? Raise error? */
204 /* Now loop over, grabbing the paths.
205 Subkeys before main library */
206 for(index=0;;index++) {
207 int adjust;
208 long reqdSize = dataSize;
209 DWORD rc = RegEnumKey(newKey,
210 index, keyBuf,MAX_PATH+1);
211 if (rc) break;
212 rc = RegQueryValue(newKey,
213 keyBuf, dataBuf+off, &reqdSize);
214 if (rc) break;
215 if (reqdSize>1) {
216 /* If Nothing, or only '\0' copied. */
217 adjust = strlen(dataBuf+off);
218 dataSize -= adjust;
219 off += adjust;
220 dataBuf[off++] = ';';
221 dataBuf[off] = '\0';
222 dataSize--;
225 /* Additionally, win32s doesnt work as expected, so
226 the specific strlen() is required for 3.1. */
227 rc = RegQueryValue(newKey, "", dataBuf+off, &dataSize);
228 if (rc==ERROR_SUCCESS) {
229 if (strlen(dataBuf)==0)
230 free(dataBuf);
231 else
232 retval = dataBuf; /* caller will free */
234 else
235 free(dataBuf);
238 if (newKey)
239 RegCloseKey(newKey);
240 return retval;
242 #endif /* MS_WIN32 */
244 static void
245 get_progpath(void)
247 extern char *Py_GetProgramName(void);
248 char *path = getenv("PATH");
249 char *prog = Py_GetProgramName();
251 #ifdef MS_WIN32
252 if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
253 return;
254 #endif
255 if (prog == NULL || *prog == '\0')
256 prog = "python";
258 /* If there is no slash in the argv0 path, then we have to
259 * assume python is on the user's $PATH, since there's no
260 * other way to find a directory to start the search from. If
261 * $PATH isn't exported, you lose.
263 #ifdef ALTSEP
264 if (strchr(prog, SEP) || strchr(prog, ALTSEP))
265 #else
266 if (strchr(prog, SEP))
267 #endif
268 strcpy(progpath, prog);
269 else if (path) {
270 while (1) {
271 char *delim = strchr(path, DELIM);
273 if (delim) {
274 int len = delim - path;
275 strncpy(progpath, path, len);
276 *(progpath + len) = '\0';
278 else
279 strcpy(progpath, path);
281 join(progpath, prog);
282 if (exists(progpath))
283 break;
285 if (!delim) {
286 progpath[0] = '\0';
287 break;
289 path = delim + 1;
292 else
293 progpath[0] = '\0';
296 static void
297 calculate_path(void)
299 char argv0_path[MAXPATHLEN+1];
300 char *buf;
301 int bufsz;
302 char *pythonhome = Py_GetPythonHome();
303 char *envpath = Py_GETENV("PYTHONPATH");
304 #ifdef MS_WIN32
305 char *machinepath, *userpath;
307 /* Are we running under Windows 3.1(1) Win32s? */
308 if (PyWin_IsWin32s()) {
309 /* Only CLASSES_ROOT is supported */
310 machinepath = getpythonregpath(HKEY_CLASSES_ROOT, TRUE);
311 userpath = NULL;
312 } else {
313 machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, FALSE);
314 userpath = getpythonregpath(HKEY_CURRENT_USER, FALSE);
316 #endif
318 get_progpath();
319 strcpy(argv0_path, progpath);
320 reduce(argv0_path);
321 if (pythonhome == NULL || *pythonhome == '\0') {
322 if (search_for_prefix(argv0_path, LANDMARK))
323 pythonhome = prefix;
324 else
325 pythonhome = NULL;
327 else {
328 char *delim;
330 strcpy(prefix, pythonhome);
332 /* Extract Any Optional Trailing EXEC_PREFIX */
333 /* e.g. PYTHONHOME=<prefix>:<exec_prefix> */
334 delim = strchr(prefix, DELIM);
335 if (delim) {
336 *delim = '\0';
337 strcpy(exec_prefix, delim+1);
338 } else
339 strcpy(exec_prefix, EXEC_PREFIX);
342 if (envpath && *envpath == '\0')
343 envpath = NULL;
345 /* We need to construct a path from the following parts:
346 (1) the PYTHONPATH environment variable, if set;
347 (2) for Win32, the machinepath and userpath, if set;
348 (3) the PYTHONPATH config macro, with the leading "."
349 of each component replaced with pythonhome, if set;
350 (4) the directory containing the executable (argv0_path).
351 The length calculation calculates #3 first.
354 /* Calculate size of return buffer */
355 if (pythonhome != NULL) {
356 char *p;
357 bufsz = 1;
358 for (p = PYTHONPATH; *p; p++) {
359 if (*p == DELIM)
360 bufsz++; /* number of DELIM plus one */
362 bufsz *= strlen(pythonhome);
364 else
365 bufsz = 0;
366 bufsz += strlen(PYTHONPATH) + 1;
367 if (envpath != NULL)
368 bufsz += strlen(envpath) + 1;
369 bufsz += strlen(argv0_path) + 1;
370 #ifdef MS_WIN32
371 if (machinepath)
372 bufsz += strlen(machinepath) + 1;
373 if (userpath)
374 bufsz += strlen(userpath) + 1;
375 #endif
377 module_search_path = buf = malloc(bufsz);
378 if (buf == NULL) {
379 /* We can't exit, so print a warning and limp along */
380 fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
381 if (envpath) {
382 fprintf(stderr, "Using default static $PYTHONPATH.\n");
383 module_search_path = envpath;
385 else {
386 fprintf(stderr, "Using environment $PYTHONPATH.\n");
387 module_search_path = PYTHONPATH;
389 return;
392 if (envpath) {
393 strcpy(buf, envpath);
394 buf = strchr(buf, '\0');
395 *buf++ = DELIM;
397 #ifdef MS_WIN32
398 if (machinepath) {
399 strcpy(buf, machinepath);
400 buf = strchr(buf, '\0');
401 *buf++ = DELIM;
403 if (userpath) {
404 strcpy(buf, userpath);
405 buf = strchr(buf, '\0');
406 *buf++ = DELIM;
408 #endif
409 if (pythonhome == NULL) {
410 strcpy(buf, PYTHONPATH);
411 buf = strchr(buf, '\0');
413 else {
414 char *p = PYTHONPATH;
415 char *q;
416 int n;
417 for (;;) {
418 q = strchr(p, DELIM);
419 if (q == NULL)
420 n = strlen(p);
421 else
422 n = q-p;
423 if (p[0] == '.' && is_sep(p[1])) {
424 strcpy(buf, pythonhome);
425 buf = strchr(buf, '\0');
426 p++;
427 n--;
429 strncpy(buf, p, n);
430 buf += n;
431 if (q == NULL)
432 break;
433 *buf++ = DELIM;
434 p = q+1;
437 if (argv0_path) {
438 *buf++ = DELIM;
439 strcpy(buf, argv0_path);
440 buf = strchr(buf, '\0');
442 *buf = '\0';
446 /* External interface */
448 char *
449 Py_GetPath(void)
451 if (!module_search_path)
452 calculate_path();
454 return module_search_path;
457 char *
458 Py_GetPrefix(void)
460 if (!module_search_path)
461 calculate_path();
463 return prefix;
466 char *
467 Py_GetExecPrefix(void)
469 if (!module_search_path)
470 calculate_path();
472 return exec_prefix;
475 char *
476 Py_GetProgramFullPath(void)
478 if (!module_search_path)
479 calculate_path();
481 return progpath;