Blame RCReader.cc

Packit a4aae4
// -*- mode: c++; c-basic-offset:4 -*-
Packit a4aae4
Packit a4aae4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
Packit a4aae4
// Access Protocol.
Packit a4aae4
Packit a4aae4
// Copyright (c) 2002,2003 OPeNDAP, Inc.
Packit a4aae4
// Author: Jose Garcia <jgarcia@ucar.edu>
Packit a4aae4
//
Packit a4aae4
// This library is free software; you can redistribute it and/or
Packit a4aae4
// modify it under the terms of the GNU Lesser General Public
Packit a4aae4
// License as published by the Free Software Foundation; either
Packit a4aae4
// version 2.1 of the License, or (at your option) any later version.
Packit a4aae4
//
Packit a4aae4
// This library is distributed in the hope that it will be useful,
Packit a4aae4
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4aae4
// Lesser General Public License for more details.
Packit a4aae4
//
Packit a4aae4
// You should have received a copy of the GNU Lesser General Public
Packit a4aae4
// License along with this library; if not, write to the Free Software
Packit a4aae4
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit a4aae4
//
Packit a4aae4
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
Packit a4aae4
Packit a4aae4
// (c) COPYRIGHT URI/MIT 2001,2002
Packit a4aae4
// Please read the full copyright statement in the file COPYRIGHT_URI.
Packit a4aae4
//
Packit a4aae4
// Authors:
Packit a4aae4
// jose Jose Garcia <jgarcia@ucar.edu>
Packit a4aae4
Packit a4aae4
/** A singleton which reads and parses the .dodsrc file. This code was
Packit a4aae4
 extracted from Connect (which has since changed considerably).
Packit a4aae4
Packit a4aae4
 @author: jose */
Packit a4aae4
Packit a4aae4
// #define DODS_DEBUG
Packit a4aae4
#include "config.h"
Packit a4aae4
Packit a4aae4
#include <cstring>
Packit a4aae4
#include <cstdlib>
Packit a4aae4
Packit a4aae4
#include <unistd.h>  // for stat
Packit a4aae4
#include <sys/types.h>
Packit a4aae4
#include <sys/stat.h>
Packit a4aae4
Packit a4aae4
#ifdef WIN32
Packit a4aae4
#define FALSE 0
Packit a4aae4
// Win32 does not define F_OK. 08/21/02 jhrg
Packit a4aae4
#define F_OK 0
Packit a4aae4
#define DIR_SEP_STRING "\\"
Packit a4aae4
#define DIR_SEP_CHAR   '\\'
Packit a4aae4
#include <direct.h>
Packit a4aae4
#else
Packit a4aae4
#define DIR_SEP_STRING "/"
Packit a4aae4
#define DIR_SEP_CHAR   '/'
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#include <pthread.h>
Packit a4aae4
Packit a4aae4
#include <fstream>
Packit a4aae4
Packit a4aae4
#include "debug.h"
Packit a4aae4
#include "RCReader.h"
Packit a4aae4
#include "Error.h"
Packit a4aae4
Packit a4aae4
using namespace std;
Packit a4aae4
Packit a4aae4
namespace libdap {
Packit a4aae4
Packit a4aae4
RCReader* RCReader::_instance = 0;
Packit a4aae4
Packit a4aae4
// This variable (instance_control) is used to ensure that in a MT
Packit a4aae4
// environment _instance is correctly initialized. See the get_instance
Packit a4aae4
// method. 08/07/02 jhrg
Packit a4aae4
static pthread_once_t instance_control = PTHREAD_ONCE_INIT;
Packit a4aae4
Packit a4aae4
/** Using values from this instance of RCReader, write out values for a
Packit a4aae4
 default .dodsrc file. Nominally this will use the defaults for each thing
Packit a4aae4
 that might be read from the configuration file. */
Packit a4aae4
Packit a4aae4
bool RCReader::write_rc_file(const string &pathname)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Writing the RC file to " << pathname << endl);
Packit a4aae4
    ofstream fpo(pathname.c_str());
Packit a4aae4
Packit a4aae4
    // If the file couldn't be created.  Nothing needs to be done here,
Packit a4aae4
    // the program will simply use the defaults.
Packit a4aae4
Packit a4aae4
    if (fpo) {
Packit a4aae4
        // This means we just created the file.  We will now save
Packit a4aae4
        // the defaults in it for future use.
Packit a4aae4
        fpo << "# OPeNDAP client configuration file. See the OPeNDAP" << endl;
Packit a4aae4
        fpo << "# users guide for information." << endl;
Packit a4aae4
        fpo << "USE_CACHE=" << _dods_use_cache << endl;
Packit a4aae4
        fpo << "# Cache and object size are given in megabytes (20 ==> 20Mb)." << endl;
Packit a4aae4
        fpo << "MAX_CACHE_SIZE=" << _dods_cache_max << endl;
Packit a4aae4
        fpo << "MAX_CACHED_OBJ=" << _dods_cached_obj << endl;
Packit a4aae4
        fpo << "IGNORE_EXPIRES=" << _dods_ign_expires << endl;
Packit a4aae4
        fpo << "CACHE_ROOT=" << d_cache_root << endl;
Packit a4aae4
        fpo << "DEFAULT_EXPIRES=" << _dods_default_expires << endl;
Packit a4aae4
        fpo << "ALWAYS_VALIDATE=" << _dods_always_validate << endl;
Packit a4aae4
        fpo << "# Request servers compress responses if possible?" << endl;
Packit a4aae4
        fpo << "# 1 (yes) or 0 (false)." << endl;
Packit a4aae4
        fpo << "DEFLATE=" << _dods_deflate << endl;
Packit a4aae4
Packit a4aae4
        fpo << "# Should SSL certificates and hosts be validated? SSL" << endl;
Packit a4aae4
        fpo << "# will only work with signed certificates." << endl;
Packit a4aae4
        fpo << "VALIDATE_SSL=" << d_validate_ssl << endl;
Packit a4aae4
Packit a4aae4
        fpo << "# Proxy configuration (optional parts in []s)." << endl;
Packit a4aae4
        fpo << "# You may also use the 'http_proxy' environment variable" << endl;
Packit a4aae4
        fpo << "# but a value in this file will override that env variable." << endl;
Packit a4aae4
        fpo << "# PROXY_SERVER=[http://][username:password@]host[:port]" << endl;
Packit a4aae4
        if (!d_dods_proxy_server_host.empty()) {
Packit a4aae4
            fpo << "PROXY_SERVER=" << d_dods_proxy_server_protocol << "://"
Packit a4aae4
                    << (d_dods_proxy_server_userpw.empty() ? "" : d_dods_proxy_server_userpw + "@")
Packit a4aae4
                            + d_dods_proxy_server_host + ":" + long_to_string(d_dods_proxy_server_port) << endl;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        fpo << "# NO_PROXY_FOR=<host|domain>" << endl;
Packit a4aae4
        if (!d_dods_no_proxy_for_host.empty()) {
Packit a4aae4
            fpo << "NO_PROXY_FOR=" << d_dods_no_proxy_for_host << endl;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        fpo << "# AIS_DATABASE=<file or url>" << endl;
Packit a4aae4
Packit a4aae4
        fpo << "# COOKIE_JAR=.dods_cookies" << endl;
Packit a4aae4
        fpo << "# The cookie jar is a file that holds cookies sent from" << endl;
Packit a4aae4
        fpo << "# servers such as single signon systems. Uncomment this" << endl;
Packit a4aae4
        fpo << "# option and provide a file name to activate this feature." << endl;
Packit a4aae4
        fpo << "# If the value is a filename, it will be created in this" << endl;
Packit a4aae4
        fpo << "# directory; a full pathname can be used to force a specific" << endl;
Packit a4aae4
        fpo << "# location." << endl;
Packit a4aae4
Packit a4aae4
        fpo.close();
Packit a4aae4
        return true;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool RCReader::read_rc_file(const string &pathname)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Reading the RC file from " << pathname << endl);
Packit a4aae4
Packit a4aae4
    ifstream fpi(pathname.c_str());
Packit a4aae4
    if (fpi) {
Packit a4aae4
        // The file exists and we may now begin to parse it.
Packit a4aae4
        // Defaults are already stored in the variables, if the correct
Packit a4aae4
        // tokens are found in the file then those defaults will be
Packit a4aae4
        // overwritten.
Packit a4aae4
        char *value;
Packit a4aae4
        // TODO Replace with a vector<char>
Packit a4aae4
        //char *tempstr = new char[1024];
Packit a4aae4
        vector<char> tempstr(1024);
Packit a4aae4
        int tokenlength;
Packit a4aae4
        while (true) {
Packit a4aae4
            fpi.getline(&tempstr[0], 1023);
Packit a4aae4
            if (!fpi.good()) break;
Packit a4aae4
Packit a4aae4
            value = strchr(&tempstr[0], '=');
Packit a4aae4
            if (!value) continue;
Packit a4aae4
            tokenlength = value - &tempstr[0];
Packit a4aae4
            value++;
Packit a4aae4
Packit a4aae4
            if ((strncmp(&tempstr[0], "USE_CACHE", 9) == 0) && tokenlength == 9) {
Packit a4aae4
                _dods_use_cache = atoi(value) ? true : false;
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "MAX_CACHE_SIZE", 14) == 0) && tokenlength == 14) {
Packit a4aae4
                _dods_cache_max = atoi(value);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "MAX_CACHED_OBJ", 14) == 0) && tokenlength == 14) {
Packit a4aae4
                _dods_cached_obj = atoi(value);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "IGNORE_EXPIRES", 14) == 0) && tokenlength == 14) {
Packit a4aae4
                _dods_ign_expires = atoi(value);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "DEFLATE", 7) == 0) && tokenlength == 7) {
Packit a4aae4
                _dods_deflate = atoi(value) ? true : false;
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "CACHE_ROOT", 10) == 0) && tokenlength == 10) {
Packit a4aae4
                d_cache_root = value;
Packit a4aae4
                if (d_cache_root[d_cache_root.length() - 1] != DIR_SEP_CHAR) d_cache_root += string(DIR_SEP_STRING);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "DEFAULT_EXPIRES", 15) == 0) && tokenlength == 15) {
Packit a4aae4
                _dods_default_expires = atoi(value);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "ALWAYS_VALIDATE", 15) == 0) && tokenlength == 15) {
Packit a4aae4
                _dods_always_validate = atoi(value);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "VALIDATE_SSL", 12) == 0) && tokenlength == 12) {
Packit a4aae4
                d_validate_ssl = atoi(value);
Packit a4aae4
            }
Packit a4aae4
            else if (strncmp(&tempstr[0], "AIS_DATABASE", 12) == 0 && tokenlength == 12) {
Packit a4aae4
                d_ais_database = value;
Packit a4aae4
            }
Packit a4aae4
            else if (strncmp(&tempstr[0], "COOKIE_JAR", 10) == 0 && tokenlength == 10) {
Packit a4aae4
                // if the value of COOKIE_JAR starts with a slash, use it as
Packit a4aae4
                // is. However, if it does not start with a slash, prefix it
Packit a4aae4
                // with the directory that contains the .dodsrc file.
Packit a4aae4
                if (value[0] == '/') {
Packit a4aae4
                    d_cookie_jar = value;
Packit a4aae4
                }
Packit a4aae4
                else {
Packit a4aae4
                    d_cookie_jar = d_rc_file_path.substr(0, d_rc_file_path.find(".dodsrc")) + string(value);
Packit a4aae4
                } DBG(cerr << "set cookie jar to: " << d_cookie_jar << endl);
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "PROXY_SERVER", 12) == 0) && tokenlength == 12) {
Packit a4aae4
                // Setup a proxy server for all requests.
Packit a4aae4
                // The original syntax was <protocol>,<machine> where the
Packit a4aae4
                // machine could also contain the user/pass and port info.
Packit a4aae4
                // Support that but also support machine prefixed by
Packit a4aae4
                // 'http://' with and without the '<protocol>,' prefix. jhrg
Packit a4aae4
                // 4/21/08 (see bug 1095).
Packit a4aae4
                string proxy = value;
Packit a4aae4
                string::size_type comma = proxy.find(',');
Packit a4aae4
Packit a4aae4
                // Since the <protocol> is now optional, the comma might be
Packit a4aae4
                // here. If it is, check that the protocol given is http.
Packit a4aae4
                if (comma != string::npos) {
Packit a4aae4
                    d_dods_proxy_server_protocol = proxy.substr(0, comma);
Packit a4aae4
                    downcase(d_dods_proxy_server_protocol);
Packit a4aae4
                    if (d_dods_proxy_server_protocol != "http")
Packit a4aae4
                        throw Error("The only supported protocol for a proxy server is \"HTTP\". Correct your \".dodsrc\" file.");
Packit a4aae4
                    proxy = proxy.substr(comma + 1);
Packit a4aae4
                }
Packit a4aae4
                else {
Packit a4aae4
                    d_dods_proxy_server_protocol = "http";
Packit a4aae4
                }
Packit a4aae4
Packit a4aae4
                // Look for a 'protocol://' prefix; skip if found
Packit a4aae4
                string::size_type protocol = proxy.find("://");
Packit a4aae4
                if (protocol != string::npos) {
Packit a4aae4
                    proxy = proxy.substr(protocol + 3);
Packit a4aae4
                }
Packit a4aae4
Packit a4aae4
                // Break apart into userpw, host and port.
Packit a4aae4
                string::size_type at_sign = proxy.find('@');
Packit a4aae4
                if (at_sign != string::npos) { // has userpw
Packit a4aae4
                    d_dods_proxy_server_userpw = proxy.substr(0, at_sign);
Packit a4aae4
                    proxy = proxy.substr(at_sign + 1);
Packit a4aae4
                }
Packit a4aae4
                else
Packit a4aae4
                    d_dods_proxy_server_userpw = "";
Packit a4aae4
Packit a4aae4
                // Get host and look for a port number
Packit a4aae4
                string::size_type colon = proxy.find(':');
Packit a4aae4
                if (colon != string::npos) {
Packit a4aae4
                    d_dods_proxy_server_host = proxy.substr(0, colon);
Packit a4aae4
                    d_dods_proxy_server_port = strtol(proxy.substr(colon + 1).c_str(), 0, 0);
Packit a4aae4
                }
Packit a4aae4
                else {
Packit a4aae4
                    d_dods_proxy_server_host = proxy;
Packit a4aae4
                    d_dods_proxy_server_port = 80;
Packit a4aae4
                }
Packit a4aae4
            }
Packit a4aae4
            else if ((strncmp(&tempstr[0], "NO_PROXY_FOR", 12) == 0) && tokenlength == 12) {
Packit a4aae4
                // Setup a proxy server for all requests.
Packit a4aae4
                string no_proxy = value;
Packit a4aae4
                string::size_type comma = no_proxy.find(',');
Packit a4aae4
Packit a4aae4
                // Since the protocol is required, the comma *must* be
Packit a4aae4
                // present. We could throw an Error on the malformed line...
Packit a4aae4
                if (comma == string::npos) {
Packit a4aae4
                    d_dods_no_proxy_for_protocol = "http";
Packit a4aae4
                    d_dods_no_proxy_for_host = no_proxy;
Packit a4aae4
                    d_dods_no_proxy_for = true;
Packit a4aae4
                }
Packit a4aae4
                else {
Packit a4aae4
                    d_dods_no_proxy_for_protocol = no_proxy.substr(0, comma);
Packit a4aae4
                    d_dods_no_proxy_for_host = no_proxy.substr(comma + 1);
Packit a4aae4
                    d_dods_no_proxy_for = true;
Packit a4aae4
                }
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        //delete [] tempstr; tempstr = 0;
Packit a4aae4
Packit a4aae4
        fpi.close(); // Close the .dodsrc file. 12/14/99 jhrg
Packit a4aae4
Packit a4aae4
        return true;
Packit a4aae4
    }  // End of cache file parsing.
Packit a4aae4
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Helper for check_env_var(). This is its main logic, separated out for the
Packit a4aae4
// cases under WIN32 where we don't use an environment variable.  09/19/03
Packit a4aae4
// jhrg
Packit a4aae4
string RCReader::check_string(string env_var)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Entering check_string... (" << env_var << ")" << endl);
Packit a4aae4
    struct stat stat_info;
Packit a4aae4
Packit a4aae4
    if (stat(env_var.c_str(), &stat_info) != 0) {
Packit a4aae4
        DBG(cerr << "stat returned non-zero" << endl);
Packit a4aae4
        return "";  // ENV VAR not a file or dir, bail
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    if (S_ISREG(stat_info.st_mode)) {
Packit a4aae4
        DBG(cerr << "S_ISREG: " << S_ISREG(stat_info.st_mode) << endl);
Packit a4aae4
        return env_var;  // ENV VAR is a file, use it
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // ENV VAR is a directory, does it contain .dodsrc? Can we create
Packit a4aae4
    // .dodsrc if it's not there?
Packit a4aae4
    if (S_ISDIR(stat_info.st_mode)) {
Packit a4aae4
        DBG(cerr << "S_ISDIR: " << S_ISDIR(stat_info.st_mode) << endl);
Packit a4aae4
        if (*env_var.rbegin() != DIR_SEP_CHAR) // Add trailing / if missing
Packit a4aae4
            env_var += DIR_SEP_STRING;
Packit a4aae4
        // Trick: set d_cache_root here in case we're going to create the
Packit a4aae4
        // .dodsrc later on. If the .dodsrc file exists, its value will
Packit a4aae4
        // overwrite this value, if not write_rc_file() will use the correct
Packit a4aae4
        // value. 09/19/03 jhrg
Packit a4aae4
        d_cache_root = env_var + string(".dods_cache") + DIR_SEP_STRING;
Packit a4aae4
        env_var += ".dodsrc";
Packit a4aae4
        if (stat(env_var.c_str(), &stat_info) == 0 && S_ISREG(stat_info.st_mode)) {
Packit a4aae4
            DBG(cerr << "Found .dodsrc in \"" << env_var << "\"" << endl);
Packit a4aae4
            return env_var; // Found .dodsrc in ENV VAR
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        // Didn't find .dodsrc in ENV VAR and ENV VAR is a directory; try to
Packit a4aae4
        // create it. Note write_rc_file uses d_cache_root (set above) when
Packit a4aae4
        // it creates the RC file's contents.
Packit a4aae4
        if (write_rc_file(env_var)) {
Packit a4aae4
            DBG(cerr << "Wrote .dodsrc in \"" << env_var << "\"" << endl);
Packit a4aae4
            return env_var;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // If we're here, then we've neither found nor created the RC file.
Packit a4aae4
    DBG(cerr << "could neither find nor create a .dodsrc file" << endl);
Packit a4aae4
    return "";
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Examine an environment variable. If the env variable is set, then if
Packit a4aae4
 this is the name of a file, use that as the name of the RC file. If this
Packit a4aae4
 is the name of a directory, look in that directory for a file called
Packit a4aae4
 .dodsrc. If there's no such file, create it using default values for its
Packit a4aae4
 parameters. In the last case, write the .dodsrc so that the .dods_cache
Packit a4aae4
 directory is located in the directory named by DODS_CONF.
Packit a4aae4
Packit a4aae4
 @return The pathname to the RC file or "" if another variable/method
Packit a4aae4
 should be used to find/create the RC file. */
Packit a4aae4
string RCReader::check_env_var(const string &variable_name)
Packit a4aae4
{
Packit a4aae4
    char *ev = getenv(variable_name.c_str());
Packit a4aae4
    if (!ev || strlen(ev) == 0) return "";
Packit a4aae4
Packit a4aae4
    return check_string(ev);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
RCReader::RCReader() // throw (Error) jhrg 7/2/15
Packit a4aae4
{
Packit a4aae4
    d_rc_file_path = "";
Packit a4aae4
    d_cache_root = "";
Packit a4aae4
Packit a4aae4
    // ** Set default values **
Packit a4aae4
    // Users must explicitly turn caching on.
Packit a4aae4
    _dods_use_cache = false;
Packit a4aae4
    _dods_cache_max = 20;
Packit a4aae4
    _dods_cached_obj = 5;
Packit a4aae4
    _dods_ign_expires = 0;
Packit a4aae4
    _dods_default_expires = 86400;
Packit a4aae4
    _dods_always_validate = 0;
Packit a4aae4
Packit a4aae4
    _dods_deflate = 0;
Packit a4aae4
    d_validate_ssl = 1;
Packit a4aae4
Packit a4aae4
    //flags for PROXY_SERVER=<protocol>,<host url>
Packit a4aae4
    // New syntax PROXY_SERVER=[http://][user:pw@]host[:port]
Packit a4aae4
    d_dods_proxy_server_protocol = "";
Packit a4aae4
    d_dods_proxy_server_host = "";
Packit a4aae4
    d_dods_proxy_server_port = 0;
Packit a4aae4
    d_dods_proxy_server_userpw = "";
Packit a4aae4
Packit a4aae4
    _dods_proxy_server_host_url = ""; // deprecated
Packit a4aae4
Packit a4aae4
    // PROXY_FOR is deprecated.
Packit a4aae4
    // flags for PROXY_FOR=<regex>,<proxy host url>,<flags>
Packit a4aae4
    _dods_proxy_for = false; // true if proxy_for is used.
Packit a4aae4
    _dods_proxy_for_regexp = "";
Packit a4aae4
    _dods_proxy_for_proxy_host_url = "";
Packit a4aae4
    _dods_proxy_for_regexp_flags = 0;
Packit a4aae4
Packit a4aae4
    //flags for NO_PROXY_FOR=<protocol>,<host>,<port>
Packit a4aae4
    // New syntax NO_PROXY_FOR=<host|domain>
Packit a4aae4
    d_dods_no_proxy_for = false;
Packit a4aae4
    d_dods_no_proxy_for_protocol = ""; // deprecated
Packit a4aae4
    d_dods_no_proxy_for_host = "";
Packit a4aae4
    // default to port 0 if not specified. This means all ports. Using 80
Packit a4aae4
    // will fail when the URL does not contain the port number. That's
Packit a4aae4
    // probably a bug in libwww. 10/23/2000 jhrg
Packit a4aae4
    _dods_no_proxy_for_port = 0; // deprecated
Packit a4aae4
Packit a4aae4
    d_cookie_jar = "";
Packit a4aae4
Packit a4aae4
#ifdef WIN32
Packit a4aae4
    string homedir = string("C:") + string(DIR_SEP_STRING) + string("Dods");
Packit a4aae4
    d_rc_file_path = check_string(homedir);
Packit a4aae4
    if (d_rc_file_path.empty()) {
Packit a4aae4
        homedir = string("C:") + string(DIR_SEP_STRING) + string("opendap");
Packit a4aae4
        d_rc_file_path = check_string(homedir);
Packit a4aae4
    }
Packit a4aae4
    //  Normally, I'd prefer this for WinNT-based systems.
Packit a4aae4
    if (d_rc_file_path.empty())
Packit a4aae4
    d_rc_file_path = check_env_var("APPDATA");
Packit a4aae4
    if (d_rc_file_path.empty())
Packit a4aae4
    d_rc_file_path = check_env_var("TEMP");
Packit a4aae4
    if (d_rc_file_path.empty())
Packit a4aae4
    d_rc_file_path = check_env_var("TMP");
Packit a4aae4
#else
Packit a4aae4
    d_rc_file_path = check_env_var("DODS_CONF");
Packit a4aae4
    if (d_rc_file_path.empty()) d_rc_file_path = check_env_var("HOME");
Packit a4aae4
#endif
Packit a4aae4
    DBG(cerr << "Looking for .dodsrc in: " << d_rc_file_path << endl);
Packit a4aae4
Packit a4aae4
    if (!d_rc_file_path.empty()) read_rc_file(d_rc_file_path);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
RCReader::~RCReader()
Packit a4aae4
{
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Static void private method. */
Packit a4aae4
void RCReader::delete_instance()
Packit a4aae4
{
Packit a4aae4
    if (RCReader::_instance) {
Packit a4aae4
        delete RCReader::_instance;
Packit a4aae4
        RCReader::_instance = 0;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Static void private method. */
Packit a4aae4
void RCReader::initialize_instance()
Packit a4aae4
{
Packit a4aae4
    DBGN(cerr << "RCReader::initialize_instance() ... ");
Packit a4aae4
Packit a4aae4
    RCReader::_instance = new RCReader;
Packit a4aae4
    atexit(RCReader::delete_instance);
Packit a4aae4
Packit a4aae4
    DBG(cerr << "exiting." << endl);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
RCReader*
Packit a4aae4
RCReader::instance()
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Entring RCReader::instance" << endl);
Packit a4aae4
    // The instance_control variable is defined at the top of this file.
Packit a4aae4
    // 08/07/02 jhrg
Packit a4aae4
    pthread_once(&instance_control, initialize_instance);
Packit a4aae4
Packit a4aae4
    DBG(cerr << "Instance value: " << hex << _instance << dec << endl);
Packit a4aae4
Packit a4aae4
    return _instance;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
RCReader*
Packit a4aae4
RCReader::instance(const string &rc_file_path)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Entring RCReader::instance" << endl);
Packit a4aae4
Packit a4aae4
    d_rc_file_path = rc_file_path;
Packit a4aae4
    // The instance_control variable is defined at the top of this file.
Packit a4aae4
    // 08/07/02 jhrg
Packit a4aae4
    pthread_once(&instance_control, initialize_instance);
Packit a4aae4
Packit a4aae4
    DBG(cerr << "Instance value: " << hex << _instance << dec << endl);
Packit a4aae4
Packit a4aae4
    return _instance;
Packit a4aae4
}
Packit a4aae4
#endif
Packit a4aae4
} // namespace libdap