prenv.c (4475B)
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 { _pr_envLock = PR_NewLock(); } 46 # define _PR_DELETE_LOCK_ENV() \ 47 { \ 48 if (_pr_envLock) { \ 49 PR_DestroyLock(_pr_envLock); \ 50 _pr_envLock = NULL; \ 51 } \ 52 } 53 # define _PR_LOCK_ENV() \ 54 { \ 55 if (_pr_envLock) PR_Lock(_pr_envLock); \ 56 } 57 # define _PR_UNLOCK_ENV() \ 58 { \ 59 if (_pr_envLock) PR_Unlock(_pr_envLock); \ 60 } 61 #endif 62 63 /************************************************************************/ 64 65 void _PR_InitEnv(void) { _PR_NEW_LOCK_ENV(); } 66 67 void _PR_CleanupEnv(void) { _PR_DELETE_LOCK_ENV(); } 68 69 PR_IMPLEMENT(char*) PR_GetEnv(const char* var) { 70 char* ev; 71 72 if (!_pr_initialized) { 73 _PR_ImplicitInitialization(); 74 } 75 76 _PR_LOCK_ENV(); 77 ev = _PR_MD_GET_ENV(var); 78 _PR_UNLOCK_ENV(); 79 return ev; 80 } 81 82 PR_IMPLEMENT(char*) PR_GetEnvSecure(const char* var) { 83 #ifdef HAVE_SECURE_GETENV 84 char* ev; 85 86 if (!_pr_initialized) { 87 _PR_ImplicitInitialization(); 88 } 89 90 _PR_LOCK_ENV(); 91 ev = secure_getenv(var); 92 _PR_UNLOCK_ENV(); 93 94 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 } 110 111 PR_IMPLEMENT(PRStatus) PR_SetEnv(const char* string) { 112 PRIntn result; 113 114 if (!_pr_initialized) { 115 _PR_ImplicitInitialization(); 116 } 117 118 if (!strchr(string, '=')) { 119 return (PR_FAILURE); 120 } 121 122 _PR_LOCK_ENV(); 123 result = _PR_MD_PUT_ENV((char*)string); 124 _PR_UNLOCK_ENV(); 125 return result ? PR_FAILURE : PR_SUCCESS; 126 } 127 128 #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H)) 129 PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) { 130 char **the_environ, **result, **end, **src, **dst; 131 132 _PR_LOCK_ENV(); 133 # ifdef DARWIN 134 the_environ = *(_NSGetEnviron()); 135 # else 136 the_environ = environ; 137 # endif 138 139 for (end = the_environ; *end != NULL; end++) /* empty loop body */; 140 141 result = (char**)PR_Malloc(sizeof(char*) * (end - the_environ + 1)); 142 if (result != NULL) { 143 for (src = the_environ, dst = result; src != end; src++, dst++) { 144 size_t len; 145 146 len = strlen(*src) + 1; 147 *dst = PR_Malloc(len); 148 if (*dst == NULL) { 149 /* Allocation failed. Must clean up the half-copied env. */ 150 char** to_delete; 151 152 for (to_delete = result; to_delete != dst; to_delete++) { 153 PR_Free(*to_delete); 154 } 155 PR_Free(result); 156 result = NULL; 157 goto out; 158 } 159 memcpy(*dst, *src, len); 160 } 161 *dst = NULL; 162 } 163 out: 164 _PR_UNLOCK_ENV(); 165 return result; 166 } 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