1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include <string.h>
7 #include <stdlib.h>
8 #include "primpl.h"
9 #include "prmem.h"
10
11 #if defined(XP_UNIX)
12 #include <unistd.h>
13 #if defined(DARWIN)
14 #if defined(HAVE_CRT_EXTERNS_H)
15 #include <crt_externs.h>
16 #endif /* HAVE_CRT_EXTERNS_H */
17 #else /* DARWIN */
18 PR_IMPORT_DATA(char **) environ;
19 #endif /* DARWIN */
20 #endif /* XP_UNIX */
21
22 #if !defined(HAVE_SECURE_GETENV) && defined(HAVE___SECURE_GETENV)
23 #define secure_getenv __secure_getenv
24 #define HAVE_SECURE_GETENV 1
25 #endif
26
27 /* Lock used to lock the environment */
28 #if defined(_PR_NO_PREEMPT)
29 #define _PR_NEW_LOCK_ENV()
30 #define _PR_DELETE_LOCK_ENV()
31 #define _PR_LOCK_ENV()
32 #define _PR_UNLOCK_ENV()
33 #elif defined(_PR_LOCAL_THREADS_ONLY)
34 extern _PRCPU * _pr_primordialCPU;
35 static PRIntn _is;
36 #define _PR_NEW_LOCK_ENV()
37 #define _PR_DELETE_LOCK_ENV()
38 #define _PR_LOCK_ENV() if (_pr_primordialCPU) _PR_INTSOFF(_is);
39 #define _PR_UNLOCK_ENV() if (_pr_primordialCPU) _PR_INTSON(_is);
40 #else
41 static PRLock *_pr_envLock = NULL;
42 #define _PR_NEW_LOCK_ENV() {_pr_envLock = PR_NewLock();}
43 #define _PR_DELETE_LOCK_ENV() \
44 { if (_pr_envLock) { PR_DestroyLock(_pr_envLock); _pr_envLock = NULL; } }
45 #define _PR_LOCK_ENV() { if (_pr_envLock) PR_Lock(_pr_envLock); }
46 #define _PR_UNLOCK_ENV() { if (_pr_envLock) PR_Unlock(_pr_envLock); }
47 #endif
48
49 /************************************************************************/
50
_PR_InitEnv(void)51 void _PR_InitEnv(void)
52 {
53 _PR_NEW_LOCK_ENV();
54 }
55
_PR_CleanupEnv(void)56 void _PR_CleanupEnv(void)
57 {
58 _PR_DELETE_LOCK_ENV();
59 }
60
PR_GetEnv(const char * var)61 PR_IMPLEMENT(char*) PR_GetEnv(const char *var)
62 {
63 char *ev;
64
65 if (!_pr_initialized) {
66 _PR_ImplicitInitialization();
67 }
68
69 _PR_LOCK_ENV();
70 ev = _PR_MD_GET_ENV(var);
71 _PR_UNLOCK_ENV();
72 return ev;
73 }
74
PR_GetEnvSecure(const char * var)75 PR_IMPLEMENT(char*) PR_GetEnvSecure(const char *var)
76 {
77 #ifdef HAVE_SECURE_GETENV
78 char *ev;
79
80 if (!_pr_initialized) {
81 _PR_ImplicitInitialization();
82 }
83
84 _PR_LOCK_ENV();
85 ev = secure_getenv(var);
86 _PR_UNLOCK_ENV();
87
88 return ev;
89 #else
90 #ifdef XP_UNIX
91 /*
92 ** Fall back to checking uids and gids. This won't detect any other
93 ** privilege-granting mechanisms the platform may have. This also
94 ** can't detect the case where the process already called
95 ** setuid(geteuid()) and/or setgid(getegid()).
96 */
97 if (getuid() != geteuid() || getgid() != getegid()) {
98 return NULL;
99 }
100 #endif /* XP_UNIX */
101 return PR_GetEnv(var);
102 #endif /* HAVE_SECURE_GETENV */
103 }
104
PR_SetEnv(const char * string)105 PR_IMPLEMENT(PRStatus) PR_SetEnv(const char *string)
106 {
107 PRIntn result;
108
109 if (!_pr_initialized) {
110 _PR_ImplicitInitialization();
111 }
112
113 if (!strchr(string, '=')) {
114 return(PR_FAILURE);
115 }
116
117 _PR_LOCK_ENV();
118 result = _PR_MD_PUT_ENV((char*)string);
119 _PR_UNLOCK_ENV();
120 return result ? PR_FAILURE : PR_SUCCESS;
121 }
122
123 #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H))
PR_DuplicateEnvironment(void)124 PR_IMPLEMENT(char **) PR_DuplicateEnvironment(void)
125 {
126 char **the_environ, **result, **end, **src, **dst;
127
128 _PR_LOCK_ENV();
129 #ifdef DARWIN
130 the_environ = *(_NSGetEnviron());
131 #else
132 the_environ = environ;
133 #endif
134
135 for (end = the_environ; *end != NULL; end++)
136 /* empty loop body */;
137
138 result = (char **)PR_Malloc(sizeof(char *) * (end - the_environ + 1));
139 if (result != NULL) {
140 for (src = the_environ, dst = result; src != end; src++, dst++) {
141 size_t len;
142
143 len = strlen(*src) + 1;
144 *dst = PR_Malloc(len);
145 if (*dst == NULL) {
146 /* Allocation failed. Must clean up the half-copied env. */
147 char **to_delete;
148
149 for (to_delete = result; to_delete != dst; to_delete++) {
150 PR_Free(*to_delete);
151 }
152 PR_Free(result);
153 result = NULL;
154 goto out;
155 }
156 memcpy(*dst, *src, len);
157 }
158 *dst = NULL;
159 }
160 out:
161 _PR_UNLOCK_ENV();
162 return result;
163 }
164 #else
165 /* This platform doesn't support raw access to the environ block. */
PR_DuplicateEnvironment(void)166 PR_IMPLEMENT(char **) PR_DuplicateEnvironment(void)
167 {
168 return NULL;
169 }
170 #endif
171