blob: b6279e775ac68b46577abd7b6f2b22b52a197511 [file] [log] [blame]
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Return the initial module search path. */
33/* Used by DOS, OS/2, Windows 3.1. Works on NT too. */
34
35#include "Python.h"
36#include "osdefs.h"
37
Guido van Rossum8f1b6511997-08-13 19:55:43 +000038#ifdef MS_WIN32
39#include <windows.h>
40#endif
41
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000042#include <sys/types.h>
43#include <sys/stat.h>
44#include <string.h>
45
46#if HAVE_UNISTD_H
47#include <unistd.h>
48#endif /* HAVE_UNISTD_H */
49
50/* Search in some common locations for the associated Python libraries.
51 *
52 * This version always returns "" for both prefix and exec_prefix.
53 *
54 * Py_GetPath() tries to return a sensible Python module search path.
55 *
56 * First, we look to see if the executable is in a subdirectory of
57 * the Python build directory. We calculate the full path of the
58 * directory containing the executable as progpath. We work backwards
59 * along progpath and look for $dir/Modules/Setup.in, a distinctive
60 * landmark. If found, we use $dir/Lib as $root. The returned
61 * Python path is the compiled #define PYTHONPATH with all the initial
62 * "./lib" replaced by $root.
63 *
64 * Otherwise, if there is a PYTHONPATH environment variable, we return that.
65 *
66 * Otherwise we try to find $progpath/lib/string.py, and if found, then
67 * root is $progpath/lib, and we return Python path as compiled PYTHONPATH
68 * with all "./lib" replaced by $root (as above).
69 *
70 */
71
72#ifndef LANDMARK
73#define LANDMARK "Modules\\Setup.in"
74#endif
75
76static char prefix[MAXPATHLEN+1];
77static char progpath[MAXPATHLEN+1];
78static char *module_search_path = NULL;
79
80static int
81is_sep(ch) /* determine if "ch" is a separator character */
82 char ch;
83{
84#ifdef ALTSEP
85 return ch == SEP || ch == ALTSEP;
86#else
87 return ch == SEP;
88#endif
89}
90
91static void
92reduce(dir)
93 char *dir;
94{
95 int i = strlen(dir);
96 while (i > 0 && !is_sep(dir[i]))
97 --i;
98 dir[i] = '\0';
99}
100
101
102static int
103exists(filename)
104 char *filename;
105{
106 struct stat buf;
107 return stat(filename, &buf) == 0;
108}
109
110
111static void
112join(buffer, stuff)
113 char *buffer;
114 char *stuff;
115{
116 int n, k;
117 if (is_sep(stuff[0]))
118 n = 0;
119 else {
120 n = strlen(buffer);
121 if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
122 buffer[n++] = SEP;
123 }
124 k = strlen(stuff);
125 if (n + k > MAXPATHLEN)
126 k = MAXPATHLEN - n;
127 strncpy(buffer+n, stuff, k);
128 buffer[n+k] = '\0';
129}
130
131
132static int
133search_for_prefix(argv0_path, landmark)
134 char *argv0_path;
135 char *landmark;
136{
137 int n;
138
139 /* Search from argv0_path, until root is found */
140 strcpy(prefix, argv0_path);
141 do {
142 n = strlen(prefix);
143 join(prefix, landmark);
144 if (exists(prefix))
145 return 1;
146 prefix[n] = '\0';
147 reduce(prefix);
148 } while (prefix[0]);
149 return 0;
150}
151
152static void
153get_progpath()
154{
155#ifdef MS_WIN32
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000156 if (!GetModuleFileName(NULL, progpath, MAXPATHLEN))
157 progpath[0] = '\0'; /* failure */
158#else
159 extern char *Py_GetProgramName();
160 char *path = getenv("PATH");
161 char *prog = Py_GetProgramName();
162
163 /* If there is no slash in the argv0 path, then we have to
164 * assume python is on the user's $PATH, since there's no
165 * other way to find a directory to start the search from. If
166 * $PATH isn't exported, you lose.
167 */
168#ifdef ALTSEP
169 if (strchr(prog, SEP) || strchr(prog, ALTSEP))
170#else
171 if (strchr(prog, SEP))
172#endif
173 strcpy(progpath, prog);
174 else if (path) {
175 while (1) {
176 char *delim = strchr(path, DELIM);
177
178 if (delim) {
179 int len = delim - path;
180 strncpy(progpath, path, len);
181 *(progpath + len) = '\0';
182 }
183 else
184 strcpy(progpath, path);
185
186 join(progpath, prog);
187 if (exists(progpath))
188 break;
189
190 if (!delim) {
191 progpath[0] = '\0';
192 break;
193 }
194 path = delim + 1;
195 }
196 }
197 else
198 progpath[0] = '\0';
199#endif
200}
201
202static void
203calculate_path()
204{
205 char ch, *pt, *pt2;
206 char argv0_path[MAXPATHLEN+1];
207 char *buf;
208 int bufsz;
209
210 get_progpath();
211 strcpy(argv0_path, progpath);
212 reduce(argv0_path);
213
214 if (search_for_prefix(argv0_path, LANDMARK)) {
215 reduce(prefix);
216 reduce(prefix);
217 join(prefix, "lib");
218 }
219 else if ((module_search_path = getenv("PYTHONPATH")) != 0) {
220 return; /* if PYTHONPATH environment variable exists, we are done */
221 }
222 else { /* Try the executable_directory/lib */
223 strcpy(prefix, progpath);
224 reduce(prefix);
225 join(prefix, "lib");
226 join(prefix, "string.py"); /* Look for lib/string.py */
227 if (exists(prefix)) {
228 reduce(prefix);
229 }
230 else { /* No module search path!!! */
231 module_search_path = PYTHONPATH;
232 return;
233 }
234 }
235
236
237 /* If we get here, we need to return a path equal to the compiled
238 PYTHONPATH with ".\lib" replaced by our "prefix" directory */
239
240 bufsz = 1; /* Calculate size of return buffer. */
241 for (pt = PYTHONPATH; *pt; pt++)
242 if (*pt == DELIM)
243 bufsz++; /* number of DELIM plus one */
244 bufsz *= strlen(PYTHONPATH) + strlen(prefix); /* high estimate */
Guido van Rossum8f1b6511997-08-13 19:55:43 +0000245 bufsz += strlen(argv0_path) + 1;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000246
247 module_search_path = buf = malloc(bufsz);
248
249 if (buf == NULL) {
250 /* We can't exit, so print a warning and limp along */
251 fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
252 fprintf(stderr, "Using default static PYTHONPATH.\n");
253 module_search_path = PYTHONPATH;
254 return;
255 }
256 for (pt = PYTHONPATH; *pt; pt++) {
257 if (!strncmp(pt, ".\\lib", 5) &&
Guido van Rossum8f1b6511997-08-13 19:55:43 +0000258 ((ch = *(pt + 5)) == '\\' || ch == DELIM || !ch)) {
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000259 pt += 4;
260 for (pt2 = prefix; *pt2; pt2++)
261 *buf++ = *pt2;
262 }
263 else
264 *buf++ = *pt;
265 }
Guido van Rossum8f1b6511997-08-13 19:55:43 +0000266 *buf++ = DELIM;
267 strcpy(buf, argv0_path);
268 buf += strlen(buf);
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000269 *buf = '\0';
270}
271
272
273/* External interface */
274
275char *
276Py_GetPath()
277{
278 if (!module_search_path)
279 calculate_path();
280 return module_search_path;
281}
282
283char *
284Py_GetPrefix()
285{
286 return "";
287}
288
289char *
290Py_GetExecPrefix()
291{
292 return "";
293}
294
295char *
296Py_GetProgramFullPath() /* Full path to Python executable */
297{
298 if (!module_search_path)
299 calculate_path();
300 return progpath;
301}