root/juggler/branches/2.2/modules/sonix/snx/snxmain.cpp

Revision 20870, 9.2 kB (checked in by patrick, 1 year ago)

MFT r20869: Protect against operator error if an invalid path is set in the

module's …_BASE_DIR environment variable.

  • Property svn:eol-style set to native
Line 
1 /****************** <SNX heading BEGIN do not edit this line> *****************
2  *
3  * sonix
4  *
5  * Original Authors:
6  *   Kevin Meinert, Carolina Cruz-Neira
7  *
8  ****************** <SNX heading END do not edit this line> ******************/
9
10 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
11  *
12  * VR Juggler is (C) Copyright 1998-2007 by Iowa State University
13  *
14  * Original Authors:
15  *   Allen Bierbaum, Christopher Just,
16  *   Patrick Hartling, Kevin Meinert,
17  *   Carolina Cruz-Neira, Albert Baker
18  *
19  * This library is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU Library General Public
21  * License as published by the Free Software Foundation; either
22  * version 2 of the License, or (at your option) any later version.
23  *
24  * This library is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27  * Library General Public License for more details.
28  *
29  * You should have received a copy of the GNU Library General Public
30  * License along with this library; if not, write to the
31  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32  * Boston, MA 02111-1307, USA.
33  *
34  *************** <auto-copyright.pl END do not edit this line> ***************/
35
36 #include <snx/snxConfig.h>
37
38 #include <iostream>
39 #include <sstream>
40 #include <cstdlib>
41 #include <string>
42
43 #if ! defined(WIN32) && ! defined(WIN64)
44 include <dlfcn.h>
45 #endif
46
47 #include <boost/filesystem/path.hpp>
48 #include <boost/filesystem/operations.hpp>
49 #include <boost/filesystem/exception.hpp>
50
51 #include <vpr/vpr.h>
52
53
54 namespace fs = boost::filesystem;
55
56 #if defined(WIN32) || defined(WIN64)
57 /**
58  * Windows DLL entry point function. This ensures that the environment
59  * variable \c SNX_BASE_DIR is set as soon as this DLL is attached to the
60  * process. If it is not set, then it sets it based on an assumption about the
61  * structure of a Sonix installation. More specifically, an assumption is made
62  * that this DLL lives in the \c lib subdirectory of the Sonix installation.
63  * Therefore, the root of the Sonix installation is the parent of the
64  * directory containing this DLL.
65  */
66 BOOL __stdcall DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
67 {
68    switch (reason)
69    {
70       case DLL_PROCESS_ATTACH:
71          {
72             char* env_dir(NULL);
73 #if defined(_MSC_VER) && _MSC_VER >= 1400
74             size_t len;
75             _dupenv_s(&env_dir, &len, "SNX_BASE_DIR");
76 #else
77             env_dir = std::getenv("SNX_BASE_DIR");
78 #endif
79
80             try
81             {
82                fs::path base_dir;
83
84                // If SNX_BASE_DIR is not set, look up the path to this DLL and
85                // use it to provide a default setting for that environment
86                // variable.
87                if ( NULL == env_dir )
88                {
89                   char tmppath[1024];
90                   std::memset(tmppath, 0, sizeof(tmppath));
91                   GetModuleFileName(module, tmppath, sizeof(tmppath));
92
93                   const fs::path dll_path(tmppath, fs::native);
94                   base_dir = dll_path.branch_path().branch_path();
95 #if (defined(JUGGLER_DEBUG) || defined(SNX_DEBUG)) && ! defined(_DEBUG)
96                   // The debug DLL linked against the release runtime is in
97                   // <base_dir>\lib\debug.
98                   base_dir = base_dir.branch_path();
99 #endif
100
101                   const std::string base_dir_str =
102                      base_dir.native_directory_string();
103
104 #if defined(_MSC_VER) && _MSC_VER >= 1400
105                   _putenv_s("SNX_BASE_DIR", base_dir_str.c_str());
106 #else
107                   std::ostringstream env_stream;
108                   env_stream << "SNX_BASE_DIR=" << base_dir_str;
109                   putenv(env_stream.str().c_str());
110 #endif
111                }
112                else
113                {
114                   base_dir = fs::path(env_dir, fs::native);
115 #if defined(_MSC_VER) && _MSC_VER >= 1400
116                   std::free(env_dir);
117                   env_dir = NULL;
118 #endif
119                }
120
121 #if defined(_MSC_VER) && _MSC_VER >= 1400
122                _dupenv_s(&env_dir, &len, "SNX_DATA_DIR");
123 #else
124                env_dir = std::getenv("SNX_DATA_DIR");
125 #endif
126
127                // If SNX_BASE_DIR is not set, set a default relative to
128                // base_dir.
129                if ( NULL == env_dir )
130                {
131                   fs::path data_dir(base_dir / "share" / "sonix");
132                   const std::string data_dir_str =
133                      data_dir.native_directory_string();
134
135 #if defined(_MSC_VER) && _MSC_VER >= 1400
136                   _putenv_s("SNX_DATA_DIR", data_dir_str.c_str());
137 #else
138                   std::ostringstream env_stream;
139                   env_stream << "SNX_DATA_DIR=" << data_dir_str;
140                   putenv(env_stream.str().c_str());
141 #endif
142                }
143 #if defined(_MSC_VER) && _MSC_VER >= 1400
144                else
145                {
146                   std::free(env_dir);
147                   env_dir = NULL;
148                }
149 #endif
150             }
151             catch (fs::filesystem_error& ex)
152             {
153                std::cerr << "Automatic assignment of Sonix environment "
154                          << "variables failed:\n" << ex.what() << std::endl;
155
156 #if defined(_MSC_VER) && _MSC_VER >= 1400
157                if ( NULL != env_dir )
158                {
159                   std::free(env_dir);
160                }
161 #endif
162             }
163          }
164          break;
165       default:
166          break;
167    }
168
169    return TRUE;
170 }
171 #else
172 /**
173  * Non-Windows shared library constructor. This ensures that the environment
174  * variable \c SNX_BASE_DIR is set as soon as this shared library is loaded.
175  * If it is not set, then it sets it based on an assumption about the
176  * structure of a Sonix installation. More specifically, an assumption is made
177  * that this shared library lives in the \c lib subdirectory of the Sonix
178  * installation. Therefore, the root of the Sonix installation is the parent
179  * of the directory containing this shared library.
180  */
181 extern "C" void __attribute ((constructor)) snxLibraryInit()
182 {
183    fs::path base_dir;
184    const char* env_dir = std::getenv("SNX_BASE_DIR");
185
186    // If SNX_BASE_DIR is not set, look up the path to this shared library and
187    // use it to provide a default setting for that environment variable.
188    if ( NULL == env_dir )
189    {
190       Dl_info info;
191       info.dli_fname = 0;
192       const int result =
193 #if defined(__GNUC__) && __GNUC_MAJOR__ < 4
194          dladdr((void*) &snxLibraryInit, &info);
195 #else
196          dladdr(reinterpret_cast<void*>(&snxLibraryInit), &info);
197 #endif
198
199       // NOTE: dladdr(3) really does return a non-zero value on success.
200       if ( 0 != result )
201       {
202          try
203          {
204             fs::path lib_file(info.dli_fname, fs::native);
205             lib_file = fs::system_complete(lib_file);
206
207 #if defined(VPR_OS_IRIX) && defined(_ABIN32)
208             const std::string bit_suffix("32");
209 #elif defined(VPR_OS_IRIX) && defined(_ABI64) || \
210       defined(VPR_OS_Linux) && defined(__x86_64__)
211             const std::string bit_suffix("64");
212 #else
213             const std::string bit_suffix("");
214 #endif
215
216             // Get the directory containing this shared library.
217             const fs::path lib_path = lib_file.branch_path();
218
219             // Start the search for the root of the Sonix installation in the
220             // parent of the directory containing this shared library.
221             base_dir = lib_path.branch_path();
222
223             // Use the lib subdirectory to figure out when we have found the
224             // root of the Sonix installation tree.
225             const fs::path lib_subdir(std::string("lib") + bit_suffix);
226
227             bool found(false);
228             while ( ! found && ! base_dir.empty() )
229             {
230                try
231                {
232                   if ( ! fs::exists(base_dir / lib_subdir) )
233                   {
234                      base_dir = base_dir.branch_path();
235                   }
236                   else
237                   {
238                      found = true;
239                   }
240                }
241                catch (fs::filesystem_error&)
242                {
243                   base_dir = base_dir.branch_path();
244                }
245             }
246
247             if ( found )
248             {
249                setenv("SNX_BASE_DIR",
250                       base_dir.native_directory_string().c_str(), 1);
251             }
252          }
253          catch (fs::filesystem_error& ex)
254          {
255             std::cerr << "Automatic assignment of SNX_BASE_DIR failed:\n"
256                       << ex.what() << std::endl;
257          }
258       }
259    }
260    else
261    {
262       try
263       {
264          base_dir = fs::path(env_dir, fs::native);
265       }
266       catch (fs::filesystem_error& ex)
267       {
268          std::cerr << "Invalid path set in SNX_BASE_DIR environment "
269                    << "variable:\n" << ex.what() << std::endl;
270       }
271    }
272
273    if ( ! base_dir.empty() )
274    {
275       // If base_dir were empty, this would result in data_dir being relative
276       // to the current working directory.
277       const fs::path data_dir = base_dir / SNX_SHARE_DIR;
278
279       // We use the overwrite value of 0 as a way around testing whether the
280       // environment variable is already set.
281       setenv("SNX_DATA_DIR", data_dir.native_directory_string().c_str(), 0);
282    }
283 }
284 #endif  /* defined(WIN32) || defined(WIN64) */
Note: See TracBrowser for help on using the browser.