/src/nspr/pr/src/misc/prenv.c
Line | Count | Source (jump to first uncovered line) |
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() \ |
39 | | if (_pr_primordialCPU) _PR_INTSOFF(_is); |
40 | | # define _PR_UNLOCK_ENV() \ |
41 | | if (_pr_primordialCPU) _PR_INTSON(_is); |
42 | | #else |
43 | | static PRLock* _pr_envLock = NULL; |
44 | | # define _PR_NEW_LOCK_ENV() \ |
45 | 1 | { _pr_envLock = PR_NewLock(); } |
46 | | # define _PR_DELETE_LOCK_ENV() \ |
47 | 0 | { \ |
48 | 0 | if (_pr_envLock) { \ |
49 | 0 | PR_DestroyLock(_pr_envLock); \ |
50 | 0 | _pr_envLock = NULL; \ |
51 | 0 | } \ |
52 | 0 | } |
53 | | # define _PR_LOCK_ENV() \ |
54 | 17 | { \ |
55 | 17 | if (_pr_envLock) PR_Lock(_pr_envLock); \ |
56 | 17 | } |
57 | | # define _PR_UNLOCK_ENV() \ |
58 | 17 | { \ |
59 | 17 | if (_pr_envLock) PR_Unlock(_pr_envLock); \ |
60 | 17 | } |
61 | | #endif |
62 | | |
63 | | /************************************************************************/ |
64 | | |
65 | 1 | void _PR_InitEnv(void) { _PR_NEW_LOCK_ENV(); } |
66 | | |
67 | 0 | void _PR_CleanupEnv(void) { _PR_DELETE_LOCK_ENV(); } |
68 | | |
69 | 14 | PR_IMPLEMENT(char*) PR_GetEnv(const char* var) { |
70 | 14 | char* ev; |
71 | | |
72 | 14 | if (!_pr_initialized) { |
73 | 0 | _PR_ImplicitInitialization(); |
74 | 0 | } |
75 | | |
76 | 14 | _PR_LOCK_ENV(); |
77 | 14 | ev = _PR_MD_GET_ENV(var); |
78 | 14 | _PR_UNLOCK_ENV(); |
79 | 14 | return ev; |
80 | 14 | } |
81 | | |
82 | 3 | PR_IMPLEMENT(char*) PR_GetEnvSecure(const char* var) { |
83 | 3 | #ifdef HAVE_SECURE_GETENV |
84 | 3 | char* ev; |
85 | | |
86 | 3 | if (!_pr_initialized) { |
87 | 1 | _PR_ImplicitInitialization(); |
88 | 1 | } |
89 | | |
90 | 3 | _PR_LOCK_ENV(); |
91 | 3 | ev = secure_getenv(var); |
92 | 3 | _PR_UNLOCK_ENV(); |
93 | | |
94 | 3 | return ev; |
95 | | #else |
96 | | # ifdef XP_UNIX |
97 | | /* |
98 | | ** Fall back to checking uids and gids. This won't detect any other |
99 | | ** privilege-granting mechanisms the platform may have. This also |
100 | | ** can't detect the case where the process already called |
101 | | ** setuid(geteuid()) and/or setgid(getegid()). |
102 | | */ |
103 | | if (getuid() != geteuid() || getgid() != getegid()) { |
104 | | return NULL; |
105 | | } |
106 | | # endif /* XP_UNIX */ |
107 | | return PR_GetEnv(var); |
108 | | #endif /* HAVE_SECURE_GETENV */ |
109 | 3 | } |
110 | | |
111 | 0 | PR_IMPLEMENT(PRStatus) PR_SetEnv(const char* string) { |
112 | 0 | PRIntn result; |
113 | |
|
114 | 0 | if (!_pr_initialized) { |
115 | 0 | _PR_ImplicitInitialization(); |
116 | 0 | } |
117 | |
|
118 | 0 | if (!strchr(string, '=')) { |
119 | 0 | return (PR_FAILURE); |
120 | 0 | } |
121 | | |
122 | 0 | _PR_LOCK_ENV(); |
123 | 0 | result = _PR_MD_PUT_ENV((char*)string); |
124 | 0 | _PR_UNLOCK_ENV(); |
125 | 0 | return result ? PR_FAILURE : PR_SUCCESS; |
126 | 0 | } |
127 | | |
128 | | #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H)) |
129 | 0 | PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) { |
130 | 0 | char **the_environ, **result, **end, **src, **dst; |
131 | |
|
132 | 0 | _PR_LOCK_ENV(); |
133 | | # ifdef DARWIN |
134 | | the_environ = *(_NSGetEnviron()); |
135 | | # else |
136 | 0 | the_environ = environ; |
137 | 0 | # endif |
138 | |
|
139 | 0 | for (end = the_environ; *end != NULL; end++) /* empty loop body */; |
140 | |
|
141 | 0 | result = (char**)PR_Malloc(sizeof(char*) * (end - the_environ + 1)); |
142 | 0 | if (result != NULL) { |
143 | 0 | for (src = the_environ, dst = result; src != end; src++, dst++) { |
144 | 0 | size_t len; |
145 | |
|
146 | 0 | len = strlen(*src) + 1; |
147 | 0 | *dst = PR_Malloc(len); |
148 | 0 | if (*dst == NULL) { |
149 | | /* Allocation failed. Must clean up the half-copied env. */ |
150 | 0 | char** to_delete; |
151 | |
|
152 | 0 | for (to_delete = result; to_delete != dst; to_delete++) { |
153 | 0 | PR_Free(*to_delete); |
154 | 0 | } |
155 | 0 | PR_Free(result); |
156 | 0 | result = NULL; |
157 | 0 | goto out; |
158 | 0 | } |
159 | 0 | memcpy(*dst, *src, len); |
160 | 0 | } |
161 | 0 | *dst = NULL; |
162 | 0 | } |
163 | 0 | out: |
164 | 0 | _PR_UNLOCK_ENV(); |
165 | 0 | return result; |
166 | 0 | } |
167 | | #else |
168 | | /* This platform doesn't support raw access to the environ block. */ |
169 | | PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) { return NULL; } |
170 | | #endif |