Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dtool/src/dtoolutil/executionEnvironment.cxx

Go to the documentation of this file.
00001 // Filename: executionEnvironment.cxx
00002 // Created by:  drose (15May00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "executionEnvironment.h"
00020 #include <assert.h>
00021 #include <errno.h>
00022 #include <stdio.h>  // for perror
00023 
00024 #ifdef WIN32_VC
00025 // Windows requires this for getcwd().
00026 #include <direct.h>
00027 #define getcwd _getcwd
00028 #endif
00029 
00030 
00031 // We define the symbol PREREAD_ENVIRONMENT if we cannot rely on
00032 // getenv() to read environment variables at static init time.  In
00033 // this case, we must read all of the environment variables directly
00034 // and cache them locally.
00035 
00036 #ifndef STATIC_INIT_GETENV
00037 #define PREREAD_ENVIRONMENT
00038 #endif
00039 
00040 
00041 // We define the symbol HAVE_GLOBAL_ARGV if we have global variables
00042 // named GLOBAL_ARGC/GLOBAL_ARGV that we can read at static init time
00043 // to determine our command-line arguments.
00044 
00045 #if defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
00046 extern char **GLOBAL_ARGV;
00047 extern int GLOBAL_ARGC;
00048 #endif
00049 
00050 // Linux with GNU libc does have global argv/argc variables, but we
00051 // can't safely access them at stat init time--at least, not in libc5.
00052 // (It does seem to work with glibc2, however.)
00053 
00054 ExecutionEnvironment *ExecutionEnvironment::_global_ptr = NULL;
00055 
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: ExecutionEnvironment::Constructor
00059 //       Access: Private
00060 //  Description: You shouldn't need to construct one of these; there's
00061 //               only one and it constructs itself.
00062 ////////////////////////////////////////////////////////////////////
00063 ExecutionEnvironment::
00064 ExecutionEnvironment() {
00065   read_environment_variables();
00066   read_args();
00067 }
00068 
00069 ////////////////////////////////////////////////////////////////////
00070 //     Function: ExecutionEnviroment::expand_string
00071 //       Access: Public, Static
00072 //  Description: Reads the string, looking for environment variable
00073 //               names marked by a $.  Expands all such variable
00074 //               names.  A repeated dollar sign ($$) is mapped to a
00075 //               single dollar sign.
00076 //
00077 //               Returns the expanded string.
00078 ////////////////////////////////////////////////////////////////////
00079 string ExecutionEnvironment::
00080 expand_string(const string &str) {
00081   string result;
00082 
00083   size_t last = 0;
00084   size_t dollar = str.find('$');
00085   while (dollar != string::npos && dollar + 1 < str.length()) {
00086     size_t start = dollar + 1;
00087 
00088     if (str[start] == '$') {
00089       // A double dollar sign maps to a single dollar sign.
00090       result += str.substr(last, start - last);
00091       last = start + 1;
00092 
00093     } else {
00094       string varname;
00095       size_t end = start;
00096 
00097       if (str[start] == '{') {
00098         // Curly braces delimit the variable name explicitly.
00099         end = str.find('}', start + 1);
00100         if (end != string::npos) {
00101           varname = str.substr(start + 1, end - (start + 1));
00102           end++;
00103         }
00104       }
00105 
00106       if (end == start) {
00107         // Scan for the end of the variable name.
00108         while (end < str.length() && (isalnum(str[end]) || str[end] == '_')) {
00109           end++;
00110         }
00111         varname = str.substr(start, end - start);
00112       }
00113 
00114       string subst =
00115       result += str.substr(last, dollar - last);
00116       result += get_environment_variable(varname);
00117       last = end;
00118     }
00119 
00120     dollar = str.find('$', last);
00121   }
00122 
00123   result += str.substr(last);
00124 
00125   return result;
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: ExecutionEnviroment::get_cwd
00130 //       Access: Public, Static
00131 //  Description: Returns the name of the current working directory.
00132 ////////////////////////////////////////////////////////////////////
00133 Filename ExecutionEnvironment::
00134 get_cwd() {
00135   // getcwd() requires us to allocate a dynamic buffer and grow it on
00136   // demand.
00137   static size_t bufsize = 1024;
00138   static char *buffer = NULL;
00139 
00140   if (buffer == (char *)NULL) {
00141     buffer = new char[bufsize];
00142   }
00143 
00144   while (getcwd(buffer, bufsize) == (char *)NULL) {
00145     if (errno != ERANGE) {
00146       perror("getcwd");
00147       return string();
00148     }
00149     delete[] buffer;
00150     bufsize = bufsize * 2;
00151     buffer = new char[bufsize];
00152     assert(buffer != (char *)NULL);
00153   }
00154 
00155   return Filename::from_os_specific(buffer);
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: ExecutionEnvironment::ns_has_environment_variable
00160 //       Access: Private
00161 //  Description: Returns true if the indicated environment variable
00162 //               is defined.  The nonstatic implementation.
00163 ////////////////////////////////////////////////////////////////////
00164 bool ExecutionEnvironment::
00165 ns_has_environment_variable(const string &var) const {
00166 #ifdef PREREAD_ENVIRONMENT
00167   return _variables.count(var) != 0;
00168 #else
00169   return getenv(var.c_str()) != (char *)NULL;
00170 #endif
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: ExecutionEnvironment::ns_get_environment_variable
00175 //       Access: Private
00176 //  Description: Returns the definition of the indicated environment
00177 //               variable, or the empty string if the variable is
00178 //               undefined.  The nonstatic implementation.
00179 ////////////////////////////////////////////////////////////////////
00180 string ExecutionEnvironment::
00181 ns_get_environment_variable(const string &var) const {
00182 #ifdef PREREAD_ENVIRONMENT
00183   EnvironmentVariables::const_iterator evi;
00184   evi = _variables.find(var);
00185   if (evi != _variables.end()) {
00186     return (*evi).second;
00187   }
00188   return string();
00189 #else
00190   const char *def = getenv(var.c_str());
00191   if (def != (char *)NULL) {
00192     return def;
00193   }
00194   return string();
00195 #endif
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: ExecutionEnvironment::ns_set_environment_variable
00200 //       Access: Private
00201 //  Description: Changes the definition of the indicated environment
00202 //               variable.  The nonstatic implementation.
00203 ////////////////////////////////////////////////////////////////////
00204 void ExecutionEnvironment::
00205 ns_set_environment_variable(const string &var, const string &value) {
00206   _variables[var] = value;
00207   string putstr = var + "=" + value;
00208 
00209   // putenv() requires us to malloc a new C-style string.
00210   char *put = (char *)malloc(putstr.length() + 1);
00211   strcpy(put, putstr.c_str());
00212   putenv(put);
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: ExecutionEnvironment::ns_get_num_args
00217 //       Access: Private
00218 //  Description: Returns the number of command-line arguments
00219 //               available, not counting arg 0, the binary name.  The
00220 //               nonstatic implementation.
00221 ////////////////////////////////////////////////////////////////////
00222 int ExecutionEnvironment::
00223 ns_get_num_args() const {
00224   return _args.size();
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: ExecutionEnvironment::ns_get_arg
00229 //       Access: Private
00230 //  Description: Returns the nth command-line argument.  The index n
00231 //               must be in the range [0 .. get_num_args()).  The
00232 //               first parameter, n == 0, is the first actual
00233 //               parameter, not the binary name.  The nonstatic
00234 //               implementation.
00235 ////////////////////////////////////////////////////////////////////
00236 string ExecutionEnvironment::
00237 ns_get_arg(int n) const {
00238   assert(n >= 0 && n < ns_get_num_args());
00239   return _args[n];
00240 }
00241 
00242 ////////////////////////////////////////////////////////////////////
00243 //     Function: ExecutionEnvironment::ns_get_binary_name
00244 //       Access: Private
00245 //  Description: Returns the name of the binary executable that
00246 //               started this program, if it can be determined.  The
00247 //               nonstatic implementation.
00248 ////////////////////////////////////////////////////////////////////
00249 string ExecutionEnvironment::
00250 ns_get_binary_name() const {
00251   if (_binary_name.empty()) {
00252     return "unknown";
00253   }
00254   return _binary_name;
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: ExecutionEnvironment::get_ptr
00259 //       Access: Private, Static
00260 //  Description: Returns a static pointer that may be used to access
00261 //               the global ExecutionEnvironment object.
00262 ////////////////////////////////////////////////////////////////////
00263 ExecutionEnvironment *ExecutionEnvironment::
00264 get_ptr() {
00265   if (_global_ptr == (ExecutionEnvironment *)NULL) {
00266     _global_ptr = new ExecutionEnvironment;
00267   }
00268   return _global_ptr;
00269 }
00270 
00271 
00272 ////////////////////////////////////////////////////////////////////
00273 //     Function: ExecutionEnvironment::read_environment_variables
00274 //       Access: Private
00275 //  Description: Fills up the internal table of existing environment
00276 //               variables, if we are in PREREAD_ENVIRONMENT mode.
00277 //               Otherwise, does nothing.
00278 ////////////////////////////////////////////////////////////////////
00279 void ExecutionEnvironment::
00280 read_environment_variables() {
00281 #ifdef PREREAD_ENVIRONMENT
00282 #if defined(HAVE_PROC_SELF_ENVIRON)
00283   // In Linux, and possibly in other systems, we might not be able to
00284   // use getenv() at static init time.  However, we may be lucky and
00285   // have a file called /proc/self/environ that may be read to
00286   // determine all of our environment variables.
00287 
00288   ifstream proc("/proc/self/environ");
00289   if (proc.fail()) {
00290     cerr << "Cannot read /proc/self/environ; environment variables unavailable.\n";
00291     return;
00292   }
00293 
00294   int ch = proc.get();
00295   while (!proc.eof() && !proc.fail()) {
00296     string variable;
00297     string value;
00298 
00299     while (!proc.eof() && !proc.fail() && ch != '=' && ch != '\0') {
00300       variable += (char)ch;
00301       ch = proc.get();
00302     }
00303 
00304     if (ch == '=') {
00305       ch = proc.get();
00306       while (!proc.eof() && !proc.fail() && ch != '\0') {
00307         value += (char)ch;
00308         ch = proc.get();
00309       }
00310     }
00311 
00312     if (!variable.empty()) {
00313       _variables[variable] = value;
00314     }
00315     ch = proc.get();
00316   }
00317 #else
00318   cerr << "Warning: environment variables unavailable to dconfig.\n";
00319 #endif
00320 #endif // PREREAD_ENVIRONMENT
00321 }
00322 
00323 ////////////////////////////////////////////////////////////////////
00324 //     Function: ExecutionEnvironment::read_args
00325 //       Access: Private
00326 //  Description: Reads all the command-line arguments and the name of
00327 //               the binary file, if possible.
00328 ////////////////////////////////////////////////////////////////////
00329 void ExecutionEnvironment::
00330 read_args() {
00331 #if defined(HAVE_GLOBAL_ARGV)
00332   int argc = GLOBAL_ARGC;
00333   if (argc > 0) {
00334     _binary_name = GLOBAL_ARGV[0];
00335   }
00336 
00337   for (int i = 1; i < argc; i++) {
00338     _args.push_back(GLOBAL_ARGV[i]);
00339   }
00340 
00341 #elif defined(HAVE_PROC_SELF_CMDLINE)
00342   // In Linux, and possibly in other systems as well, we might not be
00343   // able to use the global ARGC/ARGV variables at static init time.
00344   // However, we may be lucky and have a file called
00345   // /proc/self/cmdline that may be read to determine all of our
00346   // command-line arguments.
00347 
00348   ifstream proc("/proc/self/cmdline");
00349   if (proc.fail()) {
00350     cerr << "Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n";
00351     return;
00352   }
00353 
00354   int ch = proc.get();
00355   int index = 0;
00356   while (!proc.eof() && !proc.fail()) {
00357     string arg;
00358 
00359     while (!proc.eof() && !proc.fail() && ch != '\0') {
00360       arg += (char)ch;
00361       ch = proc.get();
00362     }
00363 
00364     if (index == 0) {
00365       _binary_name = arg;
00366     } else {
00367       _args.push_back(arg);
00368     }
00369     index++;
00370 
00371     ch = proc.get();
00372   }
00373 #else
00374   cerr << "Warning: command line parameters unavailable to dconfig.\n";
00375 #endif
00376 }

Generated on Thu May 1 22:12:59 2003 for DTool by doxygen1.3