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