Back to index

lightning-sunbird  0.9+nobinonly
nsEnvironment.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla embedding code.
00016  *
00017  * The Initial Developers of the Original Code are
00018  * Benjamin Smedberg <bsmedberg@covad.net> and 
00019  * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
00020  *
00021  * Portions created by the Initial Developer are Copyright (C) 2003/2004
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsEnvironment.h"
00041 #include "prenv.h"
00042 #include "prprf.h"
00043 #include "nsAutoLock.h"
00044 #include "nsBaseHashtable.h"
00045 #include "nsHashKeys.h"
00046 #include "nsPromiseFlatString.h"
00047 #include "nsDependentString.h"
00048 #include "nsNativeCharsetUtils.h"
00049 
00050 NS_IMPL_THREADSAFE_ISUPPORTS1(nsEnvironment, nsIEnvironment)
00051 
00052 NS_METHOD
00053 nsEnvironment::Create(nsISupports *aOuter, REFNSIID aIID,
00054                       void **aResult)
00055 {
00056     nsresult rv;
00057     *aResult = nsnull;
00058 
00059     if (aOuter != nsnull) {
00060         return NS_ERROR_NO_AGGREGATION;
00061     }
00062 
00063     nsEnvironment* obj = new nsEnvironment();
00064     if (!obj) {
00065         return NS_ERROR_OUT_OF_MEMORY;
00066     }
00067 
00068     obj->mLock = PR_NewLock();
00069     if (!obj->mLock) {
00070         delete obj;
00071         return NS_ERROR_OUT_OF_MEMORY;
00072     }
00073 
00074     rv = obj->QueryInterface(aIID, aResult);
00075     if (NS_FAILED(rv)) {
00076       delete obj;
00077     }
00078     return rv;
00079 }
00080 
00081 nsEnvironment::~nsEnvironment()
00082 {
00083     if (mLock)
00084         PR_DestroyLock(mLock);
00085 }
00086 
00087 NS_IMETHODIMP
00088 nsEnvironment::Exists(const nsAString& aName, PRBool *aOutValue)
00089 {
00090     nsCAutoString nativeName;
00091     nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
00092     NS_ENSURE_SUCCESS(rv, rv);
00093 
00094     nsCAutoString nativeVal;
00095 #if defined(XP_UNIX)
00096     /* For Unix/Linux platforms we follow the Unix definition:
00097      * An environment variable exists when |getenv()| returns a non-NULL value.
00098      * An environment variable does not exist when |getenv()| returns NULL.
00099      */
00100     const char *value = PR_GetEnv(nativeName.get());
00101     
00102     *aOutValue = (value)?(PR_TRUE):(PR_FALSE);
00103 #else
00104     /* For non-Unix/Linux platforms we have to fall back to a 
00105      * "portable" definition (which is incorrect for Unix/Linux!!!!)
00106      * which simply checks whether the string returned by |Get()| is empty
00107      * or not.
00108      */
00109     nsAutoString value;
00110     Get(aName, value);
00111     *aOutValue = (value.IsEmpty())?(PR_FALSE):(PR_TRUE);
00112 #endif /* XP_UNIX */
00113 
00114     return NS_OK;
00115 }
00116 
00117 NS_IMETHODIMP
00118 nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue)
00119 {
00120     nsCAutoString nativeName;
00121     nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
00122     NS_ENSURE_SUCCESS(rv, rv);
00123 
00124     nsCAutoString nativeVal;
00125     const char *value = PR_GetEnv(nativeName.get());
00126     if (value) {
00127         rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue);
00128     } else {
00129         aOutValue.Truncate();
00130         rv = NS_OK;
00131     }
00132 
00133     return rv;
00134 }
00135 
00136 /* Environment strings must have static duration; We're gonna leak all of this
00137  * at shutdown: this is by design, caused how Unix/Linux implement environment
00138  * vars. 
00139  */
00140 
00141 typedef nsBaseHashtableET<nsCStringHashKey,char*> EnvEntryType;
00142 typedef nsTHashtable<EnvEntryType> EnvHashType;
00143 
00144 static EnvHashType *gEnvHash = nsnull;
00145 
00146 static PRBool
00147 EnsureEnvHash()
00148 {
00149     if (gEnvHash)
00150         return PR_TRUE;
00151 
00152     gEnvHash = new EnvHashType;
00153     if (!gEnvHash)
00154         return PR_FALSE;
00155 
00156     if(gEnvHash->Init())
00157         return PR_TRUE;
00158 
00159     delete gEnvHash;
00160     gEnvHash = nsnull;
00161     return PR_FALSE;
00162 }
00163 
00164 NS_IMETHODIMP
00165 nsEnvironment::Set(const nsAString& aName, const nsAString& aValue)
00166 {
00167     nsCAutoString nativeName;
00168     nsCAutoString nativeVal;
00169 
00170     nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
00171     NS_ENSURE_SUCCESS(rv, rv);
00172 
00173     rv = NS_CopyUnicodeToNative(aValue, nativeVal);
00174     NS_ENSURE_SUCCESS(rv, rv);
00175 
00176     nsAutoLock lock(mLock); // autolock unlocks automagically
00177 
00178     if (!EnsureEnvHash()){
00179         return NS_ERROR_UNEXPECTED;
00180     }
00181 
00182     EnvEntryType* entry = gEnvHash->PutEntry(nativeName);
00183     if (!entry) {
00184         return NS_ERROR_OUT_OF_MEMORY;
00185     }
00186     
00187     char* newData = PR_smprintf("%s=%s",
00188                                 nativeName.get(),
00189                                 nativeVal.get());
00190     if (!newData) {
00191         return NS_ERROR_OUT_OF_MEMORY;
00192     } 
00193     
00194     PR_SetEnv(newData);
00195     if (entry->mData) {
00196         PR_smprintf_free(entry->mData);
00197     }
00198     entry->mData = newData;
00199     return NS_OK;
00200 }
00201 
00202