/* * Copyright (c) 1999 Apple Computer, 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@ */ #ifdef __APPLE_PR3375657_HACK__ /* * When mutexes or spinlocks were added for thread safety, the system would * hang during the boot process, just after changing to the blue background. * So for the common case of not calling _s[eh]m_hack_{add,init}(), we just * use static name lists. This should be reinvestigated when there is time. */ #define PRIVATE __private_extern__ //#define SEM_DEBUG_FILE "/tmp/sem_names" //#define SHM_DEBUG_FILE "/tmp/shm_names" #if defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) #include #include #endif /* defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) */ #include #include #include #ifdef SEM_DEBUG_FILE #define SEM_PRINTF(fmt, args...) \ { \ FILE *_sem_fp_; \ if (access(SEM_DEBUG_FILE, F_OK) == 0 && \ (_sem_fp_ = fopen(SEM_DEBUG_FILE, "a")) != NULL) { \ fprintf(_sem_fp_, fmt, ## args); \ fclose(_sem_fp_); \ } \ } #endif /* SEM_DEBUG_FILE */ #ifdef SHM_DEBUG_FILE #define SHM_PRINTF(fmt, args...) \ { \ FILE *_shm_fp_; \ if (access(SHM_DEBUG_FILE, F_OK) == 0 && \ (_shm_fp_ = fopen(SHM_DEBUG_FILE, "a")) != NULL) { \ fprintf(_shm_fp_, fmt, ## args); \ fclose(_shm_fp_); \ } \ } #endif /* SHM_DEBUG_FILE */ /*----------------------------------------------------------------------- * For the Hack structure: * * first >= 0 starting serial number * first < 0 no serial number * last ending serial number (only if first >= 0) * debug whether an option 'D' can be appended *-----------------------------------------------------------------------*/ typedef struct { const char *name; int first; int last; int debug; } Hack; /*----------------------------------------------------------------------- * For the HackList structure: * * list the list of Hack structures * cur the number of valid Hack structures in list * max the actual number of Hack structures allocated *-----------------------------------------------------------------------*/ #define HACKLISTDELTA 16 #define HACKLISTSTART 16 typedef struct { const Hack *list; int cur; int max; } HackList; static const Hack sem_hack_default_names[] = { {"EDBPool", 1, 255, 0}, {"EDDPoolLock", -1, 0, 0}, {"Mso97SharedDg", 1920, 2047, 1}, {"Office", 1920, 2047, 1}, {"PT_EDBPool", 1, 255, 0}, {"PT_EDDPoolLock", -1, 0, 0}, {"PT_Mso97SharedDg", 1920, 2047, 0}, {"PT_Office", 1920, 2047, 0}, {"ShMemExtCritSection", -1, 0, 0}, {"ShMemIntCritSection", -1, 0, 0}, {NULL, 0, 0, 0}, }; static HackList sem_hack_defaults = { sem_hack_default_names, (sizeof(sem_hack_default_names) / sizeof(const Hack)) - 1, 0 }; static HackList *sem_hack_names = &sem_hack_defaults; static const Hack shm_hack_default_names[] = { {"EDBPool", 1, 255, 0}, {"EDDPoolLock", -1, 0, 0}, {"Mso97SharedDg", 1920, 2047, 1}, {"Office", 1920, 2047, 1}, {"PT_EDBPool", 1, 255, 0}, {"PT_EDDPoolLock", -1, 0, 0}, {"PT_Mso97SharedDg", 1920, 2047, 0}, {"PT_Office", 1920, 2047, 0}, {"PT_ShMemRefCount", -1, 0, 0}, /* not specified by MS, but seen */ {"ShMemRefCount", -1, 0, 0}, {NULL, 0, 0, 0}, }; static HackList shm_hack_defaults = { shm_hack_default_names, (sizeof(shm_hack_default_names) / sizeof(const Hack)) - 1, 0 }; static HackList *shm_hack_names = &shm_hack_defaults; static int comparkey(const void *key, const void *hname); static int comparstr(const void *a, const void *b); static int dosearch(const char *name, const HackList *hl); static int hl_add(HackList *hl, const Hack *h); static void hl_free(HackList *hl); static HackList *hl_init(void); static HackList *initList(const Hack *list); int _sem_hack_add(const Hack *list); void _sem_hack_init(void); PRIVATE int _sem_match(const char *name); int _shm_hack_add(const Hack *list); void _shm_hack_init(void); PRIVATE int _shm_match(const char *name); /*----------------------------------------------------------------------- * comparkey - used by bsearch to find the Hack structure with the given key *-----------------------------------------------------------------------*/ static int comparkey(const void *key, const void *h) { return strcmp(key, ((const Hack *)h)->name); } /*----------------------------------------------------------------------- * comparstr - used by qsort to sort the Hack list *-----------------------------------------------------------------------*/ static int comparstr(const void *a, const void *b) { return strcmp(((const Hack *)a)->name, ((const Hack *)b)->name); } /*----------------------------------------------------------------------- * dosearch - search of the given name in the given HackList. First see * if there is a trailing D, and a serial number. If the serial number * exists, try to match without the serial number, checking the series * range and whether the trailing D is allowed. Otherwise, try to match * the whole string, but check if the matched Hack structure requires a * serial number. *-----------------------------------------------------------------------*/ static int dosearch(const char *name, const HackList *hl) { int series; int len = strlen(name); const char *end, *p; char *key; const Hack *h; end = name + len - 1; if (*end != 'D') end++; p = end - 1; while (p >= name && *p >= '0' && *p <= '9') p--; p++; if (p < end && (len = p - name) > 0) { key = alloca(len + 1); if (key) { series = atoi(p); strncpy(key, name, len); key[len] = 0; h = (const Hack *)bsearch(key, hl->list, hl->cur, sizeof(const Hack), comparkey); if (h && h->first >= 0 && series >= h->first && series <= h->last && (*end == 0 || h->debug)) return 1; } } h = (const Hack *)bsearch(name, hl->list, hl->cur, sizeof(const Hack), comparkey); return (h && h->first < 0); } /*----------------------------------------------------------------------- * hl_add - append to the given HackList a copy of the given Hack structure *-----------------------------------------------------------------------*/ static int hl_add(HackList *hl, const Hack *c) { int i = hl->cur; Hack *h; if (!c->name) return -1; if (i >= hl->max) { int s = hl->max + HACKLISTDELTA; const Hack *new = (const Hack *)realloc((void *)hl->list, s * sizeof(const Hack)); if (!new) return -1; hl->list = new; hl->max = s; } h = (Hack *)(hl->list + i); if ((h->name = strdup(c->name)) == NULL) return -1; h->first = c->first; h->last = c->last; h->debug = c->debug; hl->cur++; return 0; } /*----------------------------------------------------------------------- * hl_free - deallocate all memory from the given HackList *-----------------------------------------------------------------------*/ static void hl_free(HackList *hl) { const Hack *h; int i; for (h = hl->list, i = hl->cur; i > 0; h++, i--) free((void *)h->name); free((void *)hl->list); free(hl); } /*----------------------------------------------------------------------- * hl_init - create a new HackList, with preallocated Hack structures *-----------------------------------------------------------------------*/ static HackList * hl_init(void) { HackList *hl = (HackList *)malloc(sizeof(HackList)); if (!hl) return NULL; hl->list = (Hack *)malloc(HACKLISTSTART * sizeof(Hack)); if (!hl->list) { free(hl); return NULL; } hl->cur = 0; hl->max = HACKLISTSTART; return hl; } /*----------------------------------------------------------------------- * initList - initialize a new HackList with the given list of Hack structures *-----------------------------------------------------------------------*/ static HackList * initList(const Hack *list) { HackList *hl = hl_init(); if (hl == NULL) return NULL; for (; list->name; list++) if (hl_add(hl, list) < 0) { hl_free(hl); return NULL; } return hl; } /*----------------------------------------------------------------------- * PUBLIC _sem_hack_add - add the given Hack list to sem_hack_names. *-----------------------------------------------------------------------*/ int _sem_hack_add(const Hack *list) { if (list == NULL) return -1; if (sem_hack_names == &sem_hack_defaults) { HackList *hl = initList(sem_hack_default_names); if (!hl) return -1; sem_hack_names = hl; } for (; list->name; list++) if (hl_add(sem_hack_names, list) < 0) return -1; qsort((void *)sem_hack_names->list, sem_hack_names->cur, sizeof(const Hack), comparstr); return 0; } /*----------------------------------------------------------------------- * PUBLIC _sem_hack_init - reinitialize sem_hack_names to the default *-----------------------------------------------------------------------*/ void _sem_hack_init(void) { if (sem_hack_names == &sem_hack_defaults) return; hl_free(sem_hack_names); sem_hack_names = &sem_hack_defaults; } /*----------------------------------------------------------------------- * _sem_match - try to match the given named to sem_hack_names. Called * by sem_open() and sem_unlink(). *-----------------------------------------------------------------------*/ PRIVATE int _sem_match(const char *name) { #ifdef SEM_DEBUG_FILE int match; #endif /* SEM_DEBUG_FILE */ if (!name || !*name) return 0; #ifdef SEM_DEBUG_FILE match = dosearch(name, sem_hack_names); if (!match) SEM_PRINTF("%s\n", name); return match; #else /* SEM_DEBUG_FILE */ return dosearch(name, sem_hack_names); #endif /* SEM_DEBUG_FILE */ } /*----------------------------------------------------------------------- * PUBLIC _shm_hack_add - add the given Hack list to shm_hack_names. *-----------------------------------------------------------------------*/ int _shm_hack_add(const Hack *list) { if (list == NULL) return -1; if (shm_hack_names == &shm_hack_defaults) { HackList *hl = initList(shm_hack_default_names); if (!hl) return -1; shm_hack_names = hl; } for (; list->name; list++) if (hl_add(shm_hack_names, list) < 0) return -1; qsort((void *)shm_hack_names->list, shm_hack_names->cur, sizeof(const Hack), comparstr); return 0; } /*----------------------------------------------------------------------- * PUBLIC _shm_hack_init - reinitialize shm_hack_names to the default *-----------------------------------------------------------------------*/ void _shm_hack_init(void) { if (shm_hack_names == &shm_hack_defaults) return; hl_free(shm_hack_names); shm_hack_names = &shm_hack_defaults; } /*----------------------------------------------------------------------- * _shm_match - try to match the given named to shm_hack_names. Called * by shm_open() and shm_unlink(). *-----------------------------------------------------------------------*/ PRIVATE int _shm_match(const char *name) { #ifdef SHM_DEBUG_FILE int match; #endif /* SHM_DEBUG_FILE */ if (!name || !*name) return 0; #ifdef SHM_DEBUG_FILE match = dosearch(name, shm_hack_names); if (!match) SHM_PRINTF("%s\n", name); return match; #else /* SHM_DEBUG_FILE */ return dosearch(name, shm_hack_names); #endif /* SHM_DEBUG_FILE */ } #endif /* __APPLE_PR3375657_HACK__ */