|
1 /*********************************************************** |
|
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, |
|
3 The Netherlands. |
|
4 |
|
5 All Rights Reserved |
|
6 |
|
7 Permission to use, copy, modify, and distribute this software and its |
|
8 documentation for any purpose and without fee is hereby granted, |
|
9 provided that the above copyright notice appear in all copies and that |
|
10 both that copyright notice and this permission notice appear in |
|
11 supporting documentation, and that the names of Stichting Mathematisch |
|
12 Centrum or CWI or Corporation for National Research Initiatives or |
|
13 CNRI not be used in advertising or publicity pertaining to |
|
14 distribution of the software without specific, written prior |
|
15 permission. |
|
16 |
|
17 While CWI is the initial source for this software, a modified version |
|
18 is made available by the Corporation for National Research Initiatives |
|
19 (CNRI) at the Internet address ftp://ftp.python.org. |
|
20 |
|
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH |
|
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF |
|
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH |
|
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL |
|
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
|
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
|
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
28 PERFORMANCE OF THIS SOFTWARE. |
|
29 |
|
30 ******************************************************************/ |
|
31 |
|
32 /* A special version for minimal installs, where |
|
33 the bootstrap path is the directory in which |
|
34 the executable lives. |
|
35 Gordon McMillan, McMillan Enterprises, Inc. */ |
|
36 |
|
37 /* Return the initial module search path. */ |
|
38 |
|
39 #include "Python.h" |
|
40 #include "osdefs.h" |
|
41 |
|
42 #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 #ifdef WITH_NEXT_FRAMEWORK |
|
51 #include <mach-o/dyld.h> |
|
52 #endif |
|
53 |
|
54 static char prefix[MAXPATHLEN+1]; |
|
55 static char *exec_prefix; |
|
56 static char progpath[MAXPATHLEN+1]; |
|
57 static char *module_search_path = NULL; |
|
58 |
|
59 static void |
|
60 reduce(char *dir) |
|
61 { |
|
62 int i = strlen(dir); |
|
63 while (i > 0 && dir[i] != SEP) |
|
64 --i; |
|
65 dir[i] = '\0'; |
|
66 } |
|
67 |
|
68 |
|
69 #ifndef S_ISREG |
|
70 #define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) |
|
71 #endif |
|
72 |
|
73 #ifndef S_ISDIR |
|
74 #define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) |
|
75 #endif |
|
76 #if 0 |
|
77 static int |
|
78 isfile(char *filename) /* Is file, not directory */ |
|
79 { |
|
80 struct stat buf; |
|
81 if (stat(filename, &buf) != 0) |
|
82 return 0; |
|
83 if (!S_ISREG(buf.st_mode)) |
|
84 return 0; |
|
85 return 1; |
|
86 } |
|
87 #endif |
|
88 #if 0 |
|
89 static int |
|
90 ismodule(char *filename) /* Is module -- check for .pyc/.pyo too */ |
|
91 { |
|
92 if (isfile(filename)) |
|
93 return 1; |
|
94 |
|
95 /* Check for the compiled version of prefix. */ |
|
96 if (strlen(filename) < MAXPATHLEN) { |
|
97 strcat(filename, Py_OptimizeFlag ? "o" : "c"); |
|
98 if (isfile(filename)) |
|
99 return 1; |
|
100 } |
|
101 return 0; |
|
102 } |
|
103 #endif |
|
104 |
|
105 static int |
|
106 isxfile(char *filename) /* Is executable file */ |
|
107 { |
|
108 struct stat buf; |
|
109 if (stat(filename, &buf) != 0) |
|
110 return 0; |
|
111 if (!S_ISREG(buf.st_mode)) |
|
112 return 0; |
|
113 if ((buf.st_mode & 0111) == 0) |
|
114 return 0; |
|
115 return 1; |
|
116 } |
|
117 |
|
118 #if 0 |
|
119 static int |
|
120 isdir(char *filename) /* Is directory */ |
|
121 { |
|
122 struct stat buf; |
|
123 if (stat(filename, &buf) != 0) |
|
124 return 0; |
|
125 if (!S_ISDIR(buf.st_mode)) |
|
126 return 0; |
|
127 return 1; |
|
128 } |
|
129 #endif |
|
130 |
|
131 static void |
|
132 joinpath(char *buffer, char *stuff) |
|
133 { |
|
134 int n, k; |
|
135 if (stuff[0] == SEP) |
|
136 n = 0; |
|
137 else { |
|
138 n = strlen(buffer); |
|
139 if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN) |
|
140 buffer[n++] = SEP; |
|
141 } |
|
142 k = strlen(stuff); |
|
143 if (n + k > MAXPATHLEN) |
|
144 k = MAXPATHLEN - n; |
|
145 strncpy(buffer+n, stuff, k); |
|
146 buffer[n+k] = '\0'; |
|
147 } |
|
148 |
|
149 static void |
|
150 calculate_path(void) |
|
151 { |
|
152 char *prog = Py_GetProgramName(); /* use Py_SetProgramName(argv[0]) before Py_Initialize() */ |
|
153 char argv0_path[MAXPATHLEN+1]; |
|
154 char *epath; |
|
155 char *path = NULL; |
|
156 char *ppath = NULL; |
|
157 int numchars; |
|
158 |
|
159 if (strchr(prog, SEP)) |
|
160 strcpy(progpath, prog); |
|
161 else { |
|
162 #if HAVE_READLINK |
|
163 sprintf(argv0_path, "/proc/%d/exe", getpid()); |
|
164 numchars = readlink(argv0_path, progpath, MAXPATHLEN); |
|
165 if (numchars > 0) |
|
166 progpath[numchars] = '\0'; |
|
167 else { |
|
168 #endif |
|
169 epath = getenv("PATH"); |
|
170 if (epath) |
|
171 path = malloc(strlen(epath)+3); |
|
172 if (path) { |
|
173 strcpy(path, ".:"); |
|
174 strcat(path, epath); |
|
175 ppath = path; |
|
176 while (1) { |
|
177 char *delim = strchr(ppath, DELIM); |
|
178 |
|
179 if (delim) { |
|
180 int len = delim - ppath; |
|
181 strncpy(progpath, ppath, len); |
|
182 *(progpath + len) = '\0'; |
|
183 } |
|
184 else |
|
185 strcpy(progpath, ppath); |
|
186 |
|
187 joinpath(progpath, prog); |
|
188 if (isxfile(progpath)) |
|
189 break; |
|
190 |
|
191 if (!delim) { |
|
192 progpath[0] = '\0'; |
|
193 break; |
|
194 } |
|
195 ppath = delim + 1; |
|
196 } |
|
197 free(path); |
|
198 } |
|
199 else |
|
200 progpath[0] = '\0'; |
|
201 #if HAVE_READLINK |
|
202 } |
|
203 #endif |
|
204 } |
|
205 /* at this point progpath includes the executable */ |
|
206 strcpy(argv0_path, progpath); |
|
207 |
|
208 #if HAVE_READLINK |
|
209 { |
|
210 char tmpbuffer[MAXPATHLEN+1]; |
|
211 int linklen = readlink(progpath, tmpbuffer, MAXPATHLEN); |
|
212 while (linklen != -1) { |
|
213 /* It's not null terminated! */ |
|
214 tmpbuffer[linklen] = '\0'; |
|
215 if (tmpbuffer[0] == SEP) |
|
216 strcpy(argv0_path, tmpbuffer); |
|
217 else { |
|
218 /* Interpret relative to progpath */ |
|
219 reduce(argv0_path); |
|
220 joinpath(argv0_path, tmpbuffer); |
|
221 } |
|
222 linklen = readlink(argv0_path, tmpbuffer, MAXPATHLEN); |
|
223 } |
|
224 strcpy(progpath, argv0_path); |
|
225 } |
|
226 #endif /* HAVE_READLINK */ |
|
227 |
|
228 reduce(argv0_path); |
|
229 /* now argv0_path is the directory of the executable */ |
|
230 |
|
231 strcpy(prefix, argv0_path); |
|
232 exec_prefix = prefix; |
|
233 module_search_path = malloc(strlen(prefix)+1); |
|
234 strcpy(module_search_path, prefix); |
|
235 |
|
236 } |
|
237 /* External interface */ |
|
238 |
|
239 char * |
|
240 Py_GetPath(void) |
|
241 { |
|
242 if (!module_search_path) |
|
243 calculate_path(); |
|
244 return module_search_path; |
|
245 } |
|
246 |
|
247 char * |
|
248 Py_GetPrefix(void) |
|
249 { |
|
250 if (!module_search_path) |
|
251 calculate_path(); |
|
252 return prefix; |
|
253 } |
|
254 |
|
255 char * |
|
256 Py_GetExecPrefix(void) |
|
257 { |
|
258 if (!module_search_path) |
|
259 calculate_path(); |
|
260 return exec_prefix; |
|
261 } |
|
262 |
|
263 char * |
|
264 Py_GetProgramFullPath(void) |
|
265 { |
|
266 if (!module_search_path) |
|
267 calculate_path(); |
|
268 return progpath; |
|
269 } |