This commit was manufactured by cvs2svn to create tag
[python/dscho.git] / Mac / Python / macgetpath.c
blobb79e90b001ec76ce797692c1ac5c5a140e7ea132
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
41 #ifdef TARGET_API_MAC_OSX
42 #define PATHNAMELEN 1024
43 #else
44 #define PATHNAMELEN 256
45 #endif
47 /* Return the initial python search path. This is called once from
48 ** initsys() to initialize sys.path.
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.
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.
59 #include <Files.h>
60 #include <Aliases.h>
61 #include <Folders.h>
62 #include <Resources.h>
63 #include <TextUtils.h>
64 #include <Dialogs.h>
66 #ifdef USE_GUSI1
67 #include <GUSI.h>
68 #endif
70 #ifndef USE_BUILTIN_PATH
71 staticforward char *PyMac_GetPythonPath();
72 #endif
74 #define PYTHONPATH "\
75 :\n\
76 :Lib\n\
77 :Lib:stdwin\n\
78 :Lib:test\n\
79 :Lib:mac"
81 static int
82 getpreffilefss(FSSpec *fssp)
84 static int diditbefore=0;
85 static int rv = 1;
86 static FSSpec fss;
87 short prefdirRefNum;
88 long prefdirDirID;
89 long pyprefdirDirID;
90 Handle namehandle;
91 OSErr err;
93 if ( !diditbefore ) {
94 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
95 (void)StopAlert(NOPREFNAME_ID, NULL);
96 exit(1);
99 if ( **namehandle == '\0' ) {
100 /* Empty string means don't use preferences file */
101 rv = 0;
102 } else {
103 /* There is a filename, construct the fsspec */
104 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
105 &prefdirDirID) != noErr ) {
106 /* Something wrong with preferences folder */
107 (void)StopAlert(NOPREFDIR_ID, NULL);
108 exit(1);
110 /* make fsspec for the "Python" folder inside the prefs folder */
111 err = FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython", &fss);
112 if (err == fnfErr) {
113 /* it doesn't exist: create it */
114 err = FSpDirCreate(&fss, smSystemScript, &pyprefdirDirID);
115 } else {
116 /* it does exist, now find out the dirID of the Python prefs folder, brrr. */
117 CInfoPBRec info;
118 info.dirInfo.ioVRefNum = fss.vRefNum;
119 info.dirInfo.ioDrDirID = fss.parID;
120 info.dirInfo.ioNamePtr = fss.name;
121 info.dirInfo.ioFDirIndex = 0;
122 info.dirInfo.ioACUser = 0;
123 err = PBGetCatInfo(&info, 0);
124 if (err == noErr) {
125 pyprefdirDirID = info.dirInfo.ioDrDirID;
128 if (err != noErr) {
129 (void)StopAlert(NOPREFDIR_ID, NULL);
130 exit(1);
132 HLock(namehandle);
133 err = FSMakeFSSpec(fss.vRefNum, pyprefdirDirID, (unsigned char *)*namehandle, &fss);
134 HUnlock(namehandle);
135 if (err != noErr && err != fnfErr) {
136 (void)StopAlert(NOPREFDIR_ID, NULL);
137 exit(1);
140 ReleaseResource(namehandle);
141 diditbefore = 1;
143 *fssp = fss;
144 return rv;
147 char *
148 Py_GetPath()
150 /* Modified by Jack to do something a bit more sensible:
151 ** - Prepend the python home-directory (which is obtained from a Preferences
152 ** resource)
153 ** - Add :
155 static char *pythonpath;
156 char *p, *endp;
157 int newlen;
158 char *curwd;
160 if ( pythonpath ) return pythonpath;
161 #ifndef USE_BUILTIN_PATH
162 if ( pythonpath = PyMac_GetPythonPath() )
163 return pythonpath;
164 printf("Warning: No pythonpath resource found, using builtin default\n");
165 #endif
166 curwd = PyMac_GetPythonDir();
167 p = PYTHONPATH;
168 endp = p;
169 pythonpath = malloc(2);
170 if ( pythonpath == NULL ) return PYTHONPATH;
171 strcpy(pythonpath, ":");
172 while (*endp) {
173 endp = strchr(p, '\n');
174 if ( endp == NULL )
175 endp = p + strlen(p);
176 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
177 pythonpath = realloc(pythonpath, newlen+1);
178 if ( pythonpath == NULL ) return PYTHONPATH;
179 strcat(pythonpath, "\n");
180 if ( *p == ':' ) {
181 p++;
182 strcat(pythonpath, curwd);
183 strncat(pythonpath, p, (endp-p));
184 newlen--; /* Ok, ok, we've allocated one byte too much */
185 } else {
186 /* We've allocated too much in this case */
187 newlen -= strlen(curwd);
188 pythonpath = realloc(pythonpath, newlen+1);
189 if ( pythonpath == NULL ) return PYTHONPATH;
190 strncat(pythonpath, p, (endp-p));
192 pythonpath[newlen] = '\0';
193 p = endp + 1;
195 return pythonpath;
200 ** Open/create the Python Preferences file, return the handle
202 short
203 PyMac_OpenPrefFile()
205 AliasHandle handle;
206 FSSpec dirspec;
207 short prefrh;
208 OSErr err;
210 if ( !getpreffilefss(&dirspec))
211 return -1;
212 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
213 if ( prefrh < 0 ) {
214 #if 0
215 action = CautionAlert(NOPREFFILE_ID, NULL);
216 if ( action == NOPREFFILE_NO )
217 exit(1);
218 #endif
219 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
220 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
221 if ( prefrh == -1 ) {
222 /* This "cannot happen":-) */
223 printf("Cannot create preferences file, error %d\n", ResError());
224 exit(1);
226 if ( (err=PyMac_init_process_location()) != 0 ) {
227 printf("Cannot get application location, error %d\n", err);
228 exit(1);
230 dirspec = PyMac_ApplicationFSSpec;
231 dirspec.name[0] = 0;
232 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
233 printf("Cannot make alias to application directory, error %d\n", err);
234 exit(1);
236 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
237 UpdateResFile(prefrh);
239 } else {
240 UseResFile(prefrh);
242 return prefrh;
246 ** Return the name of the Python directory
248 char *
249 PyMac_GetPythonDir()
251 static int diditbefore = 0;
252 static char name[PATHNAMELEN] = {':', '\0'};
253 AliasHandle handle;
254 FSSpec dirspec;
255 Boolean modified = 0;
256 short oldrh, prefrh = -1, homerh;
258 if ( diditbefore )
259 return name;
261 oldrh = CurResFile();
263 /* First look for an override in the application file */
264 UseResFile(PyMac_AppRefNum);
265 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
266 UseResFile(oldrh);
267 if ( handle != NULL ) {
268 homerh = PyMac_AppRefNum;
269 } else {
270 /* Try to open preferences file in the preferences folder. */
271 prefrh = PyMac_OpenPrefFile();
272 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
273 if ( handle == NULL ) {
274 /* (void)StopAlert(BADPREFFILE_ID, NULL); */
275 diditbefore=1;
276 return ":";
278 homerh = prefrh;
280 /* It exists. Resolve it (possibly updating it) */
281 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
282 (void)StopAlert(BADPREFFILE_ID, NULL);
283 diditbefore=1;
284 return ":";
286 if ( modified ) {
287 ChangedResource((Handle)handle);
288 UpdateResFile(homerh);
290 if ( prefrh != -1 ) CloseResFile(prefrh);
291 UseResFile(oldrh);
293 if ( PyMac_GetFullPathname(&dirspec, name, PATHNAMELEN) == 0 ) {
294 strcat(name, ":");
295 } else {
296 /* If all fails, we return the current directory */
297 printf("Python home dir exists but I cannot find the pathname!!\n");
298 name[0] = 0;
299 (void)getcwd(name, sizeof(name));
301 diditbefore = 1;
302 return name;
305 #ifndef USE_BUILTIN_PATH
306 char *
307 PyMac_GetPythonPath(void)
309 short oldrh, prefrh = -1;
310 char *rv;
311 int i, newlen;
312 Str255 pathitem;
313 int resource_id;
314 OSErr err;
315 Handle h;
317 oldrh = CurResFile();
319 ** This is a bit tricky. We check here whether the application file
320 ** contains an override. This is to forestall us finding another STR# resource
321 ** with "our" id and using that for path initialization
323 UseResFile(PyMac_AppRefNum);
324 SetResLoad(0);
325 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
326 ReleaseResource(h);
327 resource_id = PYTHONPATHOVERRIDE_ID;
328 } else {
329 resource_id = PYTHONPATH_ID;
331 SetResLoad(1);
332 UseResFile(oldrh);
334 /* Open the preferences file only if there is no override */
335 if ( resource_id != PYTHONPATHOVERRIDE_ID )
336 prefrh = PyMac_OpenPrefFile();
337 /* At this point, we may or may not have the preferences file open, and it
338 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
339 ** exist we use the one from the application (the default).
340 ** We put an initial '\n' in front of the path that we don't return to the caller
342 if( (rv = malloc(2)) == NULL )
343 goto out;
344 strcpy(rv, "\n");
346 for(i=1; ; i++) {
347 GetIndString(pathitem, resource_id, i);
348 if( pathitem[0] == 0 )
349 break;
350 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
351 /* We have to put the directory in place */
352 char *dir = PyMac_GetPythonDir();
354 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
355 if( (rv=realloc(rv, newlen)) == NULL)
356 goto out;
357 strcat(rv, dir);
358 /* Skip a colon at the beginning of the item */
359 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
360 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
361 newlen--;
362 } else {
363 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
365 rv[newlen-2] = '\n';
366 rv[newlen-1] = 0;
367 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
368 /* This is the application itself */
370 if ( (err=PyMac_init_process_location()) != 0 ) {
371 printf("Cannot get application location, error %d\n", err);
372 exit(1);
375 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
376 if( (rv=realloc(rv, newlen)) == NULL)
377 goto out;
378 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
379 rv[newlen-2] = '\n';
380 rv[newlen-1] = 0;
382 } else {
383 /* Use as-is */
384 newlen = strlen(rv) + (pathitem[0]) + 2;
385 if( (rv=realloc(rv, newlen)) == NULL)
386 goto out;
387 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
388 rv[newlen-2] = '\n';
389 rv[newlen-1] = 0;
392 if( strlen(rv) == 1) {
393 free(rv);
394 rv = NULL;
396 if ( rv ) {
397 rv[strlen(rv)-1] = 0;
398 rv++;
400 out:
401 if ( prefrh != -1) CloseResFile(prefrh);
402 UseResFile(oldrh);
403 return rv;
405 #endif /* !USE_BUILTIN_PATH */
407 void
408 PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
410 short oldrh, prefrh = -1;
411 Handle handle;
412 int size;
413 PyMac_PrefRecord *p;
414 int action;
417 oldrh = CurResFile();
419 /* Attempt to load overrides from application */
420 UseResFile(PyMac_AppRefNum);
421 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
422 UseResFile(oldrh);
424 /* Otherwise get options from prefs file or any other open resource file */
425 if ( handle == NULL ) {
426 prefrh = PyMac_OpenPrefFile();
427 handle = GetResource('Popt', PYTHONOPTIONS_ID);
429 if ( handle == NULL ) {
430 return;
432 HLock(handle);
433 size = GetHandleSize(handle);
434 p = (PyMac_PrefRecord *)*handle;
435 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
436 *pr = *p;
437 } else {
438 action = CautionAlert(BADPREFERENCES_ID, NULL);
439 if ( action == BADPREF_DELETE ) {
440 OSErr err;
442 RemoveResource(handle);
443 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
444 if ( prefrh != -1 ) {
445 UpdateResFile(prefrh);
446 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
448 } else if ( action == BADPREF_QUIT )
449 exit(1);
451 HUnlock(handle);
453 if ( prefrh != -1) CloseResFile(prefrh);
454 UseResFile(oldrh);
457 #ifdef USE_GUSI1
458 void
459 PyMac_SetGUSIOptions()
461 Handle h;
462 short oldrh, prefrh = -1;
464 oldrh = CurResFile();
466 /* Try override from the application resource fork */
467 UseResFile(PyMac_AppRefNum);
468 h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
469 UseResFile(oldrh);
471 /* If that didn't work try nonoverride from anywhere */
472 if ( h == NULL ) {
473 prefrh = PyMac_OpenPrefFile();
474 h = GetResource('GU\267I', GUSIOPTIONS_ID);
476 if ( h ) GUSILoadConfiguration(h);
477 if ( prefrh != -1) CloseResFile(prefrh);
478 UseResFile(oldrh);
480 #endif /* USE_GUSI1 */