1 #ifndef NCBIENV__HPP
2 #define NCBIENV__HPP
3 
4 /*  $Id: ncbienv.hpp 574926 2018-11-20 20:23:54Z ucko $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors:  Denis Vakatov, Eugene Vasilchenko
30  *
31  *
32  */
33 
34 /// @file ncbienv.hpp
35 /// Defines unified interface to application:
36 /// - Environment        -- CNcbiEnvironment
37 /// - Command-line args  -- CNcbiArguments
38 
39 
40 #include <corelib/ncbimtx.hpp>
41 #include <map>
42 #include <iterator>
43 
44 /// Avoid name clash with the NCBI C Toolkit.
45 #if !defined(NCBI_OS_UNIX)  ||  defined(HAVE_NCBI_C)
46 #  if defined(GetProgramName)
47 #    undef GetProgramName
48 #  endif
49 #  define GetProgramName GetProgramName
50 #  if defined(SetProgramName)
51 #    undef SetProgramName
52 #  endif
53 #  define SetProgramName SetProgramName
54 #endif
55 
56 
57 /** @addtogroup Environment
58  *
59  * @{
60  */
61 
62 
63 BEGIN_NCBI_SCOPE
64 
65 
66 /////////////////////////////////////////////////////////////////////////////
67 ///
68 /// CArgumentsException --
69 ///
70 /// Define exceptions generated by CArgumentsApplication.
71 ///
72 /// CArgumentsException inherits its basic functionality from CCoreException
73 /// and defines additional error codes for applications.
74 
75 class NCBI_XNCBI_EXPORT CArgumentsException : public CCoreException
76 {
77 public:
78     /// Error types that arguments processing can generate.
79     enum EErrCode {
80         eNegativeArgc,  ///< Negative argc value
81         eNoArgs         ///< No arguments
82     };
83 
84     /// Translate from the error code value to its string representation.
85     virtual const char* GetErrCodeString(void) const override;
86 
87     // Standard exception boilerplate code.
88     NCBI_EXCEPTION_DEFAULT(CArgumentsException, CCoreException);
89 };
90 
91 
92 
93 /////////////////////////////////////////////////////////////////////////////
94 ///
95 /// CNcbiEnvironment --
96 ///
97 /// Define the application environment.
98 ///
99 /// CNcbiEnvironment provides a data structure for storing, accessing and
100 /// modifying the environment variables accessed by the C library routine
101 /// getenv().
102 
103 class NCBI_XNCBI_EXPORT CNcbiEnvironment
104 {
105 public:
106     /// Constructor.
107     CNcbiEnvironment(void);
108 
109     /// Constructor with the envp parameter.
110     CNcbiEnvironment(const char* const* envp);
111 
112     /// Destructor.
113     virtual ~CNcbiEnvironment(void);
114 
115     /// Reset environment.
116     ///
117     /// Delete all cached entries, load new ones from "envp" (if not NULL).
118     void Reset(const char* const* envp = 0);
119 
120     /// Get environment value by name.
121     ///
122     /// If environmnent value is not cached then call "Load(name)" to load
123     /// the environmnent value.  The loaded name/value pair will then be
124     /// cached, too, after the call to "Get()".
125     const string& Get(const string& name, bool* found = NULL) const;
126 
127     /// Find all variable names starting with an optional prefix.
128     void Enumerate(list<string>& names, const string& prefix = kEmptyStr)
129         const;
130 
131     /// Set an environment variable by name
132     ///
133     /// This will throw an exception if setting the variable fails
134     void Set(const string& name, const string& value);
135 
136     /// Delete an environment variable by name
137     /// @param name environment variable name [in]
138     void Unset(const string& name);
139 
140 protected:
141     /// Load value of specified environment variable.
142     virtual string Load(const string& name, bool& found) const;
143 
144 private:
145     /// Cached environment <name,value> pair.
146     struct SEnvValue {
SEnvValueCNcbiEnvironment::SEnvValue147         SEnvValue(void) : ptr(NULL) {}
SEnvValueCNcbiEnvironment::SEnvValue148         SEnvValue(const string& v, const TXChar* p) : value(v), ptr(p) {}
149 
150         string value;  // cached value
151         // NULL if the corresponding environment variable is unset.
152         // kEmptyXCStr if the value was loaded from the environment.
153         // A string created by strdup() if the value came from Set().
154         const TXChar* ptr;
155     };
156     typedef map<string, SEnvValue> TCache;
157     mutable TCache m_Cache;
158     mutable CFastMutex m_CacheMutex;
159 };
160 
161 
162 
163 /////////////////////////////////////////////////////////////////////////////
164 ///
165 /// CAutoEnvironmentVariable --
166 ///
167 /// Establish an environment setting for a limited time.
168 ///
169 /// CAutoEnvironmentVariable establishes an environment variable setting
170 /// for the lifetime of the instance (which may be associated with a unit
171 /// test case), restoring the previous value (if any) when destroyed.
172 class NCBI_XNCBI_EXPORT CAutoEnvironmentVariable
173 {
174 public:
175     /// Initializes the environment variable passed as an argument to the
176     /// corresponding value ("1" by default)
177     /// @param var_name environment variable name [in]
178     /// @param value value to set the environment variable to [in]
179     CAutoEnvironmentVariable(const CTempString& var_name,
180                              const CTempString& value = "1",
181                              CNcbiEnvironment*  env = NULL);
182 
183     /// Destructor which restores the modifications made in the environment by
184     /// this class
185     ~CAutoEnvironmentVariable();
186 
187 private:
188     /// Affected CNcbiEnvironment instance
189     AutoPtr<CNcbiEnvironment> m_Env;
190     /// Name of the environment variable manipulated
191     string                    m_VariableName;
192     /// Previous value of the environment variable manipulated
193     string                    m_PrevValue;
194     /// Was the variable originally set at all?
195     bool                      m_WasSet;
196 };
197 
198 
199 
200 /////////////////////////////////////////////////////////////////////////////
201 ///
202 /// CEnvironmentCleaner --
203 ///
204 /// Remove unwanted settings from the environment, for instance to allow
205 /// test suites to start from suitably clean slates (in which case a global
206 /// static instance may be in order).
207 class NCBI_XNCBI_EXPORT CEnvironmentCleaner
208 {
209 public:
210     /// Immediately clean some settings, to be passed in as a NULL-terminated
211     /// sequence of C strings.
212     CEnvironmentCleaner(const char* s = NULL, ...);
213 
214     /// Clean the specified setting.
215     void Clean(const string& name);
216 };
217 
218 
219 
220 /////////////////////////////////////////////////////////////////////////////
221 ///
222 /// CNcbiArguments --
223 ///
224 /// Store application command-line arguments & application name.
225 ///
226 /// CNcbiArgument provides a data structure for storing and accessing the
227 /// command line arguments and application name.
228 
229 class NCBI_XNCBI_EXPORT CNcbiArguments
230 {
231 public:
232     /// Constructor.
233     CNcbiArguments(int argc,                ///< Standard argument count
234                    const char* const* argv, ///< Standard argument vector
235                    const string& program_name = kEmptyStr, ///< Program name
236                    const string& real_name = kEmptyStr ///< Resolved name
237                   );
238 
239     /// Destructor.
240     virtual ~CNcbiArguments(void);
241 
242     /// Copy constructor.
243     CNcbiArguments(const CNcbiArguments& args);
244 
245     /// Assignment operator.
246     CNcbiArguments& operator= (const CNcbiArguments& args);
247 
248     /// Reset arguments.
249     ///
250     /// Delete all cached args and program name.  Load new ones from "argc",
251     /// "argv", "program_name", and "real_name".
252     void Reset(int argc,                    ///< Standard argument count
253                const char* const* argv,     ///< Standard argument vector
254                const string& program_name = kEmptyStr, ///< Program name
255                const string& real_name = kEmptyStr ///< Resolved name
256               );
257 
258     /// Get size (number) of arguments.
Size(void) const259     SIZE_TYPE Size(void) const { return m_Args.size(); }
260 
261     /// Get the argument specified by "pos".
operator [](SIZE_TYPE pos) const262     const string& operator[] (SIZE_TYPE pos) const { return m_Args[pos]; }
263 
264     /// Add a new argument.
265     void Add(const string& arg);
266 
267     /// Delete arguments from 1 to n.
268     void Shift(int n=1);
269 
270     /// Get program name.
271     const string& GetProgramName(EFollowLinks follow_links = eIgnoreLinks)
272         const;
273 
274     /// Get program base name.
275     string GetProgramBasename(EFollowLinks follow_links = eIgnoreLinks) const;
276 
277     /// Get program directory name.
278     ///
279     /// Program name includes the last '/'.
280     string GetProgramDirname (EFollowLinks follow_links = eIgnoreLinks) const;
281 
282     /// Set program name.  If real_name is supplied, it should be the
283     /// fully resolved path to the executable (whereas program_name
284     /// may legitimately involve symlinks).
285     void SetProgramName(const string& program_name,
286                         const string& real_name = kEmptyStr);
287 
288 private:
289     string        m_ProgramName;  ///< Program name if different from the
290                                   ///< default m_Args[0]
291     deque<string> m_Args;         ///< Queue of arguments
292 
293     mutable string     m_ResolvedName;
294     mutable CFastMutex m_ResolvedNameMutex;
295 };
296 
297 
298 END_NCBI_SCOPE
299 
300 
301 /* @} */
302 
303 #endif  /* NCBIENV__HPP */
304