blob: b79d55511f07772e4e79e259a5200adf421dcf8e [file] [log] [blame]
Jack Jansen42218ce1997-01-31 16:15:11 +00001/***********************************************************
2Copyright 1991-1997 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
Jack Jansen12fce3e1995-08-14 12:31:44 +000032#include "Python.h"
33#include "osdefs.h"
Jack Jansen3f7d2b41996-09-06 22:21:07 +000034#include "macglue.h"
Jack Jansen41e25cc2000-07-14 22:16:01 +000035#include "macdefs.h"
Jack Jansen12fce3e1995-08-14 12:31:44 +000036#include "pythonresources.h"
Jack Jansen9ae898b2000-07-11 21:16:03 +000037#ifdef HAVE_UNISTD_H
38#include <unistd.h>
39#endif
Jack Jansen12fce3e1995-08-14 12:31:44 +000040
Jack Jansen697842f2001-09-10 22:00:39 +000041#ifdef TARGET_API_MAC_OSX
42#define PATHNAMELEN 1024
43#else
44#define PATHNAMELEN 256
45#endif
Jack Jansen12fce3e1995-08-14 12:31:44 +000046
47/* Return the initial python search path. This is called once from
48** initsys() to initialize sys.path.
49**
50** If USE_BUILTIN_PATH is defined the path defined here is used
51** (after prepending the python home dir to each item).
52** If it is not defined the path is gotten from a resource in the
53** Preferences file.
54**
55** XXXX This code needs cleaning up. The routines here have moved
56** around quite a bit, and they're pretty messy for that reason.
57*/
58
59#include <Files.h>
60#include <Aliases.h>
61#include <Folders.h>
62#include <Resources.h>
63#include <TextUtils.h>
Jack Jansenb39be211995-09-01 11:48:10 +000064#include <Dialogs.h>
Jack Jansen12fce3e1995-08-14 12:31:44 +000065
Jack Jansen9ae898b2000-07-11 21:16:03 +000066#ifndef USE_BUILTIN_PATH
Jeremy Hylton938ace62002-07-17 16:30:39 +000067static char *PyMac_GetPythonPath();
Jack Jansen9ae898b2000-07-11 21:16:03 +000068#endif
69
Jack Jansen12fce3e1995-08-14 12:31:44 +000070#define PYTHONPATH "\
71:\n\
72:Lib\n\
73:Lib:stdwin\n\
74:Lib:test\n\
75:Lib:mac"
76
Jack Jansenac82b6a1998-07-13 13:38:29 +000077static int
Jack Jansen83c74df1996-10-22 15:25:42 +000078getpreffilefss(FSSpec *fssp)
79{
80 static int diditbefore=0;
Jack Jansenac82b6a1998-07-13 13:38:29 +000081 static int rv = 1;
Jack Jansen83c74df1996-10-22 15:25:42 +000082 static FSSpec fss;
Jack Jansenabdf93c1998-07-31 09:33:28 +000083 short prefdirRefNum;
84 long prefdirDirID;
Just van Rossum26a69db1999-02-02 15:49:03 +000085 long pyprefdirDirID;
Jack Jansenabdf93c1998-07-31 09:33:28 +000086 Handle namehandle;
Just van Rossum26a69db1999-02-02 15:49:03 +000087 OSErr err;
Jack Jansenabdf93c1998-07-31 09:33:28 +000088
89 if ( !diditbefore ) {
Jack Jansenabdf93c1998-07-31 09:33:28 +000090 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
91 (void)StopAlert(NOPREFNAME_ID, NULL);
92 exit(1);
93 }
94
Jack Jansenabdf93c1998-07-31 09:33:28 +000095 if ( **namehandle == '\0' ) {
96 /* Empty string means don't use preferences file */
97 rv = 0;
98 } else {
99 /* There is a filename, construct the fsspec */
Just van Rossum26a69db1999-02-02 15:49:03 +0000100 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
101 &prefdirDirID) != noErr ) {
102 /* Something wrong with preferences folder */
103 (void)StopAlert(NOPREFDIR_ID, NULL);
104 exit(1);
105 }
106 /* make fsspec for the "Python" folder inside the prefs folder */
107 err = FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython", &fss);
108 if (err == fnfErr) {
109 /* it doesn't exist: create it */
110 err = FSpDirCreate(&fss, smSystemScript, &pyprefdirDirID);
111 } else {
112 /* it does exist, now find out the dirID of the Python prefs folder, brrr. */
113 CInfoPBRec info;
114 info.dirInfo.ioVRefNum = fss.vRefNum;
115 info.dirInfo.ioDrDirID = fss.parID;
116 info.dirInfo.ioNamePtr = fss.name;
117 info.dirInfo.ioFDirIndex = 0;
118 info.dirInfo.ioACUser = 0;
119 err = PBGetCatInfo(&info, 0);
120 if (err == noErr) {
121 pyprefdirDirID = info.dirInfo.ioDrDirID;
122 }
123 }
124 if (err != noErr) {
125 (void)StopAlert(NOPREFDIR_ID, NULL);
126 exit(1);
127 }
128 HLock(namehandle);
129 err = FSMakeFSSpec(fss.vRefNum, pyprefdirDirID, (unsigned char *)*namehandle, &fss);
130 HUnlock(namehandle);
131 if (err != noErr && err != fnfErr) {
132 (void)StopAlert(NOPREFDIR_ID, NULL);
133 exit(1);
134 }
Jack Jansenac82b6a1998-07-13 13:38:29 +0000135 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000136 ReleaseResource(namehandle);
137 diditbefore = 1;
138 }
139 *fssp = fss;
Jack Jansenac82b6a1998-07-13 13:38:29 +0000140 return rv;
Jack Jansen83c74df1996-10-22 15:25:42 +0000141}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000142
143char *
Jack Jansena547dca1996-07-10 15:48:25 +0000144Py_GetPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000145{
146 /* Modified by Jack to do something a bit more sensible:
147 ** - Prepend the python home-directory (which is obtained from a Preferences
148 ** resource)
149 ** - Add :
150 */
151 static char *pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000152 char *p, *endp;
153 int newlen;
Jack Jansen83c74df1996-10-22 15:25:42 +0000154 char *curwd;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000155
156 if ( pythonpath ) return pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000157#ifndef USE_BUILTIN_PATH
Jack Jansen83c74df1996-10-22 15:25:42 +0000158 if ( pythonpath = PyMac_GetPythonPath() )
Jack Jansen12fce3e1995-08-14 12:31:44 +0000159 return pythonpath;
160 printf("Warning: No pythonpath resource found, using builtin default\n");
161#endif
Jack Jansen83c74df1996-10-22 15:25:42 +0000162 curwd = PyMac_GetPythonDir();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000163 p = PYTHONPATH;
164 endp = p;
165 pythonpath = malloc(2);
166 if ( pythonpath == NULL ) return PYTHONPATH;
167 strcpy(pythonpath, ":");
168 while (*endp) {
169 endp = strchr(p, '\n');
170 if ( endp == NULL )
171 endp = p + strlen(p);
172 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
173 pythonpath = realloc(pythonpath, newlen+1);
174 if ( pythonpath == NULL ) return PYTHONPATH;
175 strcat(pythonpath, "\n");
176 if ( *p == ':' ) {
177 p++;
178 strcat(pythonpath, curwd);
179 strncat(pythonpath, p, (endp-p));
180 newlen--; /* Ok, ok, we've allocated one byte too much */
181 } else {
182 /* We've allocated too much in this case */
183 newlen -= strlen(curwd);
184 pythonpath = realloc(pythonpath, newlen+1);
185 if ( pythonpath == NULL ) return PYTHONPATH;
186 strncat(pythonpath, p, (endp-p));
187 }
188 pythonpath[newlen] = '\0';
189 p = endp + 1;
190 }
191 return pythonpath;
192}
193
Jack Jansen83c74df1996-10-22 15:25:42 +0000194
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000195/*
196** Open/create the Python Preferences file, return the handle
197*/
Jack Jansenee081042000-04-21 23:53:37 +0000198short
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000199PyMac_OpenPrefFile()
200{
Jack Jansenabdf93c1998-07-31 09:33:28 +0000201 AliasHandle handle;
202 FSSpec dirspec;
203 short prefrh;
204 OSErr err;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000205
Jack Jansenac82b6a1998-07-13 13:38:29 +0000206 if ( !getpreffilefss(&dirspec))
207 return -1;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000208 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
209 if ( prefrh < 0 ) {
Jack Jansen532e3c21996-02-21 15:36:26 +0000210 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000211 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
212 if ( prefrh == -1 ) {
213 /* This "cannot happen":-) */
Jack Jansenb39be211995-09-01 11:48:10 +0000214 printf("Cannot create preferences file, error %d\n", ResError());
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000215 exit(1);
216 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000217 if ( (err=PyMac_init_process_location()) != 0 ) {
218 printf("Cannot get application location, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000219 exit(1);
220 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000221 dirspec = PyMac_ApplicationFSSpec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000222 dirspec.name[0] = 0;
Jack Jansenb39be211995-09-01 11:48:10 +0000223 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
224 printf("Cannot make alias to application directory, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000225 exit(1);
226 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000227 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
228 UpdateResFile(prefrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000229
230 } else {
231 UseResFile(prefrh);
232 }
233 return prefrh;
234}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000235
236/*
237** Return the name of the Python directory
238*/
Jack Jansen5b3c9711997-09-08 13:22:49 +0000239char *
Jack Jansen12fce3e1995-08-14 12:31:44 +0000240PyMac_GetPythonDir()
241{
Jack Jansen83c74df1996-10-22 15:25:42 +0000242 static int diditbefore = 0;
Jack Jansen697842f2001-09-10 22:00:39 +0000243 static char name[PATHNAMELEN] = {':', '\0'};
Jack Jansenabdf93c1998-07-31 09:33:28 +0000244 AliasHandle handle;
245 FSSpec dirspec;
246 Boolean modified = 0;
247 short oldrh, prefrh = -1, homerh;
248
249 if ( diditbefore )
250 return name;
251
252 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000253
Jack Jansenabdf93c1998-07-31 09:33:28 +0000254 /* First look for an override in the application file */
255 UseResFile(PyMac_AppRefNum);
256 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
257 UseResFile(oldrh);
258 if ( handle != NULL ) {
259 homerh = PyMac_AppRefNum;
260 } else {
261 /* Try to open preferences file in the preferences folder. */
262 prefrh = PyMac_OpenPrefFile();
263 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
264 if ( handle == NULL ) {
265 /* (void)StopAlert(BADPREFFILE_ID, NULL); */
266 diditbefore=1;
267 return ":";
268 }
269 homerh = prefrh;
270 }
271 /* It exists. Resolve it (possibly updating it) */
272 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
273 (void)StopAlert(BADPREFFILE_ID, NULL);
274 diditbefore=1;
275 return ":";
276 }
277 if ( modified ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000278 ChangedResource((Handle)handle);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000279 UpdateResFile(homerh);
280 }
281 if ( prefrh != -1 ) CloseResFile(prefrh);
282 UseResFile(oldrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000283
Jack Jansen697842f2001-09-10 22:00:39 +0000284 if ( PyMac_GetFullPathname(&dirspec, name, PATHNAMELEN) == 0 ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000285 strcat(name, ":");
Jack Jansenabdf93c1998-07-31 09:33:28 +0000286 } else {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000287 /* If all fails, we return the current directory */
288 printf("Python home dir exists but I cannot find the pathname!!\n");
Jack Jansen12fce3e1995-08-14 12:31:44 +0000289 name[0] = 0;
Jack Jansen031b7792001-12-14 22:57:34 +0000290 (void)getcwd(name, sizeof(name));
Jack Jansen12fce3e1995-08-14 12:31:44 +0000291 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000292 diditbefore = 1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000293 return name;
294}
295
296#ifndef USE_BUILTIN_PATH
Jack Jansen5b3c9711997-09-08 13:22:49 +0000297char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000298PyMac_GetPythonPath(void)
Jack Jansen12fce3e1995-08-14 12:31:44 +0000299{
Jack Jansenabdf93c1998-07-31 09:33:28 +0000300 short oldrh, prefrh = -1;
301 char *rv;
302 int i, newlen;
303 Str255 pathitem;
304 int resource_id;
305 OSErr err;
306 Handle h;
307
308 oldrh = CurResFile();
309 /*
310 ** This is a bit tricky. We check here whether the application file
311 ** contains an override. This is to forestall us finding another STR# resource
312 ** with "our" id and using that for path initialization
313 */
314 UseResFile(PyMac_AppRefNum);
315 SetResLoad(0);
316 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
317 ReleaseResource(h);
318 resource_id = PYTHONPATHOVERRIDE_ID;
319 } else {
320 resource_id = PYTHONPATH_ID;
321 }
322 SetResLoad(1);
323 UseResFile(oldrh);
324
325 /* Open the preferences file only if there is no override */
326 if ( resource_id != PYTHONPATHOVERRIDE_ID )
327 prefrh = PyMac_OpenPrefFile();
328 /* At this point, we may or may not have the preferences file open, and it
329 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
330 ** exist we use the one from the application (the default).
331 ** We put an initial '\n' in front of the path that we don't return to the caller
332 */
333 if( (rv = malloc(2)) == NULL )
334 goto out;
335 strcpy(rv, "\n");
Jack Jansenf12e7091996-09-05 15:19:24 +0000336
Jack Jansenabdf93c1998-07-31 09:33:28 +0000337 for(i=1; ; i++) {
338 GetIndString(pathitem, resource_id, i);
339 if( pathitem[0] == 0 )
340 break;
341 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
342 /* We have to put the directory in place */
343 char *dir = PyMac_GetPythonDir();
344
345 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
346 if( (rv=realloc(rv, newlen)) == NULL)
347 goto out;
348 strcat(rv, dir);
349 /* Skip a colon at the beginning of the item */
350 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
Jack Jansen12fce3e1995-08-14 12:31:44 +0000351 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
352 newlen--;
353 } else {
354 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
355 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000356 rv[newlen-2] = '\n';
357 rv[newlen-1] = 0;
358 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
359 /* This is the application itself */
Jack Jansena486a551996-04-04 15:39:18 +0000360
Jack Jansenabdf93c1998-07-31 09:33:28 +0000361 if ( (err=PyMac_init_process_location()) != 0 ) {
Jack Jansen26ee1261996-11-09 18:45:18 +0000362 printf("Cannot get application location, error %d\n", err);
Jack Jansena486a551996-04-04 15:39:18 +0000363 exit(1);
364 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000365
366 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
Jack Jansenabdf93c1998-07-31 09:33:28 +0000367 if( (rv=realloc(rv, newlen)) == NULL)
368 goto out;
369 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
370 rv[newlen-2] = '\n';
371 rv[newlen-1] = 0;
Jack Jansena486a551996-04-04 15:39:18 +0000372
Jack Jansenabdf93c1998-07-31 09:33:28 +0000373 } else {
374 /* Use as-is */
375 newlen = strlen(rv) + (pathitem[0]) + 2;
376 if( (rv=realloc(rv, newlen)) == NULL)
377 goto out;
378 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
379 rv[newlen-2] = '\n';
380 rv[newlen-1] = 0;
381 }
Jack Jansen12fce3e1995-08-14 12:31:44 +0000382 }
383 if( strlen(rv) == 1) {
384 free(rv);
385 rv = NULL;
386 }
387 if ( rv ) {
388 rv[strlen(rv)-1] = 0;
389 rv++;
390 }
391out:
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000392 if ( prefrh != -1) CloseResFile(prefrh);
393 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000394 return rv;
395}
396#endif /* !USE_BUILTIN_PATH */
397
Jack Jansena4b7e141996-02-21 16:46:57 +0000398void
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000399PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
Jack Jansena4b7e141996-02-21 16:46:57 +0000400{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000401 short oldrh, prefrh = -1;
Jack Jansena4b7e141996-02-21 16:46:57 +0000402 Handle handle;
403 int size;
Jack Jansen5b3c9711997-09-08 13:22:49 +0000404 PyMac_PrefRecord *p;
405 int action;
Jack Jansena4b7e141996-02-21 16:46:57 +0000406
407
Jack Jansenabdf93c1998-07-31 09:33:28 +0000408 oldrh = CurResFile();
409
410 /* Attempt to load overrides from application */
411 UseResFile(PyMac_AppRefNum);
412 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
413 UseResFile(oldrh);
414
415 /* Otherwise get options from prefs file or any other open resource file */
416 if ( handle == NULL ) {
417 prefrh = PyMac_OpenPrefFile();
418 handle = GetResource('Popt', PYTHONOPTIONS_ID);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000419 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000420 if ( handle == NULL ) {
421 return;
422 }
423 HLock(handle);
424 size = GetHandleSize(handle);
425 p = (PyMac_PrefRecord *)*handle;
426 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
427 *pr = *p;
428 } else {
429 action = CautionAlert(BADPREFERENCES_ID, NULL);
430 if ( action == BADPREF_DELETE ) {
431 OSErr err;
432
433 RemoveResource(handle);
434 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
435 if ( prefrh != -1 ) {
436 UpdateResFile(prefrh);
437 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
438 }
439 } else if ( action == BADPREF_QUIT )
440 exit(1);
441 }
442 HUnlock(handle);
Jack Jansena4b7e141996-02-21 16:46:57 +0000443
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000444 if ( prefrh != -1) CloseResFile(prefrh);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000445 UseResFile(oldrh);
Jack Jansena4b7e141996-02-21 16:46:57 +0000446}