/PC/os2vacpp/getpathp.c

http://unladen-swallow.googlecode.com/ · C · 482 lines · 355 code · 52 blank · 75 comment · 92 complexity · 21bccf9374282acfc988ba2af8d5927a MD5 · raw file

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