| /* |
| * Copyright (c) 2008-2009 Brent Fulgham <bfulgham@gmail.org>. All rights reserved. |
| * |
| * This source code is a modified version of the CoreFoundation sources released by Apple Inc. under |
| * the terms of the APSL version 2.0 (see below). |
| * |
| * For information about changes from the original Apple source release can be found by reviewing the |
| * source control system for the project at https://sourceforge.net/svn/?group_id=246198. |
| * |
| * The original license information is as follows: |
| * |
| * Copyright (c) 2008 Apple Inc. All rights reserved. |
| * |
| * @APPLE_LICENSE_HEADER_START@ |
| * |
| * This file contains Original Code and/or Modifications of Original Code |
| * as defined in and that are subject to the Apple Public Source License |
| * Version 2.0 (the 'License'). You may not use this file except in |
| * compliance with the License. Please obtain a copy of the License at |
| * http://www.opensource.apple.com/apsl/ and read it before using this |
| * file. |
| * |
| * The Original Code and all software distributed under the License are |
| * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
| * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
| * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
| * Please see the License for the specific language governing rights and |
| * limitations under the License. |
| * |
| * @APPLE_LICENSE_HEADER_END@ |
| */ |
| /* CFStringDefaultEncoding.h |
| Copyright (c) 1998-2007, Apple Inc. All rights reserved. |
| */ |
| |
| #if !defined(__COREFOUNDATION_CFSTRINGDEFAULTENCODING__) |
| #define __COREFOUNDATION_CFSTRINGDEFAULTENCODING__ 1 |
| |
| /* This file defines static inline functions used both by CarbonCore & CF. */ |
| |
| #include <CoreFoundation/CFBase.h> |
| |
| #if defined(__MACH__) |
| #include <stdlib.h> |
| #include <fcntl.h> |
| #include <pwd.h> |
| #include <sys/param.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <xlocale.h> |
| |
| CF_EXTERN_C_BEGIN |
| |
| #define __kCFUserEncodingEnvVariableName ("__CF_USER_TEXT_ENCODING") |
| #define __kCFMaxDefaultEncodingFileLength (24) |
| #define __kCFUserEncodingFileName ("/.CFUserTextEncoding") |
| |
| /* This function is used to obtain users' default script/region code. |
| The function first looks at environment variable __kCFUserEncodingEnvVariableName, then, reads the configuration file in user's home directory. |
| */ |
| CF_INLINE void __CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) { |
| char *stringValue; |
| char buffer[__kCFMaxDefaultEncodingFileLength]; |
| int uid = getuid(); |
| |
| if ((stringValue = getenv(__kCFUserEncodingEnvVariableName)) != NULL) { |
| if ((uid == strtol_l(stringValue, &stringValue, 0, NULL)) && (':' == *stringValue)) { |
| ++stringValue; |
| } else { |
| stringValue = NULL; |
| } |
| } |
| |
| if ((stringValue == NULL) && ((uid > 0) || getenv("HOME"))) { |
| struct passwd *passwdp; |
| |
| if ((passwdp = getpwuid((uid_t)uid))) { |
| char filename[MAXPATHLEN + 1]; |
| |
| const char *path = NULL; |
| if (!_CFIsSetUgid()) { |
| path = getenv("CFFIXED_USER_HOME"); |
| } |
| if (!path) { |
| path = passwdp->pw_dir; |
| } |
| |
| strlcpy(filename, path, sizeof(filename)); |
| strlcat(filename, __kCFUserEncodingFileName, sizeof(filename)); |
| |
| int no_hang_fd = open("/dev/autofs_nowait", 0); |
| int fd = open(filename, O_RDONLY, 0); |
| if (fd == -1) { |
| // Cannot open the file. Let's fallback to smRoman/verUS |
| snprintf(filename, sizeof(filename), "0x%X:0:0", uid); |
| setenv(__kCFUserEncodingEnvVariableName, filename, 1); |
| } else { |
| int readSize; |
| |
| // cjk: We do not turn on F_NOCACHE on the fd here, because |
| // many processes read this file on startup, and caching the |
| // is probably a good thing, for the system as a whole. |
| readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1); |
| buffer[(readSize < 0 ? 0 : readSize)] = '\0'; |
| close(fd); |
| stringValue = buffer; |
| |
| // Well, we already have a buffer, let's reuse it |
| snprintf(filename, sizeof(filename), "0x%X:%s", uid, buffer); |
| setenv(__kCFUserEncodingEnvVariableName, filename, 1); |
| } |
| close(no_hang_fd); |
| } |
| } |
| |
| if (stringValue) { |
| *oScriptValue = strtol_l(stringValue, &stringValue, 0, NULL); |
| if (*stringValue == ':') { |
| if (oRegionValue) *oRegionValue = strtol_l(++stringValue, NULL, 0, NULL); |
| return; |
| } |
| } |
| |
| // Falling back |
| *oScriptValue = 0; // smRoman |
| if (oRegionValue) *oRegionValue = 0; // verUS |
| } |
| |
| CF_INLINE uint32_t __CFStringGetInstallationRegion() { |
| char *stringValue = NULL; |
| char buffer[__kCFMaxDefaultEncodingFileLength]; |
| struct passwd *passwdp; |
| |
| if ((passwdp = getpwuid((uid_t)0))) { |
| char filename[MAXPATHLEN + 1]; |
| |
| const char *path = NULL; |
| if (!_CFIsSetUgid()) { |
| path = getenv("CFFIXED_USER_HOME"); |
| } |
| if (!path) { |
| path = passwdp->pw_dir; |
| } |
| |
| strlcpy(filename, path, sizeof(filename)); |
| strlcat(filename, __kCFUserEncodingFileName, sizeof(filename)); |
| |
| int no_hang_fd = open("/dev/autofs_nowait", 0); |
| int fd = open(filename, O_RDONLY, 0); |
| if (fd == -1) { |
| int readSize; |
| |
| // cjk: We do not turn on F_NOCACHE on the fd here, because |
| // many processes read this file on startup, and caching the |
| // is probably a good thing, for the system as a whole. |
| readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1); |
| buffer[(readSize < 0 ? 0 : readSize)] = '\0'; |
| close(fd); |
| stringValue = buffer; |
| } |
| close(no_hang_fd); |
| } |
| |
| if (stringValue) { |
| (void)strtol_l(stringValue, &stringValue, 0, NULL); |
| if (*stringValue == ':') return strtol_l(++stringValue, NULL, 0, NULL); |
| } |
| |
| return 0; // verUS |
| } |
| |
| CF_INLINE void __CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) { |
| char *stringValue = NULL; |
| char buffer[__kCFMaxDefaultEncodingFileLength]; |
| struct passwd *passwdp; |
| |
| *encoding = 0; *region = 0; |
| |
| if ((passwdp = getpwuid((uid_t)0))) { |
| char filename[MAXPATHLEN + 1]; |
| |
| const char *path = NULL; |
| if (!_CFIsSetUgid()) { |
| path = getenv("CFFIXED_USER_HOME"); |
| } |
| if (!path) { |
| path = passwdp->pw_dir; |
| } |
| |
| strlcpy(filename, path, sizeof(filename)); |
| strlcat(filename, __kCFUserEncodingFileName, sizeof(filename)); |
| |
| int no_hang_fd = open("/dev/autofs_nowait", 0); |
| int fd = open(filename, O_RDONLY, 0); |
| if (fd == -1) { |
| int readSize; |
| |
| readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1); |
| buffer[(readSize < 0 ? 0 : readSize)] = '\0'; |
| close(fd); |
| stringValue = buffer; |
| } |
| close(no_hang_fd); |
| } |
| |
| if (stringValue) { |
| *encoding = strtol_l(stringValue, &stringValue, 0, NULL); |
| if (*stringValue == ':') *region = strtol_l(++stringValue, NULL, 0, NULL); |
| } |
| } |
| |
| CF_INLINE void __CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) { |
| struct passwd *passwdp; |
| |
| if ((passwdp = getpwuid(getuid()))) { |
| char filename[MAXPATHLEN + 1]; |
| |
| const char *path = NULL; |
| if (!_CFIsSetUgid()) { |
| path = getenv("CFFIXED_USER_HOME"); |
| } |
| if (!path) { |
| path = passwdp->pw_dir; |
| } |
| |
| strlcpy(filename, path, sizeof(filename)); |
| strlcat(filename, __kCFUserEncodingFileName, sizeof(filename)); |
| |
| int no_hang_fd = open("/dev/autofs_nowait", 0); |
| (void)unlink(filename); // In case, file exists |
| int fd = open(filename, O_WRONLY|O_CREAT, 0400); |
| if (fd == -1) { |
| char buffer[__kCFMaxDefaultEncodingFileLength]; |
| unsigned int writeSize; |
| |
| writeSize = snprintf(buffer, __kCFMaxDefaultEncodingFileLength, "0x%X:0x%X", (unsigned int)iScriptValue, (unsigned int)iRegionValue); |
| (void)write(fd, buffer, (writeSize > __kCFMaxDefaultEncodingFileLength ? __kCFMaxDefaultEncodingFileLength : writeSize)); |
| close(fd); |
| } |
| close(no_hang_fd); |
| } |
| } |
| |
| CF_EXTERN_C_END |
| |
| #endif |
| |
| #endif /* ! __COREFOUNDATION_CFSTRINGDEFAULTENCODING__ */ |
| |