]>
Commit | Line | Data |
---|---|---|
9385eb3d A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
9385eb3d A |
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 | ||
9385eb3d A |
24 | /* |
25 | * When mutexes or spinlocks were added for thread safety, the system would | |
26 | * hang during the boot process, just after changing to the blue background. | |
27 | * So for the common case of not calling _s[eh]m_hack_{add,init}(), we just | |
28 | * use static name lists. This should be reinvestigated when there is time. | |
29 | */ | |
30 | ||
31 | #define PRIVATE __private_extern__ | |
32 | //#define SEM_DEBUG_FILE "/tmp/sem_names" | |
33 | //#define SHM_DEBUG_FILE "/tmp/shm_names" | |
34 | ||
35 | #if defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) | |
36 | #include <stdio.h> | |
37 | #include <unistd.h> | |
38 | #endif /* defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) */ | |
39 | #include <stdlib.h> | |
40 | #include <string.h> | |
41 | #include <stdlib.h> | |
42 | ||
43 | #ifdef SEM_DEBUG_FILE | |
44 | #define SEM_PRINTF(fmt, args...) \ | |
45 | { \ | |
46 | FILE *_sem_fp_; \ | |
47 | if (access(SEM_DEBUG_FILE, F_OK) == 0 && \ | |
48 | (_sem_fp_ = fopen(SEM_DEBUG_FILE, "a")) != NULL) { \ | |
49 | fprintf(_sem_fp_, fmt, ## args); \ | |
50 | fclose(_sem_fp_); \ | |
51 | } \ | |
52 | } | |
53 | #endif /* SEM_DEBUG_FILE */ | |
54 | #ifdef SHM_DEBUG_FILE | |
55 | #define SHM_PRINTF(fmt, args...) \ | |
56 | { \ | |
57 | FILE *_shm_fp_; \ | |
58 | if (access(SHM_DEBUG_FILE, F_OK) == 0 && \ | |
59 | (_shm_fp_ = fopen(SHM_DEBUG_FILE, "a")) != NULL) { \ | |
60 | fprintf(_shm_fp_, fmt, ## args); \ | |
61 | fclose(_shm_fp_); \ | |
62 | } \ | |
63 | } | |
64 | #endif /* SHM_DEBUG_FILE */ | |
65 | ||
66 | /*----------------------------------------------------------------------- | |
67 | * For the Hack structure: | |
68 | * | |
69 | * first >= 0 starting serial number | |
70 | * first < 0 no serial number | |
71 | * last ending serial number (only if first >= 0) | |
72 | * debug whether an option 'D' can be appended | |
73 | *-----------------------------------------------------------------------*/ | |
74 | typedef struct { | |
75 | const char *name; | |
76 | int first; | |
77 | int last; | |
78 | int debug; | |
79 | } Hack; | |
80 | ||
81 | /*----------------------------------------------------------------------- | |
82 | * For the HackList structure: | |
83 | * | |
84 | * list the list of Hack structures | |
85 | * cur the number of valid Hack structures in list | |
86 | * max the actual number of Hack structures allocated | |
87 | *-----------------------------------------------------------------------*/ | |
88 | #define HACKLISTDELTA 16 | |
89 | #define HACKLISTSTART 16 | |
90 | typedef struct { | |
91 | const Hack *list; | |
92 | int cur; | |
93 | int max; | |
94 | } HackList; | |
95 | ||
96 | static const Hack sem_hack_default_names[] = { | |
97 | {"EDBPool", 1, 255, 0}, | |
98 | {"EDDPoolLock", -1, 0, 0}, | |
99 | {"Mso97SharedDg", 1920, 2047, 1}, | |
100 | {"Office", 1920, 2047, 1}, | |
101 | {"PT_EDBPool", 1, 255, 0}, | |
102 | {"PT_EDDPoolLock", -1, 0, 0}, | |
103 | {"PT_Mso97SharedDg", 1920, 2047, 0}, | |
104 | {"PT_Office", 1920, 2047, 0}, | |
105 | {"ShMemExtCritSection", -1, 0, 0}, | |
106 | {"ShMemIntCritSection", -1, 0, 0}, | |
107 | {NULL, 0, 0, 0}, | |
108 | }; | |
109 | static HackList sem_hack_defaults = { | |
110 | sem_hack_default_names, | |
111 | (sizeof(sem_hack_default_names) / sizeof(const Hack)) - 1, | |
112 | 0 | |
113 | }; | |
114 | static HackList *sem_hack_names = &sem_hack_defaults; | |
115 | ||
116 | static const Hack shm_hack_default_names[] = { | |
117 | {"EDBPool", 1, 255, 0}, | |
118 | {"EDDPoolLock", -1, 0, 0}, | |
119 | {"Mso97SharedDg", 1920, 2047, 1}, | |
120 | {"Office", 1920, 2047, 1}, | |
121 | {"PT_EDBPool", 1, 255, 0}, | |
122 | {"PT_EDDPoolLock", -1, 0, 0}, | |
123 | {"PT_Mso97SharedDg", 1920, 2047, 0}, | |
124 | {"PT_Office", 1920, 2047, 0}, | |
125 | {"PT_ShMemRefCount", -1, 0, 0}, /* not specified by MS, but seen */ | |
126 | {"ShMemRefCount", -1, 0, 0}, | |
127 | {NULL, 0, 0, 0}, | |
128 | }; | |
129 | static HackList shm_hack_defaults = { | |
130 | shm_hack_default_names, | |
131 | (sizeof(shm_hack_default_names) / sizeof(const Hack)) - 1, | |
132 | 0 | |
133 | }; | |
134 | static HackList *shm_hack_names = &shm_hack_defaults; | |
135 | ||
136 | static int comparkey(const void *key, const void *hname); | |
137 | static int comparstr(const void *a, const void *b); | |
138 | static int dosearch(const char *name, const HackList *hl); | |
139 | static int hl_add(HackList *hl, const Hack *h); | |
140 | static void hl_free(HackList *hl); | |
141 | static HackList *hl_init(void); | |
142 | static HackList *initList(const Hack *list); | |
143 | int _sem_hack_add(const Hack *list); | |
144 | void _sem_hack_init(void); | |
145 | PRIVATE int _sem_match(const char *name); | |
146 | int _shm_hack_add(const Hack *list); | |
147 | void _shm_hack_init(void); | |
148 | PRIVATE int _shm_match(const char *name); | |
149 | ||
150 | /*----------------------------------------------------------------------- | |
151 | * comparkey - used by bsearch to find the Hack structure with the given key | |
152 | *-----------------------------------------------------------------------*/ | |
153 | static int | |
154 | comparkey(const void *key, const void *h) | |
155 | { | |
156 | return strcmp(key, ((const Hack *)h)->name); | |
157 | } | |
158 | ||
159 | /*----------------------------------------------------------------------- | |
160 | * comparstr - used by qsort to sort the Hack list | |
161 | *-----------------------------------------------------------------------*/ | |
162 | static int | |
163 | comparstr(const void *a, const void *b) | |
164 | { | |
165 | return strcmp(((const Hack *)a)->name, ((const Hack *)b)->name); | |
166 | } | |
167 | ||
168 | /*----------------------------------------------------------------------- | |
169 | * dosearch - search of the given name in the given HackList. First see | |
170 | * if there is a trailing D, and a serial number. If the serial number | |
171 | * exists, try to match without the serial number, checking the series | |
172 | * range and whether the trailing D is allowed. Otherwise, try to match | |
173 | * the whole string, but check if the matched Hack structure requires a | |
174 | * serial number. | |
175 | *-----------------------------------------------------------------------*/ | |
176 | static int | |
177 | dosearch(const char *name, const HackList *hl) | |
178 | { | |
179 | int series; | |
180 | int len = strlen(name); | |
181 | const char *end, *p; | |
182 | char *key; | |
183 | const Hack *h; | |
184 | ||
185 | end = name + len - 1; | |
186 | if (*end != 'D') | |
187 | end++; | |
188 | p = end - 1; | |
189 | while (p >= name && *p >= '0' && *p <= '9') | |
190 | p--; | |
191 | p++; | |
192 | if (p < end && (len = p - name) > 0) { | |
193 | key = alloca(len + 1); | |
194 | if (key) { | |
195 | series = atoi(p); | |
196 | strncpy(key, name, len); | |
197 | key[len] = 0; | |
198 | h = (const Hack *)bsearch(key, hl->list, hl->cur, | |
199 | sizeof(const Hack), comparkey); | |
200 | if (h && h->first >= 0 | |
201 | && series >= h->first && series <= h->last | |
202 | && (*end == 0 || h->debug)) | |
203 | return 1; | |
204 | } | |
205 | } | |
206 | h = (const Hack *)bsearch(name, hl->list, hl->cur, sizeof(const Hack), | |
207 | comparkey); | |
208 | return (h && h->first < 0); | |
209 | } | |
210 | ||
211 | /*----------------------------------------------------------------------- | |
212 | * hl_add - append to the given HackList a copy of the given Hack structure | |
213 | *-----------------------------------------------------------------------*/ | |
214 | static int | |
215 | hl_add(HackList *hl, const Hack *c) | |
216 | { | |
217 | int i = hl->cur; | |
218 | Hack *h; | |
219 | ||
220 | if (!c->name) | |
221 | return -1; | |
222 | if (i >= hl->max) { | |
223 | int s = hl->max + HACKLISTDELTA; | |
224 | const Hack *new = (const Hack *)realloc((void *)hl->list, | |
225 | s * sizeof(const Hack)); | |
226 | ||
227 | if (!new) | |
228 | return -1; | |
229 | hl->list = new; | |
230 | hl->max = s; | |
231 | } | |
232 | h = (Hack *)(hl->list + i); | |
233 | if ((h->name = strdup(c->name)) == NULL) | |
234 | return -1; | |
235 | h->first = c->first; | |
236 | h->last = c->last; | |
237 | h->debug = c->debug; | |
238 | hl->cur++; | |
239 | return 0; | |
240 | } | |
241 | ||
242 | /*----------------------------------------------------------------------- | |
243 | * hl_free - deallocate all memory from the given HackList | |
244 | *-----------------------------------------------------------------------*/ | |
245 | static void | |
246 | hl_free(HackList *hl) | |
247 | { | |
248 | const Hack *h; | |
249 | int i; | |
250 | ||
251 | for (h = hl->list, i = hl->cur; i > 0; h++, i--) | |
252 | free((void *)h->name); | |
253 | free((void *)hl->list); | |
254 | free(hl); | |
255 | } | |
256 | ||
257 | /*----------------------------------------------------------------------- | |
258 | * hl_init - create a new HackList, with preallocated Hack structures | |
259 | *-----------------------------------------------------------------------*/ | |
260 | static HackList * | |
261 | hl_init(void) | |
262 | { | |
263 | HackList *hl = (HackList *)malloc(sizeof(HackList)); | |
264 | ||
265 | if (!hl) | |
266 | return NULL; | |
267 | hl->list = (Hack *)malloc(HACKLISTSTART * sizeof(Hack)); | |
268 | if (!hl->list) { | |
269 | free(hl); | |
270 | return NULL; | |
271 | } | |
272 | hl->cur = 0; | |
273 | hl->max = HACKLISTSTART; | |
274 | return hl; | |
275 | } | |
276 | ||
277 | /*----------------------------------------------------------------------- | |
278 | * initList - initialize a new HackList with the given list of Hack structures | |
279 | *-----------------------------------------------------------------------*/ | |
280 | static HackList * | |
281 | initList(const Hack *list) | |
282 | { | |
283 | HackList *hl = hl_init(); | |
284 | ||
285 | if (hl == NULL) | |
286 | return NULL; | |
287 | for (; list->name; list++) | |
288 | if (hl_add(hl, list) < 0) { | |
289 | hl_free(hl); | |
290 | return NULL; | |
291 | } | |
292 | return hl; | |
293 | } | |
294 | ||
295 | /*----------------------------------------------------------------------- | |
296 | * PUBLIC _sem_hack_add - add the given Hack list to sem_hack_names. | |
297 | *-----------------------------------------------------------------------*/ | |
298 | int | |
299 | _sem_hack_add(const Hack *list) | |
300 | { | |
301 | if (list == NULL) | |
302 | return -1; | |
303 | if (sem_hack_names == &sem_hack_defaults) { | |
304 | HackList *hl = initList(sem_hack_default_names); | |
305 | if (!hl) | |
306 | return -1; | |
307 | sem_hack_names = hl; | |
308 | } | |
309 | for (; list->name; list++) | |
310 | if (hl_add(sem_hack_names, list) < 0) | |
311 | return -1; | |
312 | qsort((void *)sem_hack_names->list, sem_hack_names->cur, | |
313 | sizeof(const Hack), comparstr); | |
314 | return 0; | |
315 | } | |
316 | ||
317 | /*----------------------------------------------------------------------- | |
318 | * PUBLIC _sem_hack_init - reinitialize sem_hack_names to the default | |
319 | *-----------------------------------------------------------------------*/ | |
320 | void | |
321 | _sem_hack_init(void) | |
322 | { | |
323 | if (sem_hack_names == &sem_hack_defaults) | |
324 | return; | |
325 | hl_free(sem_hack_names); | |
326 | sem_hack_names = &sem_hack_defaults; | |
327 | } | |
328 | ||
329 | /*----------------------------------------------------------------------- | |
330 | * _sem_match - try to match the given named to sem_hack_names. Called | |
331 | * by sem_open() and sem_unlink(). | |
332 | *-----------------------------------------------------------------------*/ | |
333 | PRIVATE int | |
334 | _sem_match(const char *name) | |
335 | { | |
336 | #ifdef SEM_DEBUG_FILE | |
337 | int match; | |
338 | #endif /* SEM_DEBUG_FILE */ | |
339 | ||
340 | if (!name || !*name) | |
341 | return 0; | |
342 | #ifdef SEM_DEBUG_FILE | |
343 | match = dosearch(name, sem_hack_names); | |
344 | if (!match) | |
345 | SEM_PRINTF("%s\n", name); | |
346 | return match; | |
347 | #else /* SEM_DEBUG_FILE */ | |
348 | return dosearch(name, sem_hack_names); | |
349 | #endif /* SEM_DEBUG_FILE */ | |
350 | } | |
351 | ||
352 | /*----------------------------------------------------------------------- | |
353 | * PUBLIC _shm_hack_add - add the given Hack list to shm_hack_names. | |
354 | *-----------------------------------------------------------------------*/ | |
355 | int | |
356 | _shm_hack_add(const Hack *list) | |
357 | { | |
358 | if (list == NULL) | |
359 | return -1; | |
360 | if (shm_hack_names == &shm_hack_defaults) { | |
361 | HackList *hl = initList(shm_hack_default_names); | |
362 | if (!hl) | |
363 | return -1; | |
364 | shm_hack_names = hl; | |
365 | } | |
366 | for (; list->name; list++) | |
367 | if (hl_add(shm_hack_names, list) < 0) | |
368 | return -1; | |
369 | qsort((void *)shm_hack_names->list, shm_hack_names->cur, | |
370 | sizeof(const Hack), comparstr); | |
371 | return 0; | |
372 | } | |
373 | ||
374 | /*----------------------------------------------------------------------- | |
375 | * PUBLIC _shm_hack_init - reinitialize shm_hack_names to the default | |
376 | *-----------------------------------------------------------------------*/ | |
377 | void | |
378 | _shm_hack_init(void) | |
379 | { | |
380 | if (shm_hack_names == &shm_hack_defaults) | |
381 | return; | |
382 | hl_free(shm_hack_names); | |
383 | shm_hack_names = &shm_hack_defaults; | |
384 | } | |
385 | ||
386 | /*----------------------------------------------------------------------- | |
387 | * _shm_match - try to match the given named to shm_hack_names. Called | |
388 | * by shm_open() and shm_unlink(). | |
389 | *-----------------------------------------------------------------------*/ | |
390 | PRIVATE int | |
391 | _shm_match(const char *name) | |
392 | { | |
393 | #ifdef SHM_DEBUG_FILE | |
394 | int match; | |
395 | #endif /* SHM_DEBUG_FILE */ | |
396 | ||
397 | if (!name || !*name) | |
398 | return 0; | |
399 | #ifdef SHM_DEBUG_FILE | |
400 | match = dosearch(name, shm_hack_names); | |
401 | if (!match) | |
402 | SHM_PRINTF("%s\n", name); | |
403 | return match; | |
404 | #else /* SHM_DEBUG_FILE */ | |
405 | return dosearch(name, shm_hack_names); | |
406 | #endif /* SHM_DEBUG_FILE */ | |
407 | } |