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