os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacEnv.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* 
     2  * tclMacEnv.c --
     3  *
     4  *	Implements the "environment" on a Macintosh.
     5  *
     6  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
     7  *
     8  * See the file "license.terms" for information on usage and redistribution
     9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    10  *
    11  * RCS: @(#) $Id: tclMacEnv.c,v 1.2 1998/09/14 18:40:04 stanton Exp $
    12  */
    13 
    14 #include <Gestalt.h>
    15 #include <Folders.h>
    16 #include <TextUtils.h>
    17 #include <Resources.h>
    18 #include <string.h>
    19 
    20 #include "tcl.h"
    21 #include "tclInt.h"
    22 #include "tclMacInt.h"
    23 #include "tclPort.h"
    24 
    25 #define kMaxEnvStringSize 	255
    26 #define kMaxEnvVarSize 		100
    27 #define kLoginnameTag 		"LOGIN="
    28 #define kUsernameTag 		"USER="
    29 #define kDefaultDirTag 		"HOME="
    30 
    31 /* 
    32  * The following specifies a text file where additional environment variables 
    33  * can be set.  The file must reside in the preferences folder.  If the file 
    34  * doesn't exist NO error will occur.  Commet out the difinition if you do 
    35  * NOT want to use an environment variables file. 
    36  */
    37 #define kPrefsFile	 		"Tcl Environment Variables"
    38 
    39 /* 
    40  * The following specifies the Name of a 'STR#' resource in the application 
    41  * where additional environment variables may be set.  If the resource doesn't
    42  * exist no errors will occur.  Commet it out if you don't want it.
    43  */
    44 #define REZ_ENV "\pTcl Environment Variables"
    45 
    46 /* Globals */
    47 char **environ = NULL;
    48 
    49 /*
    50  * Declarations for local procedures defined in this file:
    51  */
    52 static char ** RezRCVariables _ANSI_ARGS_((void));
    53 static char ** FileRCVariables _ANSI_ARGS_((void));
    54 static char ** PathVariables _ANSI_ARGS_((void));
    55 static char ** SystemVariables _ANSI_ARGS_((void));
    56 static char * MakeFolderEnvVar _ANSI_ARGS_((char * prefixTag,
    57 	long whichFolder));
    58 static char * GetUserName _ANSI_ARGS_((void));
    59 
    60 /*
    61  *----------------------------------------------------------------------
    62  *
    63  * RezRCVariables --
    64  *
    65  *  Creates environment variables from the applications resource fork.
    66  *  The function looks for the 'STR#' resource with the name defined
    67  *  in the #define REZ_ENV.  If the define is not defined this code
    68  *  will not be included.  If the resource doesn't exist or no strings
    69  *  reside in the resource nothing will happen.
    70  *
    71  * Results:
    72  *	ptr to value on success, NULL if error.
    73  *
    74  * Side effects:
    75  *	Memory is allocated and returned to the caller.
    76  *
    77  *----------------------------------------------------------------------
    78  */
    79 
    80 #ifdef REZ_ENV
    81 static char ** 
    82 RezRCVariables()
    83 {
    84     Handle envStrs = NULL;
    85     char** rezEnv = NULL;
    86     short int numStrs;
    87 
    88     envStrs = GetNamedResource('STR#', REZ_ENV);
    89     if (envStrs == NULL) return NULL;
    90     numStrs = *((short *) (*envStrs));
    91 	
    92     rezEnv = (char **) ckalloc((numStrs + 1) * sizeof(char *));
    93 
    94     if (envStrs != NULL) {
    95 	ResType	theType;
    96 	Str255 theName;
    97 	short theID, index = 1;
    98 	int i = 0;
    99 	char* string;
   100 	
   101 	GetResInfo(envStrs, &theID, &theType, theName);
   102 	for(;;) {
   103 	    GetIndString(theName, theID, index++);
   104 	    if (theName[0] == '\0') break;
   105 	    string = (char *) ckalloc(theName[0] + 2);
   106 	    strncpy(string, (char *) theName + 1, theName[0]);
   107 	    string[theName[0]] = '\0';
   108 	    rezEnv[i++] = string;
   109 	}
   110 	ReleaseResource(envStrs);
   111 		
   112 	rezEnv[i] = NULL;
   113 	return rezEnv;
   114     }
   115 	
   116     return NULL;
   117 }
   118 #endif
   119 
   120 /*
   121  *----------------------------------------------------------------------
   122  *
   123  * FileRCVariables --
   124  *
   125  *  Creates environment variables from a file in the system preferences
   126  *  folder.  The function looks for a file in the preferences folder 
   127  *  a name defined in the #define kPrefsFile.  If the define is not 
   128  *  defined this code will not be included.  If the resource doesn't exist or
   129  *  no strings reside in the resource nothing will happen.
   130  *
   131  * Results:
   132  *	ptr to value on success, NULL if error.
   133  *
   134  * Side effects:
   135  *	Memory is allocated and returned to the caller.
   136  *
   137  *----------------------------------------------------------------------
   138  */
   139 
   140 #ifdef kPrefsFile
   141 static char ** 
   142 FileRCVariables()
   143 {
   144     char *prefsFolder = NULL;
   145     char *tempPtr = NULL;
   146     char **fileEnv = NULL;
   147     FILE *thePrefsFile = NULL;
   148     int	i;
   149     FSSpec prefDir;
   150     OSErr err;
   151     Handle theString = NULL;
   152     Tcl_Channel chan;
   153     int size;
   154     Tcl_DString lineRead;
   155 	
   156     err = FSpFindFolder(kOnSystemDisk, kPreferencesFolderType, 
   157 	    kDontCreateFolder, &prefDir);
   158     if (err != noErr) {
   159 	return NULL;
   160     }
   161     err = FSpPathFromLocation(&prefDir, &size, &theString);
   162     if (err != noErr) {
   163 	return NULL;
   164     }
   165     (void) Munger(theString, size, NULL, 0, kPrefsFile, strlen(kPrefsFile));
   166 
   167     HLock(theString);
   168     chan = Tcl_OpenFileChannel(NULL, *theString, "r", 0);
   169     HUnlock(theString);
   170     DisposeHandle(theString);
   171     if (chan == NULL) {
   172 	return NULL;
   173     }
   174 
   175     /*
   176      * We found a env file.  Let start parsing it.
   177      */
   178     fileEnv = (char **) ckalloc((kMaxEnvVarSize + 1) * sizeof(char *));
   179 
   180     i = 0;
   181     Tcl_DStringInit(&lineRead);
   182     while (Tcl_Gets(chan, &lineRead) != -1) {
   183 	/*
   184 	 * First strip off new line char
   185 	 */
   186 	if (lineRead.string[lineRead.length-1] == '\n') {
   187 	    lineRead.string[lineRead.length-1] = '\0';
   188 	}
   189 	if (lineRead.string[0] == '\0' || lineRead.string[0] == '#') {
   190 	    /*
   191 	     * skip empty lines or commented lines
   192 	     */
   193 	    Tcl_DStringSetLength(&lineRead, 0);
   194 	    continue;
   195 	}
   196 		
   197 	tempPtr = (char *) ckalloc(lineRead.length + 1);
   198 	strcpy(tempPtr, lineRead.string);
   199 	fileEnv[i++] = tempPtr;
   200 	Tcl_DStringSetLength(&lineRead, 0);
   201     }
   202 	
   203     fileEnv[i] = NULL;
   204     Tcl_Close(NULL, chan);
   205     Tcl_DStringFree(&lineRead);
   206 	
   207     return fileEnv;
   208 }
   209 #endif
   210 
   211 /*
   212  *----------------------------------------------------------------------
   213  *
   214  * MakeFolderEnvVar --
   215  *
   216  *	This function creates "environment" variable by taking a prefix and
   217  *	appending a folder path to a directory.  The directory is specified
   218  *	by a integer value acceptable by the FindFolder function.
   219  *
   220  * Results:
   221  *	The function returns an *allocated* string.  If the folder doesn't
   222  *	exist the return string is still allocated and just contains the
   223  *	given prefix.
   224  *
   225  * Side effects:
   226  *	Memory is allocated and returned to the caller.
   227  *
   228  *----------------------------------------------------------------------
   229  */
   230 
   231 static char * 
   232 MakeFolderEnvVar(
   233     char * prefixTag,		/* Prefix added before result. */
   234     long whichFolder)		/* Constant for FSpFindFolder. */
   235 {
   236     char * thePath = NULL;
   237     char * result = NULL;
   238     OSErr theErr = noErr;
   239     Handle theString = NULL;
   240     FSSpec theFolder;
   241     int size;
   242     Tcl_DString pathStr;
   243     Tcl_DString tagPathStr;
   244     
   245     Tcl_DStringInit(&pathStr);
   246     theErr = FSpFindFolder(kOnSystemDisk, whichFolder, 
   247 	    kDontCreateFolder, &theFolder);
   248     if (theErr == noErr) {
   249 	theErr = FSpPathFromLocation(&theFolder, &size, &theString);
   250 		
   251 	HLock(theString);
   252 	tclPlatform = TCL_PLATFORM_MAC;
   253 	Tcl_DStringAppend(&pathStr, *theString, -1);
   254 	HUnlock(theString);
   255 	DisposeHandle(theString);
   256 		
   257 	Tcl_DStringInit(&tagPathStr);
   258 	Tcl_DStringAppend(&tagPathStr, prefixTag, strlen(prefixTag));
   259 	Tcl_DStringAppend(&tagPathStr, pathStr.string, pathStr.length);
   260 	Tcl_DStringFree(&pathStr);
   261 	
   262 	/*
   263 	 * Make sure the path ends with a ':'
   264 	 */
   265 	if (tagPathStr.string[tagPathStr.length - 1] != ':') {
   266 	    Tcl_DStringAppend(&tagPathStr, ":", 1);
   267 	}
   268 
   269 	/*
   270 	 * Don't free tagPathStr - rather make sure it's allocated
   271 	 * and return it as the result.
   272 	 */
   273 	if (tagPathStr.string == tagPathStr.staticSpace) {
   274 	    result = (char *) ckalloc(tagPathStr.length + 1);
   275 	    strcpy(result, tagPathStr.string);
   276 	} else {
   277 	    result = tagPathStr.string;
   278 	}
   279     } else {
   280 	result = (char *) ckalloc(strlen(prefixTag) + 1);
   281 	strcpy(result, prefixTag);
   282     }
   283 	
   284     return result;
   285 }
   286 
   287 /*
   288  *----------------------------------------------------------------------
   289  *
   290  * PathVariables --
   291  *
   292  *  Creates environment variables from the system call FSpFindFolder.
   293  *  The function generates environment variables for many of the 
   294  *  commonly used paths on the Macintosh.
   295  *
   296  * Results:
   297  *	ptr to value on success, NULL if error.
   298  *
   299  * Side effects:
   300  *	Memory is allocated and returned to the caller.
   301  *
   302  *----------------------------------------------------------------------
   303  */
   304 
   305 static char ** 
   306 PathVariables()
   307 {
   308     int i = 0;
   309     char **sysEnv;
   310     char *thePath = NULL;
   311     
   312     sysEnv = (char **) ckalloc((12) * sizeof(char *));
   313 
   314     sysEnv[i++] = MakeFolderEnvVar("PREF_FOLDER=", kPreferencesFolderType);
   315     sysEnv[i++] = MakeFolderEnvVar("SYS_FOLDER=", kSystemFolderType);
   316     sysEnv[i++] = MakeFolderEnvVar("TEMP=", kTemporaryFolderType);
   317     sysEnv[i++] = MakeFolderEnvVar("APPLE_M_FOLDER=", kAppleMenuFolderType);
   318     sysEnv[i++] = MakeFolderEnvVar("CP_FOLDER=", kControlPanelFolderType);
   319     sysEnv[i++] = MakeFolderEnvVar("DESK_FOLDER=", kDesktopFolderType);
   320     sysEnv[i++] = MakeFolderEnvVar("EXT_FOLDER=", kExtensionFolderType);
   321     sysEnv[i++] = MakeFolderEnvVar("PRINT_MON_FOLDER=",
   322 	    kPrintMonitorDocsFolderType);
   323     sysEnv[i++] = MakeFolderEnvVar("SHARED_TRASH_FOLDER=",
   324 	    kWhereToEmptyTrashFolderType);
   325     sysEnv[i++] = MakeFolderEnvVar("TRASH_FOLDER=", kTrashFolderType);
   326     sysEnv[i++] = MakeFolderEnvVar("START_UP_FOLDER=", kStartupFolderType);
   327     sysEnv[i++] = NULL;
   328 	
   329     return sysEnv;
   330 }
   331 
   332 /*
   333  *----------------------------------------------------------------------
   334  *
   335  * SystemVariables --
   336  *
   337  *  Creates environment variables from various Mac system calls.
   338  *
   339  * Results:
   340  *	ptr to value on success, NULL if error.
   341  *
   342  * Side effects:
   343  *	Memory is allocated and returned to the caller.
   344  *
   345  *----------------------------------------------------------------------
   346  */
   347 
   348 static char ** 
   349 SystemVariables()
   350 {
   351     int i = 0;
   352     char ** sysEnv;
   353     char * thePath = NULL;
   354     Handle theString = NULL;
   355     FSSpec currentDir;
   356     int size;
   357     
   358     sysEnv = (char **) ckalloc((4) * sizeof(char *));
   359 
   360     /*
   361      * Get user name from chooser.  It will be assigned to both
   362      * the USER and LOGIN environment variables.
   363      */
   364     thePath = GetUserName();
   365     if (thePath != NULL) {
   366 	sysEnv[i] = (char *) ckalloc(strlen(kLoginnameTag) + strlen(thePath) + 1);
   367 	strcpy(sysEnv[i], kLoginnameTag);
   368 	strcpy(sysEnv[i]+strlen(kLoginnameTag), thePath);
   369 	i++;
   370 	sysEnv[i] = (char *) ckalloc(strlen(kUsernameTag) + strlen(thePath) + 1);
   371 	strcpy(sysEnv[i], kUsernameTag);
   372 	strcpy(sysEnv[i]+strlen(kUsernameTag), thePath);
   373 	i++;
   374     }
   375 
   376     /*
   377      * Get 'home' directory
   378      */
   379 #ifdef kDefaultDirTag
   380     FSpGetDefaultDir(&currentDir);
   381     FSpPathFromLocation(&currentDir, &size, &theString);
   382     HLock(theString);
   383     sysEnv[i] = (char *) ckalloc(strlen(kDefaultDirTag) + size + 4);
   384     strcpy(sysEnv[i], kDefaultDirTag);
   385     strncpy(sysEnv[i]+strlen(kDefaultDirTag) , *theString, size);
   386     if (sysEnv[i][strlen(kDefaultDirTag) + size - 1] != ':') {
   387 	sysEnv[i][strlen(kDefaultDirTag) + size] = ':';
   388 	sysEnv[i][strlen(kDefaultDirTag) + size + 1] = '\0';
   389     } else {
   390 	sysEnv[i][strlen(kDefaultDirTag) + size] = '\0';
   391     }
   392     HUnlock(theString);
   393     DisposeHandle(theString);
   394     i++;
   395 #endif
   396 
   397     sysEnv[i++] = NULL;
   398     return sysEnv;
   399 }
   400 
   401 /*
   402  *----------------------------------------------------------------------
   403  *
   404  * TclMacCreateEnv --
   405  *
   406  *	This function allocates and populates the global "environ"
   407  *	variable.  Entries are in traditional Unix format but variables
   408  *	are, hopefully, a bit more relevant for the Macintosh.
   409  *
   410  * Results:
   411  *	The number of elements in the newly created environ array.
   412  *
   413  * Side effects:
   414  *	Memory is allocated and pointed too by the environ variable.
   415  *
   416  *----------------------------------------------------------------------
   417  */
   418 
   419 int
   420 TclMacCreateEnv()
   421 {
   422     char ** sysEnv = NULL;
   423     char ** pathEnv = NULL;
   424     char ** fileEnv = NULL;
   425     char ** rezEnv = NULL;
   426     int count = 0;
   427     int i, j;
   428 
   429     sysEnv = SystemVariables();
   430     if (sysEnv != NULL) {
   431 	for (i = 0; sysEnv[i] != NULL; count++, i++) {
   432 	    /* Empty Loop */
   433 	}
   434     }
   435 
   436     pathEnv = PathVariables();
   437     if (pathEnv != NULL) {
   438 	for (i = 0; pathEnv[i] != NULL; count++, i++) {
   439 	    /* Empty Loop */
   440 	}
   441     }
   442 
   443 #ifdef kPrefsFile
   444     fileEnv = FileRCVariables();
   445     if (fileEnv != NULL) {
   446 	for (i = 0; fileEnv[i] != NULL; count++, i++) {
   447 	    /* Empty Loop */
   448 	}
   449     }
   450 #endif
   451 
   452 #ifdef REZ_ENV
   453     rezEnv = RezRCVariables();
   454     if (rezEnv != NULL) {
   455 	for (i = 0; rezEnv[i] != NULL; count++, i++) {
   456 	    /* Empty Loop */
   457 	}
   458     }
   459 #endif
   460 
   461     /*
   462      * Create environ variable
   463      */
   464     environ = (char **) ckalloc((count + 1) * sizeof(char *));
   465     j = 0;
   466 	
   467     if (sysEnv != NULL) {
   468 	for (i = 0; sysEnv[i] != NULL;)
   469 	    environ[j++] = sysEnv[i++];
   470 	ckfree((char *) sysEnv);
   471     }
   472 
   473     if (pathEnv != NULL) {
   474 	for (i = 0; pathEnv[i] != NULL;)
   475 	    environ[j++] = pathEnv[i++];
   476 	ckfree((char *) pathEnv);
   477     }
   478 
   479 #ifdef kPrefsFile
   480     if (fileEnv != NULL) {
   481 	for (i = 0; fileEnv[i] != NULL;)
   482 	    environ[j++] = fileEnv[i++];
   483 	ckfree((char *) fileEnv);
   484     }
   485 #endif
   486 
   487 #ifdef REZ_ENV
   488     if (rezEnv != NULL) {
   489 	for (i = 0; rezEnv[i] != NULL;)
   490 	    environ[j++] = rezEnv[i++];
   491 	ckfree((char *) rezEnv);
   492     }
   493 #endif
   494 
   495     environ[j] = NULL;
   496     return j;
   497 }
   498 
   499 /*
   500  *----------------------------------------------------------------------
   501  *
   502  * GetUserName --
   503  *
   504  *	Get the user login name.
   505  *
   506  * Results:
   507  *  ptr to static string, NULL if error.
   508  *
   509  * Side effects:
   510  *	None.
   511  *
   512  *----------------------------------------------------------------------
   513  */
   514 
   515 static char *
   516 GetUserName()
   517 {
   518     static char buf[33];
   519     short refnum;
   520     Handle h;
   521 	
   522     refnum = CurResFile();
   523     UseResFile(0);
   524     h = GetResource('STR ', -16096);
   525     UseResFile(refnum);
   526     if (h == NULL) {
   527 	return NULL;
   528     }
   529     
   530     HLock(h);
   531     strncpy(buf, (*h)+1, **h);
   532     buf[**h] = '\0';
   533     HUnlock(h);
   534     ReleaseResource(h);
   535     return(buf[0] ? buf : NULL);
   536 }