home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / mac / tclMacEnv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  13.4 KB  |  537 lines  |  [TEXT/CWIE]

  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.  * SCCS: @(#) tclMacEnv.c 1.29 96/12/06 14:19:57
  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(¤tDir);
  381.     FSpPathFromLocation(¤tDir, &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. }
  537.