#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="
#define kPrefsFile "Tcl Environment Variables"
#define REZ_ENV "\pTcl Environment Variables"
char **environ = NULL;
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));
#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
#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;
}
fileEnv = (char **) ckalloc((kMaxEnvVarSize + 1) * sizeof(char *));
i = 0;
Tcl_DStringInit(&lineRead);
while (Tcl_Gets(chan, &lineRead) != -1) {
if (lineRead.string[lineRead.length-1] == '\n') {
lineRead.string[lineRead.length-1] = '\0';
}
if (lineRead.string[0] == '\0' || lineRead.string[0] == '#') {
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
static char *
MakeFolderEnvVar(
char * prefixTag,
long whichFolder)
{
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);
if (tagPathStr.string[tagPathStr.length - 1] != ':') {
Tcl_DStringAppend(&tagPathStr, ":", 1);
}
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;
}
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;
}
static char **
SystemVariables()
{
int i = 0;
char ** sysEnv;
char * thePath = NULL;
Handle theString = NULL;
FSSpec currentDir;
int size;
sysEnv = (char **) ckalloc((4) * sizeof(char *));
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++;
}
#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;
}
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++) {
}
}
pathEnv = PathVariables();
if (pathEnv != NULL) {
for (i = 0; pathEnv[i] != NULL; count++, i++) {
}
}
#ifdef kPrefsFile
fileEnv = FileRCVariables();
if (fileEnv != NULL) {
for (i = 0; fileEnv[i] != NULL; count++, i++) {
}
}
#endif
#ifdef REZ_ENV
rezEnv = RezRCVariables();
if (rezEnv != NULL) {
for (i = 0; rezEnv[i] != NULL; count++, i++) {
}
}
#endif
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;
}
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);
}