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