mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			475 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			475 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /***********************************************************
 | |
| Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
 | |
| The Netherlands.
 | |
| 
 | |
|                         All Rights Reserved
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this software and its
 | |
| documentation for any purpose and without fee is hereby granted,
 | |
| provided that the above copyright notice appear in all copies and that
 | |
| both that copyright notice and this permission notice appear in
 | |
| supporting documentation, and that the names of Stichting Mathematisch
 | |
| Centrum or CWI or Corporation for National Research Initiatives or
 | |
| CNRI not be used in advertising or publicity pertaining to
 | |
| distribution of the software without specific, written prior
 | |
| permission.
 | |
| 
 | |
| While CWI is the initial source for this software, a modified version
 | |
| is made available by the Corporation for National Research Initiatives
 | |
| (CNRI) at the Internet address ftp://ftp.python.org.
 | |
| 
 | |
| STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
 | |
| REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 | |
| MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
 | |
| CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 | |
| DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 | |
| PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | |
| PERFORMANCE OF THIS SOFTWARE.
 | |
| 
 | |
| ******************************************************************/
 | |
| 
 | |
| #include "Python.h"
 | |
| #include "osdefs.h"
 | |
| #include "macglue.h"
 | |
| #include "macdefs.h"
 | |
| #include "pythonresources.h"
 | |
| #ifdef HAVE_UNISTD_H
 | |
| #include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* Return the initial python search path.  This is called once from
 | |
| ** initsys() to initialize sys.path.
 | |
| **
 | |
| ** If USE_BUILTIN_PATH is defined the path defined here is used
 | |
| ** (after prepending the python home dir to each item).
 | |
| ** If it is not defined the path is gotten from a resource in the
 | |
| ** Preferences file.
 | |
| **
 | |
| ** XXXX This code needs cleaning up. The routines here have moved
 | |
| ** around quite a bit, and they're pretty messy for that reason.
 | |
| */
 | |
| 
 | |
| #include <Files.h>
 | |
| #include <Aliases.h>
 | |
| #include <Folders.h>
 | |
| #include <Resources.h>
 | |
| #include <TextUtils.h>
 | |
| #include <Dialogs.h>
 | |
| 
 | |
| #ifdef USE_GUSI1
 | |
| #include <GUSI.h>
 | |
| #endif
 | |
| 
 | |
| #ifndef USE_BUILTIN_PATH
 | |
| staticforward char *PyMac_GetPythonPath();
 | |
| #endif
 | |
| 
 | |
| #define PYTHONPATH "\
 | |
| :\n\
 | |
| :Lib\n\
 | |
| :Lib:stdwin\n\
 | |
| :Lib:test\n\
 | |
| :Lib:mac"
 | |
| 
 | |
| static int
 | |
| getpreffilefss(FSSpec *fssp)
 | |
| {
 | |
| 	static int diditbefore=0;
 | |
| 	static int rv = 1;
 | |
| 	static FSSpec fss;
 | |
| 	short prefdirRefNum;
 | |
| 	long prefdirDirID;
 | |
| 	long pyprefdirDirID;
 | |
| 	Handle namehandle;
 | |
| 	OSErr err;
 | |
| 	
 | |
| 	if ( !diditbefore ) {
 | |
| 		if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
 | |
| 			(void)StopAlert(NOPREFNAME_ID, NULL);
 | |
| 			exit(1);
 | |
| 		}
 | |
| 		
 | |
| 		if ( **namehandle == '\0' ) {
 | |
| 			/* Empty string means don't use preferences file */
 | |
| 			rv = 0;
 | |
| 		} else {
 | |
| 			/* There is a filename, construct the fsspec */
 | |
| 			if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
 | |
| 							&prefdirDirID) != noErr ) {
 | |
| 				/* Something wrong with preferences folder */
 | |
| 				(void)StopAlert(NOPREFDIR_ID, NULL);
 | |
| 				exit(1);
 | |
| 			}
 | |
| 			/* make fsspec for the "Python" folder inside the prefs folder */
 | |
| 			err = FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython", &fss);
 | |
| 			if (err == fnfErr) {
 | |
| 				/* it doesn't exist: create it */
 | |
| 				err = FSpDirCreate(&fss, smSystemScript, &pyprefdirDirID);
 | |
| 			} else {
 | |
| 				/* it does exist, now find out the dirID of the Python prefs folder, brrr. */
 | |
| 				CInfoPBRec info;
 | |
| 				info.dirInfo.ioVRefNum 		= fss.vRefNum;
 | |
| 				info.dirInfo.ioDrDirID 		= fss.parID;
 | |
| 				info.dirInfo.ioNamePtr 		= fss.name;
 | |
| 				info.dirInfo.ioFDirIndex 	= 0;
 | |
| 				info.dirInfo.ioACUser 		= 0;
 | |
| 				err = PBGetCatInfo(&info, 0);
 | |
| 				if (err == noErr) {
 | |
| 					pyprefdirDirID = info.dirInfo.ioDrDirID;
 | |
| 				}
 | |
| 			}
 | |
| 			if (err != noErr) {
 | |
| 				(void)StopAlert(NOPREFDIR_ID, NULL);
 | |
| 				exit(1);
 | |
| 			}
 | |
| 			HLock(namehandle);
 | |
| 			err = FSMakeFSSpec(fss.vRefNum, pyprefdirDirID, (unsigned char *)*namehandle, &fss);
 | |
| 			HUnlock(namehandle);
 | |
| 			if (err != noErr && err != fnfErr) {
 | |
| 				(void)StopAlert(NOPREFDIR_ID, NULL);
 | |
| 				exit(1);
 | |
| 			}
 | |
| 		}
 | |
| 		ReleaseResource(namehandle);
 | |
| 		diditbefore = 1;
 | |
| 	}
 | |
| 	*fssp = fss;
 | |
| 	return rv;
 | |
| }
 | |
| 
 | |
| char *
 | |
| Py_GetPath()
 | |
| {
 | |
| 	/* Modified by Jack to do something a bit more sensible:
 | |
| 	** - Prepend the python home-directory (which is obtained from a Preferences
 | |
| 	**   resource)
 | |
| 	** - Add :
 | |
| 	*/
 | |
| 	static char *pythonpath;
 | |
| 	char *p, *endp;
 | |
| 	int newlen;
 | |
| 	char *curwd;
 | |
| 	
 | |
| 	if ( pythonpath ) return pythonpath;
 | |
| #ifndef USE_BUILTIN_PATH
 | |
| 	if ( pythonpath = PyMac_GetPythonPath() )
 | |
| 		return pythonpath;
 | |
| 	printf("Warning: No pythonpath resource found, using builtin default\n");
 | |
| #endif
 | |
| 	curwd = PyMac_GetPythonDir();
 | |
| 	p = PYTHONPATH;
 | |
| 	endp = p;
 | |
| 	pythonpath = malloc(2);
 | |
| 	if ( pythonpath == NULL ) return PYTHONPATH;
 | |
| 	strcpy(pythonpath, ":");
 | |
| 	while (*endp) {
 | |
| 		endp = strchr(p, '\n');
 | |
| 		if ( endp == NULL )
 | |
| 			endp = p + strlen(p);
 | |
| 		newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
 | |
| 		pythonpath = realloc(pythonpath, newlen+1);
 | |
| 		if ( pythonpath == NULL ) return PYTHONPATH;
 | |
| 		strcat(pythonpath, "\n");
 | |
| 		if ( *p == ':' ) {
 | |
| 			p++;
 | |
| 			strcat(pythonpath, curwd);
 | |
| 			strncat(pythonpath, p, (endp-p));
 | |
| 			newlen--;   /* Ok, ok, we've allocated one byte too much */
 | |
| 		} else {
 | |
| 			/* We've allocated too much in this case */
 | |
| 			newlen -= strlen(curwd);
 | |
| 			pythonpath = realloc(pythonpath, newlen+1);
 | |
| 			if ( pythonpath == NULL ) return PYTHONPATH;
 | |
| 			strncat(pythonpath, p, (endp-p));
 | |
| 		}
 | |
| 		pythonpath[newlen] = '\0';
 | |
| 		p = endp + 1;
 | |
| 	}
 | |
| 	return pythonpath;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ** Open/create the Python Preferences file, return the handle
 | |
| */
 | |
| short
 | |
| PyMac_OpenPrefFile()
 | |
| {
 | |
| 	AliasHandle handle;
 | |
| 	FSSpec dirspec;
 | |
| 	short prefrh;
 | |
| 	OSErr err;
 | |
| 
 | |
| 	if ( !getpreffilefss(&dirspec))
 | |
| 		return -1;
 | |
| 	prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
 | |
| 	if ( prefrh < 0 ) {
 | |
| #if 0
 | |
| 		action = CautionAlert(NOPREFFILE_ID, NULL);
 | |
| 		if ( action == NOPREFFILE_NO )
 | |
| 			exit(1);
 | |
| #endif
 | |
| 		FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
 | |
| 		prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
 | |
| 		if ( prefrh == -1 ) {
 | |
| 			/* This "cannot happen":-) */
 | |
| 			printf("Cannot create preferences file, error %d\n", ResError());
 | |
| 			exit(1);
 | |
| 		}
 | |
| 		if ( (err=PyMac_init_process_location()) != 0 ) {
 | |
| 			printf("Cannot get application location, error %d\n", err);
 | |
| 			exit(1);
 | |
| 		}
 | |
| 		dirspec = PyMac_ApplicationFSSpec;
 | |
| 		dirspec.name[0] = 0;
 | |
| 		if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
 | |
| 			printf("Cannot make alias to application directory, error %d\n", err);
 | |
| 			exit(1);
 | |
| 		}
 | |
| 		AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
 | |
| 		UpdateResFile(prefrh);
 | |
| 
 | |
| 	} else {
 | |
| 		UseResFile(prefrh);
 | |
| 	}
 | |
| 	return prefrh;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ** Return the name of the Python directory
 | |
| */
 | |
| char *
 | |
| PyMac_GetPythonDir()
 | |
| {
 | |
| 	static int diditbefore = 0;
 | |
| 	static char name[256] = {':', '\0'};
 | |
| 	AliasHandle handle;
 | |
| 	FSSpec dirspec;
 | |
| 	Boolean modified = 0;
 | |
| 	short oldrh, prefrh = -1, homerh;
 | |
| 	
 | |
| 	if ( diditbefore )
 | |
| 		return name;
 | |
| 		
 | |
| 	oldrh = CurResFile();
 | |
| 
 | |
| 	/* First look for an override in the application file */
 | |
| 	UseResFile(PyMac_AppRefNum);
 | |
| 	handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
 | |
| 	UseResFile(oldrh);
 | |
| 	if ( handle != NULL ) {
 | |
| 		homerh = PyMac_AppRefNum;
 | |
| 	} else {   
 | |
| 		/* Try to open preferences file in the preferences folder. */
 | |
| 		prefrh = PyMac_OpenPrefFile();
 | |
| 		handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
 | |
| 		if ( handle == NULL ) {
 | |
| 			/* (void)StopAlert(BADPREFFILE_ID, NULL); */
 | |
| 			diditbefore=1;
 | |
| 			return ":";
 | |
| 		}
 | |
| 		homerh = prefrh;
 | |
| 	}
 | |
| 	/* It exists. Resolve it (possibly updating it) */
 | |
| 	if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
 | |
| 		(void)StopAlert(BADPREFFILE_ID, NULL);
 | |
| 		diditbefore=1;
 | |
| 		return ":";
 | |
| 	}
 | |
| 	if ( modified ) {
 | |
|    		ChangedResource((Handle)handle);
 | |
| 		UpdateResFile(homerh);
 | |
| 	}
 | |
| 	if ( prefrh != -1 ) CloseResFile(prefrh);
 | |
| 	UseResFile(oldrh);
 | |
| 
 | |
|    	if ( PyMac_GetFullPath(&dirspec, name) == 0 ) {
 | |
|    		strcat(name, ":");
 | |
| 	} else {
 | |
|  		/* If all fails, we return the current directory */
 | |
|    		printf("Python home dir exists but I cannot find the pathname!!\n");
 | |
| 		name[0] = 0;
 | |
| 		(void)getwd(name);
 | |
| 	}
 | |
| 	diditbefore = 1;
 | |
| 	return name;
 | |
| }
 | |
| 
 | |
| #ifndef USE_BUILTIN_PATH
 | |
| char *
 | |
| PyMac_GetPythonPath(void)
 | |
| {
 | |
| 	short oldrh, prefrh = -1;
 | |
| 	char *rv;
 | |
| 	int i, newlen;
 | |
| 	Str255 pathitem;
 | |
| 	int resource_id;
 | |
| 	OSErr err;
 | |
| 	Handle h;
 | |
| 	
 | |
| 	oldrh = CurResFile();
 | |
| 	/*
 | |
| 	** This is a bit tricky. We check here whether the application file
 | |
| 	** contains an override. This is to forestall us finding another STR# resource
 | |
| 	** with "our" id and using that for path initialization
 | |
| 	*/
 | |
| 	UseResFile(PyMac_AppRefNum);
 | |
| 	SetResLoad(0);
 | |
| 	if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
 | |
| 		ReleaseResource(h);
 | |
| 		resource_id = PYTHONPATHOVERRIDE_ID;
 | |
| 	} else {
 | |
| 		resource_id = PYTHONPATH_ID;
 | |
| 	}
 | |
| 	SetResLoad(1);
 | |
| 	UseResFile(oldrh);
 | |
| 	
 | |
| 	/* Open the preferences file only if there is no override */
 | |
| 	if ( resource_id != PYTHONPATHOVERRIDE_ID )
 | |
| 		prefrh = PyMac_OpenPrefFile();
 | |
| 	/* At this point, we may or may not have the preferences file open, and it
 | |
| 	** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
 | |
| 	** exist we use the one from the application (the default).
 | |
| 	** We put an initial '\n' in front of the path that we don't return to the caller
 | |
| 	*/
 | |
| 	if( (rv = malloc(2)) == NULL )
 | |
| 		goto out;
 | |
| 	strcpy(rv, "\n");
 | |
| 
 | |
| 	for(i=1; ; i++) {
 | |
| 		GetIndString(pathitem, resource_id, i);
 | |
| 		if( pathitem[0] == 0 )
 | |
| 			break;
 | |
| 		if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
 | |
| 			/* We have to put the directory in place */
 | |
| 			char *dir = PyMac_GetPythonDir();
 | |
| 			
 | |
| 			newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
 | |
| 			if( (rv=realloc(rv, newlen)) == NULL)
 | |
| 				goto out;
 | |
| 			strcat(rv, dir);
 | |
| 			/* Skip a colon at the beginning of the item */
 | |
| 			if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
 | |
| 				memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
 | |
| 				newlen--;
 | |
| 			} else {
 | |
| 				memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
 | |
| 			}
 | |
| 			rv[newlen-2] = '\n';
 | |
| 			rv[newlen-1] = 0;
 | |
| 		} else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
 | |
| 			/* This is the application itself */
 | |
| 			
 | |
| 			if ( (err=PyMac_init_process_location()) != 0 ) {
 | |
| 				printf("Cannot get  application location, error %d\n", err);
 | |
| 				exit(1);
 | |
| 			}
 | |
| 
 | |
| 			newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
 | |
| 			if( (rv=realloc(rv, newlen)) == NULL)
 | |
| 				goto out;
 | |
| 			strcpy(rv+strlen(rv), PyMac_ApplicationPath);
 | |
| 			rv[newlen-2] = '\n';
 | |
| 			rv[newlen-1] = 0;
 | |
| 
 | |
| 		} else {
 | |
| 			/* Use as-is */
 | |
| 			newlen = strlen(rv) + (pathitem[0]) + 2;
 | |
| 			if( (rv=realloc(rv, newlen)) == NULL)
 | |
| 				goto out;
 | |
| 			memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
 | |
| 			rv[newlen-2] = '\n';
 | |
| 			rv[newlen-1] = 0;
 | |
| 		}
 | |
| 	}
 | |
| 	if( strlen(rv) == 1) {
 | |
| 		free(rv);
 | |
| 		rv = NULL;
 | |
| 	}
 | |
| 	if ( rv ) {
 | |
| 		rv[strlen(rv)-1] = 0;
 | |
| 		rv++;
 | |
| 	}
 | |
| out:
 | |
| 	if ( prefrh != -1) CloseResFile(prefrh);
 | |
| 	UseResFile(oldrh);
 | |
| 	return rv;
 | |
| }
 | |
| #endif /* !USE_BUILTIN_PATH */
 | |
| 
 | |
| void
 | |
| PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
 | |
| {
 | |
| 	short oldrh, prefrh = -1;
 | |
| 	Handle handle;
 | |
| 	int size;
 | |
| 	PyMac_PrefRecord *p;
 | |
| 	int action;
 | |
| 	
 | |
| 	
 | |
| 	oldrh = CurResFile();
 | |
| 	
 | |
| 	/* Attempt to load overrides from application */
 | |
| 	UseResFile(PyMac_AppRefNum);
 | |
| 	handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
 | |
| 	UseResFile(oldrh);
 | |
| 	
 | |
| 	/* Otherwise get options from prefs file or any other open resource file */
 | |
| 	if ( handle == NULL ) {
 | |
| 		prefrh = PyMac_OpenPrefFile();
 | |
| 		handle = GetResource('Popt', PYTHONOPTIONS_ID);
 | |
| 	}
 | |
| 	if ( handle == NULL ) {
 | |
| 		return;
 | |
| 	}
 | |
| 	HLock(handle);
 | |
| 	size = GetHandleSize(handle);
 | |
| 	p = (PyMac_PrefRecord *)*handle;
 | |
| 	if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
 | |
| 		*pr = *p;
 | |
| 	} else {
 | |
| 		action = CautionAlert(BADPREFERENCES_ID, NULL);
 | |
| 		if ( action == BADPREF_DELETE ) {
 | |
| 			OSErr err;
 | |
| 			
 | |
| 			RemoveResource(handle);
 | |
| 			if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
 | |
| 			if ( prefrh != -1 ) {
 | |
| 				UpdateResFile(prefrh);
 | |
| 				if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
 | |
| 			}
 | |
| 		} else if ( action == BADPREF_QUIT )
 | |
| 			exit(1);
 | |
| 	}
 | |
| 	HUnlock(handle);
 | |
| 
 | |
|    	if ( prefrh != -1) CloseResFile(prefrh);
 | |
| 	UseResFile(oldrh);
 | |
| }
 | |
| 
 | |
| #ifdef USE_GUSI1
 | |
| void
 | |
| PyMac_SetGUSIOptions()
 | |
| {
 | |
| 	Handle h;
 | |
| 	short oldrh, prefrh = -1;
 | |
| 	
 | |
| 	oldrh = CurResFile();
 | |
| 	
 | |
| 	/* Try override from the application resource fork */
 | |
| 	UseResFile(PyMac_AppRefNum);
 | |
| 	h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
 | |
| 	UseResFile(oldrh);
 | |
| 	
 | |
| 	/* If that didn't work try nonoverride from anywhere */
 | |
| 	if ( h == NULL ) {
 | |
| 		prefrh = PyMac_OpenPrefFile();
 | |
| 		h = GetResource('GU\267I', GUSIOPTIONS_ID);
 | |
| 	}
 | |
| 	if ( h ) GUSILoadConfiguration(h);
 | |
|    	if ( prefrh != -1) CloseResFile(prefrh);
 | |
| 	UseResFile(oldrh);
 | |
| }
 | |
| #endif /* USE_GUSI1 */	
 | 
