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: 6.52 $
33 *
34 * File Description:
35 *       portable environment functions, companions for ncbimain.c
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * $Log: ncbienv.c,v $
40 * Revision 6.52  2016/09/02 15:03:08  ucko
41 * Nlm_OpenConfigFile: Look in /etc/ncbi if the environment variable NCBI
42 * is unset, as already done in Debian/Ubuntu packages.
43 *
44 * Revision 6.51  2011/01/20 17:08:07  lavr
45 * Do not simply truncate size_t into Int2, use max instead NOJIRA
46 *
47 * Revision 6.50  2011/01/19 19:09:34  lavr
48 * Heed a warning NOJIRA
49 *
50 * Revision 6.49  2010/06/30 15:54:38  ucko
51 * Handle 64-bit Darwin builds, which require disabling WIN_MAC because
52 * Carbon is 32-bit-only.
53 *
54 * Revision 6.48  2009/08/17 19:56:13  lavr
55 * Delete explicit cast from SetProgramName() argument
56 *
57 * Revision 6.47  2009/08/14 18:01:09  lavr
58 * Use {Get|Set}ProgramName()
59 *
60 * Revision 6.46  2007/05/04 13:43:59  kans
61 * GetOpSysString now checks for Windows VISTA
62 *
63 * Revision 6.45  2007/04/06 21:47:56  kans
64 * Nlm_GetOpSysString checks gestaltSystemVersion and returns actual Mac OS X version
65 *
66 * Revision 6.44  2007/04/03 00:39:41  kans
67 * GetOpSysString does run-time check for Rosetta
68 *
69 * Revision 6.43  2005/12/02 13:40:00  rsmith
70 * In ProgramPath on Mac use case-insensitive compare to check the file extension.
71 *
72 * Revision 6.42  2005/12/01 19:52:19  rsmith
73 * Change impl of Mac's Nlm_ProgramPath_ST to only use CoreFoundation calls.
74 *
75 * Revision 6.41  2005/11/28 21:04:25  rsmith
76 * Don't need to call GetProcess in Mac's ProgramPath
77 *
78 * Revision 6.40  2005/11/22 20:53:19  rsmith
79 * Nlm_ProgramPath on Mac always return path to the .app bundle.
80 *
81 * Revision 6.39  2005/11/16 16:36:11  kans
82 * support for PowerPC and Intel chips for Macintosh
83 *
84 * Revision 6.38  2004/10/27 20:00:44  kans
85 * Ncbienv_FileOpen suppresses missing file error post
86 *
87 * Revision 6.37  2004/08/06 20:56:27  kans
88 * G/SetAppParam on PC no longer uses PrivateProfileString functions - instead it checks USERPROFILE, SYSTEMROOT, and then NCBI environment variables
89 *
90 * Revision 6.36  2004/02/11 18:40:00  kans
91 * enhanced GetOpSysString to report specific version of MS Windows
92 *
93 * Revision 6.35  2003/09/19 15:49:20  coulouri
94 * NetBSD fixes
95 *
96 * Revision 6.34  2003/06/24 19:45:39  ucko
97 * GCC/Darwin: Restore Nlm_IsApplicationPackage and the skeleton of
98 * Nlm_SetupArguments_ST_Mac.
99 *
100 * Revision 6.33  2003/06/24 15:39:42  ucko
101 * Switch back to the generic Unix ProgramPath code when building Darwin
102 * binaries with GCC until we find a framework that defines the relevant
103 * symbols without breaking support for remote execution.
104 *
105 * Revision 6.32  2003/06/06 15:01:03  rsmith
106 * fixed ProgramPath for OS Darwin & Mac, Added IsApplicationPackage for Darwin. ProgramPath on Darwin now returns the seen application not the executable buried in the package.
107 *
108 * Revision 6.31  2003/01/29 20:57:36  kans
109 * added linux, sgi, and solaris intel to GetOpSysString
110 *
111 * Revision 6.30  2003/01/29 19:37:14  kans
112 * added GetOpSysString to return allocated string describing operating system running the program
113 *
114 * Revision 6.29  2003/01/27 14:54:24  kans
115 * for darwin, also check /Contents/Resources/ of Mac OS X package for initial prepackaged config file
116 *
117 * Revision 6.28  2003/01/17 20:59:02  kans
118 * for Mach-O, try home/Library/Preferences/xxx.cnf first
119 *
120 * Revision 6.27  2002/10/03 16:22:03  kans
121 * changed fgets to Nlm_FileGets
122 *
123 * Revision 6.26  2002/03/28 13:29:08  kans
124 * checks for OS_UNIX_DARWIN (EN)
125 *
126 * Revision 6.25  2001/08/02 14:44:10  vakatov
127 * [OSF1]  NLM_XOPEN_SOURCE_500:: Kludge-fix for the weak-minded native
128 * preprocessor
129 *
130 * Revision 6.24  2001/08/01 16:15:38  vakatov
131 * Rollback to R6.22
132 *
133 * Revision 6.22  2001/05/25 17:58:27  vakatov
134 * [MAC] OpenConfigFile() -- replaced C++ style comments by the C-style ones
135 *
136 * Revision 6.21  2001/05/25 15:44:26  vakatov
137 * [AIX]  Tweaked conditions for NLM_POSIX1B
138 *
139 * Revision 6.20  2001/01/19 20:14:44  kans
140 * added checks for OS_UNIX_DARWIN (contributed by William Van Etten)
141 *
142 * Revision 6.19  2000/10/30 18:11:41  beloslyu
143 * FreeBSD was added
144 *
145 * Revision 6.18  2000/08/30 16:43:23  vakatov
146 * Nlm_WorkGetAppParam() -- do not try to open the same config file
147 * again (and again, and again) if failed to open it just before.
148 *
149 * Revision 6.17  2000/08/28 21:35:48  vakatov
150 * Figure out #LOGNAME_MAX value a little earlier in the code
151 *
152 * Revision 6.16  2000/08/28 18:32:18  vakatov
153 * Nlm_GetHome() -- split for s_GetHomeByUID() + s_GetHomeByLOGIN().
154 * Try s_GetHomeByUID() *before* s_GetHomeByLOGIN() to fix a problem
155 * reported by "Ray.Hookway@compaq.com" for LSF's Remote Execution Server.
156 *
157 * Revision 6.15  2000/06/28 14:50:43  vakatov
158 * Nlm_GetHome() -- IRIX, NLM_POSIX1B, getpwnam_r():  dont rely on the
159 * returned value only;  check for non-zero "pwd_ptr"
160 *
161 * Revision 6.14  2000/06/01 16:57:03  vakatov
162 * [IRIX]  Nlm_GetHome() -- added an extra check for the "pwd_ptr"
163 * (as per request by "Lack Mr G M" from SGI, gml4410@ggr.co.uk)
164 *
165 * Revision 6.13  2000/03/15 20:59:53  kans
166 * Mac version of Nlm_OpenConfigFile was opening file for reading even under writeMode - fixed
167 *
168 * Revision 6.12  1999/12/30 16:36:37  kans
169 * additional cleanup (Churchill)
170 *
171 * Revision 6.11  1999/12/21 18:22:17  kans
172 * new blessed file finding function needed to convert filename back to C string for fopen
173 *
174 * Revision 6.10  1999/12/21 17:52:39  kans
175 * removed MPW/THINKC conditional code, starting upgrade to Carbon compatibility - Churchill
176 *
177 * Revision 6.9  1999/11/29 19:58:49  vakatov
178 * To parse command-line arguments:
179 * + ECmdLineQuote, Nlm_ParseCmdLineArguments(), Nlm_FreeCmdLineArguments()
180 *
181 * Revision 6.8  1999/03/24 22:12:49  vakatov
182 * Nlm_ReadConfigFile():  free "Nlm_bottomComment" to avoid mem.leak
183 *
184 * Revision 6.7  1999/02/12 16:01:39  vakatov
185 * Added a draft version of Nlm_GetEnvParamEx()
186 * Got rid of the old "PROTO" and "LIBCALL" prototype junk, etc.
187 *
188 * Revision 6.6  1998/12/10 17:04:06  vakatov
189 * Fixed to compile under LINUX(Red Hat 2.XX, gcc, with POSIX threads)
190 *
191 * Revision 6.5  1997/11/26 21:26:10  vakatov
192 * Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers
193 *
194 * Revision 6.4  1997/10/29 02:43:31  vakatov
195 * Type castings to pass through the C++ compiler
196 *
197 * Revision 6.3  1997/10/27 21:58:11  vakatov
198 * Added Nlm_FreeArgs() to reset args earlier set by GetArgs[Silent]()
199 *
200 * Revision 6.2  1997/09/09 00:05:43  vakatov
201 * Nlm_x_HasConsole() -- "fileno" instead of "_fileno" to pass Borland compiler
202 *
203 * Revision 6.1  1997/08/27 16:16:38  vakatov
204 * [WIN32] Nlm_x_HasConsole() -- fixed for the case when the
205 * Vibrant-based(GUI) application is run from the console(command prompt)
206 *
207 * Revision 5.18  1997/07/22 19:11:18  vakatov
208 * Separated Main() from GetArg[svc]() functions;  [WIN_MSWIN] converged
209 * console and GUI libraries; [for WIN32-DLL] encapsulated global variables
210 *
211 * Revision 5.17  1997/06/02 15:28:36  vakatov
212 * [WIN32]  Read/write config(*.ini) files via WinSDK calls([WIN_MSWIN]-like)
213 *
214 * Revision 5.16  1997/05/08 19:37:08  vakatov
215 * [WIN_MSWIN]  Nlm_SetupArguments_ST() -- interpret all text(including
216 * space symbols) embraced by a pair of ""(or '') quote marks as a
217 * single command argument;  strip the embracing quote marks
218 *
219 * Revision 5.15  1997/03/05 20:32:55  vakatov
220 * Nlm_WorkGetAppParam: now free Nlm_lastParamFile before reset, avoid mem.leak
221 *
222  * Revision 5.14  1997/03/03  16:44:00  kans
223  * cleanup of memory leaks accidentally freed the cached file name,
224  * so now only the Nlm_envList is freed with Nlm_FreeEnvData
225  *
226  * Revision 5.13  1997/02/27  19:33:48  vakatov
227  * Nlm_ReadConfigFile():  free the obsolete config data --> fight memory leaks
228  *
229  * Revision 5.12  1997/01/28  21:19:12  kans
230  * <Desk.h>, <OSEvents.h> and <GestaltEqu.h> are obsolete in CodeWarrior
231  *
232  * Revision 5.11  1997/01/24  17:03:49  epstein
233  * make threaded version compatible with OSF/1
234  *
235  * Revision 5.10  1997/01/03  16:12:07  vakatov
236  * Fixed inaccurate string copying -- <mostly potential> 1-byte exceeding of
237  * the string size by StringNCat;  missing terminating '\0' by StringNCpy.
238  *
239  * Revision 5.9  1996/12/30  15:13:12  vakatov
240  * [WIN_MSWIN]  Command-line parsing implemented inside Nlm_SetupArguments()
241  *
242  * Revision 5.8  1996/12/16  22:38:53  vakatov
243  * Rolled back the changes made in "* Revision 5.4.  1996/11/27  20:38:14
244  * epstein"
245  *
246  * Revision 5.7  1996/12/04  21:44:47  vakatov
247  * [OS_UNIX][POSIX_THREADS_AVAIL]  Added _POSIX1C case (see Rev.5.5)
248  *
249  * Revision 5.6  1996/12/03  21:48:33  vakatov
250  * Adopted for 32-bit MS-Windows DLLs
251  *
252  * Revision 5.5  1996/11/27  21:55:17  vakatov
253  * [OS_UNIX][POSIX_THREADS_AVAIL]  Added (_POSIX_C_SOURCE - 0 >= 199506L)
254  * preprocessor condition to match POSIX.1c function interface.
255  *
256  * Revision 5.4  1996/11/27  20:38:14  epstein
257  * disable error logging when opening files in parameter fetching functions
258  *
259  * Revision 5.3  1996/11/25  19:04:26  vakatov
260  * Wrapped all basic functions to MT-safe wrappers(named by adding '_ST'
261  * suffix to the original function names).
262  *
263  * Revision 5.2  1996/08/19  18:46:06  vakatov
264  * [WIN32]  Made modifications to let one create console applications
265  *
266  * Revision 4.9  1996/02/15  22:00:49  kans
267  * changed platform symbol back to OS_NT
268  *
269  * Revision 4.8  1996/01/31  20:29:57  epstein
270  * fix uninitialized ptr in Nlm_GetHome()
271  *
272  * Revision 4.7  1996/01/29  22:33:37  epstein
273  * Added GetHome() changes per Mr. G.M. Lack (gml4410@ggr.co.uk)
274  *
275  * Revision 4.6  1995/12/13  17:18:51  kans
276  * fixed caching bug (JE & JK)
277  *
278  * Revision 4.5  1995/10/28  15:03:20  ostell
279  * added casts to quiet DOS compile warnings
280  *
281  * Revision 4.4  1995/10/11  13:53:05  kans
282  * made some variables static
283  *
284  * Revision 4.3  1995/10/06  19:59:18  epstein
285  * more performance fixes
286  *
287  * Revision 4.2  1995/10/06  15:53:31  epstein
288  * add CacheAppParam() and FlushAppParam() for improved performance
289  *
290  * Revision 4.1  1995/10/03  15:59:21  epstein
291  * add NCBI_DONT_USE_LOCAL_CONFIG environment variable to avoid local config files
292  *
293 *  7/7/91   Kans        Multiple configuration files, get and set functions
294 *  9-20-91  Schuler     GetAppParam takes default value as an argument
295 * 01-14-94  Epstein     Merged ncbienv.{unx,vms,dos,msw,mac} into a single file
296 * 06-14-94  Schuler     Put SetAppPropery("ProgramName",..) in SetupArguments
297 * 06-14-94  Schuler     Add LIBCALL to SetupArguments
298 * 08-23-94  Schuler     Add SetupArguments case for OS_NT/WIN_DUMB
299 * 01-29-96  Epstein     Added GetHome() changes per Mr. G.M. Lack
300 *
301 * ==========================================================================
302 */
303 
304 #ifdef OS_MAC
305 #ifdef PROC_MC680X0
306 #define OBSOLETE
307 #endif
308 #endif
309 
310 #include "corepriv.h"
311 
312 #ifdef OS_UNIX
313 #include <pwd.h>
314 #endif /* OS_UNIX */
315 #ifdef OS_MAC
316 #include <Gestalt.h>
317 #include <Folders.h>
318 #include <Processes.h>
319 #include <Script.h>
320 #endif /* OS_MAC */
321 
322 
323 typedef struct nlm_env_item {
324   struct nlm_env_item* next;
325   Nlm_Char*            name;
326   Nlm_Char*            comment;
327   Nlm_Char*            value;
328 } Nlm_env_item, *Nlm_env_itemPtr;
329 
330 typedef struct nlm_env_sect {
331   struct nlm_env_sect* next;
332   Nlm_Char*            name;
333   Nlm_Char*            comment;
334   Nlm_Boolean          transientOnly; /* this field used only by Transient */
335   struct nlm_env_item* children;
336 } Nlm_env_sect, *Nlm_env_sectPtr;
337 
338 typedef struct nlm_env_file {
339   struct nlm_env_file* next;
340   Nlm_Char*            name;
341   Nlm_env_sectPtr      envList;
342 } Nlm_env_file, *Nlm_env_filePtr;
343 
344 
345 static Nlm_env_filePtr Nlm_transientFileList = NULL;
346 static Nlm_Boolean caching = FALSE;
347 static Nlm_Boolean dirty = FALSE;
348 static Nlm_Boolean mustCreateFile = TRUE;
349 
350 static Nlm_Boolean Nlm_Qualified(const Nlm_Char* path);
351 static Nlm_Boolean Nlm_TransientLookup(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* dflt, Nlm_Char* buf, size_t buflen);
352 static void Nlm_TransientLogSetApp(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* value);
353 static void Nlm_FreeEnvData(Nlm_env_sectPtr esp);
354 static void Nlm_FreeTransientData(void);
355 
356 static FILE* Nlm_OpenConfigFile(const Nlm_Char* file, Nlm_Boolean writeMode, Nlm_Boolean create);
357 static Nlm_Char* Nlm_TrimString(Nlm_Char* str);
358 static Nlm_Boolean Nlm_ReadConfigFile(FILE* fp);
359 static Nlm_env_sectPtr Nlm_FindConfigSection(const Nlm_Char* section);
360 static Nlm_env_itemPtr Nlm_FindConfigItem(const Nlm_Char* section, const Nlm_Char* type, Nlm_Boolean create);
361 static Nlm_Boolean Nlm_WriteConfigFile(FILE* fp);
362 static void Nlm_PutComment(const Nlm_Char* s, FILE* fp);
363 static void Nlm_FreeConfigFileData(void);
364 static void Nlm_FlushConfigFile(const Nlm_Char* file, Nlm_Boolean create);
365 
366 static Nlm_env_sectPtr Nlm_envList = NULL;
367 static Nlm_Char* Nlm_lastParamFile = NULL;
368 static Nlm_Char* Nlm_bottomComment = NULL;
369 
370 /* always FALSE, because this file is trying to emulating MS Windows's  */
371 /* handling of comments in Param files; however, just change this value */
372 /* to TRUE to turn this approach around                                 */
373 static Nlm_Boolean destroyDeadComments = FALSE;
374 
375 /*****************************************************************************
376 *
377 * The "guts" of:
378 *   Nlm_GetAppParam (file, section, type, dflt, buf, buflen)
379 *      finds parameters from configuration files
380 *      this version, searching for configuration file(s) in a
381 *      platform-dependent basis as handled by Nlm_OpenConfigFile()
382 *
383 *      if configuration file is found, tries to read the parameter from it.
384 *
385 *****************************************************************************/
386 
Ncbienv_FileOpen(const char * filename,const char * mode)387 static FILE* LIBCALL Ncbienv_FileOpen (const char *filename, const char *mode)
388 
389 {
390   FILE    *fp;
391   ErrSev  sev;
392 
393   sev = ErrSetMessageLevel (SEV_ERROR);
394   fp = FileOpen (filename, mode);
395   ErrSetMessageLevel (sev);
396   return fp;
397 }
398 
399 static Nlm_Int2
Nlm_WorkGetAppParam(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * dflt,Nlm_Char * buf,Nlm_Int2 buflen,Nlm_Boolean searchTransient)400 Nlm_WorkGetAppParam(const Nlm_Char* file,
401                     const Nlm_Char* section,
402                     const Nlm_Char* type,
403                     const Nlm_Char* dflt,
404                     Nlm_Char* buf,
405                     Nlm_Int2 buflen,
406                     Nlm_Boolean searchTransient)
407 {
408   Nlm_env_itemPtr  eip;
409   FILE             *fp;
410 
411   if (buf == NULL  ||  buflen <= 0)
412     return 0;
413 
414   *buf = '\0';
415   if (searchTransient  &&
416       Nlm_TransientLookup(file, section, type, dflt, buf, buflen))
417     {
418       return (Nlm_Int2)Nlm_StringLen(buf);
419     }
420 
421   if ( dflt )
422     Nlm_StringNCpy_0(buf, dflt, buflen);
423 
424   if (file    == NULL   ||  *file    == '\0'  ||
425       section == NULL   ||  *section == '\0')
426     return (Nlm_Int2)Nlm_StringLen( buf );
427 
428   if (Nlm_lastParamFile == NULL  ||
429       Nlm_StringICmp(Nlm_lastParamFile, file) != 0)
430     {
431       mustCreateFile = TRUE;
432       if ( caching )
433         Nlm_FlushAppParam();
434       Nlm_FreeConfigFileData();
435       fp = Nlm_OpenConfigFile(file, FALSE, FALSE);
436       MemFree( Nlm_lastParamFile );
437       Nlm_lastParamFile = Nlm_StringSave( file );
438       if (fp != NULL)
439         {
440           Nlm_ReadConfigFile( fp );
441           Nlm_FileClose( fp );
442         }
443     }
444 
445   if (type != NULL  &&  *type != '\0')
446     {
447       eip = Nlm_FindConfigItem(section, type, FALSE);
448       if (eip != NULL)
449         Nlm_StringNCpy_0(buf, eip->value, buflen);
450     }
451   else
452     { /* return all the types in that section */
453       Nlm_env_sectPtr  esp    = Nlm_FindConfigSection( section );
454       Nlm_Int2         totlen = 0;
455       *buf = '\0';
456       if (esp == NULL)
457         return 0;
458 
459       /* traverse the children, allowing the null chars to be inserted */
460       /* in between each type-name                                     */
461       for (eip = esp->children;
462            eip != NULL  &&  totlen != buflen;  eip = eip->next)
463         {
464           Nlm_Int2 bytesToAppend = StrLen(eip->name) + 1;
465           bytesToAppend = MIN(bytesToAppend, buflen - totlen);
466           StrNCpy(&buf[totlen], eip->name, bytesToAppend - 1);
467           totlen += bytesToAppend;
468           buf[totlen - 1] = '\0';
469         }
470     }
471 
472   return (Nlm_Int2)Nlm_StringLen(buf);
473 }
474 
475 
476 /*****************************************************************************
477 *
478 *   Nlm_SetAppParam (file, section, type, value)
479 *      finds paths for types of data and fills in path in buf
480 *      this version
481 *      1)  looks in the current directory for ".filerc", but will not
482 *          create a new file in this directory.
483 *      2)  then looks in the home directory for ".filerc".
484 *      3)  then looks for an environment variable "NCBI" and takes its
485 *          value as a complete path to a directory containing the
486 *          configuration file ".filerc".
487 *      if configuration file is found, tries to write the parameter to it.
488 *
489 *****************************************************************************/
490 
Nlm_SetAppParam_ST(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * value)491 static Nlm_Boolean Nlm_SetAppParam_ST(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* value)
492 {
493   Nlm_env_itemPtr  eip;
494   Nlm_env_sectPtr  esp;
495   FILE             *fp = NULL;
496   Nlm_Boolean      rsult;
497 
498   rsult = FALSE;
499   if (file != NULL && *file != '\0' && section != NULL && *section != '\0') {
500     Nlm_TransientLogSetApp (file, section, type, value);
501 
502     if (Nlm_lastParamFile == NULL || Nlm_StringICmp(Nlm_lastParamFile, file) != 0) {
503       mustCreateFile = TRUE;
504     }
505     if (mustCreateFile)
506       fp = Nlm_OpenConfigFile (file, FALSE, TRUE);
507 
508     if (TRUE) {
509       if (fp != NULL) {
510         Nlm_FlushAppParam();
511         Nlm_FreeConfigFileData();
512         Nlm_lastParamFile = Nlm_StringSave(file);
513         Nlm_ReadConfigFile (fp);
514         Nlm_FileClose (fp);
515         mustCreateFile = FALSE;
516       }
517       if (type != NULL && *type != '\0')
518       {
519         eip = Nlm_FindConfigItem (section, type, TRUE);
520         if (eip != NULL) {
521           if (eip->value != NULL) {
522             eip->value = (Nlm_Char*) Nlm_MemFree (eip->value);
523           }
524           eip->value = Nlm_StringSave (value);
525           rsult = TRUE;
526         }
527       }
528       else { /* wipe out that section */
529         esp = Nlm_FindConfigSection (section);
530         if (esp != NULL) { /* kill section by deleting name (leave comments)*/
531           esp->name = (Nlm_Char*) Nlm_MemFree(esp->name);
532           rsult = TRUE;
533         }
534       }
535 
536       if (rsult) {
537         dirty = TRUE;
538       }
539       if (! caching) {
540         Nlm_FlushConfigFile(file, TRUE);
541       }
542     }
543   }
544 
545   return rsult;
546 }
547 
548 /*****************************************************************************
549 *
550 *   Nlm_FlushAppParam()
551 *      flush the current parameter file's parameters to disk
552 *
553 *****************************************************************************/
Nlm_FlushAppParam_ST(void)554 static void Nlm_FlushAppParam_ST(void)
555 {
556   if (Nlm_lastParamFile != NULL)
557     Nlm_FlushConfigFile(Nlm_lastParamFile, TRUE);
558 }
559 
560 /*****************************************************************************
561 *
562 *   Nlm_CacheAppParam()
563 *      Indicates whether data should be flushed to disk after each call
564 *      to SetAppParam()
565 *
566 *****************************************************************************/
Nlm_CacheAppParam_ST(Nlm_Boolean value)567 static Nlm_Boolean Nlm_CacheAppParam_ST(Nlm_Boolean value)
568 {
569   Nlm_Boolean oldvalue = caching;
570 
571   caching = value;
572   if (! value)
573     Nlm_FlushAppParam();
574 
575   return oldvalue;
576 }
577 
578 
579 #ifdef OS_UNIX
580 
581 /* This is a special kludge for OSF1 native compiler which apparently
582  * cannot handle (_XOPEN_SOURCE == 500) when _XOPEN_SOURCE is defined
583  * to nothing
584  */
585 #if (_XOPEN_SOURCE == 500)
586 #  define NLM_XOPEN_SOURCE_500 1
587 #else
588 #  define NLM_XOPEN_SOURCE_500 0
589 #endif
590 
591 #define NLM_POSIX1B \
592     (_POSIX1B || _POSIX1C || \
593     (_POSIX_C_SOURCE - 0 >= 199309L) || \
594     defined(_POSIX_PTHREAD_SEMANTICS) || \
595     (defined(OS_UNIX_AIX)  &&  NLM_XOPEN_SOURCE_500  &&  !defined(_UNIX95)))
596 
597 #ifndef LOGNAME_MAX
598 #  if defined(MAXLOGNAME)
599 #    define LOGNAME_MAX MAXLOGNAME
600 #  elif defined(_POSIX_LOGIN_NAME_MAX)
601 #    define LOGNAME_MAX _POSIX_LOGIN_NAME_MAX
602 #  endif
603 #endif /* ndef LOGNAME_MAX */
604 
605 
606 /*****************************************************************************
607 *
608 *   Nlm_GetHome (buf, buflen)
609 *      returns the path of the home directory
610 *
611 *****************************************************************************/
612 
613 
614 /* This function is used by Nlm_GetHome(), see below
615  */
s_GetHomeByUID(Nlm_Char * buf,size_t buf_size)616 static Nlm_Boolean s_GetHomeByUID(Nlm_Char* buf, size_t buf_size)
617 {
618     struct passwd* pwd_ptr = 0;
619 
620     /* Get the info using user ID */
621 #if  (defined(SOLARIS_THREADS_AVAIL) || defined(POSIX_THREADS_AVAIL)) && !defined(OS_UNIX_FREEBSD) && !defined(OS_UNIX_DARWIN) && !defined(OS_UNIX_NETBSD)
622     struct passwd pwd;
623     Nlm_Char      pwd_buffer[LOGNAME_MAX + PATH_MAX + 1024 + 1];
624 
625 #  if NLM_POSIX1B
626     if (getpwuid_r(getuid(), &pwd, pwd_buffer, sizeof(pwd_buffer),
627                    &pwd_ptr) != 0) {
628         pwd_ptr = 0;
629     }
630 #  else
631     pwd_ptr = getpwuid_r(getuid(), &pwd, pwd_buffer, sizeof(pwd_buffer));
632 #  endif
633 #else
634     pwd_ptr = getpwuid(getuid());
635 #endif
636 
637     if (!pwd_ptr  ||  pwd_ptr->pw_dir[0] == '\0')
638         return FALSE;
639     Nlm_StringNCpy_0(buf, pwd_ptr->pw_dir, buf_size);
640     return TRUE;
641 }
642 
643 
644 /* This function is used by Nlm_GetHome(), see below
645  */
s_GetHomeByLOGIN(Nlm_Char * buf,Nlm_Int2 buf_size)646 static Nlm_Boolean s_GetHomeByLOGIN(Nlm_Char* buf, Nlm_Int2 buf_size)
647 {
648     struct passwd* pwd_ptr = 0;
649 
650     /* Get the user login name */
651 #if (defined(SOLARIS_THREADS_AVAIL) || defined(POSIX_THREADS_AVAIL)) && !defined(OS_UNIX_FREEBSD) && !defined(OS_UNIX_DARWIN) && !defined(OS_UNIX_NETBSD)
652     struct passwd pwd;
653     Nlm_Char      login_name[LOGNAME_MAX + 1];
654     Nlm_Char      pwd_buffer[LOGNAME_MAX + PATH_MAX + 1024 + 1];
655     Nlm_Boolean   ok = getlogin_r(login_name, sizeof(login_name)) ?
656 #  if NLM_POSIX1B
657         FALSE : TRUE;
658 #  else
659     TRUE : FALSE;
660 #  endif
661 #else
662 
663     Nlm_Char* login_name = getlogin();
664     Nlm_Boolean ok       = (login_name != NULL);
665 #endif
666 
667     /* Get the info using user login-name */
668     if ( !ok )
669         return FALSE;
670 
671 #if (defined(SOLARIS_THREADS_AVAIL) || defined(POSIX_THREADS_AVAIL)) && !defined(OS_UNIX_FREEBSD) && !defined(OS_UNIX_DARWIN) && !defined(OS_UNIX_NETBSD)
672     pwd_ptr = &pwd;
673 #  if NLM_POSIX1B
674     if (getpwnam_r(login_name, &pwd, pwd_buffer, sizeof(pwd_buffer),
675                    &pwd_ptr) != 0) {
676         pwd_ptr = 0;
677     }
678 #  else
679     pwd_ptr = getpwnam_r(login_name, &pwd, pwd_buffer, sizeof(pwd_buffer));
680 #  endif
681 #else
682     pwd_ptr = getpwnam(login_name);
683 #endif
684 
685     if (!pwd_ptr  ||  pwd_ptr->pw_dir[0] == '\0')
686         return FALSE;
687     Nlm_StringNCpy_0(buf, pwd_ptr->pw_dir, buf_size);
688     return TRUE;
689 }
690 
691 
Nlm_GetHome(Nlm_Char * buf,Nlm_Int2 buflen)692 static Nlm_Boolean Nlm_GetHome(Nlm_Char* buf, Nlm_Int2 buflen)
693 {
694   static Nlm_Boolean s_Saved = FALSE;
695   static Nlm_Char    s_SaveHome[PATH_MAX + 1];
696   static TNlmMutex   s_SaveHomeMutex;
697 
698   /* Have we passed this way before?  If not, then try get the info. */
699   if ( !s_Saved ) {
700 #if  defined(SOLARIS_THREADS_AVAIL)  ||  defined(POSIX_THREADS_AVAIL)
701     VERIFY_HARD( NlmMutexLockEx( &s_SaveHomeMutex ) == 0 );
702     if ( !s_Saved ) {
703 #endif
704       s_Saved = TRUE;
705 
706       /* Try to retrieve the home dir -- first use user's ID,
707        * and if failed, then use user's login name.
708        */
709       if (!s_GetHomeByUID(s_SaveHome, sizeof(s_SaveHome))  &&
710           !s_GetHomeByLOGIN(s_SaveHome, sizeof(s_SaveHome))) {
711         s_SaveHome[0] = '\0';
712       }
713 #if  defined(SOLARIS_THREADS_AVAIL)  ||  defined(POSIX_THREADS_AVAIL)
714     }
715     VERIFY_HARD( NlmMutexUnlock(s_SaveHomeMutex) == 0 );
716 #endif
717   }
718   Nlm_StringNCpy_0(buf, s_SaveHome, buflen);
719   return (Nlm_Boolean) (*buf != '\0');
720 }
721 
722 
723 
724 /*****************************************************************************
725 *
726 *   Nlm_OpenConfigFile (file, writeMode, create)
727 *      returns a file pointer to the specified configuration file.
728 *      1)  looks in the current directory for ".filerc", but will not
729 *          create a new file in this directory.
730 *      2)  then looks in the home directory for ".filerc".
731 *      3)  then looks for an environment variable "NCBI" and takes its
732 *          value as a complete path to a directory containing the
733 *          configuration file "filerc" or ".filerc".
734 *
735 *      Steps (1) and (2) above are omitted if the NCBI_DONT_USE_LOCAL_CONFIG
736 *      environment variable is set.  This can be used to allow specific
737 *      production applications to avoid stray .ncbirc files which may have
738 *      been erroneously generated.
739 *
740 *****************************************************************************/
741 
Nlm_OpenConfigFile(const Nlm_Char * file,Nlm_Boolean writeMode,Nlm_Boolean create)742 static FILE* Nlm_OpenConfigFile(const Nlm_Char* file, Nlm_Boolean writeMode, Nlm_Boolean create)
743 
744 {
745   Nlm_Char  ch;
746   FILE      *fp;
747   Nlm_Int2  i;
748   Nlm_Int2  len;
749   FILE      *newfp;
750   Nlm_Char  path [PATH_MAX+1];
751   char      *pth;
752   Nlm_Char  str [FILENAME_MAX+1];
753   Nlm_Boolean dontUseLocalConfig;
754 
755   fp = NULL;
756   if (file != NULL) {
757 #ifdef OS_UNIX_DARWIN
758     /* For Mach-O executables, check username/Library/Preferences/xxx.cnf first */
759     Nlm_StringNCpy_0(str, file, sizeof(str) - 4);
760     if ( ! Nlm_Qualified (str) ) {
761         /* if the user has already supplied a name with .xxx use that name
762          * otherwise add the .cnf here */
763         Nlm_StringCat(str, ".cnf");
764     }
765     /* if the name isn't all lowercase, make it so now */
766     len = (Nlm_Int2) Nlm_StringLen (str);
767     for (i = 0; i < len; i++) {
768       ch = str [i];
769       str [i] = TO_LOWER (ch);
770     }
771     if (Nlm_GetHome (path, sizeof (path))) {
772       Nlm_FileBuildPath(path, "Library", NULL);
773       Nlm_FileBuildPath(path, "Preferences", NULL);
774       Nlm_FileBuildPath(path, NULL, str);
775       fp = Ncbienv_FileOpen (path, "r");
776       if (fp == NULL && create) {
777         fp = Ncbienv_FileOpen (path, "w");
778         Nlm_FileClose (fp);
779         fp = Ncbienv_FileOpen (path, "r");
780       }
781       if (writeMode && fp != NULL) {
782         Nlm_FileClose (fp);
783         fp = Ncbienv_FileOpen (path, "w");
784       }
785       if (fp != NULL) {
786         return fp;
787       }
788     }
789     /* also check within Contents/Resources of Mac OS X package */
790     ProgramPath (path, sizeof (path));
791     if (IsApplicationPackage(path)) {
792       FileBuildPath(path, "Contents", NULL);
793       FileBuildPath (path, "Resources", NULL);
794       Nlm_FileBuildPath (path, NULL, str);
795       fp = Ncbienv_FileOpen (path, "r");
796       if (fp != NULL) {
797         return fp;
798       }
799     }
800 #endif
801     dontUseLocalConfig = getenv("NCBI_DONT_USE_LOCAL_CONFIG") != NULL;
802     newfp = NULL;
803     Nlm_StringMove(str, ".");
804     Nlm_StringNCat(str, file, sizeof(str) - 4);
805     if ( ! Nlm_Qualified (str))
806     { /* use the user's extension instead of the "rc" extension */
807       Nlm_StringCat(str, "rc");
808     }
809     len = (Nlm_Int2) Nlm_StringLen (str);
810     for (i = 0; i < len; i++) {
811       ch = str [i];
812       str [i] = TO_LOWER (ch);
813     }
814     Nlm_StringNCpy_0(path, str, sizeof(path));
815 
816     if (! dontUseLocalConfig)
817       fp = Ncbienv_FileOpen (path, "r");
818     if (fp == NULL) {
819       if (Nlm_GetHome (path, sizeof (path))) {
820         Nlm_FileBuildPath(path, NULL, str);
821       } else {
822         Nlm_StringNCpy_0(path, str, sizeof(path));
823       }
824       if (! dontUseLocalConfig)
825         fp = Ncbienv_FileOpen (path, "r");
826       if (fp == NULL && create) {
827         newfp = Ncbienv_FileOpen (path, "w");
828         Nlm_FileClose (newfp);
829         newfp = Ncbienv_FileOpen (path, "r");
830       }
831     }
832     if (fp == NULL) {
833       path[0] = '\0';
834       pth = getenv ("NCBI");
835       if (pth == NULL)
836         pth = "/etc/ncbi";
837       Nlm_FileBuildPath(path, pth, str + 1);
838       fp = Ncbienv_FileOpen (path, "r");
839       if (fp == NULL) {
840         path[0] = '\0';
841         Nlm_FileBuildPath(path, pth, str);
842         fp = Ncbienv_FileOpen (path, "r");
843       }
844     }
845     if (newfp != NULL) {
846       if (fp != NULL) {
847         Nlm_FileClose (newfp);
848         newfp = NULL;
849       } else {
850         fp = newfp;
851       }
852     }
853     if (writeMode && fp != NULL) {
854       Nlm_FileClose (fp);
855       fp = Ncbienv_FileOpen (path, "w");
856     }
857   }
858   return fp;
859 }
860 
861 #endif /* OS_UNIX */
862 
863 #ifdef OS_MSWIN
864 /*****************************************************************************
865 *
866 *   Nlm_OpenConfigFile (file, writeMode, create)
867 *      returns a file pointer to the specified configuration file.
868 *      1)  looks in the current directory for "file.ini", but will not
869 *          create a new file in this directory.
870 *      2)  then looks in the home directory for ".filerc".
871 *      3)  then looks for an environment variable "NCBI" and takes its
872 *          value as a complete path to a directory containing the
873 *          configuration file "filerc" or ".filerc".
874 *
875 *      Steps (1) and (2) above are omitted if the NCBI_DONT_USE_LOCAL_CONFIG
876 *      environment variable is set.  This can be used to allow specific
877 *      production applications to avoid stray .ncbirc files which may have
878 *      been erroneously generated.
879 *
880 *****************************************************************************/
881 
Nlm_OpenConfigFile(const Nlm_Char * file,Nlm_Boolean writeMode,Nlm_Boolean create)882 static FILE* Nlm_OpenConfigFile(const Nlm_Char* file, Nlm_Boolean writeMode, Nlm_Boolean create)
883 
884 {
885   Nlm_Char  ch;
886   FILE      *fp;
887   Nlm_Int2  i;
888   Nlm_Int2  len;
889   FILE      *newfp;
890   Nlm_Char  path [PATH_MAX+1];
891   Nlm_Char  str [FILENAME_MAX+1];
892   Nlm_CharPtr  tmp;
893 
894   fp = NULL;
895   newfp = NULL;
896 
897   if (file != NULL) {
898 
899     /* normalize file name */
900     Nlm_StringNCpy_0(str, file, sizeof(str) - 4);
901     if ( ! Nlm_Qualified (str) ) {
902         /* if the user has already supplied a name with .xxx use that name
903          * otherwise add the .ini here */
904         Nlm_StringCat(str, ".INI");
905     }
906     /* if the name isn't all uppercase, make it so now */
907     len = (Nlm_Int2) Nlm_StringLen (str);
908     for (i = 0; i < len; i++) {
909       ch = str [i];
910       str [i] = TO_UPPER (ch);
911     }
912 
913     /* first try user directory */
914 
915     tmp = getenv ("USERPROFILE");
916     if (tmp != NULL && *tmp != '\0') {
917       StringNCpy_0 (path, tmp, sizeof (path));
918       Nlm_FileBuildPath(path, NULL, str);
919       fp = Ncbienv_FileOpen (path, "r");
920       if (fp == NULL && create) {
921         newfp = Ncbienv_FileOpen (path, "w");
922         Nlm_FileClose (newfp);
923         newfp = Ncbienv_FileOpen (path, "r");
924       }
925     }
926 
927     /* next try c:\winnt for backward compatibility - read only */
928 
929     if (fp == NULL) {
930       tmp = getenv ("SYSTEMROOT");
931       if (tmp != NULL && *tmp != '\0') {
932         StringNCpy_0 (path, tmp, sizeof (path));
933         Nlm_FileBuildPath(path, NULL, str);
934         fp = Ncbienv_FileOpen (path, "r");
935       }
936     }
937 
938     /* last try environment variable path - read only */
939 
940     if (fp == NULL) {
941       tmp = getenv ("NCBI");
942       if (tmp != NULL && *tmp != '\0') {
943         StringNCpy_0 (path, tmp, sizeof (path));
944         Nlm_FileBuildPath(path, NULL, str);
945         fp = Ncbienv_FileOpen (path, "r");
946       }
947     }
948 
949     if (newfp != NULL) {
950       if (fp != NULL) {
951         Nlm_FileClose (newfp);
952         newfp = NULL;
953       } else {
954         fp = newfp;
955       }
956     }
957     if (writeMode && fp != NULL) {
958       Nlm_FileClose (fp);
959       fp = Ncbienv_FileOpen (path, "w");
960     }
961   }
962   return fp;
963 }
964 #endif /* OS_MSWIN */
965 
966 
967 #if defined(OS_MAC) && !defined(OS_UNIX_DARWIN)
968 /*****************************************************************************
969  *
970  *   Nlm_OpenConfigFile (file, writeMode, create)
971  *
972  *       file        char string with name of file to open or optionally create
973  *       writeMode   don't know what this does, but all calling functions seem
974  *                   to pass FALSE??
975  *       create      Boolean to create the file if it doesn't already exist
976  *
977  *  Returns:
978  *      A ncbi FILE pointer to the specified configuration file.  NULL if all
979  *      fails for some reason
980  *
981  *      1)  Finds "System Folder:Preferences" for "file.cnf"
982  *
983  *  Implementation Notes:
984  *      Implicit assumptions:
985  *      System softare is 6.0.5 or newer (Gestalt)
986  *      System softare is 7.0 or newer (FindFolder)
987  *
988  *  We find the active preferences folder and either open a pre-existing file
989  *  or create a new one with type 'TEXT' and creator '    '.  The absolute
990  *  pathname is not derived or needed, since we can use HSetVol to perform the
991  *  MacOS equivalent of a "cd" command.
992  *
993  *   pchurchill 12/10/99
994  *
995  *****************************************************************************/
996 
997 static FILE*
Nlm_OpenConfigFile(const Nlm_Char * file,Nlm_Boolean writeMode,Nlm_Boolean create)998 Nlm_OpenConfigFile(const Nlm_Char* file,
999                    Nlm_Boolean writeMode,
1000                    Nlm_Boolean create )
1001 {
1002     Nlm_Char    ch;
1003     Nlm_Char    str [FILENAME_MAX+1];
1004     Nlm_Int2    len;
1005     long        gesResponse;
1006     OSErr       err;
1007     long        dirID, saveDirID;
1008     short       vRefNum, saveVRefNum;
1009     FSSpec      spec;
1010     FILE        *fp = NULL;
1011     int         i;
1012 
1013     if( file == NULL || *file == '\0' ){
1014         return NULL;
1015     }
1016 
1017     /* copy no more than (FILENAME_MAX - 4) to allow for the length of
1018      * our postfix */
1019     Nlm_StringNCpy_0(str, file, sizeof(str) - 4);
1020     if ( ! Nlm_Qualified (str) ) {
1021         /* if the user has already supplied a name with .xxx use that name
1022          * otherwise add the .cnf here */
1023         Nlm_StringCat(str, ".cnf");
1024     }
1025     /* if the name isn't all lowercase, make it so now */
1026     len = (Nlm_Int2) Nlm_StringLen (str);
1027     for (i = 0; i < len; i++) {
1028       ch = str [i];
1029       str [i] = TO_LOWER (ch);
1030     }
1031 
1032     /* convert to pascal string for Mac toolbox */
1033     Nlm_CtoPstr( str);
1034 
1035     /* Make sure we can use FindFolder() if not, then report error and
1036      * return NULL */
1037     if ( Gestalt (gestaltFindFolderAttr, &gesResponse) != noErr ||
1038         (gesResponse & (1 << gestaltFindFolderPresent) == 0)) {
1039         /* notify user of the error */
1040         Nlm_Message(MSG_OK,
1041                     "We need Mac OS 7.0 or newer, continue at your own risk.");
1042         return NULL;
1043     }
1044 
1045     /* store the current active directory */
1046     HGetVol( (StringPtr) 0, &saveVRefNum, &saveDirID);
1047 
1048     /* first look for file in "system", then "preferences".  Only create it
1049      * in prefs if both of those fail... */
1050     err = FindFolder(kOnSystemDisk, kSystemFolderType,
1051                        kDontCreateFolder, &vRefNum, &dirID);
1052     if (err == noErr) {
1053         err = FSMakeFSSpec( vRefNum, dirID, (StringPtr)str, &spec);
1054     }
1055 
1056     if( err != noErr){
1057         /* i.e. file not in "system"
1058          * find the preferences folder in the active System folder */
1059         err = FindFolder(kOnSystemDisk, kPreferencesFolderType,
1060                        kCreateFolder, &vRefNum, &dirID);
1061         if (err == noErr) {
1062             err = FSMakeFSSpec( vRefNum, dirID, (StringPtr)str, &spec);
1063         }
1064     }
1065 
1066     /* convert to back to C string for fopen */
1067     Nlm_PtoCstr( str);
1068 
1069     if( err == noErr){      /* the file is already there */
1070         HSetVol( (StringPtr) 0, vRefNum, dirID);
1071         if (writeMode) {
1072             fp = fopen (str, "w");
1073         } else {
1074             fp = fopen (str, "r");
1075         }
1076         HSetVol( (StringPtr) 0, saveVRefNum, saveDirID);
1077     }
1078     else if( err == fnfErr && create){
1079         /* no file with that name was found, create one */
1080         err = FSpCreate( &spec, '    ', 'TEXT', smSystemScript);
1081         if( err == noErr){
1082             /* set the default directory (same as doing "cd" in unix)
1083              * and actually open the file */
1084             HSetVol( (StringPtr) 0, vRefNum, dirID);
1085             fp = fopen (str, "w");
1086             HSetVol( (StringPtr) 0, saveVRefNum, saveDirID);
1087         }
1088         if( fp == NULL){
1089             Nlm_Message( MSG_OK,
1090                          "Couldn't create the preferences file, "
1091                          "is the boot volume locked?");
1092         }
1093     }
1094   return fp;
1095 }
1096 #endif /* defined(OS_MAC) && !defined(OS_UNIX_DARWIN) */
1097 
1098 #ifdef OS_VMS
1099 /*****************************************************************************
1100 *
1101 *   Nlm_GetHome (buf, buflen)
1102 *      returns the path of the home directory
1103 *
1104 *****************************************************************************/
1105 
Nlm_GetHome(Nlm_Char * buf,Nlm_Int2 buflen)1106 static Nlm_Boolean Nlm_GetHome(Nlm_Char* buf, Nlm_Int2 buflen)
1107 {
1108   Nlm_StringNCpy_0(buf, getenv("SYS$LOGIN"), buflen);
1109   return TRUE;
1110 }
1111 
1112 /*****************************************************************************
1113 *
1114 *   Nlm_OpenConfigFile (file, writeMode, create)
1115 *      returns a file pointer to the specified configuration file.
1116 *      1)  looks in the current directory for "file.cfg", but will not
1117 *          create a new file in this directory.
1118 *      2)  then looks in the home directory for "file.cfg".
1119 *      3)  then looks for an environment variable "NCBI" and takes its
1120 *          value as a complete path to a directory containing the
1121 *          configuration file "file.cfg".
1122 *
1123 *****************************************************************************/
1124 
Nlm_OpenConfigFile(const Nlm_Char * file,Nlm_Boolean writeMode,Nlm_Boolean create)1125 static FILE* Nlm_OpenConfigFile(const Nlm_Char* file, Nlm_Boolean writeMode, Nlm_Boolean create)
1126 
1127 {
1128   Nlm_Char  ch;
1129   FILE      *fp;
1130   Nlm_Int2  i;
1131   Nlm_Int2  len;
1132   FILE      *newfp;
1133   Nlm_Char  path [PATH_MAX+1];
1134   char      *pth;
1135   Nlm_Char  str [FILENAME_MAX+1];
1136 
1137   fp = NULL;
1138 
1139   if (file != NULL) {
1140     newfp = NULL;
1141     Nlm_StringNCpy_0(str, file, sizeof(str) - 4);
1142     if ( ! Nlm_Qualified (str) ) {
1143       Nlm_StringCat (str, ".cfg");
1144     }
1145     len = (Nlm_Int2) Nlm_StringLen (str);
1146     for (i = 0; i < len; i++) {
1147       ch = str [i];
1148       str [i] = TO_LOWER (ch);
1149     }
1150     Nlm_StringNCpy_0(path, str, sizeof(path));
1151 
1152     fp = Ncbienv_FileOpen (path, "r");  /* File exists? */
1153     if (fp == NULL) {
1154       if (Nlm_GetHome (path, sizeof (path))) {
1155         Nlm_FileBuildPath(path, NULL, str);
1156       } else {
1157         Nlm_StringNCpy_0(path, str, sizeof(path));
1158       }
1159       fp = Ncbienv_FileOpen (path, "r");   /* File exists? */
1160       if (fp == NULL && create) {
1161         newfp = Ncbienv_FileOpen (path, "w");
1162         Nlm_FileClose (newfp);
1163         newfp = Ncbienv_FileOpen (path, "r");
1164       }
1165     }
1166 
1167     if (fp == NULL) {
1168       path[0] = '\0';
1169       pth = getenv ("NCBI");
1170       if (pth != NULL) {
1171         Nlm_FileBuildPath(path, pth, str);
1172         fp = Ncbienv_FileOpen (path, "r");
1173       }
1174     }
1175 
1176     if (newfp != NULL) {
1177       if (fp != NULL) {
1178         Nlm_FileClose (newfp);
1179         newfp = NULL;
1180       } else {
1181         fp = newfp;
1182       }
1183     }
1184 
1185     /*
1186     ** On VMS if a file is opened for write a new version is created.
1187     ** This section of code check for "writeMode" and an existing file
1188     ** if both are true.  Get the currently open file's name and delete
1189     ** it.  Open a new one in write mode.
1190     **
1191     ** Side effects: This will replace the highest existing file version,
1192     ** but not older version.  There exists the possibility that a user's
1193     ** custom change may get lost.  A possible workaround for this would
1194     ** be to have the calling program make a new copy (one higher version)
1195     ** of the existing file before doing extensive write to the params
1196     ** file OR keep a static flag in this routine which does  delete the
1197     ** first time time.
1198     */
1199 
1200     if (writeMode && fp != NULL) {
1201       char temp[256];
1202       fgetname(fp,temp);
1203       Nlm_FileClose (fp);
1204       delete(temp);
1205       fp = Ncbienv_FileOpen (path, "w");
1206     }
1207   }
1208   return fp;
1209 }
1210 
1211 #endif /* OS_VMS */
1212 
1213 
1214 /*****************************************************************************
1215 *
1216 *   Nlm_TrimString (str)
1217 *      strips trailing spaces, \r, \n
1218 *
1219 *****************************************************************************/
1220 
Nlm_TrimString(Nlm_Char * str)1221 static Nlm_Char* Nlm_TrimString(Nlm_Char* str)
1222 
1223 {
1224   Nlm_Char   ch;
1225   Nlm_Char*  spc;
1226   Nlm_Char*  tmp;
1227 
1228   if (str != NULL) {
1229     ch = *str;
1230     while (ch == ' ' || ch == '\t') {
1231       str++;
1232       ch = *str;
1233     }
1234     tmp = str;
1235     spc = NULL;
1236     ch = *tmp;
1237     while (ch != '\0' && ch != '\r' && ch != '\n') {
1238       if (ch == ' ' || ch == '\t') {
1239         if (spc == NULL) {
1240           spc = tmp;
1241         }
1242       } else {
1243         spc = NULL;
1244       }
1245       tmp++;
1246       ch = *tmp;
1247     }
1248     *tmp = '\0';
1249     if (spc != NULL) {
1250       *spc = '\0';
1251     }
1252   }
1253   return str;
1254 }
1255 
1256 /*****************************************************************************
1257 *
1258 *   Nlm_ReadConfigFile (fp)
1259 *      reads parameters from configuration file to memory structure
1260 *
1261 *****************************************************************************/
1262 
Nlm_ReadConfigFile(FILE * fp)1263 static Nlm_Boolean Nlm_ReadConfigFile(FILE* fp)
1264 
1265 {
1266   Nlm_Char         ch;
1267   Nlm_env_itemPtr  eip;
1268   Nlm_env_sectPtr  esp;
1269   Nlm_env_itemPtr  lastEip;
1270   Nlm_env_sectPtr  lastEsp;
1271   Nlm_Char*      mid;
1272   Nlm_Char         str [256];
1273   Nlm_Char*      tmp;
1274   Nlm_Char*      comment;
1275 
1276   if (fp != NULL) {
1277     if (Nlm_envList != NULL) {
1278       Nlm_FreeEnvData (Nlm_envList);
1279       Nlm_envList = NULL;
1280     }
1281     esp = NULL;
1282     lastEsp = NULL;
1283     eip = NULL;
1284     lastEip = NULL;
1285     comment = NULL;
1286     while (Nlm_FileGets (str, sizeof (str), fp)) {
1287       ch = *str;
1288       if (ch != '\n' && ch != '\r') {
1289         if (ch == ';') { /* comment */
1290           if (comment == NULL) { /* first comment */
1291              comment = Nlm_StringSave(str);
1292           }
1293           else { /* append to existing comment */
1294              tmp = (Nlm_Char*) Nlm_MemNew(StrLen(comment) + StrLen(str) + 1);
1295              StrCpy(tmp, comment);
1296              StrCat(tmp, str);
1297              comment = (Nlm_Char*) Nlm_MemFree(comment);
1298              comment = tmp;
1299           }
1300         } else if (ch == '[') {
1301           if (esp == NULL) {
1302             esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
1303             lastEsp = esp;
1304             Nlm_envList = esp;
1305           } else {
1306             esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
1307             lastEsp->next = esp;
1308             lastEsp = esp;
1309           }
1310           esp->comment = comment;
1311           comment = NULL;
1312           tmp = str;
1313           ch = *tmp;
1314           while (ch != '\0' && ch != ']') {
1315             tmp++;
1316             ch = *tmp;
1317           }
1318           *tmp = '\0';
1319           esp->name = Nlm_StringSave (str + 1);
1320           eip = NULL;
1321           lastEip = NULL;
1322         } else if (esp != NULL) {
1323           if (eip == NULL) {
1324             eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
1325             lastEip = eip;
1326             esp->children = eip;
1327           } else {
1328             eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
1329             lastEip->next = eip;
1330             lastEip = eip;
1331           }
1332           eip->comment = comment;
1333           comment = NULL;
1334           tmp = str;
1335           mid = str;
1336           ch = *tmp;
1337           while (ch != '\0' && ch != '\n' && ch != '\r') {
1338             if (ch == '=' && mid == str) {
1339               mid = tmp;
1340               *mid++ = '\0';
1341             }
1342             tmp++;
1343             ch = *tmp;
1344           }
1345           *tmp = '\0';
1346           eip->name = Nlm_StringSave (Nlm_TrimString (str));
1347           eip->value = Nlm_StringSave (Nlm_TrimString (mid));
1348         }
1349       }
1350     }
1351 
1352     /* any comments which appeared after the final key of the final section */
1353     Nlm_bottomComment = (Nlm_Char*)Nlm_MemFree(Nlm_bottomComment);
1354     Nlm_bottomComment = comment;
1355   }
1356   return TRUE;
1357 }
1358 
Nlm_FindConfigSection(const Nlm_Char * section)1359 static Nlm_env_sectPtr Nlm_FindConfigSection(const Nlm_Char* section)
1360 {
1361   Nlm_env_sectPtr esp;
1362 
1363   if (section == NULL)
1364     return NULL;
1365 
1366   for (esp = Nlm_envList; esp != NULL; esp = esp->next)
1367   {
1368     if (esp->name != NULL && Nlm_StringICmp(section, esp->name) == 0)
1369        return esp;
1370   }
1371 
1372   return NULL;
1373 }
1374 
1375 /*****************************************************************************
1376 *
1377 *   Nlm_FindConfigItem (section, type, create)
1378 *      finds parameter in memory structure
1379 *
1380 *****************************************************************************/
1381 
Nlm_FindConfigItem(const Nlm_Char * section,const Nlm_Char * type,Nlm_Boolean create)1382 static Nlm_env_itemPtr Nlm_FindConfigItem(const Nlm_Char* section, const Nlm_Char* type, Nlm_Boolean create)
1383 
1384 {
1385   Nlm_env_itemPtr  eip;
1386   Nlm_env_sectPtr  esp;
1387   Nlm_Boolean      goOn;
1388   Nlm_env_itemPtr  lastEip;
1389   Nlm_env_sectPtr  lastEsp;
1390 
1391   eip = NULL;
1392   if (section != NULL && type != NULL) {
1393     goOn = TRUE;
1394     esp = Nlm_envList;
1395     lastEsp = esp;
1396     while (esp != NULL && goOn) {
1397       if (esp->name != NULL && Nlm_StringICmp (section, esp->name) == 0) {
1398         goOn = FALSE;
1399       } else {
1400         lastEsp = esp;
1401         esp = esp->next;
1402       }
1403     }
1404     if (goOn && create) {
1405       if (Nlm_envList != NULL) {
1406         esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
1407         if (esp != NULL) {
1408           esp->name = Nlm_StringSave (section);
1409           lastEsp->next = esp;
1410         }
1411       } else {
1412         esp = (Nlm_env_sectPtr) Nlm_MemNew (sizeof (Nlm_env_sect));
1413         if (esp != NULL) {
1414           esp->name = Nlm_StringSave (section);
1415         }
1416         Nlm_envList = esp;
1417       }
1418     }
1419     if (esp != NULL) {
1420       eip = esp->children;
1421       if (eip != NULL) {
1422         goOn = TRUE;
1423         lastEip = eip;
1424         while (eip != NULL && goOn) {
1425           if (eip->name != NULL && Nlm_StringICmp (type, eip->name) == 0) {
1426             goOn = FALSE;
1427           } else {
1428             lastEip = eip;
1429             eip = eip->next;
1430           }
1431         }
1432         if (goOn && create) {
1433           eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
1434           if (eip != NULL) {
1435             eip->name = Nlm_StringSave (type);
1436             lastEip->next = eip;
1437           }
1438         }
1439       } else if (create) {
1440         eip = (Nlm_env_itemPtr) Nlm_MemNew (sizeof (Nlm_env_item));
1441         if (eip != NULL) {
1442           eip->name = Nlm_StringSave (type);
1443           esp->children = eip;
1444         }
1445       }
1446     }
1447   }
1448   return eip;
1449 }
1450 
1451 /*****************************************************************************
1452 *
1453 *   Nlm_WriteConfigFile (fp)
1454 *      writes parameters to configuration file from memory structure
1455 *
1456 *****************************************************************************/
1457 
Nlm_WriteConfigFile(FILE * fp)1458 static Nlm_Boolean Nlm_WriteConfigFile(FILE* fp)
1459 
1460 {
1461   Nlm_env_itemPtr  eip;
1462   Nlm_env_sectPtr  esp;
1463 
1464   if (Nlm_envList != NULL && fp != NULL) {
1465     esp = Nlm_envList;
1466     while (esp != NULL) {
1467       if (! destroyDeadComments || esp->name != NULL)
1468       {
1469         Nlm_PutComment (esp->comment, fp);
1470       }
1471       if (esp->name != NULL)
1472       {
1473         fputc ('[', fp);
1474         fputs (esp->name, fp);
1475         fputs ("]\n", fp);
1476       }
1477       eip = esp->children;
1478       while (eip != NULL) {
1479         if (! destroyDeadComments)
1480         {
1481           Nlm_PutComment (eip->comment, fp);
1482         }
1483         if (esp->name != NULL && eip->name != NULL && eip->value != NULL) {
1484           if (destroyDeadComments)
1485           {
1486             Nlm_PutComment (eip->comment, fp);
1487           }
1488           fputs (eip->name, fp);
1489           fputc ('=', fp);
1490           fputs (eip->value, fp);
1491           fputc ('\n', fp);
1492         }
1493         eip = eip->next;
1494       }
1495       if (esp->name != NULL)
1496       {
1497         fputc ('\n', fp);
1498       }
1499       esp = esp->next;
1500     }
1501   }
1502 
1503   if (fp != NULL)
1504     Nlm_PutComment(Nlm_bottomComment, fp);
1505 
1506   return TRUE;
1507 }
1508 
1509 /*****************************************************************************
1510 *
1511 *   Nlm_FreeConfigFileData ()
1512 *      frees parameter structure in memory
1513 *
1514 *****************************************************************************/
1515 
Nlm_FreeConfigFileData(void)1516 static void Nlm_FreeConfigFileData(void)
1517 
1518 {
1519   mustCreateFile = TRUE;
1520   Nlm_bottomComment = (Nlm_Char*) Nlm_MemFree(Nlm_bottomComment);
1521   if (Nlm_lastParamFile != NULL)
1522     Nlm_lastParamFile = (Nlm_Char*) Nlm_MemFree(Nlm_lastParamFile);
1523 
1524   if (Nlm_envList != NULL) {
1525     Nlm_FreeEnvData (Nlm_envList);
1526     Nlm_envList = NULL;
1527   }
1528 }
1529 
1530 
1531 /*****************************************************************************
1532 *
1533 *   Nlm_FlushConfigFile()
1534 *      flush the specified file's parameters to disk
1535 *
1536 *****************************************************************************/
1537 
Nlm_FlushConfigFile(const Nlm_Char * file,Nlm_Boolean create)1538 static void Nlm_FlushConfigFile(const Nlm_Char* file, Nlm_Boolean create)
1539 {
1540   FILE* fp;
1541 
1542   if (dirty && file != NULL)
1543   {
1544     fp = Nlm_OpenConfigFile (file, TRUE, create);
1545     if (fp != NULL) {
1546       Nlm_WriteConfigFile (fp);
1547       Nlm_FileClose (fp);
1548     }
1549   }
1550   dirty = FALSE;
1551 }
1552 
1553 /*****************************************************************************
1554 *
1555 *   Nlm_FreeConfigStruct ()
1556 *      frees parameter structure in memory, and perform other cleanup
1557 *
1558 *****************************************************************************/
1559 
Nlm_FreeConfigStruct_ST(void)1560 static void Nlm_FreeConfigStruct_ST(void)
1561 {
1562   Nlm_FlushAppParam();
1563   Nlm_FreeConfigFileData ();
1564   Nlm_FreeTransientData ();
1565 }
1566 
1567 
1568 /*****************************************************************************
1569 *
1570 *   Nlm_PutComment()
1571 *      output a comment to the config file
1572 *
1573 *****************************************************************************/
1574 
Nlm_PutComment(const Nlm_Char * s,FILE * fp)1575 static void Nlm_PutComment(const Nlm_Char* s, FILE* fp)
1576 {
1577   if (s != NULL)
1578     fputs(s, fp);
1579 }
1580 
1581 
1582 /*****************************************************************************
1583 *   Nlm_Qualified ()
1584 *      Appears to check if we've got an n.3 notation sting (i.e. if there is
1585 *       a "." in the last 4 chars of the string passed)
1586 *****************************************************************************/
Nlm_Qualified(const Nlm_Char * path)1587 static Nlm_Boolean Nlm_Qualified( const Nlm_Char* path )
1588 {
1589   Nlm_Int4 l,k;
1590   const Nlm_Char*  p;
1591 
1592   l = Nlm_StrLen(path);
1593   p = path+l;
1594   k = 0;
1595   while (k < l && k <= 4) {
1596      if (*p-- == '.') return TRUE;
1597      k++;
1598   }
1599   return FALSE;
1600 }
1601 
1602 
1603 /*****************************************************************************
1604 *
1605 *   Nlm_FindPath (file, section, type, buf, buflen)
1606 *      finds paths for types of data from configuration files.
1607 *      if configuration file is found, tries to read the parameter from it,
1608 *      then appends a directory delimiter character, if necessary.
1609 *
1610 *****************************************************************************/
1611 
Nlm_FindPath(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,Nlm_Char * buf,Nlm_Int2 buflen)1612 NLM_EXTERN Nlm_Boolean Nlm_FindPath(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, Nlm_Char* buf, Nlm_Int2 buflen)   /* length of path buffer */
1613 {
1614   Nlm_Boolean rsult = FALSE;
1615 
1616   if (file == NULL  ||  section == 0  ||  type == NULL  ||
1617       buf == NULL  ||  buflen <= 0)
1618     return FALSE;
1619 
1620   NlmMutexLockEx( &corelibMutex );
1621 
1622   *buf = '\0';
1623   if (*file != '\0'  &&  *section != '\0'  &&  *type != '\0'  &&
1624       Nlm_GetAppParam(file, section, type, "", buf, buflen - 1)  &&
1625       *buf != '\0')
1626     {
1627       Nlm_FileBuildPath(buf, NULL, NULL);
1628       rsult = TRUE;
1629     }
1630 
1631   NlmMutexUnlock( corelibMutex );
1632   return rsult;
1633 }
1634 
1635 
Nlm_TransientSetAppParam_ST(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * value)1636 static Nlm_Boolean Nlm_TransientSetAppParam_ST(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* value)
1637 {
1638   Nlm_env_filePtr  theFile;
1639   Nlm_env_itemPtr  eip;
1640   Nlm_env_sectPtr  esp;
1641   Nlm_env_itemPtr  nextEip;
1642 
1643   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
1644     return FALSE;
1645 
1646   for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
1647   {
1648     if (StringICmp(theFile->name, file) == 0)
1649     {
1650       for (esp = theFile->envList; esp != NULL; esp = esp->next)
1651       {
1652         if (esp->name != NULL && StringICmp(esp->name, section) == 0)
1653         {
1654           if (type == NULL || type[0] == '\0')
1655           {
1656             /* free all children */
1657             for (eip = esp->children; eip != NULL; eip = nextEip)
1658             {
1659               nextEip = eip->next;
1660               eip->next    = (Nlm_env_itemPtr)(-1);
1661               eip->name    = (Nlm_Char*) Nlm_MemFree (eip->name);
1662               eip->comment = (Nlm_Char*) Nlm_MemFree (eip->comment);
1663               eip->value   = (Nlm_Char*) Nlm_MemFree (eip->value);
1664               Nlm_MemFree (eip);
1665             }
1666             esp->children = NULL;
1667             esp->transientOnly = TRUE;
1668           } else { /* append this type to the section */
1669             eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
1670             eip->name = StringSave(type);
1671             eip->value = StringSave(value);
1672             eip->next = esp->children;
1673             esp->children = eip;
1674           }
1675           return TRUE;
1676         }
1677       }
1678       break;
1679     }
1680   }
1681 
1682   /* create the file data structure if needed */
1683   if (theFile == NULL)
1684   {
1685     theFile = (Nlm_env_filePtr) MemNew(sizeof(*theFile));
1686     theFile->name = StringSave(file);
1687     theFile->next = Nlm_transientFileList;
1688     Nlm_transientFileList = theFile;
1689   }
1690 
1691   /* create the section and type */
1692   esp = (Nlm_env_sectPtr) MemNew(sizeof(*esp));
1693   esp->name = StringSave(section);
1694   esp->next = theFile->envList;
1695   theFile->envList = esp;
1696   if (type == NULL || type[0] == '\0')
1697   {
1698     esp->transientOnly = TRUE;
1699   } else { /* create the section */
1700     esp->transientOnly = FALSE;
1701     eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
1702     eip->name = StringSave(type);
1703     eip->value = StringSave(value);
1704     eip->next = NULL;
1705     esp->children = eip;
1706   }
1707 
1708   return TRUE;
1709 }
1710 
1711 
1712 /* SetAppParam is writing a value to the real config file, so log this value,
1713    if necessary, into the "transient" data structures */
Nlm_TransientLogSetApp(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * value)1714 static void Nlm_TransientLogSetApp(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* value)
1715 
1716 {
1717   Nlm_env_filePtr  theFile;
1718   Nlm_env_itemPtr  eip;
1719   Nlm_env_sectPtr  esp;
1720 
1721   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
1722     return;
1723 
1724   if (type == NULL || type[0] == '\0')
1725   {
1726     for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
1727     {
1728       if (StringICmp(theFile->name, file) == 0)
1729       {
1730         for (esp = theFile->envList; esp != NULL; esp = esp->next)
1731         {
1732           if (esp->name != NULL && StringICmp(esp->name, section) == 0)
1733           { /* delete the section by removing section name */
1734             esp->name = (Nlm_Char*) MemFree(esp->name);
1735           }
1736         }
1737       }
1738     }
1739   } else {
1740     for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
1741     {
1742       if (StringICmp(theFile->name, file) == 0)
1743       {
1744         for (esp = theFile->envList; esp != NULL; esp = esp->next)
1745         {
1746           if (esp->name != NULL && StringICmp(esp->name, section) == 0 &&
1747               esp->transientOnly)
1748           { /* append this type to the section */
1749             eip = (Nlm_env_itemPtr) MemNew(sizeof(*eip));
1750             eip->name = StringSave(type);
1751             eip->value = StringSave(value);
1752             eip->next = esp->children;
1753             esp->children = eip;
1754           }
1755         }
1756       }
1757     }
1758   }
1759 }
1760 
Nlm_TransientLookup(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * dflt,Nlm_Char * buf,size_t buflen)1761 static Nlm_Boolean Nlm_TransientLookup(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* dflt, Nlm_Char* buf, size_t buflen)
1762 {
1763   Nlm_env_filePtr  theFile;
1764   Nlm_env_itemPtr  eip;
1765   Nlm_env_sectPtr  esp;
1766   Nlm_Int4         totlen;
1767   Nlm_Int4         bytesToAppend;
1768 
1769   if (file == NULL || *file == '\0' || section == NULL || *section == '\0')
1770     return FALSE;
1771 
1772   for (theFile = Nlm_transientFileList; theFile != NULL; theFile = theFile->next)
1773   {
1774     if (StringICmp(theFile->name, file) == 0)
1775     {
1776       for (esp = theFile->envList; esp != NULL; esp = esp->next)
1777       {
1778         if (esp->name != NULL && StringICmp(esp->name, section) == 0)
1779         {
1780           if (type == NULL || type[0] == '\0')
1781           { /* concatenate all types (keys) within section */
1782             *buf = '\0';
1783             totlen = 0;
1784             for (eip = esp->children; eip != NULL; eip = eip->next)
1785             {
1786               bytesToAppend = StrLen(eip->name) + 1;
1787               bytesToAppend = MIN(bytesToAppend, (Nlm_Int4)buflen - totlen);
1788               StrNCpy(&buf[totlen], eip->name, bytesToAppend);
1789               totlen += bytesToAppend;
1790             }
1791             if (totlen > 0 && buf[totlen] == '\0')
1792             {
1793                 totlen--; /* account for final null character */
1794             }
1795             /* now append the GetAppParam() data */
1796             if (! esp->transientOnly)
1797             { /* GetAppParam data can be trusted ... append it to buf */
1798               Nlm_WorkGetAppParam(file, section, NULL, "", &buf[totlen],
1799                                   (Nlm_Int2)(buflen - totlen), FALSE);
1800             }
1801             return TRUE;
1802           } else {
1803             for (eip = esp->children; eip != NULL; eip = eip->next)
1804             {
1805               if (StringICmp(eip->name, type) == 0)
1806               {
1807                 Nlm_StringNCpy_0(buf, eip->value, buflen);
1808                 return TRUE;
1809               }
1810             }
1811             if (esp->transientOnly)
1812             { /* GetAppParam data cannot be trusted ... use the default */
1813               Nlm_StringNCpy_0(buf, dflt, buflen);
1814               return TRUE;
1815             }
1816           }
1817         }
1818       }
1819     }
1820   }
1821 
1822   /* not found ... GetAppParam() should search the real config file */
1823   return FALSE;
1824 }
1825 
Nlm_FreeEnvData(Nlm_env_sectPtr esp)1826 static void Nlm_FreeEnvData(Nlm_env_sectPtr esp)
1827 
1828 {
1829   Nlm_env_itemPtr  eip;
1830   Nlm_env_itemPtr  nextEip;
1831   Nlm_env_sectPtr  nextEsp;
1832 
1833   while (esp != NULL) {
1834     nextEsp = esp->next;
1835     eip = esp->children;
1836     while (eip != NULL) {
1837       nextEip = eip->next;
1838       eip->next    = (Nlm_env_itemPtr)(-1);
1839       eip->name    = (Nlm_Char*) Nlm_MemFree (eip->name);
1840       eip->comment = (Nlm_Char*) Nlm_MemFree (eip->comment);
1841       eip->value   = (Nlm_Char*) Nlm_MemFree (eip->value);
1842       Nlm_MemFree (eip);
1843       eip = nextEip;
1844     }
1845     esp->next    = (Nlm_env_sectPtr)(-1);
1846     esp->name    = (Nlm_Char*) Nlm_MemFree (esp->name);
1847     esp->comment = (Nlm_Char*) Nlm_MemFree (esp->comment);
1848     Nlm_MemFree (esp);
1849     esp = nextEsp;
1850   }
1851 }
1852 
1853 
Nlm_FreeTransientData(void)1854 static void Nlm_FreeTransientData(void)
1855 {
1856   Nlm_env_filePtr efp, nextEfp;
1857 
1858   efp = Nlm_transientFileList;
1859   while (efp != NULL) {
1860     nextEfp = efp->next;
1861     Nlm_FreeEnvData (efp->envList);
1862     efp->envList = NULL;
1863     efp->next = (Nlm_env_filePtr)(-1);
1864     efp->name = (Nlm_Char*) Nlm_MemFree (efp->name);
1865     Nlm_MemFree (efp);
1866     efp = nextEfp;
1867   }
1868   Nlm_transientFileList = NULL;
1869 }
1870 
1871 
1872 
Nlm_GetEnvParamEx(const Nlm_Char * conf_file,const Nlm_Char * conf_section,const Nlm_Char * env_name,const Nlm_Char * conf_name,Nlm_Char * buf,size_t bufsize,const Nlm_Char * dflt)1873 extern size_t Nlm_GetEnvParamEx
1874 (const Nlm_Char* conf_file, const Nlm_Char* conf_section,
1875  const Nlm_Char* env_name, const Nlm_Char* conf_name,
1876  Nlm_Char* buf, size_t bufsize, const Nlm_Char* dflt)
1877 {
1878   static const Nlm_Char s_DefConfigFile   [] = "ncbi";
1879   static const Nlm_Char s_DefConfigSection[] = "NCBI";
1880 
1881   size_t len = 0;
1882   ASSERT ( (env_name  &&  *env_name)  ||  (conf_name  &&  *conf_name) );
1883   ASSERT ( buf  &&  bufsize );
1884   buf[0] = '\0';
1885 
1886   /* arg fallbacks */
1887   if (conf_name  &&  *conf_name) {
1888     if ( !conf_file )
1889       conf_file = s_DefConfigFile;
1890     if ( !conf_section )
1891       conf_section = s_DefConfigSection;
1892   }
1893 
1894   /* Search in the list of transient parameters */
1895   if (conf_name  &&  *conf_name  &&
1896       Nlm_TransientLookup(conf_file, conf_section, conf_name,
1897                           dflt, buf, bufsize)) {
1898     return Nlm_StrLen(buf);
1899   }
1900 
1901   /* Fetch from the environment variable */
1902 #if defined(OS_UNIX) || defined(OS_MSWIN)
1903   if (env_name  &&  *env_name) {
1904     const Nlm_Char* str = getenv(env_name);
1905     if (str  &&  *str) {
1906       len = Nlm_StrLen(str);
1907       if (len >= bufsize)
1908         len = 0;
1909       else
1910         Nlm_StrCpy(buf, str);
1911     }
1912   }
1913 #endif
1914 
1915   /* Search in the configuration file */
1916   if (!len  &&  conf_name  &&  *conf_name) {
1917     len = GetAppParam(conf_file, conf_section, conf_name, dflt, buf,
1918                       bufsize < INT2_MAX ? (Nlm_Int2) bufsize : INT2_MAX);
1919   }
1920 
1921   /* Store the value in the transient parameter list */
1922   ASSERT(len == Nlm_StrLen(buf));
1923   if ( len )
1924     VERIFY(Nlm_TransientSetAppParam(conf_file, conf_section, conf_name, buf));
1925 
1926   return len;
1927 }
1928 
1929 
Nlm_GetEnvParam(const Nlm_Char * conf_file,const Nlm_Char * conf_section,const Nlm_Char * env_conf_name,Nlm_Char * buf,size_t bufsize,const Nlm_Char * dflt)1930 NLM_EXTERN size_t Nlm_GetEnvParam
1931 (const Nlm_Char* conf_file, const Nlm_Char* conf_section,
1932  const Nlm_Char* env_conf_name,
1933  Nlm_Char* buf, size_t bufsize, const Nlm_Char* dflt)
1934 {
1935   return Nlm_GetEnvParamEx(conf_file, conf_section,
1936                            env_conf_name, env_conf_name,
1937                            buf, bufsize, dflt);
1938 }
1939 
1940 
1941 
1942 /*****************************************************************************
1943 *
1944 *   Command-line arguments
1945 *     &
1946 *   Nlm_ProgramPath (buf, maxsize)
1947 *   	returns full path to executing program
1948 *
1949 *****************************************************************************/
1950 
1951 static Nlm_Boolean wasSetup = FALSE;
1952 static int    targc = 0;
1953 static char **targv = NULL;
1954 
1955 
1956 #if defined(WIN_MAC) || defined(OS_UNIX_DARWIN)
1957 static FSSpec       apFileSpec;
1958 static Str255       apName;
1959 static Handle       apParam;
1960 static short        apRefNum;
1961 
Nlm_SetupArguments_ST_Mac(void)1962 static Nlm_Boolean Nlm_SetupArguments_ST_Mac(void)
1963 {
1964 #ifndef __GNUC__
1965 /* At least in 10.1, this seems to introduce an unwanted dep. on Carbon. */
1966   ProcessInfoRec       pirec;
1967   ProcessSerialNumber  psn;
1968 
1969   GetCurrentProcess (&psn);
1970   pirec.processInfoLength = sizeof (ProcessInfoRec);
1971   pirec.processName = apName;
1972   pirec.processAppSpec = &apFileSpec;
1973   GetProcessInformation (&psn, &pirec);
1974   Nlm_PtoCstr ((Nlm_Char*) apFileSpec.name);
1975   Nlm_PtoCstr ((Nlm_Char*) apName);
1976 
1977   SetProgramName(apName);
1978 #endif
1979   return TRUE;
1980 }
1981 
1982 #if defined(OS_UNIX_DARWIN)
1983 /* this requires the CoreFoundation framework, but nothing more. */
Nlm_ProgramPath_ST(Nlm_Char * appPath,size_t pathSize)1984 static void Nlm_ProgramPath_ST(Nlm_Char* appPath, size_t pathSize)
1985 {
1986   CFBundleRef thisBundle;
1987   CFURLRef    thisURL;
1988   int        pathsuffix_pos;
1989   static const char* appsuffix = ".app";
1990 
1991   thisBundle = CFBundleGetMainBundle();
1992   if (thisBundle == NULL)
1993     return;
1994 
1995   thisURL = CFBundleCopyBundleURL(thisBundle);
1996   if (thisURL == NULL) return;
1997   if (!CFURLGetFileSystemRepresentation( thisURL, true, (UInt8 *) appPath, pathSize)) {
1998         return;
1999   }
2000   /* Does this path end with the .app suffix? */
2001   pathsuffix_pos = strlen(appPath) - strlen(appsuffix);
2002   if (pathsuffix_pos > 0  &&
2003       0 == Nlm_StrICmp(appPath + pathsuffix_pos, appsuffix) ) {
2004       /* this is a bundled app. */
2005       return;
2006   }
2007 
2008   /* this is not a bundled app. The above got me my directory. */
2009   thisURL = CFBundleCopyExecutableURL(thisBundle);
2010   if (thisURL == NULL)
2011     return;
2012   CFURLGetFileSystemRepresentation( thisURL, true, (UInt8 *) appPath, pathSize);
2013 }
2014 
2015 /*
2016   is the application at filePath actually a application bundle/package?
2017   i.e. a folder containing subfolders, resource files and the actual executable.
2018   Pass the value returned by ProgramPath for best results.
2019 */
Nlm_IsApplicationPackage(char * filePath)2020 NLM_EXTERN Nlm_Boolean Nlm_IsApplicationPackage(char *filePath)
2021 {
2022     OSErr   err;
2023     char    aPath[1024];
2024     FSRef   contentsFRef;
2025     Boolean isDirectory;
2026 
2027     StrCpy(aPath, filePath);
2028     FileBuildPath(aPath, "Contents", NULL);
2029     err = FSPathMakeRef ((unsigned char *) aPath, &contentsFRef, &isDirectory);
2030     if (err == noErr  &&  isDirectory) {
2031         return TRUE;
2032     }
2033     /* else gets err == -120, no such directory. */
2034     return FALSE;
2035 }
2036 
2037 #else
Nlm_ProgramPath_ST(Nlm_Char * buf,size_t maxsize)2038 static void Nlm_ProgramPath_ST(Nlm_Char* buf, size_t maxsize)
2039 {
2040   CInfoPBRec  block;
2041   Nlm_Char    path [256];
2042   Nlm_Char    temp [256];
2043   short nErr;
2044 
2045   if (buf != NULL && maxsize > 0) {
2046     *buf = '\0';
2047     if (wasSetup) {
2048       memset (&block, 0, sizeof (CInfoPBRec));
2049       Nlm_StringNCpy_0(path, (Nlm_Char*)apFileSpec.name, sizeof (path));
2050 
2051       block.dirInfo.ioNamePtr = (StringPtr) path;
2052       block.dirInfo.ioDrParID = apFileSpec.parID;
2053 
2054       do {
2055         Nlm_StringCpy (temp, path);
2056         block.dirInfo.ioVRefNum = apFileSpec.vRefNum;
2057         block.dirInfo.ioFDirIndex = -1;
2058         block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
2059         nErr = PBGetCatInfo (&block, FALSE);
2060         if (nErr != noErr) break;
2061         Nlm_PtoCstr ((Nlm_Char*) path);
2062         Nlm_StringCat (path, DIRDELIMSTR);
2063         Nlm_StringCat (path, temp);
2064       } while (block.dirInfo.ioDrDirID != fsRtDirID);
2065 
2066       Nlm_StringNCpy_0(buf, path, maxsize);
2067     }
2068   }
2069 }
2070 #endif /* defined(OS_UNIX_DARWIN) */
2071 #endif /* defined(WIN_MAC) || defined(OS_UNIX_DARWIN) */
2072 
2073 
2074 #if defined(OS_MSWIN) || defined(OS_VMS)
Nlm_ProgramPath_ST(Nlm_Char * buf,size_t maxsize)2075 static void Nlm_ProgramPath_ST(Nlm_Char* buf, size_t maxsize)
2076 {
2077   if (!buf  ||  maxsize <= 0)
2078     return;
2079 
2080   *buf = '\0';
2081   if (wasSetup  &&  targv  &&  targv[0])
2082     Nlm_StringNCpy_0(buf, targv[0], maxsize);
2083 }
2084 #endif  /* OS_MSWIN || OS_VMS */
2085 
2086 
2087 #if defined(OS_UNIX)  &&  !defined(OS_UNIX_DARWIN)
Nlm_ProgramPath_ST(Nlm_Char * buf,size_t maxsize)2088 static void Nlm_ProgramPath_ST(Nlm_Char* buf, size_t maxsize)
2089 {
2090   Nlm_Char     path [PATH_MAX];
2091   Nlm_Char*  pth;
2092   Nlm_Char*  ptr;
2093 
2094   if (buf != NULL && maxsize > 0) {
2095     *buf = '\0';
2096     if (wasSetup) {
2097       ptr = targv [0];
2098       if (ptr [0] == DIRDELIMCHR) {
2099         Nlm_StringNCpy_0(buf, targv[0], maxsize);
2100       } else if (getcwd (path, sizeof (path)) != NULL) {
2101         ptr = targv [0];
2102         while (ptr [0] == '.' || ptr [0] == DIRDELIMCHR) {
2103           if (ptr [0] == '.') {
2104             if (ptr [1] == '.' && ptr [2] == DIRDELIMCHR) {
2105               ptr += 3;
2106               pth = StringRChr (path, DIRDELIMCHR);
2107               if (pth != NULL) {
2108                 *pth = '\0';
2109               }
2110             } else if (ptr [1] == DIRDELIMCHR) {
2111               ptr += 2;
2112             } else {
2113               ptr++;
2114             }
2115           } else if (ptr [0] == DIRDELIMCHR) {
2116             ptr++;
2117           } else {
2118             ptr++;
2119           }
2120         }
2121         FileBuildPath (path, NULL, ptr);
2122         Nlm_StringNCpy_0(buf, path, maxsize);
2123       } else {
2124         Nlm_StringNCpy_0(buf, targv[0], maxsize);
2125       }
2126     }
2127   }
2128 }
2129 #endif
2130 
2131 
2132 /*****************************************************************************
2133 * Multi-Thread protected external functions
2134 *****************************************************************************/
2135 
Nlm_TransientSetAppParam(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * value)2136 NLM_EXTERN Nlm_Boolean Nlm_TransientSetAppParam(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* value)
2137 {
2138   Nlm_Boolean rsult;
2139   NlmMutexLockEx( &corelibMutex );
2140 
2141   rsult = Nlm_TransientSetAppParam_ST(file, section, type, value);
2142 
2143   NlmMutexUnlock( corelibMutex );
2144   return rsult;
2145 }
2146 
Nlm_FreeConfigStruct(void)2147 NLM_EXTERN void Nlm_FreeConfigStruct(void)
2148 {
2149   NlmMutexLockEx( &corelibMutex );
2150   Nlm_FreeConfigStruct_ST();
2151   NlmMutexUnlock( corelibMutex );
2152 }
2153 
2154 
Nlm_ParseCmdLineArguments(const char * prog_name,const char * cmd_line,int * argc_ptr,char *** argv_ptr,ECmdLineQuote quote_handling)2155 NLM_EXTERN Nlm_Boolean Nlm_ParseCmdLineArguments
2156 (const char* prog_name, const char* cmd_line, int* argc_ptr, char*** argv_ptr,
2157  ECmdLineQuote quote_handling)
2158 {
2159   char*  str;
2160   char*  p;
2161   int    xx_argc;
2162   char** xx_argv;
2163 
2164   /* Check args */
2165   if (!argc_ptr  ||  !argv_ptr)
2166     return FALSE;
2167 
2168   /* Figure out program name */
2169   if (!prog_name  &&  !(prog_name = GetProgramName()))
2170      prog_name = "";
2171 
2172   /* Special case -- no cmd.-line parameters */
2173   if ( cmd_line ) {
2174     const char* sss;
2175     for (sss = cmd_line;  *sss  &&  isspace(*sss);  sss++) continue;
2176     if ( !*sss )
2177       cmd_line = 0;
2178   }
2179   if ( !cmd_line ) {
2180     *argc_ptr = 1;
2181     *argv_ptr = (char**) Nlm_MemNew(2 * sizeof(char*));
2182     (*argv_ptr[0]) = Nlm_StringSave(prog_name);
2183     return TRUE;
2184   }
2185 
2186   /* Allocate string to hold "argv[]" values and fill it with
2187    * the program name and the command string */
2188   {{
2189     size_t size = strlen(prog_name) + strlen(cmd_line) + 2;
2190     str = (char*) Nlm_MemNew(size);
2191 
2192     StrCpy(str, prog_name);
2193     StrCpy(str + strlen(prog_name) + 1, cmd_line);
2194   }}
2195 
2196   /* Count command-line arguments and separate them by '\0' */
2197   xx_argc = 1;
2198   for (p = str + strlen(prog_name) + 1;  *p; ) {
2199     if ( isspace(*p) ) {
2200       *p++ = '\0';
2201       continue;
2202     }
2203 
2204     if (quote_handling == eProcessQuotes  &&  (*p == '\''  ||  *p == '"')) {
2205       char quote = *p;
2206       xx_argc++;
2207       while (*(++p)  &&  *p != quote) continue;
2208       if ( *p )
2209         *p++ = '\0';
2210       continue;
2211     }
2212 
2213     xx_argc++;
2214     while (*p  &&  !isspace(*p))
2215       p++;
2216   }
2217 
2218   /* Allocate and fill out "xx_argv" */
2219   {{
2220     int   n = 1;
2221     char *s = str + strlen(prog_name) + 1;
2222     xx_argv = (char**) Nlm_MemNew((xx_argc + 1) * sizeof(char*));
2223     xx_argv[0] = str;
2224     while (n < xx_argc) {
2225       while ( !*s )
2226         s++;
2227       if (quote_handling == eProcessQuotes  &&  (*s == '\''  ||  *s == '"'))
2228         s++; /* -- skip the leading quote */
2229       xx_argv[n++] = s;
2230       while ( *s )
2231         s++;
2232     }
2233     xx_argv[n] = 0;
2234 #ifdef _DEBUG
2235     while (s < p  &&  !*s)
2236       s++;
2237     ASSERT ( s == p );
2238 #endif
2239   }}
2240 
2241   *argc_ptr = xx_argc;
2242   *argv_ptr = xx_argv;
2243   return TRUE;
2244 }
2245 
2246 
Nlm_FreeCmdLineArguments(char ** argv)2247 NLM_EXTERN void Nlm_FreeCmdLineArguments(char** argv)
2248 {
2249   if ( !argv )
2250     return;
2251 
2252   ASSERT( argv[0] );
2253   Nlm_MemFree( argv[0] );
2254   Nlm_MemFree( argv );
2255 }
2256 
2257 
Nlm_SetupArguments(int argc,char * argv[])2258 NLM_EXTERN void Nlm_SetupArguments(int argc, char *argv[])
2259 {
2260   NlmMutexLockEx( &corelibMutex );
2261   wasSetup = TRUE;
2262 #if defined(WIN_MAC) || defined(OS_UNIX_DARWIN)
2263   wasSetup = Nlm_SetupArguments_ST_Mac();
2264 #elif defined(OS_UNIX)
2265   {{
2266     char *p;
2267     if ((p = strrchr(argv[0],DIRDELIMCHR)) != NULL)
2268       p++;
2269     else
2270       p = argv[0];
2271     SetProgramName(p);
2272   }}
2273 #endif
2274   targc = argc;
2275   targv = argv;
2276   NlmMutexUnlock( corelibMutex );
2277 }
2278 
Nlm_GetArgv(void)2279 NLM_EXTERN Nlm_Char** Nlm_GetArgv(void)
2280 {
2281   return targv;
2282 }
2283 
Nlm_GetArgc(void)2284 NLM_EXTERN Nlm_Int4 Nlm_GetArgc(void)
2285 {
2286   return targc;
2287 }
2288 
Nlm_ProgramPath(Nlm_Char * buf,size_t maxsize)2289 NLM_EXTERN void Nlm_ProgramPath(Nlm_Char* buf, size_t maxsize)
2290 {
2291   NlmMutexLockEx( &corelibMutex );
2292   Nlm_ProgramPath_ST(buf, maxsize);
2293   NlmMutexUnlock( corelibMutex );
2294 }
2295 
Nlm_FlushAppParam(void)2296 NLM_EXTERN void Nlm_FlushAppParam(void)
2297 {
2298   NlmMutexLockEx( &corelibMutex );
2299   Nlm_FlushAppParam_ST();
2300   NlmMutexUnlock( corelibMutex );
2301 }
2302 
Nlm_CacheAppParam(Nlm_Boolean value)2303 NLM_EXTERN Nlm_Boolean Nlm_CacheAppParam(Nlm_Boolean value)
2304 {
2305   Nlm_Boolean rsult;
2306   NlmMutexLockEx( &corelibMutex );
2307 
2308   rsult = Nlm_CacheAppParam_ST( value );
2309 
2310   NlmMutexUnlock( corelibMutex );
2311   return rsult;
2312 }
2313 
Nlm_GetAppParam(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * dflt,Nlm_Char * buf,Nlm_Int2 buflen)2314 NLM_EXTERN Nlm_Int2 Nlm_GetAppParam(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* dflt, Nlm_Char* buf, Nlm_Int2 buflen)
2315 {
2316   Nlm_Int2 rsult;
2317   NlmMutexLockEx( &corelibMutex );
2318 
2319   rsult = Nlm_WorkGetAppParam(file, section, type, dflt, buf, buflen, TRUE);
2320 
2321   NlmMutexUnlock( corelibMutex );
2322   return rsult;
2323 }
2324 
Nlm_SetAppParam(const Nlm_Char * file,const Nlm_Char * section,const Nlm_Char * type,const Nlm_Char * value)2325 NLM_EXTERN Nlm_Boolean Nlm_SetAppParam(const Nlm_Char* file, const Nlm_Char* section, const Nlm_Char* type, const Nlm_Char* value)
2326 {
2327   Nlm_Boolean rsult;
2328   NlmMutexLockEx( &corelibMutex );
2329 
2330   rsult = Nlm_SetAppParam_ST(file, section, type, value);
2331 
2332   NlmMutexUnlock( corelibMutex );
2333   return rsult;
2334 }
2335 
2336 
2337 /*****************************************************************************
2338 *
2339 *   GetAppParamBoolean()
2340 *       SetAppParamBoolean()
2341 *   GetAppParamLong()
2342 *       SetAppParamLong()
2343 *
2344 *****************************************************************************/
2345 
GetAppParamBoolean(const Nlm_Char * filebase,const Nlm_Char * sect,const Nlm_Char * key,Nlm_Boolean dflt)2346 NLM_EXTERN Nlm_Boolean GetAppParamBoolean
2347 (const Nlm_Char* filebase, const Nlm_Char* sect, const Nlm_Char* key,
2348  Nlm_Boolean dflt)
2349 {
2350   Nlm_Char buffer[32];
2351   if ( GetAppParam(filebase, sect, key, "", buffer, sizeof(buffer)) ) {
2352     if (strchr("1yYtT",buffer[0]))
2353       return TRUE;
2354     if (strchr("0nNfF",buffer[0]))
2355       return FALSE;
2356   }
2357   return dflt;
2358 }
2359 
SetAppParamBoolean(const Nlm_Char * filebase,const Nlm_Char * sect,const Nlm_Char * key,Nlm_Boolean value)2360 NLM_EXTERN Nlm_Boolean SetAppParamBoolean
2361 (const Nlm_Char* filebase, const Nlm_Char* sect, const Nlm_Char* key,
2362  Nlm_Boolean value)
2363 {
2364   return SetAppParam(filebase, sect, key, value ? "Yes" : "No");
2365 }
2366 
GetAppParamLong(const Nlm_Char * filebase,const Nlm_Char * sect,const Nlm_Char * key,long dflt)2367 NLM_EXTERN long GetAppParamLong(const Nlm_Char* filebase, const Nlm_Char* sect,
2368                                 const Nlm_Char* key, long dflt)
2369 {
2370   Nlm_Char buffer[32];
2371   return GetAppParam(filebase, sect, key, "", buffer, sizeof(buffer)) ?
2372     atol(buffer) : dflt;
2373 }
2374 
SetAppParamLong(const Nlm_Char * filebase,const Nlm_Char * sect,const Nlm_Char * key,long value)2375 NLM_EXTERN Nlm_Boolean SetAppParamLong
2376 (const Nlm_Char* filebase, const Nlm_Char* sect, const Nlm_Char* key,
2377  long value)
2378 {
2379 	char buffer[32];
2380 	sprintf(buffer,"%ld",value);
2381 	return SetAppParam((char*)filebase,(char*)sect,(char*)key,buffer);
2382 }
2383 
2384 
2385 #ifdef WIN32
Nlm_x_HasConsole(void)2386 extern int Nlm_x_HasConsole(void)
2387 {
2388   static int has_console = -1;
2389   if (has_console == -1)
2390     has_console = fileno(stdin) >= 0 ? 1 : 0;
2391 
2392   return has_console;
2393 }
2394 #endif
2395 
2396 
Nlm_FreeArgs(Nlm_Int2 numargs,Nlm_ArgPtr ap)2397 NLM_EXTERN Nlm_Boolean Nlm_FreeArgs(Nlm_Int2 numargs, Nlm_ArgPtr ap)
2398 {
2399   Nlm_Int2 i;
2400   for (i = 0;  i < numargs;  i++, ap++)
2401     {
2402       switch ( ap->type )
2403         {
2404         case ARG_BOOLEAN:
2405           ap->intvalue = 0;
2406           break;
2407         case ARG_INT:
2408           ap->intvalue = 0;
2409           break;
2410         case ARG_FLOAT:
2411           ap->floatvalue = 0.0;
2412           break;
2413         case ARG_STRING:
2414         case ARG_FILE_IN:
2415         case ARG_FILE_OUT:
2416         case ARG_DATA_IN:
2417         case ARG_DATA_OUT:
2418           ap->strvalue = (Nlm_Char*) Nlm_MemFree( ap->strvalue );
2419           break;
2420         default:
2421           ASSERT ( FALSE );
2422           return FALSE;
2423         }
2424     }
2425   return TRUE;
2426 }
2427 
2428 #ifdef OS_UNIX_DARWIN
2429 #include <sys/sysctl.h>
2430 #endif
2431 
Nlm_GetOpSysString(void)2432 NLM_EXTERN Nlm_CharPtr Nlm_GetOpSysString (void)
2433 
2434 {
2435 #ifdef OS_UNIX_DARWIN
2436 #ifdef PROC_PPC
2437   Nlm_Boolean  isRosetta = FALSE;
2438   size_t       len;
2439   int          mib [2];
2440   Nlm_Char     model [32];
2441 #endif
2442   Nlm_Int4     sysVer;
2443 #endif
2444   Nlm_CharPtr  str = "unknown";
2445 
2446 #if defined(OS_MAC) && !defined(OS_UNIX_DARWIN)
2447   long  sysVer;
2448 
2449   if ( Gestalt (gestaltSystemVersion, &sysVer) == noErr) {
2450     /* system version in low order word is hexadecimal */
2451     if (sysVer >= 4096) {
2452       str = "MAC Carbon on OS X";
2453     } else if (sysVer >= 2304) {
2454       str = "MAC Carbon on OS 9";
2455     } else {
2456       str = "MAC Carbon on OS 8";
2457     }
2458   }
2459 #endif
2460 
2461 #ifdef OS_UNIX
2462   /* initial nonspecific UNIX string */
2463   str = "UNIX";
2464 
2465 #ifdef OS_UNIX_DARWIN
2466 #ifdef PROC_PPC
2467   mib [0] = CTL_HW;
2468   mib [1] = HW_MODEL;
2469   len = sizeof (model);
2470   if (sysctl (mib, 2, &model, &len, NULL, 0) == 0) {
2471     isRosetta = (Nlm_Boolean) (len == 9 && strcmp (model, "PowerMac") == 0);
2472   }
2473   if (isRosetta) {
2474     str = "MAC Rosetta on OS X";
2475     if ( Gestalt (gestaltSystemVersion, &sysVer) == noErr) {
2476       if (sysVer >= 4192) {
2477         str = "MAC Rosetta on OS 10.6";
2478       } else if (sysVer >= 4176) {
2479         str = "MAC Rosetta on OS 10.5";
2480       } else if (sysVer >= 4160) {
2481         str = "MAC Rosetta on OS 10.4";
2482       } else if (sysVer >= 4144) {
2483         str = "MAC Rosetta on OS 10.3";
2484       } else if (sysVer >= 4128) {
2485         str = "MAC Rosetta on OS 10.2";
2486       } else if (sysVer >= 4112) {
2487         str = "MAC Rosetta on OS 10.1";
2488       } else {
2489         str = "MAC Rosetta on OS X";
2490       }
2491     }
2492   } else {
2493     str = "MAC PPC on OS X";
2494     if ( Gestalt (gestaltSystemVersion, &sysVer) == noErr) {
2495       if (sysVer >= 4192) {
2496         str = "MAC PPC on OS 10.6";
2497       } else if (sysVer >= 4176) {
2498         str = "MAC PPC on OS 10.5";
2499       } else if (sysVer >= 4160) {
2500         str = "MAC PPC on OS 10.4";
2501       } else if (sysVer >= 4144) {
2502         str = "MAC PPC on OS 10.3";
2503       } else if (sysVer >= 4128) {
2504         str = "MAC PPC on OS 10.2";
2505       } else if (sysVer >= 4112) {
2506         str = "MAC PPC on OS 10.1";
2507       } else {
2508         str = "MAC PPC on OS X";
2509       }
2510     }
2511   }
2512 #else
2513 #ifdef PROC_I80X86
2514   str = "MAC 386 on OS X";
2515   if ( Gestalt (gestaltSystemVersion, &sysVer) == noErr) {
2516     if (sysVer >= 4192) {
2517       str = "MAC 386 on OS 10.6";
2518     } else if (sysVer >= 4176) {
2519       str = "MAC 386 on OS 10.5";
2520     } else if (sysVer >= 4160) {
2521       str = "MAC 386 on OS 10.4";
2522     } else if (sysVer >= 4144) {
2523       str = "MAC 386 on OS 10.3";
2524     } else if (sysVer >= 4128) {
2525       str = "MAC 386 on OS 10.2";
2526     } else if (sysVer >= 4112) {
2527       str = "MAC 386 on OS 10.1";
2528     } else {
2529       str = "MAC 386 on OS X";
2530     }
2531   }
2532 #else
2533   str = "MAC UNIX on OS X";
2534 #endif
2535 #endif
2536 #endif
2537 
2538 #ifdef OS_UNIX_SYSV
2539   str = "SYSV UNIX";
2540 #endif
2541 
2542 #ifdef OS_UNIX_SOL
2543   str = "SOLARIS UNIX";
2544 #ifdef PROC_I80X86
2545   str = "SOLARIS INTEL UNIX";
2546 #endif
2547 #endif
2548 
2549 #ifdef OS_UNIX_SUN
2550   str = "SUN UNIX";
2551 #endif
2552 #ifdef OS_UNIX_IRIX
2553   str = "SGI UNIX";
2554 #endif
2555 #ifdef OS_UNIX_LINUX
2556   str = "LINUX UNIX";
2557 #endif
2558 #endif
2559 
2560 #ifdef OS_MSWIN
2561   DWORD  version, lowbyte;
2562 
2563   str = "MS WINDOWS";
2564   version = GetVersion ();
2565   lowbyte = (version & 0x0000FF);
2566   if ((version & 0x80000000) == 0) {
2567     if (lowbyte == 6) {
2568       str = "MS WINDOWS VISTA";
2569     } else if (lowbyte == 5) {
2570       str = "MS WINDOWS 2000/XP";
2571     } else if (lowbyte == 4) {
2572       str = "MS WINDOWS NT 4.0";
2573     } else if (lowbyte == 3) {
2574       str = "MS WINDOWS NT 3.51";
2575     }
2576   } else {
2577     if (lowbyte == 4) {
2578       str = "MS WINDOWS 95/98/Me";
2579     } else if (lowbyte == 3) {
2580       str = "MS WINDOWS 3.1";
2581     }
2582   }
2583 #endif
2584 
2585   return Nlm_StringSave (str);
2586 }
2587 
2588