Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/threads/nsEnvironment.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsEnvironment.h"
8
#include "prenv.h"
9
#include "nsBaseHashtable.h"
10
#include "nsHashKeys.h"
11
#include "nsPromiseFlatString.h"
12
#include "nsDependentString.h"
13
#include "nsNativeCharsetUtils.h"
14
#include "mozilla/Printf.h"
15
16
using namespace mozilla;
17
18
NS_IMPL_ISUPPORTS(nsEnvironment, nsIEnvironment)
19
20
nsresult
21
nsEnvironment::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
22
0
{
23
0
  nsresult rv;
24
0
  *aResult = nullptr;
25
0
26
0
  if (aOuter) {
27
0
    return NS_ERROR_NO_AGGREGATION;
28
0
  }
29
0
30
0
  nsEnvironment* obj = new nsEnvironment();
31
0
32
0
  rv = obj->QueryInterface(aIID, aResult);
33
0
  if (NS_FAILED(rv)) {
34
0
    delete obj;
35
0
  }
36
0
  return rv;
37
0
}
38
39
nsEnvironment::~nsEnvironment()
40
0
{
41
0
}
42
43
NS_IMETHODIMP
44
nsEnvironment::Exists(const nsAString& aName, bool* aOutValue)
45
0
{
46
0
  nsAutoCString nativeName;
47
0
  nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
48
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
49
0
    return rv;
50
0
  }
51
0
52
0
  nsAutoCString nativeVal;
53
0
#if defined(XP_UNIX)
54
0
  /* For Unix/Linux platforms we follow the Unix definition:
55
0
   * An environment variable exists when |getenv()| returns a non-nullptr
56
0
   * value. An environment variable does not exist when |getenv()| returns
57
0
   * nullptr.
58
0
   */
59
0
  const char* value = PR_GetEnv(nativeName.get());
60
0
  *aOutValue = value && *value;
61
#else
62
  /* For non-Unix/Linux platforms we have to fall back to a
63
   * "portable" definition (which is incorrect for Unix/Linux!!!!)
64
   * which simply checks whether the string returned by |Get()| is empty
65
   * or not.
66
   */
67
  nsAutoString value;
68
  Get(aName, value);
69
  *aOutValue = !value.IsEmpty();
70
#endif /* XP_UNIX */
71
72
0
  return NS_OK;
73
0
}
74
75
NS_IMETHODIMP
76
nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue)
77
0
{
78
0
  nsAutoCString nativeName;
79
0
  nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
80
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
81
0
    return rv;
82
0
  }
83
0
84
0
  nsAutoCString nativeVal;
85
0
  const char* value = PR_GetEnv(nativeName.get());
86
0
  if (value && *value) {
87
0
    rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue);
88
0
  } else {
89
0
    aOutValue.Truncate();
90
0
    rv = NS_OK;
91
0
  }
92
0
93
0
  return rv;
94
0
}
95
96
/* Environment strings must have static duration; We're gonna leak all of this
97
 * at shutdown: this is by design, caused how Unix/Linux implement environment
98
 * vars.
99
 */
100
101
typedef nsBaseHashtableET<nsCharPtrHashKey, char*> EnvEntryType;
102
typedef nsTHashtable<EnvEntryType> EnvHashType;
103
104
static EnvHashType* gEnvHash = nullptr;
105
106
static bool
107
EnsureEnvHash()
108
0
{
109
0
  if (gEnvHash) {
110
0
    return true;
111
0
  }
112
0
113
0
  gEnvHash = new EnvHashType;
114
0
  if (!gEnvHash) {
115
0
    return false;
116
0
  }
117
0
118
0
  return true;
119
0
}
120
121
NS_IMETHODIMP
122
nsEnvironment::Set(const nsAString& aName, const nsAString& aValue)
123
0
{
124
0
  nsAutoCString nativeName;
125
0
  nsAutoCString nativeVal;
126
0
127
0
  nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
128
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
129
0
    return rv;
130
0
  }
131
0
132
0
  rv = NS_CopyUnicodeToNative(aValue, nativeVal);
133
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
134
0
    return rv;
135
0
  }
136
0
137
0
  MutexAutoLock lock(mLock);
138
0
139
0
  if (!EnsureEnvHash()) {
140
0
    return NS_ERROR_UNEXPECTED;
141
0
  }
142
0
143
0
  EnvEntryType* entry = gEnvHash->PutEntry(nativeName.get());
144
0
  if (!entry) {
145
0
    return NS_ERROR_OUT_OF_MEMORY;
146
0
  }
147
0
148
0
  SmprintfPointer newData = mozilla::Smprintf("%s=%s",
149
0
                                              nativeName.get(),
150
0
                                              nativeVal.get());
151
0
  if (!newData) {
152
0
    return NS_ERROR_OUT_OF_MEMORY;
153
0
  }
154
0
155
0
  PR_SetEnv(newData.get());
156
0
  if (entry->mData) {
157
0
    free(entry->mData);
158
0
  }
159
0
  entry->mData = newData.release();
160
0
  return NS_OK;
161
0
}
162
163