/* * 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. * * RCS: @(#) $Id: tclMacEnv.c,v 1.2 1998/09/14 18:40:04 stanton Exp $ */ #include #include #include #include #include #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); }