py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Mac / Python / macgetpath.c
blob83117edcbfaf9a0ffe1aa6683e331733dd1828f2
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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.
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.
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.
30 ******************************************************************/
32 #include "Python.h"
33 #include "osdefs.h"
34 #include "macglue.h"
35 #include "macdefs.h"
36 #include "pythonresources.h"
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
42 /* Return the initial python search path. This is called once from
43 ** initsys() to initialize sys.path.
45 ** If USE_BUILTIN_PATH is defined the path defined here is used
46 ** (after prepending the python home dir to each item).
47 ** If it is not defined the path is gotten from a resource in the
48 ** Preferences file.
50 ** XXXX This code needs cleaning up. The routines here have moved
51 ** around quite a bit, and they're pretty messy for that reason.
54 #include <Files.h>
55 #include <Aliases.h>
56 #include <Folders.h>
57 #include <Resources.h>
58 #include <TextUtils.h>
59 #include <Dialogs.h>
61 #ifdef USE_GUSI1
62 #include <GUSI.h>
63 #endif
65 #ifndef USE_BUILTIN_PATH
66 staticforward char *PyMac_GetPythonPath();
67 #endif
69 #define PYTHONPATH "\
70 :\n\
71 :Lib\n\
72 :Lib:stdwin\n\
73 :Lib:test\n\
74 :Lib:mac"
76 static int
77 getpreffilefss(FSSpec *fssp)
79 static int diditbefore=0;
80 static int rv = 1;
81 static FSSpec fss;
82 short prefdirRefNum;
83 long prefdirDirID;
84 long pyprefdirDirID;
85 Handle namehandle;
86 OSErr err;
88 if ( !diditbefore ) {
89 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
90 (void)StopAlert(NOPREFNAME_ID, NULL);
91 exit(1);
94 if ( **namehandle == '\0' ) {
95 /* Empty string means don't use preferences file */
96 rv = 0;
97 } else {
98 /* There is a filename, construct the fsspec */
99 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
100 &prefdirDirID) != noErr ) {
101 /* Something wrong with preferences folder */
102 (void)StopAlert(NOPREFDIR_ID, NULL);
103 exit(1);
105 /* make fsspec for the "Python" folder inside the prefs folder */
106 err = FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython", &fss);
107 if (err == fnfErr) {
108 /* it doesn't exist: create it */
109 err = FSpDirCreate(&fss, smSystemScript, &pyprefdirDirID);
110 } else {
111 /* it does exist, now find out the dirID of the Python prefs folder, brrr. */
112 CInfoPBRec info;
113 info.dirInfo.ioVRefNum = fss.vRefNum;
114 info.dirInfo.ioDrDirID = fss.parID;
115 info.dirInfo.ioNamePtr = fss.name;
116 info.dirInfo.ioFDirIndex = 0;
117 info.dirInfo.ioACUser = 0;
118 err = PBGetCatInfo(&info, 0);
119 if (err == noErr) {
120 pyprefdirDirID = info.dirInfo.ioDrDirID;
123 if (err != noErr) {
124 (void)StopAlert(NOPREFDIR_ID, NULL);
125 exit(1);
127 HLock(namehandle);
128 err = FSMakeFSSpec(fss.vRefNum, pyprefdirDirID, (unsigned char *)*namehandle, &fss);
129 HUnlock(namehandle);
130 if (err != noErr && err != fnfErr) {
131 (void)StopAlert(NOPREFDIR_ID, NULL);
132 exit(1);
135 ReleaseResource(namehandle);
136 diditbefore = 1;
138 *fssp = fss;
139 return rv;
142 char *
143 Py_GetPath()
145 /* Modified by Jack to do something a bit more sensible:
146 ** - Prepend the python home-directory (which is obtained from a Preferences
147 ** resource)
148 ** - Add :
150 static char *pythonpath;
151 char *p, *endp;
152 int newlen;
153 char *curwd;
155 if ( pythonpath ) return pythonpath;
156 #ifndef USE_BUILTIN_PATH
157 if ( pythonpath = PyMac_GetPythonPath() )
158 return pythonpath;
159 printf("Warning: No pythonpath resource found, using builtin default\n");
160 #endif
161 curwd = PyMac_GetPythonDir();
162 p = PYTHONPATH;
163 endp = p;
164 pythonpath = malloc(2);
165 if ( pythonpath == NULL ) return PYTHONPATH;
166 strcpy(pythonpath, ":");
167 while (*endp) {
168 endp = strchr(p, '\n');
169 if ( endp == NULL )
170 endp = p + strlen(p);
171 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
172 pythonpath = realloc(pythonpath, newlen+1);
173 if ( pythonpath == NULL ) return PYTHONPATH;
174 strcat(pythonpath, "\n");
175 if ( *p == ':' ) {
176 p++;
177 strcat(pythonpath, curwd);
178 strncat(pythonpath, p, (endp-p));
179 newlen--; /* Ok, ok, we've allocated one byte too much */
180 } else {
181 /* We've allocated too much in this case */
182 newlen -= strlen(curwd);
183 pythonpath = realloc(pythonpath, newlen+1);
184 if ( pythonpath == NULL ) return PYTHONPATH;
185 strncat(pythonpath, p, (endp-p));
187 pythonpath[newlen] = '\0';
188 p = endp + 1;
190 return pythonpath;
195 ** Open/create the Python Preferences file, return the handle
197 short
198 PyMac_OpenPrefFile()
200 AliasHandle handle;
201 FSSpec dirspec;
202 short prefrh;
203 OSErr err;
205 if ( !getpreffilefss(&dirspec))
206 return -1;
207 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
208 if ( prefrh < 0 ) {
209 #if 0
210 action = CautionAlert(NOPREFFILE_ID, NULL);
211 if ( action == NOPREFFILE_NO )
212 exit(1);
213 #endif
214 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
215 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
216 if ( prefrh == -1 ) {
217 /* This "cannot happen":-) */
218 printf("Cannot create preferences file, error %d\n", ResError());
219 exit(1);
221 if ( (err=PyMac_init_process_location()) != 0 ) {
222 printf("Cannot get application location, error %d\n", err);
223 exit(1);
225 dirspec = PyMac_ApplicationFSSpec;
226 dirspec.name[0] = 0;
227 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
228 printf("Cannot make alias to application directory, error %d\n", err);
229 exit(1);
231 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
232 UpdateResFile(prefrh);
234 } else {
235 UseResFile(prefrh);
237 return prefrh;
241 ** Return the name of the Python directory
243 char *
244 PyMac_GetPythonDir()
246 static int diditbefore = 0;
247 static char name[256] = {':', '\0'};
248 AliasHandle handle;
249 FSSpec dirspec;
250 Boolean modified = 0;
251 short oldrh, prefrh = -1, homerh;
253 if ( diditbefore )
254 return name;
256 oldrh = CurResFile();
258 /* First look for an override in the application file */
259 UseResFile(PyMac_AppRefNum);
260 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
261 UseResFile(oldrh);
262 if ( handle != NULL ) {
263 homerh = PyMac_AppRefNum;
264 } else {
265 /* Try to open preferences file in the preferences folder. */
266 prefrh = PyMac_OpenPrefFile();
267 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
268 if ( handle == NULL ) {
269 /* (void)StopAlert(BADPREFFILE_ID, NULL); */
270 diditbefore=1;
271 return ":";
273 homerh = prefrh;
275 /* It exists. Resolve it (possibly updating it) */
276 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
277 (void)StopAlert(BADPREFFILE_ID, NULL);
278 diditbefore=1;
279 return ":";
281 if ( modified ) {
282 ChangedResource((Handle)handle);
283 UpdateResFile(homerh);
285 if ( prefrh != -1 ) CloseResFile(prefrh);
286 UseResFile(oldrh);
288 if ( PyMac_GetFullPath(&dirspec, name) == 0 ) {
289 strcat(name, ":");
290 } else {
291 /* If all fails, we return the current directory */
292 printf("Python home dir exists but I cannot find the pathname!!\n");
293 name[0] = 0;
294 (void)getwd(name);
296 diditbefore = 1;
297 return name;
300 #ifndef USE_BUILTIN_PATH
301 char *
302 PyMac_GetPythonPath(void)
304 short oldrh, prefrh = -1;
305 char *rv;
306 int i, newlen;
307 Str255 pathitem;
308 int resource_id;
309 OSErr err;
310 Handle h;
312 oldrh = CurResFile();
314 ** This is a bit tricky. We check here whether the application file
315 ** contains an override. This is to forestall us finding another STR# resource
316 ** with "our" id and using that for path initialization
318 UseResFile(PyMac_AppRefNum);
319 SetResLoad(0);
320 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
321 ReleaseResource(h);
322 resource_id = PYTHONPATHOVERRIDE_ID;
323 } else {
324 resource_id = PYTHONPATH_ID;
326 SetResLoad(1);
327 UseResFile(oldrh);
329 /* Open the preferences file only if there is no override */
330 if ( resource_id != PYTHONPATHOVERRIDE_ID )
331 prefrh = PyMac_OpenPrefFile();
332 /* At this point, we may or may not have the preferences file open, and it
333 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
334 ** exist we use the one from the application (the default).
335 ** We put an initial '\n' in front of the path that we don't return to the caller
337 if( (rv = malloc(2)) == NULL )
338 goto out;
339 strcpy(rv, "\n");
341 for(i=1; ; i++) {
342 GetIndString(pathitem, resource_id, i);
343 if( pathitem[0] == 0 )
344 break;
345 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
346 /* We have to put the directory in place */
347 char *dir = PyMac_GetPythonDir();
349 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
350 if( (rv=realloc(rv, newlen)) == NULL)
351 goto out;
352 strcat(rv, dir);
353 /* Skip a colon at the beginning of the item */
354 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
355 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
356 newlen--;
357 } else {
358 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
360 rv[newlen-2] = '\n';
361 rv[newlen-1] = 0;
362 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
363 /* This is the application itself */
365 if ( (err=PyMac_init_process_location()) != 0 ) {
366 printf("Cannot get application location, error %d\n", err);
367 exit(1);
370 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
371 if( (rv=realloc(rv, newlen)) == NULL)
372 goto out;
373 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
374 rv[newlen-2] = '\n';
375 rv[newlen-1] = 0;
377 } else {
378 /* Use as-is */
379 newlen = strlen(rv) + (pathitem[0]) + 2;
380 if( (rv=realloc(rv, newlen)) == NULL)
381 goto out;
382 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
383 rv[newlen-2] = '\n';
384 rv[newlen-1] = 0;
387 if( strlen(rv) == 1) {
388 free(rv);
389 rv = NULL;
391 if ( rv ) {
392 rv[strlen(rv)-1] = 0;
393 rv++;
395 out:
396 if ( prefrh != -1) CloseResFile(prefrh);
397 UseResFile(oldrh);
398 return rv;
400 #endif /* !USE_BUILTIN_PATH */
402 void
403 PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
405 short oldrh, prefrh = -1;
406 Handle handle;
407 int size;
408 PyMac_PrefRecord *p;
409 int action;
412 oldrh = CurResFile();
414 /* Attempt to load overrides from application */
415 UseResFile(PyMac_AppRefNum);
416 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
417 UseResFile(oldrh);
419 /* Otherwise get options from prefs file or any other open resource file */
420 if ( handle == NULL ) {
421 prefrh = PyMac_OpenPrefFile();
422 handle = GetResource('Popt', PYTHONOPTIONS_ID);
424 if ( handle == NULL ) {
425 return;
427 HLock(handle);
428 size = GetHandleSize(handle);
429 p = (PyMac_PrefRecord *)*handle;
430 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
431 *pr = *p;
432 } else {
433 action = CautionAlert(BADPREFERENCES_ID, NULL);
434 if ( action == BADPREF_DELETE ) {
435 OSErr err;
437 RemoveResource(handle);
438 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
439 if ( prefrh != -1 ) {
440 UpdateResFile(prefrh);
441 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
443 } else if ( action == BADPREF_QUIT )
444 exit(1);
446 HUnlock(handle);
448 if ( prefrh != -1) CloseResFile(prefrh);
449 UseResFile(oldrh);
452 #ifdef USE_GUSI1
453 void
454 PyMac_SetGUSIOptions()
456 Handle h;
457 short oldrh, prefrh = -1;
459 oldrh = CurResFile();
461 /* Try override from the application resource fork */
462 UseResFile(PyMac_AppRefNum);
463 h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
464 UseResFile(oldrh);
466 /* If that didn't work try nonoverride from anywhere */
467 if ( h == NULL ) {
468 prefrh = PyMac_OpenPrefFile();
469 h = GetResource('GU\267I', GUSIOPTIONS_ID);
471 if ( h ) GUSILoadConfiguration(h);
472 if ( prefrh != -1) CloseResFile(prefrh);
473 UseResFile(oldrh);
475 #endif /* USE_GUSI1 */