blob: d98d481206050884617eb252acad1024bf769a26 [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#define PATHNAMELEN 256
Jack Jansen12fce3e1995-08-14 12:31:44 +000042
43/* Return the initial python search path. This is called once from
44** initsys() to initialize sys.path.
45**
46** If USE_BUILTIN_PATH is defined the path defined here is used
47** (after prepending the python home dir to each item).
48** If it is not defined the path is gotten from a resource in the
49** Preferences file.
50**
51** XXXX This code needs cleaning up. The routines here have moved
52** around quite a bit, and they're pretty messy for that reason.
53*/
54
55#include <Files.h>
56#include <Aliases.h>
57#include <Folders.h>
58#include <Resources.h>
59#include <TextUtils.h>
Jack Jansenb39be211995-09-01 11:48:10 +000060#include <Dialogs.h>
Jack Jansen12fce3e1995-08-14 12:31:44 +000061
Jack Jansen9ae898b2000-07-11 21:16:03 +000062#ifndef USE_BUILTIN_PATH
Jeremy Hylton938ace62002-07-17 16:30:39 +000063static char *PyMac_GetPythonPath();
Jack Jansen9ae898b2000-07-11 21:16:03 +000064#endif
65
Jack Jansen12fce3e1995-08-14 12:31:44 +000066#define PYTHONPATH "\
67:\n\
68:Lib\n\
69:Lib:stdwin\n\
70:Lib:test\n\
71:Lib:mac"
72
Jack Jansenac82b6a1998-07-13 13:38:29 +000073static int
Jack Jansen83c74df1996-10-22 15:25:42 +000074getpreffilefss(FSSpec *fssp)
75{
76 static int diditbefore=0;
Jack Jansenac82b6a1998-07-13 13:38:29 +000077 static int rv = 1;
Jack Jansen83c74df1996-10-22 15:25:42 +000078 static FSSpec fss;
Jack Jansenabdf93c1998-07-31 09:33:28 +000079 short prefdirRefNum;
80 long prefdirDirID;
Just van Rossum26a69db1999-02-02 15:49:03 +000081 long pyprefdirDirID;
Jack Jansenabdf93c1998-07-31 09:33:28 +000082 Handle namehandle;
Just van Rossum26a69db1999-02-02 15:49:03 +000083 OSErr err;
Jack Jansenabdf93c1998-07-31 09:33:28 +000084
85 if ( !diditbefore ) {
Jack Jansenabdf93c1998-07-31 09:33:28 +000086 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
87 (void)StopAlert(NOPREFNAME_ID, NULL);
88 exit(1);
89 }
90
Jack Jansenabdf93c1998-07-31 09:33:28 +000091 if ( **namehandle == '\0' ) {
92 /* Empty string means don't use preferences file */
93 rv = 0;
94 } else {
95 /* There is a filename, construct the fsspec */
Just van Rossum26a69db1999-02-02 15:49:03 +000096 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
97 &prefdirDirID) != noErr ) {
98 /* Something wrong with preferences folder */
99 (void)StopAlert(NOPREFDIR_ID, NULL);
100 exit(1);
101 }
102 /* make fsspec for the "Python" folder inside the prefs folder */
103 err = FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython", &fss);
104 if (err == fnfErr) {
105 /* it doesn't exist: create it */
106 err = FSpDirCreate(&fss, smSystemScript, &pyprefdirDirID);
107 } else {
108 /* it does exist, now find out the dirID of the Python prefs folder, brrr. */
109 CInfoPBRec info;
110 info.dirInfo.ioVRefNum = fss.vRefNum;
111 info.dirInfo.ioDrDirID = fss.parID;
112 info.dirInfo.ioNamePtr = fss.name;
113 info.dirInfo.ioFDirIndex = 0;
114 info.dirInfo.ioACUser = 0;
115 err = PBGetCatInfo(&info, 0);
116 if (err == noErr) {
117 pyprefdirDirID = info.dirInfo.ioDrDirID;
118 }
119 }
120 if (err != noErr) {
121 (void)StopAlert(NOPREFDIR_ID, NULL);
122 exit(1);
123 }
124 HLock(namehandle);
125 err = FSMakeFSSpec(fss.vRefNum, pyprefdirDirID, (unsigned char *)*namehandle, &fss);
126 HUnlock(namehandle);
127 if (err != noErr && err != fnfErr) {
128 (void)StopAlert(NOPREFDIR_ID, NULL);
129 exit(1);
130 }
Jack Jansenac82b6a1998-07-13 13:38:29 +0000131 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000132 ReleaseResource(namehandle);
133 diditbefore = 1;
134 }
135 *fssp = fss;
Jack Jansenac82b6a1998-07-13 13:38:29 +0000136 return rv;
Jack Jansen83c74df1996-10-22 15:25:42 +0000137}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000138
139char *
Jack Jansena547dca1996-07-10 15:48:25 +0000140Py_GetPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000141{
142 /* Modified by Jack to do something a bit more sensible:
143 ** - Prepend the python home-directory (which is obtained from a Preferences
144 ** resource)
145 ** - Add :
146 */
147 static char *pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000148 char *p, *endp;
149 int newlen;
Jack Jansen83c74df1996-10-22 15:25:42 +0000150 char *curwd;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000151
152 if ( pythonpath ) return pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000153#ifndef USE_BUILTIN_PATH
Jack Jansen83c74df1996-10-22 15:25:42 +0000154 if ( pythonpath = PyMac_GetPythonPath() )
Jack Jansen12fce3e1995-08-14 12:31:44 +0000155 return pythonpath;
156 printf("Warning: No pythonpath resource found, using builtin default\n");
157#endif
Jack Jansen83c74df1996-10-22 15:25:42 +0000158 curwd = PyMac_GetPythonDir();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000159 p = PYTHONPATH;
160 endp = p;
161 pythonpath = malloc(2);
162 if ( pythonpath == NULL ) return PYTHONPATH;
163 strcpy(pythonpath, ":");
164 while (*endp) {
165 endp = strchr(p, '\n');
166 if ( endp == NULL )
167 endp = p + strlen(p);
168 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
169 pythonpath = realloc(pythonpath, newlen+1);
170 if ( pythonpath == NULL ) return PYTHONPATH;
171 strcat(pythonpath, "\n");
172 if ( *p == ':' ) {
173 p++;
174 strcat(pythonpath, curwd);
175 strncat(pythonpath, p, (endp-p));
176 newlen--; /* Ok, ok, we've allocated one byte too much */
177 } else {
178 /* We've allocated too much in this case */
179 newlen -= strlen(curwd);
180 pythonpath = realloc(pythonpath, newlen+1);
181 if ( pythonpath == NULL ) return PYTHONPATH;
182 strncat(pythonpath, p, (endp-p));
183 }
184 pythonpath[newlen] = '\0';
185 p = endp + 1;
186 }
187 return pythonpath;
188}
189
Jack Jansen83c74df1996-10-22 15:25:42 +0000190
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000191/*
192** Open/create the Python Preferences file, return the handle
193*/
Jack Jansenee081042000-04-21 23:53:37 +0000194short
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000195PyMac_OpenPrefFile()
196{
Jack Jansenabdf93c1998-07-31 09:33:28 +0000197 AliasHandle handle;
198 FSSpec dirspec;
199 short prefrh;
200 OSErr err;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000201
Jack Jansenac82b6a1998-07-13 13:38:29 +0000202 if ( !getpreffilefss(&dirspec))
203 return -1;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000204 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
205 if ( prefrh < 0 ) {
Jack Jansen532e3c21996-02-21 15:36:26 +0000206 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000207 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
208 if ( prefrh == -1 ) {
209 /* This "cannot happen":-) */
Jack Jansenb39be211995-09-01 11:48:10 +0000210 printf("Cannot create preferences file, error %d\n", ResError());
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000211 exit(1);
212 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000213 if ( (err=PyMac_init_process_location()) != 0 ) {
214 printf("Cannot get application location, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000215 exit(1);
216 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000217 dirspec = PyMac_ApplicationFSSpec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000218 dirspec.name[0] = 0;
Jack Jansenb39be211995-09-01 11:48:10 +0000219 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
220 printf("Cannot make alias to application directory, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000221 exit(1);
222 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000223 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
224 UpdateResFile(prefrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000225
226 } else {
227 UseResFile(prefrh);
228 }
229 return prefrh;
230}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000231
232/*
233** Return the name of the Python directory
234*/
Jack Jansen5b3c9711997-09-08 13:22:49 +0000235char *
Jack Jansen12fce3e1995-08-14 12:31:44 +0000236PyMac_GetPythonDir()
237{
Jack Jansen83c74df1996-10-22 15:25:42 +0000238 static int diditbefore = 0;
Jack Jansen697842f2001-09-10 22:00:39 +0000239 static char name[PATHNAMELEN] = {':', '\0'};
Jack Jansenabdf93c1998-07-31 09:33:28 +0000240 AliasHandle handle;
241 FSSpec dirspec;
242 Boolean modified = 0;
243 short oldrh, prefrh = -1, homerh;
244
245 if ( diditbefore )
246 return name;
247
248 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000249
Jack Jansenabdf93c1998-07-31 09:33:28 +0000250 /* First look for an override in the application file */
251 UseResFile(PyMac_AppRefNum);
252 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
253 UseResFile(oldrh);
254 if ( handle != NULL ) {
255 homerh = PyMac_AppRefNum;
256 } else {
257 /* Try to open preferences file in the preferences folder. */
258 prefrh = PyMac_OpenPrefFile();
259 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
260 if ( handle == NULL ) {
261 /* (void)StopAlert(BADPREFFILE_ID, NULL); */
262 diditbefore=1;
263 return ":";
264 }
265 homerh = prefrh;
266 }
267 /* It exists. Resolve it (possibly updating it) */
268 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
269 (void)StopAlert(BADPREFFILE_ID, NULL);
270 diditbefore=1;
271 return ":";
272 }
273 if ( modified ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000274 ChangedResource((Handle)handle);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000275 UpdateResFile(homerh);
276 }
277 if ( prefrh != -1 ) CloseResFile(prefrh);
278 UseResFile(oldrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000279
Jack Jansen697842f2001-09-10 22:00:39 +0000280 if ( PyMac_GetFullPathname(&dirspec, name, PATHNAMELEN) == 0 ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000281 strcat(name, ":");
Jack Jansenabdf93c1998-07-31 09:33:28 +0000282 } else {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000283 /* If all fails, we return the current directory */
284 printf("Python home dir exists but I cannot find the pathname!!\n");
Jack Jansen12fce3e1995-08-14 12:31:44 +0000285 name[0] = 0;
Jack Jansen031b7792001-12-14 22:57:34 +0000286 (void)getcwd(name, sizeof(name));
Jack Jansen12fce3e1995-08-14 12:31:44 +0000287 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000288 diditbefore = 1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000289 return name;
290}
291
292#ifndef USE_BUILTIN_PATH
Jack Jansen5b3c9711997-09-08 13:22:49 +0000293char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000294PyMac_GetPythonPath(void)
Jack Jansen12fce3e1995-08-14 12:31:44 +0000295{
Jack Jansenabdf93c1998-07-31 09:33:28 +0000296 short oldrh, prefrh = -1;
297 char *rv;
298 int i, newlen;
299 Str255 pathitem;
300 int resource_id;
301 OSErr err;
302 Handle h;
303
304 oldrh = CurResFile();
305 /*
306 ** This is a bit tricky. We check here whether the application file
307 ** contains an override. This is to forestall us finding another STR# resource
308 ** with "our" id and using that for path initialization
309 */
310 UseResFile(PyMac_AppRefNum);
311 SetResLoad(0);
312 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
313 ReleaseResource(h);
314 resource_id = PYTHONPATHOVERRIDE_ID;
315 } else {
316 resource_id = PYTHONPATH_ID;
317 }
318 SetResLoad(1);
319 UseResFile(oldrh);
320
321 /* Open the preferences file only if there is no override */
322 if ( resource_id != PYTHONPATHOVERRIDE_ID )
323 prefrh = PyMac_OpenPrefFile();
324 /* At this point, we may or may not have the preferences file open, and it
325 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
326 ** exist we use the one from the application (the default).
327 ** We put an initial '\n' in front of the path that we don't return to the caller
328 */
329 if( (rv = malloc(2)) == NULL )
330 goto out;
331 strcpy(rv, "\n");
Jack Jansenf12e7091996-09-05 15:19:24 +0000332
Jack Jansenabdf93c1998-07-31 09:33:28 +0000333 for(i=1; ; i++) {
334 GetIndString(pathitem, resource_id, i);
335 if( pathitem[0] == 0 )
336 break;
337 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
338 /* We have to put the directory in place */
339 char *dir = PyMac_GetPythonDir();
340
341 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
342 if( (rv=realloc(rv, newlen)) == NULL)
343 goto out;
344 strcat(rv, dir);
345 /* Skip a colon at the beginning of the item */
346 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
Jack Jansen12fce3e1995-08-14 12:31:44 +0000347 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
348 newlen--;
349 } else {
350 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
351 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000352 rv[newlen-2] = '\n';
353 rv[newlen-1] = 0;
354 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
355 /* This is the application itself */
Jack Jansena486a551996-04-04 15:39:18 +0000356
Jack Jansenabdf93c1998-07-31 09:33:28 +0000357 if ( (err=PyMac_init_process_location()) != 0 ) {
Jack Jansen26ee1261996-11-09 18:45:18 +0000358 printf("Cannot get application location, error %d\n", err);
Jack Jansena486a551996-04-04 15:39:18 +0000359 exit(1);
360 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000361
362 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
Jack Jansenabdf93c1998-07-31 09:33:28 +0000363 if( (rv=realloc(rv, newlen)) == NULL)
364 goto out;
365 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
366 rv[newlen-2] = '\n';
367 rv[newlen-1] = 0;
Jack Jansena486a551996-04-04 15:39:18 +0000368
Jack Jansenabdf93c1998-07-31 09:33:28 +0000369 } else {
370 /* Use as-is */
371 newlen = strlen(rv) + (pathitem[0]) + 2;
372 if( (rv=realloc(rv, newlen)) == NULL)
373 goto out;
374 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
375 rv[newlen-2] = '\n';
376 rv[newlen-1] = 0;
377 }
Jack Jansen12fce3e1995-08-14 12:31:44 +0000378 }
379 if( strlen(rv) == 1) {
380 free(rv);
381 rv = NULL;
382 }
383 if ( rv ) {
384 rv[strlen(rv)-1] = 0;
385 rv++;
386 }
387out:
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000388 if ( prefrh != -1) CloseResFile(prefrh);
389 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000390 return rv;
391}
392#endif /* !USE_BUILTIN_PATH */
393
Jack Jansena4b7e141996-02-21 16:46:57 +0000394void
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000395PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
Jack Jansena4b7e141996-02-21 16:46:57 +0000396{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000397 short oldrh, prefrh = -1;
Jack Jansena4b7e141996-02-21 16:46:57 +0000398 Handle handle;
399 int size;
Jack Jansen5b3c9711997-09-08 13:22:49 +0000400 PyMac_PrefRecord *p;
401 int action;
Jack Jansena4b7e141996-02-21 16:46:57 +0000402
403
Jack Jansenabdf93c1998-07-31 09:33:28 +0000404 oldrh = CurResFile();
405
406 /* Attempt to load overrides from application */
407 UseResFile(PyMac_AppRefNum);
408 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
409 UseResFile(oldrh);
410
411 /* Otherwise get options from prefs file or any other open resource file */
412 if ( handle == NULL ) {
413 prefrh = PyMac_OpenPrefFile();
414 handle = GetResource('Popt', PYTHONOPTIONS_ID);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000415 }
Jack Jansenabdf93c1998-07-31 09:33:28 +0000416 if ( handle == NULL ) {
417 return;
418 }
419 HLock(handle);
420 size = GetHandleSize(handle);
421 p = (PyMac_PrefRecord *)*handle;
422 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
423 *pr = *p;
424 } else {
425 action = CautionAlert(BADPREFERENCES_ID, NULL);
426 if ( action == BADPREF_DELETE ) {
427 OSErr err;
428
429 RemoveResource(handle);
430 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
431 if ( prefrh != -1 ) {
432 UpdateResFile(prefrh);
433 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
434 }
435 } else if ( action == BADPREF_QUIT )
436 exit(1);
437 }
438 HUnlock(handle);
Jack Jansena4b7e141996-02-21 16:46:57 +0000439
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000440 if ( prefrh != -1) CloseResFile(prefrh);
Jack Jansenabdf93c1998-07-31 09:33:28 +0000441 UseResFile(oldrh);
Jack Jansena4b7e141996-02-21 16:46:57 +0000442}