525 lines
13 KiB
C
525 lines
13 KiB
C
|
/*
|
|||
|
* 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.27 96/09/05 11:18:56
|
|||
|
*/
|
|||
|
|
|||
|
#include <Gestalt.h>
|
|||
|
#include <Folders.h>
|
|||
|
#include <TextUtils.h>
|
|||
|
#include <Resources.h>
|
|||
|
#include <Memory.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <unistd.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;
|
|||
|
char tempStr[kMaxEnvStringSize];
|
|||
|
FSSpec currentDir, prefDir;
|
|||
|
OSErr err;
|
|||
|
|
|||
|
/*
|
|||
|
* Save default folder and change working dir
|
|||
|
* to the preferences folder.
|
|||
|
*/
|
|||
|
FSpGetDefaultDir(¤tDir);
|
|||
|
err = FSpFindFolder(kOnSystemDisk, kPreferencesFolderType,
|
|||
|
kDontCreateFolder, &prefDir);
|
|||
|
err = FSpSetDefaultDir(&prefDir);
|
|||
|
|
|||
|
/* TODO: this code should use new channel IO. */
|
|||
|
if ((thePrefsFile = fopen(kPrefsFile, "r")) == NULL) {
|
|||
|
FSpSetDefaultDir(¤tDir);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
fileEnv = (char **) ckalloc((kMaxEnvVarSize + 1) * sizeof(char *));
|
|||
|
|
|||
|
i = 0;
|
|||
|
while (fgets(tempStr, kMaxEnvStringSize, thePrefsFile) != NULL) {
|
|||
|
/*
|
|||
|
* First strip off new line char
|
|||
|
*/
|
|||
|
if (tempStr[strlen(tempStr)-1] == '\n') {
|
|||
|
tempStr[strlen(tempStr)-1] = '\0';
|
|||
|
}
|
|||
|
if (tempStr[0] == '\0' || tempStr[0] == '#') {
|
|||
|
/*
|
|||
|
* skip empty lines or commented lines
|
|||
|
*/
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
tempPtr = (char *) ckalloc(strlen(tempStr) + 1);
|
|||
|
strcpy(tempPtr,tempStr);
|
|||
|
fileEnv[i++] = tempPtr;
|
|||
|
}
|
|||
|
|
|||
|
fileEnv[i] = NULL;
|
|||
|
fclose(thePrefsFile);
|
|||
|
|
|||
|
FSpSetDefaultDir(¤tDir);
|
|||
|
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(prefixTag, whichFolder)
|
|||
|
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();
|
|||
|
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);
|
|||
|
return(buf[0] ? buf : NULL);
|
|||
|
}
|