root/juggler/branches/2.2/modules/gadgeteer/gadget/gadgetmain.cpp

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