home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / corelib / ncbienv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-17  |  42.6 KB  |  1,463 lines  |  [TEXT/R*ch]

  1. /*   ncbienv.c
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:  ncbienv.c
  27. *
  28. * Author:  Ostell
  29. *
  30. * Version Creation Date:   7/7/91
  31. *
  32. * $Revision: 1.6 $
  33. *
  34. * File Description: 
  35. *       portable environment functions, companions for ncbimain.c
  36. *
  37. * Modifications:  
  38. * --------------------------------------------------------------------------
  39. * Date     Name        Description of modification
  40. * -------  ----------  -----------------------------------------------------
  41. * 7/7/91   Kans        Multiple configuration files, get and set functions
  42. * 9-20-91  Schuler     GetAppParam takes default value as an argument
  43. * 1-14-94  Epstein     Merged ncbienv.{unx,vms,dos,msw,mac} into a single file
  44. *
  45. * ==========================================================================
  46. */
  47.  
  48. #include <ncbi.h>
  49. #include <ncbiwin.h>
  50.  
  51. #ifdef OS_UNIX
  52. #include <pwd.h>
  53. #endif /* OS_UNIX */
  54. #ifdef OS_MAC
  55. #include <GestaltEqu.h>
  56. #include <Folders.h>
  57. #include <Strings.h>
  58. #endif /* OS_MAC */
  59. #ifdef OS_VMS
  60. #include <unixlib.h>
  61. #endif /* OS_VMS */
  62.  
  63.  
  64. typedef struct nlm_env_item {
  65.   struct nlm_env_item  PNTR next;
  66.   Nlm_CharPtr          name;
  67.   Nlm_CharPtr          comment;
  68.   Nlm_CharPtr          value;
  69. } Nlm_env_item, PNTR Nlm_env_itemPtr;
  70.  
  71. typedef struct nlm_env_sect {
  72.   struct nlm_env_sect  PNTR next;
  73.   Nlm_CharPtr          name;
  74.   Nlm_CharPtr          comment;
  75.   Nlm_Boolean          transientOnly; /* this field used only by Transient fns */
  76.   struct nlm_env_item  PNTR children;
  77. } Nlm_env_sect, PNTR Nlm_env_sectPtr;
  78.  
  79. typedef struct nlm_env_file {
  80.   struct nlm_env_file  PNTR next;
  81.   Nlm_CharPtr          name;
  82.   Nlm_env_sectPtr      envList;
  83. } Nlm_env_file, PNTR Nlm_env_filePtr;
  84.  
  85.  
  86. Nlm_env_filePtr Nlm_transientFileList = NULL;
  87.  
  88. static Nlm_Boolean Nlm_Qualified PROTO((Nlm_CharPtr path));
  89. static Nlm_Boolean Nlm_TransientLookup PROTO((Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen));
  90. static void Nlm_TransientLogSetApp PROTO((Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value));
  91. static void Nlm_FreeEnvData PROTO((Nlm_env_sectPtr esp));
  92. static void Nlm_FreeTransientData PROTO((void));
  93.  
  94. #ifndef WIN_MSWIN
  95. static FILE *Nlm_OpenConfigFile PROTO((Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create));
  96. static Nlm_CharPtr Nlm_TrimString PROTO((Nlm_CharPtr str));
  97. static Nlm_Boolean Nlm_ReadConfigFile PROTO((FILE *fp));
  98. static Nlm_env_sectPtr Nlm_FindConfigSection PROTO((Nlm_CharPtr section));
  99. static Nlm_env_itemPtr Nlm_FindConfigItem PROTO((Nlm_CharPtr section, Nlm_CharPtr type, Nlm_Boolean create));
  100. static Nlm_Boolean Nlm_WriteConfigFile PROTO((FILE *fp));
  101. static void Nlm_PutComment PROTO((Nlm_CharPtr s, FILE *fp));
  102. static void Nlm_FreeConfigFileData PROTO((void));
  103.  
  104. #ifdef OS_UNIX
  105. static Nlm_CharPtr saveHome = NULL;
  106. #endif /* OS_UNIX */
  107.  
  108. static Nlm_env_sectPtr Nlm_envList = NULL;
  109. static Nlm_CharPtr Nlm_lastParamFile = NULL;
  110. static Nlm_CharPtr Nlm_bottomComment = NULL;
  111.  
  112. /* always FALSE, because this file is trying to emulating MS Windows's  */
  113. /* handling of comments in Param files; however, just change this value */
  114. /* to TRUE to turn this approach around                                 */
  115. static Nlm_Boolean destroyDeadComments = FALSE;
  116.  
  117. /*****************************************************************************
  118. *
  119. * The "guts" of:
  120. *   Nlm_GetAppParam (file, section, type, dflt, buf, buflen)
  121. *      finds parameters from configuration files
  122. *      this version, searching for configuration file(s) in a
  123. *      platform-dependent basis as handled by Nlm_OpenConfigFile()
  124. *
  125. *      if configuration file is found, tries to read the parameter from it.
  126. *
  127. *****************************************************************************/
  128.  
  129. static Nlm_Int2 Nlm_WorkGetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen, Nlm_Boolean searchTransient)
  130.  
  131. {
  132.   Nlm_env_itemPtr  eip;
  133.   FILE             *fp;
  134.   Nlm_env_sectPtr  esp;
  135.   Nlm_Int2         totlen;
  136.   Nlm_Int2         bytesToAppend;
  137.  
  138.   if (buf != NULL && buflen > 0) {
  139.     *buf = '\0';
  140.     if (searchTransient && Nlm_TransientLookup(file, section, type, dflt, buf, buflen))
  141.     {
  142.       return Nlm_StringLen(buf);
  143.     }
  144.     if (dflt) Nlm_StringNCat (buf, dflt, buflen);
  145.     if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  146.       if (Nlm_lastParamFile == NULL ||
  147.           Nlm_StringICmp(Nlm_lastParamFile, file) != 0) {
  148.         Nlm_FreeConfigFileData();
  149.         fp = Nlm_OpenConfigFile (file, FALSE, FALSE);
  150.         if (fp != NULL) {
  151.           Nlm_lastParamFile = Nlm_StringSave(file);
  152.           Nlm_ReadConfigFile (fp);
  153.           Nlm_FileClose (fp);
  154.         }
  155.       }
  156.       if (type != NULL && *type != '\0') {
  157.         eip = Nlm_FindConfigItem (section, type, FALSE);
  158.         if (eip != NULL) {
  159.           *buf = '\0';
  160.           Nlm_StringNCat (buf, eip->value, buflen);
  161.         }
  162.       }
  163.       else { /* return all the types in that section */
  164.         *buf = '\0';
  165.         totlen = 0;
  166.         if ((esp = Nlm_FindConfigSection (section)) != NULL)
  167.         {
  168.           /* traverse the children, allowing the null chars to be inserted */
  169.           /* in between each type-name                                     */
  170.           for (eip = esp->children; eip != NULL; eip = eip->next)
  171.           {
  172.             bytesToAppend = StrLen(eip->name) + 1;
  173.             bytesToAppend = MIN(bytesToAppend, buflen - totlen);
  174.             StrNCpy(&buf[totlen], eip->name, bytesToAppend);
  175.             totlen += bytesToAppend;
  176.           }
  177.           if (totlen > 0 && buf[totlen] == '\0')
  178.             totlen--; /* account for final null character */
  179.         }
  180.         return totlen;
  181.       }
  182.     }
  183.   }
  184.  
  185.   return Nlm_StringLen(buf);
  186. }
  187.  
  188. /*****************************************************************************
  189. *
  190. *   Nlm_SetAppParam (file, section, type, value)
  191. *      finds paths for types of data and fills in path in buf
  192. *      this version
  193. *      1)  looks in the current directory for ".filerc", but will not
  194. *          create a new file in this directory.
  195. *      2)  then looks in the home directory for ".filerc".
  196. *      3)  then looks for an environment variable "NCBI" and takes its
  197. *          value as a complete path to a directory containing the
  198. *          configuration file ".filerc".
  199. *      if configuration file is found, tries to write the parameter to it.
  200. *
  201. *****************************************************************************/
  202.  
  203. Nlm_Boolean LIBCALL Nlm_SetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)
  204.  
  205. {
  206.   Nlm_env_itemPtr  eip;
  207.   Nlm_env_sectPtr  esp;
  208.   FILE             *fp;
  209.   Nlm_Boolean      rsult;
  210.  
  211.   rsult = FALSE;
  212.   if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  213.     Nlm_TransientLogSetApp (file, section, type, value);
  214.     fp = Nlm_OpenConfigFile (file, FALSE, TRUE);
  215.     if (fp != NULL) {
  216.       if (Nlm_lastParamFile == NULL ||
  217.           Nlm_StringICmp(Nlm_lastParamFile, file) != 0) {
  218.         Nlm_FreeConfigFileData();
  219.         Nlm_lastParamFile = Nlm_StringSave(file);
  220.         Nlm_ReadConfigFile (fp);
  221.       }
  222.       Nlm_FileClose (fp);
  223.       if (type != NULL && *type != '\0')
  224.       {
  225.         eip = Nlm_FindConfigItem (section, type, TRUE);
  226.         if (eip != NULL) {
  227.           if (eip->value != NULL) {
  228.             eip->value = (Nlm_CharPtr) Nlm_MemFree (eip->value);
  229.           }
  230.           eip->value = Nlm_StringSave (value);
  231.           rsult = TRUE;
  232.         }
  233.       }
  234.       else { /* wipe out that section */
  235.         esp = Nlm_FindConfigSection (section);
  236.         if (esp != NULL) { /* kill section by deleting name (leave comments)*/
  237.           esp->name = (Nlm_CharPtr) Nlm_MemFree(esp->name);
  238.           rsult = TRUE;
  239.         }
  240.       }
  241.           
  242.       fp = Nlm_OpenConfigFile (file, TRUE, FALSE);
  243.       if (fp != NULL) {
  244.         Nlm_WriteConfigFile (fp);
  245.         Nlm_FileClose (fp);
  246.       }
  247.     }
  248.   }
  249.  
  250.   return rsult;
  251. }
  252.  
  253. #ifdef OS_UNIX
  254. /*****************************************************************************
  255. *
  256. *   Nlm_GetHome (buf, buflen)
  257. *      returns the path of the home directory
  258. *
  259. *****************************************************************************/
  260.  
  261. #ifndef L_cuserid
  262. #define L_cuserid 9
  263. #endif
  264.  
  265. static Nlm_Boolean Nlm_GetHome PROTO((Nlm_CharPtr buf, Nlm_Int2 buflen));
  266. static Nlm_Boolean Nlm_GetHome (Nlm_CharPtr buf, Nlm_Int2 buflen)
  267.  
  268. {
  269.   char           *getlogin PROTO((void));
  270. /*
  271. #ifndef COMP_ACC
  272.   struct passwd  *getpwuid PROTO((uid_t uid));
  273. #endif
  274. */
  275.  
  276.   Nlm_CharPtr    cp;
  277.   Nlm_Boolean    found;
  278.   struct passwd  *pswd;
  279.   Nlm_Char       whoiam [L_cuserid + 1];
  280.  
  281.   if (saveHome != NULL)
  282.   { /* return cached value, if available */
  283.       Nlm_StringNCpy (buf, saveHome, buflen);
  284.       return TRUE;
  285.   }
  286.  
  287.   whoiam [0] = '\0';
  288.   found = FALSE;
  289.   cp = getlogin ();
  290.   if (cp != NULL && cp [0] != '\0') {
  291.     Nlm_StringNCpy (whoiam, cp, sizeof (whoiam) - 1);
  292.     whoiam [sizeof (whoiam) - 1] = '\0';
  293.     found = TRUE;
  294.   } else {
  295.     setpwent ();
  296.     pswd = getpwuid (getuid ());
  297.     if (pswd != NULL) {
  298.       Nlm_StringNCpy (whoiam, pswd->pw_name, sizeof (whoiam) - 1);
  299.       whoiam [sizeof (whoiam) - 1] = '\0';
  300.       found = TRUE;
  301.     }
  302.   }
  303.   if (found) {
  304.     setpwent ();
  305.     pswd = getpwnam (whoiam);
  306.     if (pswd != NULL) {
  307.         Nlm_StringNCpy (buf, pswd->pw_dir, buflen);
  308.         if (saveHome == NULL)
  309.         {
  310.             saveHome = Nlm_StringSave(pswd->pw_dir);
  311.         }
  312.     } else {
  313.       found = FALSE;
  314.     }
  315.   }
  316.   return found;
  317. }
  318.  
  319. /*****************************************************************************
  320. *
  321. *   Nlm_OpenConfigFile (file, writeMode, create)
  322. *      returns a file pointer to the specified configuration file.
  323. *      1)  looks in the current directory for ".filerc", but will not
  324. *          create a new file in this directory.
  325. *      2)  then looks in the home directory for ".filerc".
  326. *      3)  then looks for an environment variable "NCBI" and takes its
  327. *          value as a complete path to a directory containing the
  328. *          configuration file "filerc" or ".filerc".
  329. *
  330. *****************************************************************************/
  331.  
  332. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  333.  
  334. {
  335.   FILE      *fp;
  336.   Nlm_Int2  i;
  337.   Nlm_Int2  len;
  338.   FILE      *newfp;
  339.   Nlm_Char  path [PATH_MAX+1];
  340.   char      *pth;
  341.   Nlm_Char  str [FILENAME_MAX+1];
  342.  
  343.   fp = NULL;
  344.   if (file != NULL) {
  345.     newfp = NULL;
  346.     Nlm_StringMove (str, ".");
  347.     Nlm_StringNCat (str, file, sizeof (str) - 3);
  348.     if ( ! Nlm_Qualified (str))
  349.     { /* use the user's extension instead of the "rc" extension */
  350.       Nlm_StringCat (str, "rc");
  351.     }
  352.     len = (Nlm_Int2) Nlm_StringLen (str);
  353.     for (i = 0; i < len; i++) {
  354.       str [i] = TO_LOWER (str [i]);
  355.     }
  356.     path[0] = '\0';
  357.     Nlm_StringCpy (path, str);
  358.     fp = Nlm_FileOpen (path, "r");
  359.     if (fp == NULL) {
  360.       path[0] = '\0';
  361.       if (Nlm_GetHome (path, sizeof (path))) {
  362.         Nlm_FileBuildPath(path, NULL, str);
  363.       } else {
  364.         Nlm_StringCpy (path, str);
  365.       }
  366.       fp = Nlm_FileOpen (path, "r");
  367.       if (fp == NULL && create) {
  368.         newfp = Nlm_FileOpen (path, "w");
  369.         Nlm_FileClose (newfp);
  370.         newfp = Nlm_FileOpen (path, "r");
  371.       }
  372.     }
  373.     if (fp == NULL) {
  374.       path[0] = '\0';
  375.       pth = getenv ("NCBI");
  376.       if (pth != NULL) {
  377.         Nlm_FileBuildPath(path, pth, str + 1);
  378.         fp = Nlm_FileOpen (path, "r");
  379.         if (fp == NULL) {
  380.           path[0] = '\0';
  381.           Nlm_FileBuildPath(path, pth, str);
  382.           fp = Nlm_FileOpen (path, "r");
  383.         }
  384.       }
  385.     }
  386.     if (newfp != NULL) {
  387.       if (fp != NULL) {
  388.         Nlm_FileClose (newfp);
  389.         newfp = NULL;
  390.       } else {
  391.         fp = newfp;
  392.       }
  393.     }
  394.     if (writeMode && fp != NULL) {
  395.       Nlm_FileClose (fp);
  396.       fp = Nlm_FileOpen (path, "w");
  397.     }
  398.   }
  399.   return fp;
  400. }
  401.  
  402. #endif /* OS_UNIX */
  403.  
  404.  
  405. #ifdef OS_MAC
  406. /*****************************************************************************
  407. *
  408. *   Nlm_OpenConfigFile (file, writeMode, create)
  409. *      returns a file pointer to the specified configuration file.
  410. *      1)  looks in the System Folder for "file.cnf"
  411. *      2)  then looks in System Folder:Preferences for "file.cnf"
  412. *
  413. *****************************************************************************/
  414.  
  415. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  416.  
  417. {
  418.   WDPBRec      block;
  419.   Nlm_Char     directory [PATH_MAX];
  420.   long         dirID;
  421.   OSErr        err;
  422.   OSType       fCreator;
  423.   Nlm_Int2     fError;
  424.   FILE         *fp;
  425.   FInfo        finfo;
  426.   OSType       fType;
  427.   long         gesResponse;
  428.   Nlm_Int2     i;
  429.   Nlm_Int2     len;
  430.   CInfoPBRec   params;
  431.   Nlm_Char     str [FILENAME_MAX+1];
  432.   SysEnvRec    sysenv;
  433.   Nlm_Char     temp [PATH_MAX];
  434.   Nlm_CharPtr  tmp;
  435.   short        vRefNum;
  436.  
  437.   fp = NULL;
  438.   if (file != NULL) {
  439.     Nlm_StringNCpy (str, file, sizeof (str) - 4);
  440.     if ( ! Nlm_Qualified (str) ) {
  441.       Nlm_StringCat (str, ".cnf");
  442.     }
  443.     len = (Nlm_Int2) Nlm_StringLen (str);
  444.     for (i = 0; i < len; i++) {
  445.       str [i] = TO_LOWER (str [i]);
  446.     }
  447.     if (SysEnvirons (curSysEnvVers, &sysenv) == noErr) {
  448.       block.ioNamePtr = NULL;
  449.       block.ioVRefNum = sysenv.sysVRefNum;
  450.       block.ioWDIndex = 0;
  451.       block.ioWDProcID = 0;
  452.       PBGetWDInfo (&block, FALSE);
  453.       dirID = block.ioWDDirID;
  454.       vRefNum = block.ioWDVRefNum;
  455.       temp [0] = '\0';
  456.       params.dirInfo.ioNamePtr = (StringPtr) directory;
  457.       params.dirInfo.ioDrParID = dirID;
  458.       do {
  459.         params.dirInfo.ioVRefNum = vRefNum;
  460.         params.dirInfo.ioFDirIndex = -1;
  461.         params.dirInfo.ioDrDirID = params.dirInfo.ioDrParID;
  462.         err = PBGetCatInfo (¶ms, FALSE);
  463. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  464.   p2cstr ((StringPtr) directory);
  465. #else
  466. #ifdef COMP_THINKC
  467.   PtoCstr ((StringPtr) directory);
  468. #endif
  469. #endif
  470.         Nlm_StringCat (directory, DIRDELIMSTR);
  471.         Nlm_StringCat (directory, temp);
  472.         Nlm_StringCpy (temp, directory);
  473.       } while (params.dirInfo.ioDrDirID != fsRtDirID);
  474.       tmp = Nlm_StringMove (directory, temp);
  475.       tmp = Nlm_StringMove (tmp, str);
  476.       fp = Nlm_FileOpen (directory, "r");
  477.       if (fp == NULL) {
  478.         if (! Gestalt (gestaltFindFolderAttr, &gesResponse) &&
  479.             (gesResponse & (1 << gestaltFindFolderPresent))) {
  480.           err = FindFolder(kOnSystemDisk, kPreferencesFolderType,
  481.                            kCreateFolder, &vRefNum, &dirID);
  482.           if (err == noErr) {
  483.             params.dirInfo.ioNamePtr = (StringPtr) directory;
  484.             params.dirInfo.ioDrDirID = dirID;
  485.             params.dirInfo.ioVRefNum = vRefNum;
  486.             params.dirInfo.ioFDirIndex = -1;
  487.             err = PBGetCatInfo (¶ms, FALSE);
  488. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  489.   p2cstr ((StringPtr) directory);
  490. #else
  491. #ifdef COMP_THINKC
  492.   PtoCstr ((StringPtr) directory);
  493. #endif
  494. #endif
  495.             Nlm_StringCat (temp, directory);
  496.             Nlm_StringCat (temp, DIRDELIMSTR);
  497.             tmp = Nlm_StringMove (directory, temp);
  498.             tmp = Nlm_StringMove (tmp, str);
  499.           } else {
  500.             tmp = Nlm_StringMove (directory, temp);
  501.             tmp = Nlm_StringMove (tmp, "Preferences");
  502.             tmp = Nlm_StringMove (tmp, DIRDELIMSTR);
  503.             tmp = Nlm_StringMove (tmp, str);
  504.           }
  505.         } else {
  506.           tmp = Nlm_StringMove (directory, temp);
  507.           tmp = Nlm_StringMove (tmp, "Preferences");
  508.           tmp = Nlm_StringMove (tmp, DIRDELIMSTR);
  509.           tmp = Nlm_StringMove (tmp, str);
  510.         }
  511.         fp = Nlm_FileOpen (directory, "r");
  512.       }
  513.       if (fp == NULL && create) {
  514.         tmp = Nlm_StringMove (directory, temp);
  515.         tmp = Nlm_StringMove (tmp, str);
  516.         fp = Nlm_FileOpen (directory, "w");
  517.         Nlm_StringCpy (temp, directory);
  518. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  519.     c2pstr ((char *) temp);
  520. #else
  521. #ifdef COMP_THINKC
  522.     CtoPstr ((char *) temp);
  523. #endif
  524. #endif
  525.         fError = GetFInfo ((StringPtr) temp, 0, &finfo);
  526.         if (fError == 0) {
  527.           finfo.fdCreator = 'ttxt';
  528.           finfo.fdType = 'TEXT';
  529.           fError = SetFInfo ((StringPtr) temp, 0, &finfo);
  530.         }
  531.         Nlm_FileClose (fp);
  532.         fp = Nlm_FileOpen (directory, "r");
  533.       }
  534.       Nlm_StringCpy (temp, directory);
  535.       if (writeMode && fp != NULL) {
  536.         Nlm_FileClose (fp);
  537. #if defined(COMP_MPW) || defined(COMP_CODEWAR)
  538.     c2pstr ((char *) temp);
  539. #else
  540. #ifdef COMP_THINKC
  541.     CtoPstr ((char *) temp);
  542. #endif
  543. #endif
  544.         fType = 'TEXT';
  545.         fCreator = '    ';
  546.         fError = GetFInfo ((StringPtr) temp, 0, &finfo);
  547.         if (fError == 0) {
  548.           fCreator = finfo.fdCreator;
  549.           fType = finfo.fdType;
  550.         }
  551.         fp = Nlm_FileOpen (directory, "w");
  552.         fError = GetFInfo ((StringPtr) temp, 0, &finfo);
  553.         if (fError == 0) {
  554.           finfo.fdCreator = fCreator;
  555.           finfo.fdType = fType;
  556.           fError = SetFInfo ((StringPtr) temp, 0, &finfo);
  557.         }
  558.       }
  559.     }
  560.   }
  561.   return fp;
  562. }
  563. #endif /* OS_MAC */
  564.  
  565. #ifdef OS_VMS
  566. /*****************************************************************************
  567. *
  568. *   Nlm_GetHome (buf, buflen)
  569. *      returns the path of the home directory
  570. *
  571. *****************************************************************************/
  572.  
  573. static Nlm_Boolean Nlm_GetHome PROTO((Nlm_CharPtr buf, Nlm_Int2 buflen));
  574. static Nlm_Boolean Nlm_GetHome (Nlm_CharPtr buf, Nlm_Int2 buflen)
  575.  
  576. {
  577.   StringCpy(buf, getenv("SYS$LOGIN"));
  578.   return TRUE;
  579. }
  580.  
  581. /*****************************************************************************
  582. *
  583. *   Nlm_OpenConfigFile (file, writeMode, create)
  584. *      returns a file pointer to the specified configuration file.
  585. *      1)  looks in the current directory for "file.cfg", but will not
  586. *          create a new file in this directory.
  587. *      2)  then looks in the home directory for "file.cfg".
  588. *      3)  then looks for an environment variable "NCBI" and takes its
  589. *          value as a complete path to a directory containing the
  590. *          configuration file "file.cfg".
  591. *
  592. *****************************************************************************/
  593.  
  594. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  595.  
  596. {
  597.   FILE      *fp;
  598.   Nlm_Int2  i;
  599.   Nlm_Int2  len;
  600.   FILE      *newfp;
  601.   Nlm_Char  path [PATH_MAX+1];
  602.   char      *pth;
  603.   Nlm_Char  str [FILENAME_MAX+1];
  604.  
  605.   fp = NULL;
  606.  
  607.   if (file != NULL) {
  608.     newfp = NULL;
  609.     Nlm_StringNCpy (str, file, sizeof (str) - 3);
  610.     if ( ! Nlm_Qualified (str) ) {
  611.       Nlm_StringCat (str, ".cfg");
  612.     }
  613.     len = (Nlm_Int2) Nlm_StringLen (str);
  614.     for (i = 0; i < len; i++) {
  615.       str [i] = TO_LOWER (str [i]);
  616.     }
  617.     path[0] = '\0';
  618.     Nlm_StringCpy (path, str);
  619.  
  620.     fp = Nlm_FileOpen (path, "r");  /* File exists? */
  621.     if (fp == NULL) {
  622.       path[0] = '\0';
  623.       if (Nlm_GetHome (path, sizeof (path))) {
  624.         Nlm_FileBuildPath(path, NULL, str);
  625.       } else {
  626.         Nlm_StringCpy (path, str);
  627.       }
  628.       fp = Nlm_FileOpen (path, "r");   /* File exists? */
  629.       if (fp == NULL && create) {
  630.         newfp = Nlm_FileOpen (path, "w");
  631.         Nlm_FileClose (newfp);
  632.         newfp = Nlm_FileOpen (path, "r");
  633.       }
  634.     }
  635.  
  636.     if (fp == NULL) {
  637.       path[0] = '\0';
  638.       pth = getenv ("NCBI");
  639.       if (pth != NULL) {
  640.         Nlm_FileBuildPath(path, pth, str);
  641.         fp = Nlm_FileOpen (path, "r");
  642.       }
  643.     }
  644.  
  645.     if (newfp != NULL) {
  646.       if (fp != NULL) {
  647.         Nlm_FileClose (newfp);
  648.         newfp = NULL;
  649.       } else {
  650.         fp = newfp;
  651.       }
  652.     }
  653.  
  654.     /*
  655.     ** On VMS if a file is opened for write a new version is created.
  656.     ** This section of code check for "writeMode" and an existing file
  657.     ** if both are true.  Get the currently open file's name and delete
  658.     ** it.  Open a new one in write mode.
  659.     **
  660.     ** Side effects: This will replace the highest existing file version,
  661.     ** but not older version.  There exists the possibility that a user's
  662.     ** custom change may get lost.  A possible workaround for this would
  663.     ** be to have the calling program make a new copy (one higher version)
  664.     ** of the existing file before doing extensive write to the params
  665.     ** file OR keep a static flag in this routine which does  delete the
  666.     ** first time time.
  667.     */
  668.  
  669.     if (writeMode && fp != NULL) {
  670.       char temp[256];
  671.       fgetname(fp,temp);
  672.       Nlm_FileClose (fp);
  673.       delete(temp);
  674.       fp = Nlm_FileOpen (path, "w");
  675.     }
  676.   }
  677.   return fp;
  678. }
  679.  
  680. #endif /* OS_VMS */
  681.  
  682. #ifdef OS_DOS
  683. /*****************************************************************************
  684. *
  685. *   Nlm_OpenConfigFile (file, writeMode, create)
  686. *      returns a file pointer to the specified configuration file.
  687. *      1)  looks in the current directory for "file.cfg"
  688. *      2)  then looks for an environment variable "NCBI" and takes its
  689. *           value as a complete path to a directory containing the
  690. *           configuration file "file.cfg".
  691. *
  692. *****************************************************************************/
  693.  
  694. static FILE *Nlm_OpenConfigFile (Nlm_CharPtr file, Nlm_Boolean writeMode, Nlm_Boolean create)
  695.  
  696. {
  697.   FILE      *fp;
  698.   Nlm_Int2  i;
  699.   Nlm_Int2  len;
  700.   Nlm_Char  path [PATH_MAX+1];
  701.   char      *pth;
  702.   Nlm_Char  str [FILENAME_MAX+1];
  703.  
  704.   fp = NULL;
  705.   if (file != NULL) {
  706.     Nlm_StringNCpy (str, file, sizeof (str) - 4);
  707.     if ( ! Nlm_Qualified (str) ) {
  708.       Nlm_StringCat (str, ".cfg");
  709.     }
  710.     len = (Nlm_Int2) Nlm_StringLen (str);
  711.     for (i = 0; i < len; i++) {
  712.       str [i] = TO_LOWER (str [i]);
  713.     }
  714.     path[0] = '\0';
  715.     Nlm_StringCpy (path, str);
  716.     fp = Nlm_FileOpen (path, "r");
  717.     if (fp == NULL) {
  718.       pth = getenv ("NCBI");
  719.       if (pth != NULL) {
  720.         path[0] = '\0';
  721.         Nlm_FileBuildPath (path, pth, str);
  722.         fp = Nlm_FileOpen (path, "r");
  723.         if (fp == NULL && create) {
  724.           fp = Nlm_FileOpen (path, "w");
  725.           Nlm_FileClose (fp);
  726.           fp = Nlm_FileOpen (path, "r");
  727.         }
  728.       } else if (create) {
  729.         fp = Nlm_FileOpen (path, "w");
  730.         Nlm_FileClose (fp);
  731.         fp = Nlm_FileOpen (path, "r");
  732.       } else {
  733.         path[0] = '\0';
  734.       }
  735.     }
  736.     if (writeMode && fp != NULL) {
  737.       Nlm_FileClose (fp);
  738.       fp = Nlm_FileOpen (path, "w");
  739.     }
  740.   }
  741.   return fp;
  742. }
  743. #endif /* OS_DOS */
  744.  
  745. /*****************************************************************************
  746. *
  747. *   Nlm_TrimString (str)
  748. *      strips trailing spaces, \r, \n
  749. *
  750. *****************************************************************************/
  751.  
  752. static Nlm_CharPtr Nlm_TrimString (Nlm_CharPtr str)
  753.  
  754. {
  755.   Nlm_Char     ch;
  756.   Nlm_CharPtr  spc;
  757.   Nlm_CharPtr  tmp;
  758.  
  759.   if (str != NULL) {
  760.     ch = *str;
  761.     while (ch == ' ' || ch == '\t') {
  762.       str++;
  763.       ch = *str;
  764.     }
  765.     tmp = str;
  766.     spc = NULL;
  767.     ch = *tmp;
  768.     while (ch != '\0' && ch != '\r' && ch != '\n') {
  769.       if (ch == ' ' || ch == '\t') {
  770.         if (spc == NULL) {
  771.           spc = tmp;
  772.         }
  773.       } else {
  774.         spc = NULL;
  775.       }
  776.       tmp++;
  777.       ch = *tmp;
  778.     }
  779.     *tmp = '\0';
  780.     if (spc != NULL) {
  781.       *spc = '\0';
  782.     }
  783.   }
  784.   return str;
  785. }
  786.  
  787. /*****************************************************************************
  788. *
  789. *   Nlm_ReadConfigFile (fp)
  790. *      reads parameters from configuration file to memory structure
  791. *
  792. *****************************************************************************/
  793.  
  794. static Nlm_Boolean Nlm_ReadConfigFile (FILE *fp)
  795.  
  796. {
  797.   Nlm_Char         ch;
  798.   Nlm_env_itemPtr  eip;
  799.   Nlm_env_sectPtr  esp;
  800.   Nlm_env_itemPtr  lastEip;
  801.   Nlm_env_sectPtr  lastEsp;
  802.   Nlm_CharPtr      mid;
  803.   Nlm_Char         str [256];
  804.   Nlm_CharPtr      tmp;
  805.   Nlm_CharPtr      comment;
  806.  
  807.   if (fp != NULL) {
  808.     Nlm_envList = NULL;
  809.     esp = NULL;
  810.     lastEsp = NULL;
  811.     eip = NULL;
  812.     lastEip = NULL;
  813.     comment = NULL;
  814.     while (fgets (str, sizeof (str), fp)) {
  815.       ch = *str;
  816.       if (ch != '\n' && ch != '\r') {
  817.         if (ch == ';') { /* comment */
  818.           if (comment == NULL) { /* first comment */
  819.              comment = Nlm_StringSave(str);
  820.           }
  821.           else { /* append to existing comment */
  822.              tmp = (Nlm_CharPtr) Nlm_MemNew(StrLen(comment) + StrLen(str) + 1);
  823.              StrCpy(tmp, comment);
  824.              StrCat(tmp, str);
  825.              comment = (Nlm_CharPtr) Nlm_MemFree(comment);
  826.              comment = tmp;
  827.           }
  828.         } else if (ch == '[') {
  829.           if (esp == NULL) {
  830.             esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  831.             lastEsp = esp;
  832.             Nlm_envList = esp;
  833.           } else {
  834.             esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  835.             lastEsp->next = esp;
  836.             lastEsp = esp;
  837.           }
  838.           esp->comment = comment;
  839.           comment = NULL;
  840.           tmp = str;
  841.           ch = *tmp;
  842.           while (ch != '\0' && ch != ']') {
  843.             tmp++;
  844.             ch = *tmp;
  845.           }
  846.           *tmp = '\0';
  847.           esp->name = Nlm_StringSave (str + 1);
  848.           eip = NULL;
  849.           lastEip = NULL;
  850.         } else if (esp != NULL) {
  851.           if (eip == NULL) {
  852.             eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  853.             lastEip = eip;
  854.             esp->children = eip;
  855.           } else {
  856.             eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  857.             lastEip->next = eip;
  858.             lastEip = eip;
  859.           }
  860.           eip->comment = comment;
  861.           comment = NULL;
  862.           tmp = str;
  863.           mid = str;
  864.           ch = *tmp;
  865.           while (ch != '\0' && ch != '\n') {
  866.             if (ch == '=' && mid == str) {
  867.               mid = tmp;
  868.               *mid++ = '\0';
  869.             }
  870.             tmp++;
  871.             ch = *tmp;
  872.           }
  873.           *tmp = '\0';
  874.           eip->name = Nlm_StringSave (Nlm_TrimString (str));
  875.           eip->value = Nlm_StringSave (Nlm_TrimString (mid));
  876.         }
  877.       }
  878.     }
  879.  
  880.     /* any comments which appeared after the final key of the final section */
  881.     Nlm_bottomComment = comment;
  882.   }
  883.   return TRUE;
  884. }
  885.  
  886. static Nlm_env_sectPtr Nlm_FindConfigSection (Nlm_CharPtr section)
  887. {
  888.   Nlm_env_sectPtr esp;
  889.  
  890.   if (section == NULL)
  891.     return NULL;
  892.  
  893.   for (esp = Nlm_envList; esp != NULL; esp = esp->next)
  894.   {
  895.     if (esp->name != NULL && Nlm_StringICmp(section, esp->name) == 0)
  896.        return esp;
  897.   }
  898.  
  899.   return NULL;
  900. }
  901.  
  902. /*****************************************************************************
  903. *
  904. *   Nlm_FindConfigItem (section, type, create)
  905. *      finds parameter in memory structure
  906. *
  907. *****************************************************************************/
  908.  
  909. static Nlm_env_itemPtr Nlm_FindConfigItem (Nlm_CharPtr section, Nlm_CharPtr type, Nlm_Boolean create)
  910.  
  911. {
  912.   Nlm_env_itemPtr  eip;
  913.   Nlm_env_sectPtr  esp;
  914.   Nlm_Boolean      goOn;
  915.   Nlm_env_itemPtr  lastEip;
  916.   Nlm_env_sectPtr  lastEsp;
  917.  
  918.   eip = NULL;
  919.   if (section != NULL && type != NULL) {
  920.     goOn = TRUE;
  921.     esp = Nlm_envList;
  922.     lastEsp = esp;
  923.     while (esp != NULL && goOn) {
  924.       if (esp->name != NULL && Nlm_StringICmp (section, esp->name) == 0) {
  925.         goOn = FALSE;
  926.       } else {
  927.         lastEsp = esp;
  928.         esp = esp->next;
  929.       }
  930.     }
  931.     if (goOn && create) {
  932.       if (Nlm_envList != NULL) {
  933.         esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  934.         if (esp != NULL) {
  935.           esp->name = Nlm_StringSave (section);
  936.           lastEsp->next = esp;
  937.         }
  938.       } else {
  939.         esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
  940.         if (esp != NULL) {
  941.           esp->name = Nlm_StringSave (section);
  942.         }
  943.         Nlm_envList = esp;
  944.       }
  945.     }
  946.     if (esp != NULL) {
  947.       eip = esp->children;
  948.       if (eip != NULL) {
  949.         goOn = TRUE;
  950.         lastEip = eip;
  951.         while (eip != NULL && goOn) {
  952.           if (eip->name != NULL && Nlm_StringICmp (type, eip->name) == 0) {
  953.             goOn = FALSE;
  954.           } else {
  955.             lastEip = eip;
  956.             eip = eip->next;
  957.           }
  958.         }
  959.         if (goOn && create) {
  960.           eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  961.           if (eip != NULL) {
  962.             eip->name = Nlm_StringSave (type);
  963.             lastEip->next = eip;
  964.           }
  965.         }
  966.       } else if (create) {
  967.         eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
  968.         if (eip != NULL) {
  969.           eip->name = Nlm_StringSave (type);
  970.           esp->children = eip;
  971.         }
  972.       }
  973.     }
  974.   }
  975.   return eip;
  976. }
  977.  
  978. /*****************************************************************************
  979. *
  980. *   Nlm_WriteConfigFile (fp)
  981. *      writes parameters to configuration file from memory structure
  982. *
  983. *****************************************************************************/
  984.  
  985. static Nlm_Boolean Nlm_WriteConfigFile (FILE *fp)
  986.  
  987. {
  988.   Nlm_env_itemPtr  eip;
  989.   Nlm_env_sectPtr  esp;
  990.  
  991.   if (Nlm_envList != NULL && fp != NULL) {
  992.     esp = Nlm_envList;
  993.     while (esp != NULL) {
  994.       if (! destroyDeadComments || esp->name != NULL)
  995.       {
  996.         Nlm_PutComment (esp->comment, fp);
  997.       }
  998.       if (esp->name != NULL)
  999.       {
  1000.         fputc ('[', fp);
  1001.         fputs (esp->name, fp);
  1002.         fputs ("]\n", fp);
  1003.       }
  1004.       eip = esp->children;
  1005.       while (eip != NULL) {
  1006.         if (! destroyDeadComments)
  1007.         {
  1008.           Nlm_PutComment (eip->comment, fp);
  1009.         }
  1010.         if (esp->name != NULL && eip->name != NULL && eip->value != NULL) {
  1011.           if (destroyDeadComments)
  1012.           {
  1013.             Nlm_PutComment (eip->comment, fp);
  1014.           }
  1015.           fputs (eip->name, fp);
  1016.           fputc ('=', fp);
  1017.           fputs (eip->value, fp);
  1018.           fputc ('\n', fp);
  1019.         }
  1020.         eip = eip->next;
  1021.       }
  1022.       if (esp->name != NULL)
  1023.       {
  1024.         fputc ('\n', fp);
  1025.       }
  1026.       esp = esp->next;
  1027.     }
  1028.   }
  1029.  
  1030.   if (fp != NULL)
  1031.     Nlm_PutComment(Nlm_bottomComment, fp);
  1032.  
  1033.   return TRUE;
  1034. }
  1035.  
  1036. /*****************************************************************************
  1037. *
  1038. *   Nlm_FreeConfigFileData ()
  1039. *      frees parameter structure in memory
  1040. *
  1041. *****************************************************************************/
  1042.  
  1043. static void Nlm_FreeConfigFileData (void)
  1044.  
  1045. {
  1046.   Nlm_bottomComment = (Nlm_CharPtr) Nlm_MemFree(Nlm_bottomComment);
  1047.   if (Nlm_lastParamFile != NULL)
  1048.     Nlm_lastParamFile = (Nlm_CharPtr) Nlm_MemFree(Nlm_lastParamFile);
  1049.  
  1050.   if (Nlm_envList != NULL) {
  1051.     Nlm_FreeEnvData (Nlm_envList);
  1052.     Nlm_envList = NULL;
  1053.   }
  1054. }
  1055.  
  1056.  
  1057. /*****************************************************************************
  1058. *
  1059. *   Nlm_FreeConfigStruct ()
  1060. *      frees parameter structure in memory, and perform other cleanup
  1061. *
  1062. *****************************************************************************/
  1063.  
  1064. void LIBCALL Nlm_FreeConfigStruct (void)
  1065.  
  1066. {
  1067.   Nlm_FreeConfigFileData ();
  1068.   Nlm_FreeTransientData ();
  1069. #ifdef OS_UNIX
  1070.   if (saveHome != NULL)
  1071.   {
  1072.       saveHome = (Nlm_CharPtr) Nlm_MemFree(saveHome);
  1073.   }
  1074. #endif /* OS_UNIX */
  1075. }
  1076.  
  1077.  
  1078. /*****************************************************************************
  1079. *
  1080. *   Nlm_PutComment()
  1081. *      output a comment to the config file
  1082. *
  1083. *****************************************************************************/
  1084.  
  1085. static void Nlm_PutComment (Nlm_CharPtr s, FILE *fp)
  1086.  
  1087. {
  1088.   if (s != NULL)
  1089.     fputs(s, fp);
  1090. }
  1091.  
  1092. #else /* MS-WIN */
  1093. /*****************************************************************************
  1094. *
  1095. * The "guts" of:
  1096. *   Nlm_GetAppParam (file, section, type, buf, buflen)
  1097. *      finds parameters from configuration files
  1098. *      if configuration file is found, trys to read the parameter from it.
  1099. *
  1100. *****************************************************************************/
  1101.  
  1102. static Nlm_Int2 Nlm_WorkGetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen, Nlm_Boolean searchTransient)
  1103.  
  1104. {
  1105.   Nlm_Char     path [PATH_MAX+1];
  1106. #ifdef DCLAP
  1107.     Nlm_Int4     totlen;
  1108. #endif
  1109.  
  1110.   if (buf != NULL && buflen > 0) {
  1111.     *buf = '\0';
  1112.     if (searchTransient && Nlm_TransientLookup(file, section, type, dflt, buf, buflen))
  1113.     {
  1114.       return Nlm_StringLen(buf);
  1115.     }
  1116.     if (dflt) Nlm_StringNCat (buf, dflt, buflen);
  1117.     if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  1118.       Nlm_StringNCpy (path, file, sizeof (path) - 4);
  1119.       if ( ! Nlm_Qualified (path) ) {
  1120.         Nlm_StringCat (path, ".INI");
  1121.       }
  1122. #ifdef DCLAP
  1123.             totlen=
  1124. #endif
  1125.       GetPrivateProfileString (section, type, dflt, buf, buflen, path);
  1126.     }
  1127.   }
  1128. #ifdef DCLAP
  1129. /* we want same result here as above for type==NULL */
  1130.  if (type==NULL) return totlen;
  1131.  else
  1132. #endif
  1133.   return Nlm_StringLen (buf);
  1134. }
  1135.  
  1136. /*****************************************************************************
  1137. *
  1138. *   Nlm_SetAppParam (file, section, type, value)
  1139. *      finds paths for types of data and fills in path in buf
  1140. *      if configuration file is found, trys to write the parameter to it.
  1141. *
  1142. *****************************************************************************/
  1143.  
  1144. Nlm_Boolean LIBCALL  Nlm_SetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)    /* value */
  1145.  
  1146. {
  1147.   Nlm_Char     path [PATH_MAX+1];
  1148.   Nlm_Boolean  rsult;
  1149.  
  1150.   rsult = FALSE;
  1151.   if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
  1152.     Nlm_StringNCpy (path, file, sizeof (path) - 4);
  1153.     if ( ! Nlm_Qualified (path) ) {
  1154.       Nlm_StringCat (path, ".INI");
  1155.     }
  1156.     Nlm_TransientLogSetApp (file, section, type, value);
  1157.     if (WritePrivateProfileString (section, type, value, path)) {
  1158.       rsult = TRUE;
  1159.     }
  1160.   }
  1161.   return rsult;
  1162. }
  1163.  
  1164. /*****************************************************************************
  1165. *
  1166. *   Nlm_FreeConfigStruct ()
  1167. *      frees parameter structure in memory
  1168. *
  1169. *****************************************************************************/
  1170.  
  1171. void LIBCALL  Nlm_FreeConfigStruct (void)
  1172.  
  1173. {
  1174.   Nlm_FreeTransientData ();
  1175. }
  1176.  
  1177. #endif /* WIN_MSWIN */
  1178.  
  1179.  
  1180. static Nlm_Boolean Nlm_Qualified( Nlm_CharPtr path )
  1181. {
  1182.   Nlm_Int2 l,k;
  1183.   Nlm_CharPtr  p;
  1184.  
  1185.   l = Nlm_StrLen(path);
  1186.   p = path+l;
  1187.   k = 0;
  1188.   while (k < l && k <= 4) {
  1189.      if (*p-- == '.') return TRUE;
  1190.      k++;
  1191.   }
  1192.   return FALSE;
  1193. }
  1194.  
  1195.  
  1196. /*****************************************************************************
  1197. *
  1198. *   Nlm_FindPath (file, section, type, buf, buflen)
  1199. *      finds paths for types of data from configuration files.
  1200. *      if configuration file is found, tries to read the parameter from it,
  1201. *      then appends a directory delimiter character, if necessary.
  1202. *
  1203. *****************************************************************************/
  1204.  
  1205. Nlm_Boolean LIBCALL Nlm_FindPath (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr buf, Nlm_Int2 buflen)   /* length of path buffer */
  1206.  
  1207. {
  1208.   Nlm_Boolean  rsult;
  1209.  
  1210.   rsult = FALSE;
  1211.   if (buf != NULL && buflen > 0) {
  1212.     *buf = '\0';
  1213.     if (file != NULL && *file != '\0' && section != NULL &&
  1214.         *section != '\0' && type != NULL && *type != '\0') {
  1215.       if (Nlm_GetAppParam (file, section, type, "", buf, buflen - 1)) {
  1216.         if (*buf != '\0') {
  1217.             Nlm_FileBuildPath(buf, NULL, NULL);
  1218.         }
  1219.         rsult = TRUE;
  1220.       }
  1221.     }
  1222.   }
  1223.   return rsult;
  1224. }
  1225.  
  1226. Nlm_Int2 LIBCALL Nlm_GetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen)
  1227. {
  1228.     return Nlm_WorkGetAppParam(file, section, type, dflt, buf, buflen, TRUE);
  1229. }
  1230.  
  1231. Nlm_Boolean LIBCALL Nlm_TransientSetAppParam (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)
  1232.  
  1233. {
  1234.   Nlm_env_filePtr  theFile;
  1235.   Nlm_env_itemPtr  eip;
  1236.   Nlm_env_sectPtr  esp;
  1237.   Nlm_env_itemPtr  nextEip;
  1238.  
  1239.   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
  1240.     return FALSE;
  1241.  
  1242.   for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1243.   {
  1244.     if (StringICmp(theFile->name, file) == 0)
  1245.     {
  1246.       for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1247.       {
  1248.         if (esp->name != NULL && StringICmp(esp->name, section) == 0)
  1249.         {
  1250.           if (type == NULL || type[0] == '\0')
  1251.           {
  1252.             /* free all children */
  1253.             for (eip = esp->children; eip != NULL; eip = nextEip)
  1254.             {
  1255.               nextEip = eip->next;
  1256.               Nlm_MemFree (eip->name);
  1257.               Nlm_MemFree (eip->comment);
  1258.               Nlm_MemFree (eip->value);
  1259.               Nlm_MemFree (eip);
  1260.             }
  1261.             esp->children = NULL;
  1262.             esp->transientOnly = TRUE;
  1263.           } else { /* append this type to the section */
  1264.             eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
  1265.             eip->name = StringSave(type);
  1266.             eip->value = StringSave(value);
  1267.             eip->next = esp->children;
  1268.             esp->children = eip;
  1269.           }
  1270.           return TRUE;
  1271.         }
  1272.       }
  1273.       break;
  1274.     }
  1275.   }
  1276.  
  1277.   /* create the file data structure if needed */
  1278.   if (theFile == NULL)
  1279.   {
  1280.     theFile = (Nlm_env_filePtr) MemNew(sizeof(*theFile));
  1281.     theFile->name = StringSave(file);
  1282.     theFile->next = Nlm_transientFileList;
  1283.     Nlm_transientFileList = theFile;
  1284.   }
  1285.  
  1286.   /* create the section and type */
  1287.   esp = (Nlm_env_sectPtr) MemNew(sizeof(*esp));
  1288.   esp->name = StringSave(section);
  1289.   esp->next = theFile->envList;
  1290.   theFile->envList = esp;
  1291.   if (type == NULL || type[0] == '\0')
  1292.   {
  1293.     esp->transientOnly = TRUE;
  1294.   } else { /* create the section */
  1295.     esp->transientOnly = FALSE;
  1296.     eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
  1297.     eip->name = StringSave(type);
  1298.     eip->value = StringSave(value);
  1299.     eip->next = NULL;
  1300.     esp->children = eip;
  1301.   }
  1302.  
  1303.   return TRUE;
  1304. }
  1305.  
  1306. /* SetAppParam is writing a value to the real config file, so log this value, if
  1307.    necessary, into the "transient" data structures */
  1308. static void Nlm_TransientLogSetApp (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr value)
  1309.  
  1310. {
  1311.   Nlm_env_filePtr  theFile;
  1312.   Nlm_env_itemPtr  eip;
  1313.   Nlm_env_sectPtr  esp;
  1314.  
  1315.   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
  1316.     return;
  1317.  
  1318.   if (type == NULL || type[0] == '\0')
  1319.   {
  1320.     for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1321.     {
  1322.       if (StringICmp(theFile->name, file) == 0)
  1323.       {
  1324.         for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1325.         {
  1326.           if (esp->name != NULL && StringICmp(esp->name, section) == 0)
  1327.           { /* delete the section by removing section name */
  1328.             esp->name = (Nlm_CharPtr) MemFree(esp->name);
  1329.           }
  1330.         }
  1331.       }
  1332.     }
  1333.   } else {
  1334.     for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1335.     {
  1336.       if (StringICmp(theFile->name, file) == 0)
  1337.       {
  1338.         for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1339.         {
  1340.           if (esp->name != NULL && StringICmp(esp->name, section) == 0 &&
  1341.               esp->transientOnly)
  1342.           { /* append this type to the section */
  1343.             eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
  1344.             eip->name = StringSave(type);
  1345.             eip->value = StringSave(value);
  1346.             eip->next = esp->children;
  1347.             esp->children = eip;
  1348.           }
  1349.         }
  1350.       }
  1351.     }
  1352.   }
  1353. }
  1354.  
  1355. static Nlm_Boolean Nlm_TransientLookup (Nlm_CharPtr file, Nlm_CharPtr section, Nlm_CharPtr type, Nlm_CharPtr dflt, Nlm_CharPtr buf, Nlm_Int2 buflen)
  1356.  
  1357. {
  1358.   Nlm_env_filePtr  theFile;
  1359.   Nlm_env_itemPtr  eip;
  1360.   Nlm_env_sectPtr  esp;
  1361.   Nlm_Int2         totlen;
  1362.   Nlm_Int2         bytesToAppend;
  1363.  
  1364.   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
  1365.     return FALSE;
  1366.  
  1367.   for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
  1368.   {
  1369.     if (StringICmp(theFile->name, file) == 0)
  1370.     {
  1371.       for (esp = theFile->envList; esp != NULL; esp = esp->next)
  1372.       {
  1373.         if (esp->name != NULL && StringICmp(esp->name, section) == 0)
  1374.         {
  1375.           if (type == NULL || type[0] == '\0')
  1376.           { /* concatenate all types (keys) within section */
  1377.             *buf = '\0';
  1378.             totlen = 0;
  1379.             for (eip = esp->children; eip != NULL; eip = eip->next)
  1380.             {
  1381.               bytesToAppend = StrLen(eip->name) + 1;
  1382.               bytesToAppend = MIN(bytesToAppend, buflen - totlen);
  1383.               StrNCpy(&buf[totlen], eip->name, bytesToAppend);
  1384.               totlen += bytesToAppend;
  1385.             }
  1386.             if (totlen > 0 && buf[totlen] == '\0')
  1387.             {
  1388.                 totlen--; /* account for final null character */
  1389.             }
  1390.             /* now append the GetAppParam() data */
  1391.             if (! esp->transientOnly)
  1392.             { /* GetAppParam data can be trusted ... append it to buf */
  1393.               Nlm_WorkGetAppParam(file, section, NULL, "", &buf[totlen],
  1394.                                   buflen - totlen, FALSE);
  1395.             }
  1396.             return TRUE;
  1397.           } else {
  1398.             for (eip = esp->children; eip != NULL; eip = eip->next)
  1399.             {
  1400.               if (StringICmp(eip->name, type) == 0)
  1401.               {
  1402.                 *buf = '\0';
  1403.                 Nlm_StringNCat (buf, eip->value, buflen);
  1404.                 return TRUE;
  1405.               }
  1406.             }
  1407.             if (esp->transientOnly)
  1408.             { /* GetAppParam data cannot be trusted ... use the default */
  1409.               *buf = '\0';
  1410.               if (dflt) Nlm_StringNCat (buf, dflt, buflen);
  1411.               return TRUE;
  1412.             }
  1413.           }
  1414.         }
  1415.       }
  1416.     }
  1417.   }
  1418.  
  1419.   /* not found ... GetAppParam() should search the real config file */
  1420.   return FALSE;
  1421. }
  1422.  
  1423. static void Nlm_FreeEnvData (Nlm_env_sectPtr esp)
  1424.  
  1425. {
  1426.   Nlm_env_itemPtr  eip;
  1427.   Nlm_env_itemPtr  nextEip;
  1428.   Nlm_env_sectPtr  nextEsp;
  1429.  
  1430.   while (esp != NULL) {
  1431.     nextEsp = esp->next;
  1432.     eip = esp->children;
  1433.     while (eip != NULL) {
  1434.       nextEip = eip->next;
  1435.       Nlm_MemFree (eip->name);
  1436.       Nlm_MemFree (eip->comment);
  1437.       Nlm_MemFree (eip->value);
  1438.       Nlm_MemFree (eip);
  1439.       eip = nextEip;
  1440.     }
  1441.     Nlm_MemFree (esp->name);
  1442.     Nlm_MemFree (esp->comment);
  1443.     Nlm_MemFree (esp);
  1444.     esp = nextEsp;
  1445.   }
  1446. }
  1447.  
  1448.  
  1449. static void Nlm_FreeTransientData (void)
  1450. {
  1451.   Nlm_env_filePtr efp, nextEfp;
  1452.  
  1453.   efp = Nlm_transientFileList;
  1454.   while (efp != NULL) {
  1455.     nextEfp = efp->next;
  1456.     Nlm_FreeEnvData (efp->envList);
  1457.     Nlm_MemFree (efp->name);
  1458.     Nlm_MemFree (efp);
  1459.     efp = nextEfp;
  1460.   }
  1461.   Nlm_transientFileList = NULL;
  1462. }
  1463.