1/* 2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// globalizer - multiscope globalization services. 27// 28// This is a tentative, partial implementation. 29// Status: 30// module scope: constructs, optional cleanup 31// thread scope: constructs, optional cleanup 32// process scope: not implemented (obsolete implementation, unused) 33// system scope: not implemented (probably never will) 34// 35// @@@ Assumption: {bool,T*} atomic unless PTHREAD_STRICT 36// 37#include <security_utilities/globalizer.h> 38#include <security_utilities/debugging.h> 39#include <cstdlib> 40#include <stdexcept> 41 42// 43// The Error class thrown if Nexus operations fail 44// 45GlobalNexus::Error::~Error() throw() 46{ 47} 48 49void ModuleNexusCommon::do_create(void *(*make)()) 50{ 51 try 52 { 53 pointer = make(); 54 } 55 catch (...) 56 { 57 pointer = NULL; 58 } 59} 60 61 62 63void *ModuleNexusCommon::create(void *(*make)()) 64{ 65 dispatch_once(&once, ^{do_create(make);}); 66 67 if (pointer == NULL) 68 { 69 ModuleNexusError::throwMe(); 70 } 71 72 return pointer; 73} 74 75 76// 77// Process nexus operation 78// 79ProcessNexusBase::ProcessNexusBase(const char *identifier) 80{ 81 const char *env = getenv(identifier); 82 if (env == NULL) { // perhaps we're first... 83 auto_ptr<Store> store(new Store); 84 char form[2*sizeof(Store *) + 2]; 85 sprintf(form, "*%p", &store); 86 setenv(identifier, form, 0); // do NOT overwrite... 87 env = getenv(identifier); // ... and refetch to resolve races 88 if (sscanf(env, "*%p", &mStore) != 1) 89 throw std::runtime_error("environment communication failed"); 90 if (mStore == store.get()) // we won the race... 91 store.release(); // ... so keep the store 92 } else 93 if (sscanf(env, "*%p", &mStore) != 1) 94 throw std::runtime_error("environment communication failed"); 95} 96