diff options
Diffstat (limited to 'mac/tclMacEnv.c')
-rw-r--r-- | mac/tclMacEnv.c | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/mac/tclMacEnv.c b/mac/tclMacEnv.c new file mode 100644 index 0000000..afb6028 --- /dev/null +++ b/mac/tclMacEnv.c @@ -0,0 +1,536 @@ +/* + * tclMacEnv.c -- + * + * Implements the "environment" on a Macintosh. + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) tclMacEnv.c 1.29 96/12/06 14:19:57 + */ + +#include <Gestalt.h> +#include <Folders.h> +#include <TextUtils.h> +#include <Resources.h> +#include <string.h> + +#include "tcl.h" +#include "tclInt.h" +#include "tclMacInt.h" +#include "tclPort.h" + +#define kMaxEnvStringSize 255 +#define kMaxEnvVarSize 100 +#define kLoginnameTag "LOGIN=" +#define kUsernameTag "USER=" +#define kDefaultDirTag "HOME=" + +/* + * The following specifies a text file where additional environment variables + * can be set. The file must reside in the preferences folder. If the file + * doesn't exist NO error will occur. Commet out the difinition if you do + * NOT want to use an environment variables file. + */ +#define kPrefsFile "Tcl Environment Variables" + +/* + * The following specifies the Name of a 'STR#' resource in the application + * where additional environment variables may be set. If the resource doesn't + * exist no errors will occur. Commet it out if you don't want it. + */ +#define REZ_ENV "\pTcl Environment Variables" + +/* Globals */ +char **environ = NULL; + +/* + * Declarations for local procedures defined in this file: + */ +static char ** RezRCVariables _ANSI_ARGS_((void)); +static char ** FileRCVariables _ANSI_ARGS_((void)); +static char ** PathVariables _ANSI_ARGS_((void)); +static char ** SystemVariables _ANSI_ARGS_((void)); +static char * MakeFolderEnvVar _ANSI_ARGS_((char * prefixTag, + long whichFolder)); +static char * GetUserName _ANSI_ARGS_((void)); + +/* + *---------------------------------------------------------------------- + * + * RezRCVariables -- + * + * Creates environment variables from the applications resource fork. + * The function looks for the 'STR#' resource with the name defined + * in the #define REZ_ENV. If the define is not defined this code + * will not be included. If the resource doesn't exist or no strings + * reside in the resource nothing will happen. + * + * Results: + * ptr to value on success, NULL if error. + * + * Side effects: + * Memory is allocated and returned to the caller. + * + *---------------------------------------------------------------------- + */ + +#ifdef REZ_ENV +static char ** +RezRCVariables() +{ + Handle envStrs = NULL; + char** rezEnv = NULL; + short int numStrs; + + envStrs = GetNamedResource('STR#', REZ_ENV); + if (envStrs == NULL) return NULL; + numStrs = *((short *) (*envStrs)); + + rezEnv = (char **) ckalloc((numStrs + 1) * sizeof(char *)); + + if (envStrs != NULL) { + ResType theType; + Str255 theName; + short theID, index = 1; + int i = 0; + char* string; + + GetResInfo(envStrs, &theID, &theType, theName); + for(;;) { + GetIndString(theName, theID, index++); + if (theName[0] == '\0') break; + string = (char *) ckalloc(theName[0] + 2); + strncpy(string, (char *) theName + 1, theName[0]); + string[theName[0]] = '\0'; + rezEnv[i++] = string; + } + ReleaseResource(envStrs); + + rezEnv[i] = NULL; + return rezEnv; + } + + return NULL; +} +#endif + +/* + *---------------------------------------------------------------------- + * + * FileRCVariables -- + * + * Creates environment variables from a file in the system preferences + * folder. The function looks for a file in the preferences folder + * a name defined in the #define kPrefsFile. If the define is not + * defined this code will not be included. If the resource doesn't exist or + * no strings reside in the resource nothing will happen. + * + * Results: + * ptr to value on success, NULL if error. + * + * Side effects: + * Memory is allocated and returned to the caller. + * + *---------------------------------------------------------------------- + */ + +#ifdef kPrefsFile +static char ** +FileRCVariables() +{ + char *prefsFolder = NULL; + char *tempPtr = NULL; + char **fileEnv = NULL; + FILE *thePrefsFile = NULL; + int i; + FSSpec prefDir; + OSErr err; + Handle theString = NULL; + Tcl_Channel chan; + int size; + Tcl_DString lineRead; + + err = FSpFindFolder(kOnSystemDisk, kPreferencesFolderType, + kDontCreateFolder, &prefDir); + if (err != noErr) { + return NULL; + } + err = FSpPathFromLocation(&prefDir, &size, &theString); + if (err != noErr) { + return NULL; + } + (void) Munger(theString, size, NULL, 0, kPrefsFile, strlen(kPrefsFile)); + + HLock(theString); + chan = Tcl_OpenFileChannel(NULL, *theString, "r", 0); + HUnlock(theString); + DisposeHandle(theString); + if (chan == NULL) { + return NULL; + } + + /* + * We found a env file. Let start parsing it. + */ + fileEnv = (char **) ckalloc((kMaxEnvVarSize + 1) * sizeof(char *)); + + i = 0; + Tcl_DStringInit(&lineRead); + while (Tcl_Gets(chan, &lineRead) != -1) { + /* + * First strip off new line char + */ + if (lineRead.string[lineRead.length-1] == '\n') { + lineRead.string[lineRead.length-1] = '\0'; + } + if (lineRead.string[0] == '\0' || lineRead.string[0] == '#') { + /* + * skip empty lines or commented lines + */ + Tcl_DStringSetLength(&lineRead, 0); + continue; + } + + tempPtr = (char *) ckalloc(lineRead.length + 1); + strcpy(tempPtr, lineRead.string); + fileEnv[i++] = tempPtr; + Tcl_DStringSetLength(&lineRead, 0); + } + + fileEnv[i] = NULL; + Tcl_Close(NULL, chan); + Tcl_DStringFree(&lineRead); + + return fileEnv; +} +#endif + +/* + *---------------------------------------------------------------------- + * + * MakeFolderEnvVar -- + * + * This function creates "environment" variable by taking a prefix and + * appending a folder path to a directory. The directory is specified + * by a integer value acceptable by the FindFolder function. + * + * Results: + * The function returns an *allocated* string. If the folder doesn't + * exist the return string is still allocated and just contains the + * given prefix. + * + * Side effects: + * Memory is allocated and returned to the caller. + * + *---------------------------------------------------------------------- + */ + +static char * +MakeFolderEnvVar( + char * prefixTag, /* Prefix added before result. */ + long whichFolder) /* Constant for FSpFindFolder. */ +{ + char * thePath = NULL; + char * result = NULL; + OSErr theErr = noErr; + Handle theString = NULL; + FSSpec theFolder; + int size; + Tcl_DString pathStr; + Tcl_DString tagPathStr; + + Tcl_DStringInit(&pathStr); + theErr = FSpFindFolder(kOnSystemDisk, whichFolder, + kDontCreateFolder, &theFolder); + if (theErr == noErr) { + theErr = FSpPathFromLocation(&theFolder, &size, &theString); + + HLock(theString); + tclPlatform = TCL_PLATFORM_MAC; + Tcl_DStringAppend(&pathStr, *theString, -1); + HUnlock(theString); + DisposeHandle(theString); + + Tcl_DStringInit(&tagPathStr); + Tcl_DStringAppend(&tagPathStr, prefixTag, strlen(prefixTag)); + Tcl_DStringAppend(&tagPathStr, pathStr.string, pathStr.length); + Tcl_DStringFree(&pathStr); + + /* + * Make sure the path ends with a ':' + */ + if (tagPathStr.string[tagPathStr.length - 1] != ':') { + Tcl_DStringAppend(&tagPathStr, ":", 1); + } + + /* + * Don't free tagPathStr - rather make sure it's allocated + * and return it as the result. + */ + if (tagPathStr.string == tagPathStr.staticSpace) { + result = (char *) ckalloc(tagPathStr.length + 1); + strcpy(result, tagPathStr.string); + } else { + result = tagPathStr.string; + } + } else { + result = (char *) ckalloc(strlen(prefixTag) + 1); + strcpy(result, prefixTag); + } + + return result; +} + +/* + *---------------------------------------------------------------------- + * + * PathVariables -- + * + * Creates environment variables from the system call FSpFindFolder. + * The function generates environment variables for many of the + * commonly used paths on the Macintosh. + * + * Results: + * ptr to value on success, NULL if error. + * + * Side effects: + * Memory is allocated and returned to the caller. + * + *---------------------------------------------------------------------- + */ + +static char ** +PathVariables() +{ + int i = 0; + char **sysEnv; + char *thePath = NULL; + + sysEnv = (char **) ckalloc((12) * sizeof(char *)); + + sysEnv[i++] = MakeFolderEnvVar("PREF_FOLDER=", kPreferencesFolderType); + sysEnv[i++] = MakeFolderEnvVar("SYS_FOLDER=", kSystemFolderType); + sysEnv[i++] = MakeFolderEnvVar("TEMP=", kTemporaryFolderType); + sysEnv[i++] = MakeFolderEnvVar("APPLE_M_FOLDER=", kAppleMenuFolderType); + sysEnv[i++] = MakeFolderEnvVar("CP_FOLDER=", kControlPanelFolderType); + sysEnv[i++] = MakeFolderEnvVar("DESK_FOLDER=", kDesktopFolderType); + sysEnv[i++] = MakeFolderEnvVar("EXT_FOLDER=", kExtensionFolderType); + sysEnv[i++] = MakeFolderEnvVar("PRINT_MON_FOLDER=", + kPrintMonitorDocsFolderType); + sysEnv[i++] = MakeFolderEnvVar("SHARED_TRASH_FOLDER=", + kWhereToEmptyTrashFolderType); + sysEnv[i++] = MakeFolderEnvVar("TRASH_FOLDER=", kTrashFolderType); + sysEnv[i++] = MakeFolderEnvVar("START_UP_FOLDER=", kStartupFolderType); + sysEnv[i++] = NULL; + + return sysEnv; +} + +/* + *---------------------------------------------------------------------- + * + * SystemVariables -- + * + * Creates environment variables from various Mac system calls. + * + * Results: + * ptr to value on success, NULL if error. + * + * Side effects: + * Memory is allocated and returned to the caller. + * + *---------------------------------------------------------------------- + */ + +static char ** +SystemVariables() +{ + int i = 0; + char ** sysEnv; + char * thePath = NULL; + Handle theString = NULL; + FSSpec currentDir; + int size; + + sysEnv = (char **) ckalloc((4) * sizeof(char *)); + + /* + * Get user name from chooser. It will be assigned to both + * the USER and LOGIN environment variables. + */ + thePath = GetUserName(); + if (thePath != NULL) { + sysEnv[i] = (char *) ckalloc(strlen(kLoginnameTag) + strlen(thePath) + 1); + strcpy(sysEnv[i], kLoginnameTag); + strcpy(sysEnv[i]+strlen(kLoginnameTag), thePath); + i++; + sysEnv[i] = (char *) ckalloc(strlen(kUsernameTag) + strlen(thePath) + 1); + strcpy(sysEnv[i], kUsernameTag); + strcpy(sysEnv[i]+strlen(kUsernameTag), thePath); + i++; + } + + /* + * Get 'home' directory + */ +#ifdef kDefaultDirTag + FSpGetDefaultDir(¤tDir); + FSpPathFromLocation(¤tDir, &size, &theString); + HLock(theString); + sysEnv[i] = (char *) ckalloc(strlen(kDefaultDirTag) + size + 4); + strcpy(sysEnv[i], kDefaultDirTag); + strncpy(sysEnv[i]+strlen(kDefaultDirTag) , *theString, size); + if (sysEnv[i][strlen(kDefaultDirTag) + size - 1] != ':') { + sysEnv[i][strlen(kDefaultDirTag) + size] = ':'; + sysEnv[i][strlen(kDefaultDirTag) + size + 1] = '\0'; + } else { + sysEnv[i][strlen(kDefaultDirTag) + size] = '\0'; + } + HUnlock(theString); + DisposeHandle(theString); + i++; +#endif + + sysEnv[i++] = NULL; + return sysEnv; +} + +/* + *---------------------------------------------------------------------- + * + * TclMacCreateEnv -- + * + * This function allocates and populates the global "environ" + * variable. Entries are in traditional Unix format but variables + * are, hopefully, a bit more relevant for the Macintosh. + * + * Results: + * The number of elements in the newly created environ array. + * + * Side effects: + * Memory is allocated and pointed too by the environ variable. + * + *---------------------------------------------------------------------- + */ + +int +TclMacCreateEnv() +{ + char ** sysEnv = NULL; + char ** pathEnv = NULL; + char ** fileEnv = NULL; + char ** rezEnv = NULL; + int count = 0; + int i, j; + + sysEnv = SystemVariables(); + if (sysEnv != NULL) { + for (i = 0; sysEnv[i] != NULL; count++, i++) { + /* Empty Loop */ + } + } + + pathEnv = PathVariables(); + if (pathEnv != NULL) { + for (i = 0; pathEnv[i] != NULL; count++, i++) { + /* Empty Loop */ + } + } + +#ifdef kPrefsFile + fileEnv = FileRCVariables(); + if (fileEnv != NULL) { + for (i = 0; fileEnv[i] != NULL; count++, i++) { + /* Empty Loop */ + } + } +#endif + +#ifdef REZ_ENV + rezEnv = RezRCVariables(); + if (rezEnv != NULL) { + for (i = 0; rezEnv[i] != NULL; count++, i++) { + /* Empty Loop */ + } + } +#endif + + /* + * Create environ variable + */ + environ = (char **) ckalloc((count + 1) * sizeof(char *)); + j = 0; + + if (sysEnv != NULL) { + for (i = 0; sysEnv[i] != NULL;) + environ[j++] = sysEnv[i++]; + ckfree((char *) sysEnv); + } + + if (pathEnv != NULL) { + for (i = 0; pathEnv[i] != NULL;) + environ[j++] = pathEnv[i++]; + ckfree((char *) pathEnv); + } + +#ifdef kPrefsFile + if (fileEnv != NULL) { + for (i = 0; fileEnv[i] != NULL;) + environ[j++] = fileEnv[i++]; + ckfree((char *) fileEnv); + } +#endif + +#ifdef REZ_ENV + if (rezEnv != NULL) { + for (i = 0; rezEnv[i] != NULL;) + environ[j++] = rezEnv[i++]; + ckfree((char *) rezEnv); + } +#endif + + environ[j] = NULL; + return j; +} + +/* + *---------------------------------------------------------------------- + * + * GetUserName -- + * + * Get the user login name. + * + * Results: + * ptr to static string, NULL if error. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static char * +GetUserName() +{ + static char buf[33]; + short refnum; + Handle h; + + refnum = CurResFile(); + UseResFile(0); + h = GetResource('STR ', -16096); + UseResFile(refnum); + if (h == NULL) { + return NULL; + } + + HLock(h); + strncpy(buf, (*h)+1, **h); + buf[**h] = '\0'; + HUnlock(h); + ReleaseResource(h); + return(buf[0] ? buf : NULL); +} |