summaryrefslogtreecommitdiffstats
path: root/mac/tclMacEnv.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac/tclMacEnv.c')
-rw-r--r--mac/tclMacEnv.c536
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(&currentDir);
+ FSpPathFromLocation(&currentDir, &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);
+}