blob: 98abbd875c33c9bf27f44d063e6ce7df7f238dc6 [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 Jansen12fce3e1995-08-14 12:31:44 +000035#include "pythonresources.h"
36
37
38/* Return the initial python search path. This is called once from
39** initsys() to initialize sys.path.
40**
41** If USE_BUILTIN_PATH is defined the path defined here is used
42** (after prepending the python home dir to each item).
43** If it is not defined the path is gotten from a resource in the
44** Preferences file.
45**
46** XXXX This code needs cleaning up. The routines here have moved
47** around quite a bit, and they're pretty messy for that reason.
48*/
49
50#include <Files.h>
51#include <Aliases.h>
52#include <Folders.h>
53#include <Resources.h>
54#include <TextUtils.h>
Jack Jansenb39be211995-09-01 11:48:10 +000055#include <Dialogs.h>
Jack Jansen12fce3e1995-08-14 12:31:44 +000056
Jack Jansen3f7d2b41996-09-06 22:21:07 +000057#ifdef USE_GUSI
58#include <GUSI.h>
59#endif
60
Jack Jansen12fce3e1995-08-14 12:31:44 +000061#define PYTHONPATH "\
62:\n\
63:Lib\n\
64:Lib:stdwin\n\
65:Lib:test\n\
66:Lib:mac"
67
Jack Jansen83c74df1996-10-22 15:25:42 +000068static void
69getpreffilefss(FSSpec *fssp)
70{
71 static int diditbefore=0;
72 static FSSpec fss;
73 short prefdirRefNum;
74 long prefdirDirID;
75 Handle namehandle;
76
77 if ( !diditbefore ) {
78 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
79 &prefdirDirID) != noErr ) {
80 /* Something wrong with preferences folder */
81 (void)StopAlert(NOPREFDIR_ID, NULL);
82 exit(1);
83 }
84
85 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
86 (void)StopAlert(NOPREFNAME_ID, NULL);
87 exit(1);
88 }
89
90 HLock(namehandle);
91 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, (unsigned char *)*namehandle, &fss);
92 HUnlock(namehandle);
93 ReleaseResource(namehandle);
94 diditbefore = 1;
95 }
96 *fssp = fss;
97}
Jack Jansen12fce3e1995-08-14 12:31:44 +000098
99char *
Jack Jansena547dca1996-07-10 15:48:25 +0000100Py_GetPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000101{
102 /* Modified by Jack to do something a bit more sensible:
103 ** - Prepend the python home-directory (which is obtained from a Preferences
104 ** resource)
105 ** - Add :
106 */
107 static char *pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000108 char *p, *endp;
109 int newlen;
Jack Jansen83c74df1996-10-22 15:25:42 +0000110 char *curwd;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000111#ifndef USE_BUILTIN_PATH
Jack Jansen01fbc681996-02-28 15:42:47 +0000112 staticforward char *PyMac_GetPythonPath();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000113#endif
114
115 if ( pythonpath ) return pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000116#ifndef USE_BUILTIN_PATH
Jack Jansen83c74df1996-10-22 15:25:42 +0000117 if ( pythonpath = PyMac_GetPythonPath() )
Jack Jansen12fce3e1995-08-14 12:31:44 +0000118 return pythonpath;
119 printf("Warning: No pythonpath resource found, using builtin default\n");
120#endif
Jack Jansen83c74df1996-10-22 15:25:42 +0000121 curwd = PyMac_GetPythonDir();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000122 p = PYTHONPATH;
123 endp = p;
124 pythonpath = malloc(2);
125 if ( pythonpath == NULL ) return PYTHONPATH;
126 strcpy(pythonpath, ":");
127 while (*endp) {
128 endp = strchr(p, '\n');
129 if ( endp == NULL )
130 endp = p + strlen(p);
131 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
132 pythonpath = realloc(pythonpath, newlen+1);
133 if ( pythonpath == NULL ) return PYTHONPATH;
134 strcat(pythonpath, "\n");
135 if ( *p == ':' ) {
136 p++;
137 strcat(pythonpath, curwd);
138 strncat(pythonpath, p, (endp-p));
139 newlen--; /* Ok, ok, we've allocated one byte too much */
140 } else {
141 /* We've allocated too much in this case */
142 newlen -= strlen(curwd);
143 pythonpath = realloc(pythonpath, newlen+1);
144 if ( pythonpath == NULL ) return PYTHONPATH;
145 strncat(pythonpath, p, (endp-p));
146 }
147 pythonpath[newlen] = '\0';
148 p = endp + 1;
149 }
150 return pythonpath;
151}
152
Jack Jansen83c74df1996-10-22 15:25:42 +0000153
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000154/*
155** Open/create the Python Preferences file, return the handle
156*/
Jack Jansen01fbc681996-02-28 15:42:47 +0000157static short
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000158PyMac_OpenPrefFile()
159{
160 AliasHandle handle;
161 FSSpec dirspec;
162 short prefrh;
Jack Jansenb39be211995-09-01 11:48:10 +0000163 OSErr err;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000164
Jack Jansen83c74df1996-10-22 15:25:42 +0000165 getpreffilefss(&dirspec);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000166 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
167 if ( prefrh < 0 ) {
Jack Jansen83c74df1996-10-22 15:25:42 +0000168#if 0
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000169 action = CautionAlert(NOPREFFILE_ID, NULL);
170 if ( action == NOPREFFILE_NO )
171 exit(1);
Jack Jansen83c74df1996-10-22 15:25:42 +0000172#endif
Jack Jansen532e3c21996-02-21 15:36:26 +0000173 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000174 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
175 if ( prefrh == -1 ) {
176 /* This "cannot happen":-) */
Jack Jansenb39be211995-09-01 11:48:10 +0000177 printf("Cannot create preferences file, error %d\n", ResError());
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000178 exit(1);
179 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000180 if ( (err=PyMac_init_process_location()) != 0 ) {
181 printf("Cannot get application location, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000182 exit(1);
183 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000184 dirspec = PyMac_ApplicationFSSpec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000185 dirspec.name[0] = 0;
Jack Jansenb39be211995-09-01 11:48:10 +0000186 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
187 printf("Cannot make alias to application directory, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000188 exit(1);
189 }
190 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
191 UpdateResFile(prefrh);
192
193 } else {
194 UseResFile(prefrh);
195 }
196 return prefrh;
197}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000198
199/*
200** Return the name of the Python directory
201*/
Jack Jansen5b3c9711997-09-08 13:22:49 +0000202char *
Jack Jansen12fce3e1995-08-14 12:31:44 +0000203PyMac_GetPythonDir()
204{
Jack Jansen83c74df1996-10-22 15:25:42 +0000205 static int diditbefore = 0;
206 static char name[256] = {':', '\0'};
Jack Jansen12fce3e1995-08-14 12:31:44 +0000207 AliasHandle handle;
208 FSSpec dirspec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000209 Boolean modified = 0;
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000210 short oldrh, prefrh = -1, homerh;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000211
Jack Jansen83c74df1996-10-22 15:25:42 +0000212 if ( diditbefore )
213 return name;
214
Jack Jansen12fce3e1995-08-14 12:31:44 +0000215 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000216
217 /* First look for an override in the application file */
218 UseResFile(PyMac_AppRefNum);
219 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
Jack Jansena486a551996-04-04 15:39:18 +0000220 if ( handle != NULL ) {
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000221 homerh = PyMac_AppRefNum;
222 } else {
223 /* Try to open preferences file in the preferences folder. */
Jack Jansena486a551996-04-04 15:39:18 +0000224 prefrh = PyMac_OpenPrefFile();
Jack Jansena486a551996-04-04 15:39:18 +0000225 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
226 if ( handle == NULL ) {
227 (void)StopAlert(BADPREFFILE_ID, NULL);
Jack Jansen83c74df1996-10-22 15:25:42 +0000228 diditbefore=1;
229 return ":";
Jack Jansena486a551996-04-04 15:39:18 +0000230 }
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000231 homerh = prefrh;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000232 }
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000233 /* It exists. Resolve it (possibly updating it) */
234 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
235 (void)StopAlert(BADPREFFILE_ID, NULL);
Jack Jansen83c74df1996-10-22 15:25:42 +0000236 diditbefore=1;
237 return ":";
Jack Jansen12fce3e1995-08-14 12:31:44 +0000238 }
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000239 if ( modified ) {
240 ChangedResource((Handle)handle);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000241 UpdateResFile(homerh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000242 }
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000243 if ( prefrh != -1 ) CloseResFile(prefrh);
244 UseResFile(oldrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000245
Jack Jansen26ee1261996-11-09 18:45:18 +0000246 if ( PyMac_GetFullPath(&dirspec, name) == 0 ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000247 strcat(name, ":");
248 } else {
249 /* If all fails, we return the current directory */
250 printf("Python home dir exists but I cannot find the pathname!!\n");
Jack Jansen12fce3e1995-08-14 12:31:44 +0000251 name[0] = 0;
252 (void)getwd(name);
253 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000254 diditbefore = 1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000255 return name;
256}
257
258#ifndef USE_BUILTIN_PATH
Jack Jansen5b3c9711997-09-08 13:22:49 +0000259char *
Jack Jansen83c74df1996-10-22 15:25:42 +0000260PyMac_GetPythonPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000261{
Jack Jansen12fce3e1995-08-14 12:31:44 +0000262 short oldrh, prefrh = -1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000263 char *rv;
264 int i, newlen;
265 Str255 pathitem;
Jack Jansena486a551996-04-04 15:39:18 +0000266 int resource_id;
267 OSErr err;
Jack Jansenf12e7091996-09-05 15:19:24 +0000268 Handle h;
269
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000270 oldrh = CurResFile();
Jack Jansenf12e7091996-09-05 15:19:24 +0000271 /*
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000272 ** This is a bit tricky. We check here whether the application file
Jack Jansenf12e7091996-09-05 15:19:24 +0000273 ** contains an override. This is to forestall us finding another STR# resource
274 ** with "our" id and using that for path initialization
275 */
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000276 UseResFile(PyMac_AppRefNum);
Jack Jansenf12e7091996-09-05 15:19:24 +0000277 SetResLoad(0);
278 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
279 ReleaseResource(h);
280 resource_id = PYTHONPATHOVERRIDE_ID;
281 } else {
282 resource_id = PYTHONPATH_ID;
283 }
284 SetResLoad(1);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000285 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000286
Jack Jansen83c74df1996-10-22 15:25:42 +0000287 /* Open the preferences file only if there is no override */
288 if ( resource_id != PYTHONPATHOVERRIDE_ID )
289 prefrh = PyMac_OpenPrefFile();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000290 /* At this point, we may or may not have the preferences file open, and it
291 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
292 ** exist we use the one from the application (the default).
293 ** We put an initial '\n' in front of the path that we don't return to the caller
294 */
295 if( (rv = malloc(2)) == NULL )
296 goto out;
297 strcpy(rv, "\n");
Jack Jansenf12e7091996-09-05 15:19:24 +0000298
Jack Jansen12fce3e1995-08-14 12:31:44 +0000299 for(i=1; ; i++) {
Jack Jansena486a551996-04-04 15:39:18 +0000300 GetIndString(pathitem, resource_id, i);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000301 if( pathitem[0] == 0 )
302 break;
303 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
304 /* We have to put the directory in place */
Jack Jansen83c74df1996-10-22 15:25:42 +0000305 char *dir = PyMac_GetPythonDir();
306
Jack Jansen12fce3e1995-08-14 12:31:44 +0000307 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
308 if( (rv=realloc(rv, newlen)) == NULL)
309 goto out;
310 strcat(rv, dir);
311 /* Skip a colon at the beginning of the item */
312 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
313 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
314 newlen--;
315 } else {
316 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
317 }
318 rv[newlen-2] = '\n';
319 rv[newlen-1] = 0;
Jack Jansena486a551996-04-04 15:39:18 +0000320 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
321 /* This is the application itself */
Jack Jansena486a551996-04-04 15:39:18 +0000322
Jack Jansen26ee1261996-11-09 18:45:18 +0000323 if ( (err=PyMac_init_process_location()) != 0 ) {
324 printf("Cannot get application location, error %d\n", err);
Jack Jansena486a551996-04-04 15:39:18 +0000325 exit(1);
326 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000327
328 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
Jack Jansena486a551996-04-04 15:39:18 +0000329 if( (rv=realloc(rv, newlen)) == NULL)
330 goto out;
Jack Jansen26ee1261996-11-09 18:45:18 +0000331 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
Jack Jansena486a551996-04-04 15:39:18 +0000332 rv[newlen-2] = '\n';
333 rv[newlen-1] = 0;
334
Jack Jansen12fce3e1995-08-14 12:31:44 +0000335 } else {
336 /* Use as-is */
337 newlen = strlen(rv) + (pathitem[0]) + 2;
338 if( (rv=realloc(rv, newlen)) == NULL)
339 goto out;
340 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
341 rv[newlen-2] = '\n';
342 rv[newlen-1] = 0;
343 }
344 }
345 if( strlen(rv) == 1) {
346 free(rv);
347 rv = NULL;
348 }
349 if ( rv ) {
350 rv[strlen(rv)-1] = 0;
351 rv++;
352 }
353out:
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000354 if ( prefrh != -1) CloseResFile(prefrh);
355 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000356 return rv;
357}
358#endif /* !USE_BUILTIN_PATH */
359
Jack Jansena4b7e141996-02-21 16:46:57 +0000360void
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000361PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
Jack Jansena4b7e141996-02-21 16:46:57 +0000362{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000363 short oldrh, prefrh = -1;
Jack Jansena4b7e141996-02-21 16:46:57 +0000364 Handle handle;
365 int size;
Jack Jansen5b3c9711997-09-08 13:22:49 +0000366 PyMac_PrefRecord *p;
367 int action;
Jack Jansena4b7e141996-02-21 16:46:57 +0000368
369
370 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000371
372 /* Attempt to load overrides from application */
373 UseResFile(PyMac_AppRefNum);
374 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
375 UseResFile(oldrh);
376
377 /* Otherwise get options from prefs file or any other open resource file */
378 if ( handle == NULL ) {
379 prefrh = PyMac_OpenPrefFile();
Jack Jansena486a551996-04-04 15:39:18 +0000380 handle = GetResource('Popt', PYTHONOPTIONS_ID);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000381 }
Jack Jansena4b7e141996-02-21 16:46:57 +0000382 if ( handle == NULL ) {
383 return;
384 }
385 HLock(handle);
386 size = GetHandleSize(handle);
Jack Jansen5b3c9711997-09-08 13:22:49 +0000387 p = (PyMac_PrefRecord *)*handle;
388 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
389 *pr = *p;
390 } else {
391 action = CautionAlert(BADPREFERENCES_ID, NULL);
392 if ( action == BADPREF_DELETE ) {
393 OSErr err;
394
395 RemoveResource(handle);
396 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
397 if ( prefrh != -1 ) {
398 UpdateResFile(prefrh);
399 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
400 }
401 } else if ( action == BADPREF_QUIT )
402 exit(1);
403 }
Jack Jansena4b7e141996-02-21 16:46:57 +0000404 HUnlock(handle);
405
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000406 if ( prefrh != -1) CloseResFile(prefrh);
Jack Jansena4b7e141996-02-21 16:46:57 +0000407 UseResFile(oldrh);
408}
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000409
410#ifdef USE_GUSI
411void
412PyMac_SetGUSIOptions()
413{
414 Handle h;
415 short oldrh, prefrh = -1;
416
417 oldrh = CurResFile();
418
419 /* Try override from the application resource fork */
420 UseResFile(PyMac_AppRefNum);
421 h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
422 UseResFile(oldrh);
423
424 /* If that didn't work try nonoverride from anywhere */
425 if ( h == NULL ) {
426 prefrh = PyMac_OpenPrefFile();
427 h = GetResource('GU\267I', GUSIOPTIONS_ID);
428 }
429 if ( h ) GUSILoadConfiguration(h);
430 if ( prefrh != -1) CloseResFile(prefrh);
431 UseResFile(oldrh);
432}
433#endif /* USE_GUSI */