File: | modules/im/ximcp/imLcIm.c |
Location: | line 479, column 5 |
Description: | String copy function overflows destination buffer |
1 | /****************************************************************** | |||||
2 | ||||||
3 | Copyright 1992, 1993, 1994 by FUJITSU LIMITED | |||||
4 | Copyright 1993 by Digital Equipment Corporation | |||||
5 | ||||||
6 | Permission to use, copy, modify, distribute, and sell this software | |||||
7 | and its documentation for any purpose is hereby granted without fee, | |||||
8 | provided that the above copyright notice appear in all copies and that | |||||
9 | both that copyright notice and this permission notice appear in | |||||
10 | supporting documentation, and that the name of FUJITSU LIMITED and | |||||
11 | Digital Equipment Corporation not be used in advertising or publicity | |||||
12 | pertaining to distribution of the software without specific, written | |||||
13 | prior permission. FUJITSU LIMITED and Digital Equipment Corporation | |||||
14 | makes no representations about the suitability of this software for | |||||
15 | any purpose. It is provided "as is" without express or implied | |||||
16 | warranty. | |||||
17 | ||||||
18 | FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL | |||||
19 | WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED | |||||
20 | WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |||||
21 | FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR | |||||
22 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||||
23 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
24 | IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |||||
25 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |||||
26 | THIS SOFTWARE. | |||||
27 | ||||||
28 | Author: Takashi Fujiwara FUJITSU LIMITED | |||||
29 | fujiwara@a80.tech.yk.fujitsu.co.jp | |||||
30 | Modifier: Franky Ling Digital Equipment Corporation | |||||
31 | frankyling@hgrd01.enet.dec.com | |||||
32 | ||||||
33 | ******************************************************************/ | |||||
34 | ||||||
35 | #ifdef HAVE_CONFIG_H1 | |||||
36 | #include <config.h> | |||||
37 | #endif | |||||
38 | #include <stdio.h> | |||||
39 | ||||||
40 | #include <X11/Xmd.h> | |||||
41 | #include <X11/Xatom.h> | |||||
42 | #include <X11/Xos.h> | |||||
43 | #include "Xlibint.h" | |||||
44 | #include "Xlcint.h" | |||||
45 | #include "XlcPublic.h" | |||||
46 | #include "XlcPubI.h" | |||||
47 | #include "Ximint.h" | |||||
48 | #include <ctype.h> | |||||
49 | #include <assert.h> | |||||
50 | ||||||
51 | #ifdef COMPOSECACHE1 | |||||
52 | # include <sys/types.h> | |||||
53 | # include <sys/stat.h> | |||||
54 | # include <sys/mman.h> | |||||
55 | # include <langinfo.h> | |||||
56 | #endif | |||||
57 | ||||||
58 | ||||||
59 | #ifdef COMPOSECACHE1 | |||||
60 | ||||||
61 | /* include trailing '/' for cache directory, file prefix otherwise */ | |||||
62 | #define XIM_GLOBAL_CACHE_DIR"/var/cache/libx11/compose/" "/var/cache/libx11/compose/" | |||||
63 | #define XIM_HOME_CACHE_DIR"/.compose-cache/" "/.compose-cache/" | |||||
64 | #define XIM_CACHE_MAGIC('X' | 'i'<<8 | 'm'<<16 | 'C'<<24) ('X' | 'i'<<8 | 'm'<<16 | 'C'<<24) | |||||
65 | #define XIM_CACHE_VERSION4 4 | |||||
66 | #define XIM_CACHE_TREE_ALIGNMENT4 4 | |||||
67 | ||||||
68 | #define XIM_HASH_PRIME_113 13 | |||||
69 | #define XIM_HASH_PRIME_21234096939 1234096939 | |||||
70 | ||||||
71 | typedef INT32 DTStructIndex; | |||||
72 | struct _XimCacheStruct { | |||||
73 | INT32 id; | |||||
74 | INT32 version; | |||||
75 | DTStructIndex tree; | |||||
76 | DTStructIndex mb; | |||||
77 | DTStructIndex wc; | |||||
78 | DTStructIndex utf8; | |||||
79 | DTStructIndex size; | |||||
80 | DTIndex top; | |||||
81 | DTIndex treeused; | |||||
82 | DTCharIndex mbused; | |||||
83 | DTCharIndex wcused; | |||||
84 | DTCharIndex utf8used; | |||||
85 | char fname[1]; | |||||
86 | /* char encoding[1] */ | |||||
87 | }; | |||||
88 | ||||||
89 | static struct _XimCacheStruct* _XimCache_mmap = NULL((void*)0); | |||||
90 | static DefTreeBase _XimCachedDefaultTreeBase; | |||||
91 | static int _XimCachedDefaultTreeRefcount = 0; | |||||
92 | ||||||
93 | #endif | |||||
94 | ||||||
95 | ||||||
96 | Boolint | |||||
97 | _XimCheckIfLocalProcessing(Xim im) | |||||
98 | { | |||||
99 | FILE *fp; | |||||
100 | char *name; | |||||
101 | ||||||
102 | if(strcmp(im->core.im_name, "") == 0) { | |||||
103 | name = _XlcFileName(im->core.lcd, COMPOSE_FILE"Compose"); | |||||
104 | if (name != (char *)NULL((void*)0)) { | |||||
105 | fp = _XFopenFile (name, "r")fopen(name,"r"); | |||||
106 | Xfree(name)free((name)); | |||||
107 | if (fp != (FILE *)NULL((void*)0)) { | |||||
108 | fclose(fp); | |||||
109 | return(True1); | |||||
110 | } | |||||
111 | } | |||||
112 | return(False0); | |||||
113 | } else if(strcmp(im->core.im_name, "local") == 0 || | |||||
114 | strcmp(im->core.im_name, "none" ) == 0 ) { | |||||
115 | return(True1); | |||||
116 | } | |||||
117 | return(False0); | |||||
118 | } | |||||
119 | ||||||
120 | static void | |||||
121 | XimFreeDefaultTree( | |||||
122 | DefTreeBase *b) | |||||
123 | { | |||||
124 | if (!b) return; | |||||
125 | if (b->tree == NULL((void*)0)) return; | |||||
126 | #ifdef COMPOSECACHE1 | |||||
127 | if (b->tree == _XimCachedDefaultTreeBase.tree) { | |||||
128 | _XimCachedDefaultTreeRefcount--; | |||||
129 | /* No deleting, it's a cache after all. */ | |||||
130 | return; | |||||
131 | } | |||||
132 | #endif | |||||
133 | Xfree (b->tree)free((b->tree)); | |||||
134 | b->tree = NULL((void*)0); | |||||
135 | Xfree (b->mb)free((b->mb)); | |||||
136 | b->mb = NULL((void*)0); | |||||
137 | Xfree (b->wc)free((b->wc)); | |||||
138 | b->wc = NULL((void*)0); | |||||
139 | Xfree (b->utf8)free((b->utf8)); | |||||
140 | b->utf8 = NULL((void*)0); | |||||
141 | ||||||
142 | b->treeused = b->treesize = 0; | |||||
143 | b->mbused = b->mbsize = 0; | |||||
144 | b->wcused = b->wcsize = 0; | |||||
145 | b->utf8used = b->utf8size = 0; | |||||
146 | } | |||||
147 | ||||||
148 | void | |||||
149 | _XimLocalIMFree( | |||||
150 | Xim im) | |||||
151 | { | |||||
152 | XimFreeDefaultTree(&im->private.local.base); | |||||
153 | im->private.local.top = 0; | |||||
154 | ||||||
155 | Xfree(im->core.im_resources)free((im->core.im_resources)); | |||||
156 | im->core.im_resources = NULL((void*)0); | |||||
157 | ||||||
158 | Xfree(im->core.ic_resources)free((im->core.ic_resources)); | |||||
159 | im->core.ic_resources = NULL((void*)0); | |||||
160 | ||||||
161 | Xfree(im->core.im_values_list)free((im->core.im_values_list)); | |||||
162 | im->core.im_values_list = NULL((void*)0); | |||||
163 | ||||||
164 | Xfree(im->core.ic_values_list)free((im->core.ic_values_list)); | |||||
165 | im->core.ic_values_list = NULL((void*)0); | |||||
166 | ||||||
167 | Xfree(im->core.styles)free((im->core.styles)); | |||||
168 | im->core.styles = NULL((void*)0); | |||||
169 | ||||||
170 | Xfree(im->core.res_name)free((im->core.res_name)); | |||||
171 | im->core.res_name = NULL((void*)0); | |||||
172 | ||||||
173 | Xfree(im->core.res_class)free((im->core.res_class)); | |||||
174 | im->core.res_class = NULL((void*)0); | |||||
175 | ||||||
176 | Xfree(im->core.im_name)free((im->core.im_name)); | |||||
177 | im->core.im_name = NULL((void*)0); | |||||
178 | ||||||
179 | if (im->private.local.ctom_conv) { | |||||
180 | _XlcCloseConverter(im->private.local.ctom_conv); | |||||
181 | im->private.local.ctom_conv = NULL((void*)0); | |||||
182 | } | |||||
183 | if (im->private.local.ctow_conv) { | |||||
184 | _XlcCloseConverter(im->private.local.ctow_conv); | |||||
185 | im->private.local.ctow_conv = NULL((void*)0); | |||||
186 | } | |||||
187 | if (im->private.local.ctoutf8_conv) { | |||||
188 | _XlcCloseConverter(im->private.local.ctoutf8_conv); | |||||
189 | im->private.local.ctoutf8_conv = NULL((void*)0); | |||||
190 | } | |||||
191 | if (im->private.local.cstomb_conv) { | |||||
192 | _XlcCloseConverter(im->private.local.cstomb_conv); | |||||
193 | im->private.local.cstomb_conv = NULL((void*)0); | |||||
194 | } | |||||
195 | if (im->private.local.cstowc_conv) { | |||||
196 | _XlcCloseConverter(im->private.local.cstowc_conv); | |||||
197 | im->private.local.cstowc_conv = NULL((void*)0); | |||||
198 | } | |||||
199 | if (im->private.local.cstoutf8_conv) { | |||||
200 | _XlcCloseConverter(im->private.local.cstoutf8_conv); | |||||
201 | im->private.local.cstoutf8_conv = NULL((void*)0); | |||||
202 | } | |||||
203 | if (im->private.local.ucstoc_conv) { | |||||
204 | _XlcCloseConverter(im->private.local.ucstoc_conv); | |||||
205 | im->private.local.ucstoc_conv = NULL((void*)0); | |||||
206 | } | |||||
207 | if (im->private.local.ucstoutf8_conv) { | |||||
208 | _XlcCloseConverter(im->private.local.ucstoutf8_conv); | |||||
209 | im->private.local.ucstoutf8_conv = NULL((void*)0); | |||||
210 | } | |||||
211 | return; | |||||
212 | } | |||||
213 | ||||||
214 | static Statusint | |||||
215 | _XimLocalCloseIM( | |||||
216 | XIM xim) | |||||
217 | { | |||||
218 | Xim im = (Xim)xim; | |||||
219 | XIC ic; | |||||
220 | XIC next; | |||||
221 | ||||||
222 | ic = im->core.ic_chain; | |||||
223 | im->core.ic_chain = NULL((void*)0); | |||||
224 | while (ic) { | |||||
225 | (*ic->methods->destroy) (ic); | |||||
226 | next = ic->core.next; | |||||
227 | Xfree (ic)free((ic)); | |||||
228 | ic = next; | |||||
229 | } | |||||
230 | _XimLocalIMFree(im); | |||||
231 | _XimDestroyIMStructureList(im); | |||||
232 | return(True1); | |||||
233 | } | |||||
234 | ||||||
235 | char * | |||||
236 | _XimLocalGetIMValues( | |||||
237 | XIM xim, | |||||
238 | XIMArg *values) | |||||
239 | { | |||||
240 | Xim im = (Xim)xim; | |||||
241 | XimDefIMValues im_values; | |||||
242 | ||||||
243 | _XimGetCurrentIMValues(im, &im_values); | |||||
244 | return(_XimGetIMValueData(im, (XPointer)&im_values, values, | |||||
245 | im->core.im_resources, im->core.im_num_resources)); | |||||
246 | } | |||||
247 | ||||||
248 | char * | |||||
249 | _XimLocalSetIMValues( | |||||
250 | XIM xim, | |||||
251 | XIMArg *values) | |||||
252 | { | |||||
253 | Xim im = (Xim)xim; | |||||
254 | XimDefIMValues im_values; | |||||
255 | char *name = (char *)NULL((void*)0); | |||||
256 | ||||||
257 | _XimGetCurrentIMValues(im, &im_values); | |||||
258 | name = _XimSetIMValueData(im, (XPointer)&im_values, values, | |||||
259 | im->core.im_resources, im->core.im_num_resources); | |||||
260 | _XimSetCurrentIMValues(im, &im_values); | |||||
261 | return(name); | |||||
262 | } | |||||
263 | ||||||
264 | ||||||
265 | #ifdef COMPOSECACHE1 | |||||
266 | ||||||
267 | static Boolint | |||||
268 | _XimReadCachedDefaultTree( | |||||
269 | int fd_cache, | |||||
270 | const char *name, | |||||
271 | const char *encoding, | |||||
272 | DTStructIndex size) | |||||
273 | { | |||||
274 | struct _XimCacheStruct* m; | |||||
275 | int namelen = strlen (name) + 1; | |||||
276 | int encodinglen = strlen (encoding) + 1; | |||||
277 | ||||||
278 | m = mmap (NULL((void*)0), size, PROT_READ0x01, MAP_PRIVATE0x0002, fd_cache, 0); | |||||
279 | if (m == NULL((void*)0) || m == MAP_FAILED((void *)-1)) | |||||
280 | return False0; | |||||
281 | assert (m->id == XIM_CACHE_MAGIC)(__builtin_expect(!(m->id == ('X' | 'i'<<8 | 'm'<< 16 | 'C'<<24)), 0) ? __assert_rtn(__func__, "imLcIm.c", 281, "m->id == XIM_CACHE_MAGIC") : (void)0); | |||||
282 | assert (m->version == XIM_CACHE_VERSION)(__builtin_expect(!(m->version == 4), 0) ? __assert_rtn(__func__ , "imLcIm.c", 282, "m->version == XIM_CACHE_VERSION") : (void )0); | |||||
283 | if (size != m->size || | |||||
284 | size < XOffsetOf (struct _XimCacheStruct, fname)__builtin_offsetof(struct _XimCacheStruct, fname) + namelen + encodinglen) { | |||||
285 | fprintf (stderr__stderrp, "Ignoring broken XimCache %s [%s]\n", name, encoding); | |||||
286 | munmap (m, size); | |||||
287 | return False0; | |||||
288 | } | |||||
289 | if (strncmp (name, m->fname, namelen) != 0) { | |||||
290 | /* m->fname may *not* be terminated - but who cares here */ | |||||
291 | fprintf (stderr__stderrp, "Filename hash clash - expected %s, got %s\n", | |||||
292 | name, m->fname); | |||||
293 | munmap (m, size); | |||||
294 | return False0; | |||||
295 | } | |||||
296 | if (strncmp (encoding, m->fname + namelen, encodinglen) != 0) { | |||||
297 | /* m->fname+namelen may *not* be terminated - but who cares here */ | |||||
298 | fprintf (stderr__stderrp, "Enoding hash clash - expected %s, got %s\n", | |||||
299 | encoding, m->fname + namelen); | |||||
300 | munmap (m, size); | |||||
301 | return False0; | |||||
302 | } | |||||
303 | _XimCache_mmap = m; | |||||
304 | _XimCachedDefaultTreeBase.tree = (DefTree *) (((char *) m) + m->tree); | |||||
305 | _XimCachedDefaultTreeBase.mb = (((char *) m) + m->mb); | |||||
306 | _XimCachedDefaultTreeBase.wc = (wchar_t *) (((char *) m) + m->wc); | |||||
307 | _XimCachedDefaultTreeBase.utf8 = (((char *) m) + m->utf8); | |||||
308 | _XimCachedDefaultTreeBase.treeused = m->treeused; | |||||
309 | _XimCachedDefaultTreeBase.mbused = m->mbused; | |||||
310 | _XimCachedDefaultTreeBase.wcused = m->wcused; | |||||
311 | _XimCachedDefaultTreeBase.utf8used = m->utf8used; | |||||
312 | /* treesize etc. is ignored because only used during parsing */ | |||||
313 | _XimCachedDefaultTreeRefcount = 0; | |||||
314 | /* fprintf (stderr, "read cached tree at %p: %s\n", (void *) m, name); */ | |||||
315 | return True1; | |||||
316 | } | |||||
317 | ||||||
318 | static unsigned int strToHash ( | |||||
319 | const char *name) | |||||
320 | { | |||||
321 | unsigned int hash = 0; | |||||
322 | while (*name) | |||||
323 | hash = hash * XIM_HASH_PRIME_113 + *(unsigned const char *)name++; | |||||
324 | return hash % XIM_HASH_PRIME_21234096939; | |||||
325 | } | |||||
326 | ||||||
327 | ||||||
328 | /* Returns read-only fd of cache file, -1 if none. | |||||
329 | * Sets *res to cache filename if safe. Sets *size to file size of cache. */ | |||||
330 | static int _XimCachedFileName ( | |||||
331 | const char *dir, const char *name, | |||||
332 | const char *intname, const char *encoding, | |||||
333 | uid_t uid, int isglobal, char **res, off_t *size) | |||||
334 | { | |||||
335 | struct stat st_name, st; | |||||
336 | int fd; | |||||
337 | unsigned int len, hash, hash2; | |||||
338 | struct _XimCacheStruct *m; | |||||
339 | /* There are some races here with 'dir', but we are either in our own home | |||||
340 | * or the global cache dir, and not inside some public writable dir */ | |||||
341 | /* fprintf (stderr, "XimCachedFileName for dir %s name %s intname %s encoding %s uid %d\n", dir, name, intname, encoding, uid); */ | |||||
342 | if (stat (name, &st_name) == -1 || ! S_ISREG (st_name.st_mode)(((st_name.st_mode) & 0170000) == 0100000) | |||||
343 | || stat (dir, &st) == -1 || ! S_ISDIR (st.st_mode)(((st.st_mode) & 0170000) == 0040000) || st.st_uid != uid | |||||
344 | || (st.st_mode & 0022) != 0000) { | |||||
345 | *res = NULL((void*)0); | |||||
346 | return -1; | |||||
347 | } | |||||
348 | len = strlen (dir); | |||||
349 | hash = strToHash (intname); | |||||
350 | hash2 = strToHash (encoding); | |||||
351 | *res = Xmalloc (len + 1 + 27 + 1)malloc(((len + 1 + 27 + 1) == 0 ? 1 : (len + 1 + 27 + 1))); /* Max VERSION 9999 */ | |||||
352 | ||||||
353 | if (len == 0 || dir [len-1] != '/') | |||||
354 | sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(),__builtin___sprintf_chk (*res, 0, __builtin_object_size (*res , 2 > 1 ? 1 : 0), "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian (), 4, (unsigned int)sizeof (DefTree), hash, hash2) | |||||
355 | XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2)__builtin___sprintf_chk (*res, 0, __builtin_object_size (*res , 2 > 1 ? 1 : 0), "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian (), 4, (unsigned int)sizeof (DefTree), hash, hash2); | |||||
356 | else | |||||
357 | sprintf (*res, "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(),__builtin___sprintf_chk (*res, 0, __builtin_object_size (*res , 2 > 1 ? 1 : 0), "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian (), 4, (unsigned int)sizeof (DefTree), hash, hash2) | |||||
358 | XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2)__builtin___sprintf_chk (*res, 0, __builtin_object_size (*res , 2 > 1 ? 1 : 0), "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian (), 4, (unsigned int)sizeof (DefTree), hash, hash2); | |||||
359 | ||||||
360 | /* fprintf (stderr, "-> %s\n", *res); */ | |||||
361 | if ( (fd = _XOpenFile (*res, O_RDONLY)open(*res,0x0000)) == -1) | |||||
362 | return -1; | |||||
363 | ||||||
364 | if (fstat (fd, &st) == -1) { | |||||
365 | Xfree (*res)free((*res)); | |||||
366 | *res = NULL((void*)0); | |||||
367 | close (fd); | |||||
368 | return -1; | |||||
369 | } | |||||
370 | *size = st.st_size; | |||||
371 | ||||||
372 | if (! S_ISREG (st.st_mode)(((st.st_mode) & 0170000) == 0100000) || st.st_uid != uid | |||||
373 | || (st.st_mode & 0022) != 0000 || st.st_mtimest_mtimespec.tv_sec <= st_name.st_mtimest_mtimespec.tv_sec | |||||
374 | || (st.st_mtimest_mtimespec.tv_sec < time (NULL((void*)0)) - 24*60*60 && ! isglobal)) { | |||||
375 | ||||||
376 | close (fd); | |||||
377 | if (unlink (*res) != 0) { | |||||
378 | Xfree (*res)free((*res)); | |||||
379 | *res = NULL((void*)0); /* cache is not safe */ | |||||
380 | } | |||||
381 | return -1; | |||||
382 | } | |||||
383 | ||||||
384 | m = mmap (NULL((void*)0), sizeof (struct _XimCacheStruct), PROT_READ0x01, MAP_PRIVATE0x0002, | |||||
385 | fd, 0); | |||||
386 | if (m == NULL((void*)0) || m == MAP_FAILED((void *)-1)) { | |||||
387 | close (fd); | |||||
388 | Xfree (*res)free((*res)); | |||||
389 | *res = NULL((void*)0); | |||||
390 | return -1; | |||||
391 | } | |||||
392 | if (*size < sizeof (struct _XimCacheStruct) || m->id != XIM_CACHE_MAGIC('X' | 'i'<<8 | 'm'<<16 | 'C'<<24)) { | |||||
393 | munmap (m, sizeof (struct _XimCacheStruct)); | |||||
394 | close (fd); | |||||
395 | fprintf (stderr__stderrp, "Ignoring broken XimCache %s\n", *res); | |||||
396 | Xfree (*res)free((*res)); | |||||
397 | *res = NULL((void*)0); | |||||
398 | return -1; | |||||
399 | } | |||||
400 | if (m->version != XIM_CACHE_VERSION4) { | |||||
401 | munmap (m, sizeof (struct _XimCacheStruct)); | |||||
402 | close (fd); | |||||
403 | if (unlink (*res) != 0) { | |||||
404 | Xfree (*res)free((*res)); | |||||
405 | *res = NULL((void*)0); /* cache is not safe */ | |||||
406 | } | |||||
407 | return -1; | |||||
408 | } | |||||
409 | munmap (m, sizeof (struct _XimCacheStruct)); | |||||
410 | ||||||
411 | return fd; | |||||
412 | } | |||||
413 | ||||||
414 | ||||||
415 | static Boolint _XimLoadCache ( | |||||
416 | int fd, | |||||
417 | const char *name, | |||||
418 | const char *encoding, | |||||
419 | off_t size, | |||||
420 | Xim im) | |||||
421 | { | |||||
422 | if (_XimCache_mmap || | |||||
423 | _XimReadCachedDefaultTree (fd, name, encoding, size)) { | |||||
424 | _XimCachedDefaultTreeRefcount++; | |||||
425 | memcpy (&im->private.local.base, &_XimCachedDefaultTreeBase,__builtin___memcpy_chk (&im->private.local.base, & _XimCachedDefaultTreeBase, sizeof (_XimCachedDefaultTreeBase) , __builtin_object_size (&im->private.local.base, 0)) | |||||
426 | sizeof (_XimCachedDefaultTreeBase))__builtin___memcpy_chk (&im->private.local.base, & _XimCachedDefaultTreeBase, sizeof (_XimCachedDefaultTreeBase) , __builtin_object_size (&im->private.local.base, 0)); | |||||
427 | im->private.local.top = _XimCache_mmap->top; | |||||
428 | return True1; | |||||
429 | } | |||||
430 | ||||||
431 | return False0; | |||||
432 | } | |||||
433 | ||||||
434 | ||||||
435 | static void | |||||
436 | _XimWriteCachedDefaultTree( | |||||
437 | const char *name, | |||||
438 | const char *encoding, | |||||
439 | const char *cachename, | |||||
440 | Xim im) | |||||
441 | { | |||||
442 | int fd; | |||||
443 | FILE *fp; | |||||
444 | struct _XimCacheStruct *m; | |||||
445 | int msize = (XOffsetOf(struct _XimCacheStruct, fname)__builtin_offsetof(struct _XimCacheStruct, fname) | |||||
446 | + strlen(name) + strlen(encoding) + 2 | |||||
447 | + XIM_CACHE_TREE_ALIGNMENT4-1) & -XIM_CACHE_TREE_ALIGNMENT4; | |||||
448 | DefTreeBase *b = &im->private.local.base; | |||||
449 | ||||||
450 | if (! b->tree && ! (b->tree = Xcalloc (1, sizeof(DefTree))calloc(((1) == 0 ? 1 : (1)), (sizeof(DefTree)))) ) | |||||
451 | return; | |||||
452 | if (! b->mb && ! (b->mb = Xmalloc (1)malloc(((1) == 0 ? 1 : (1)))) ) | |||||
453 | return; | |||||
454 | if (! b->wc && ! (b->wc = Xmalloc (sizeof(wchar_t))malloc(((sizeof(wchar_t)) == 0 ? 1 : (sizeof(wchar_t))))) ) | |||||
455 | return; | |||||
456 | if (! b->utf8 && ! (b->utf8 = Xmalloc (1)malloc(((1) == 0 ? 1 : (1)))) ) | |||||
457 | return; | |||||
458 | ||||||
459 | /* First entry is always unused */ | |||||
460 | b->mb[0] = 0; | |||||
461 | b->wc[0] = 0; | |||||
462 | b->utf8[0] = 0; | |||||
463 | ||||||
464 | m = Xcalloc (1, msize)calloc(((1) == 0 ? 1 : (1)), (msize)); | |||||
465 | m->id = XIM_CACHE_MAGIC('X' | 'i'<<8 | 'm'<<16 | 'C'<<24); | |||||
466 | m->version = XIM_CACHE_VERSION4; | |||||
467 | m->top = im->private.local.top; | |||||
468 | m->treeused = b->treeused; | |||||
469 | m->mbused = b->mbused; | |||||
470 | m->wcused = b->wcused; | |||||
471 | m->utf8used = b->utf8used; | |||||
472 | /* Tree first, then wide chars, then the rest due to alignment */ | |||||
473 | m->tree = msize; | |||||
474 | m->wc = msize + sizeof (DefTree) * m->treeused; | |||||
475 | m->mb = m->wc + sizeof (wchar_t) * m->wcused; | |||||
476 | m->utf8 = m->mb + m->mbused; | |||||
477 | m->size = m->utf8 + m->utf8used; | |||||
478 | strcpy (m->fname, name)__builtin___strcpy_chk (m->fname, name, __builtin_object_size (m->fname, 2 > 1 ? 1 : 0)); | |||||
479 | strcpy (m->fname+strlen(name)+1, encoding)__builtin___strcpy_chk (m->fname+strlen(name)+1, encoding, __builtin_object_size (m->fname+strlen(name)+1, 2 > 1 ? 1 : 0)); | |||||
| ||||||
480 | ||||||
481 | /* This STILL might be racy on NFS */ | |||||
482 | if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL,open(cachename,0x0001 | 0x0200 | 0x0800,0600) | |||||
483 | 0600)open(cachename,0x0001 | 0x0200 | 0x0800,0600)) < 0) { | |||||
484 | Xfree(m)free((m)); | |||||
485 | return; | |||||
486 | } | |||||
487 | if (! (fp = fdopen (fd, "wb")) ) { | |||||
488 | close (fd); | |||||
489 | Xfree(m)free((m)); | |||||
490 | return; | |||||
491 | } | |||||
492 | fwrite (m, msize, 1, fp); | |||||
493 | fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp); | |||||
494 | fwrite (im->private.local.base.wc, sizeof(wchar_t), m->wcused, fp); | |||||
495 | fwrite (im->private.local.base.mb, 1, m->mbused, fp); | |||||
496 | fwrite (im->private.local.base.utf8, 1, m->utf8used, fp); | |||||
497 | if (fclose (fp) != 0) | |||||
498 | unlink (cachename); | |||||
499 | _XimCache_mmap = m; | |||||
500 | memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base,__builtin___memcpy_chk (&_XimCachedDefaultTreeBase, & im->private.local.base, sizeof (_XimCachedDefaultTreeBase) , __builtin_object_size (&_XimCachedDefaultTreeBase, 0)) | |||||
501 | sizeof (_XimCachedDefaultTreeBase))__builtin___memcpy_chk (&_XimCachedDefaultTreeBase, & im->private.local.base, sizeof (_XimCachedDefaultTreeBase) , __builtin_object_size (&_XimCachedDefaultTreeBase, 0)); | |||||
502 | /* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */ | |||||
503 | } | |||||
504 | ||||||
505 | #endif | |||||
506 | ||||||
507 | ||||||
508 | static void | |||||
509 | _XimCreateDefaultTree( | |||||
510 | Xim im) | |||||
511 | { | |||||
512 | FILE *fp = NULL((void*)0); | |||||
513 | char *name, *tmpname = NULL((void*)0), *intname; | |||||
514 | char *cachename = NULL((void*)0); | |||||
515 | /* Should use getpwent() instead of $HOME (cross-platform?) */ | |||||
516 | char *home = getenv("HOME"); | |||||
517 | char *cachedir = NULL((void*)0); | |||||
518 | char *tmpcachedir = NULL((void*)0); | |||||
519 | int hl = home ? strlen (home) : 0; | |||||
520 | #ifdef COMPOSECACHE1 | |||||
521 | const char *encoding = nl_langinfo (CODESET0); | |||||
522 | uid_t euid = geteuid (); | |||||
523 | gid_t egid = getegid (); | |||||
524 | int cachefd = -1; | |||||
525 | off_t size; | |||||
526 | #endif | |||||
527 | ||||||
528 | name = getenv("XCOMPOSEFILE"); | |||||
529 | if (name == (char *) NULL((void*)0)) { | |||||
530 | if (home != (char *) NULL((void*)0)) { | |||||
531 | tmpname = name = Xmalloc(hl + 10 + 1)malloc(((hl + 10 + 1) == 0 ? 1 : (hl + 10 + 1))); | |||||
532 | if (name != (char *) NULL((void*)0)) { | |||||
533 | int fd; | |||||
534 | strcpy(name, home)__builtin___strcpy_chk (name, home, __builtin_object_size (name , 2 > 1 ? 1 : 0)); | |||||
535 | strcpy(name + hl, "/.XCompose")__builtin___strcpy_chk (name + hl, "/.XCompose", __builtin_object_size (name + hl, 2 > 1 ? 1 : 0)); | |||||
536 | if ( (fd = _XOpenFile (name, O_RDONLY)open(name,0x0000)) < 0) { | |||||
537 | Xfree (name)free((name)); | |||||
538 | name = tmpname = NULL((void*)0); | |||||
539 | } else | |||||
540 | close (fd); | |||||
541 | } | |||||
542 | } | |||||
543 | } | |||||
544 | ||||||
545 | if (name == (char *) NULL((void*)0)) { | |||||
546 | tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE"Compose"); | |||||
547 | } | |||||
548 | intname = name; | |||||
549 | ||||||
550 | #ifdef COMPOSECACHE1 | |||||
551 | if (getuid () == euid && getgid () == egid && euid != 0) { | |||||
552 | char *c; | |||||
553 | /* Usage: XCOMPOSECACHE=<cachedir>[=<filename>] | |||||
554 | * cachedir: directory of cache files | |||||
555 | * filename: internally used name for cache file */ | |||||
556 | cachedir = getenv("XCOMPOSECACHE"); | |||||
557 | if (cachedir && (c = strchr (cachedir, '='))) { | |||||
558 | tmpcachedir = strdup (cachedir); | |||||
559 | intname = tmpcachedir + (c-cachedir) + 1; | |||||
560 | tmpcachedir[c-cachedir] = '\0'; | |||||
561 | cachedir = tmpcachedir; | |||||
562 | } | |||||
563 | } | |||||
564 | ||||||
565 | if (! cachedir) { | |||||
566 | cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR"/var/cache/libx11/compose/", name, intname, | |||||
567 | encoding, 0, 1, &cachename, &size); | |||||
568 | if (cachefd != -1) { | |||||
569 | if (_XimLoadCache (cachefd, intname, encoding, size, im)) { | |||||
570 | Xfree (tmpcachedir)free((tmpcachedir)); | |||||
571 | Xfree (tmpname)free((tmpname)); | |||||
572 | Xfree (cachename)free((cachename)); | |||||
573 | close (cachefd); | |||||
574 | return; | |||||
575 | } | |||||
576 | close (cachefd); | |||||
577 | } | |||||
578 | Xfree (cachename)free((cachename)); | |||||
579 | cachename = NULL((void*)0); | |||||
580 | } | |||||
581 | ||||||
582 | if (getuid () == euid && getgid () == egid && euid != 0 && home) { | |||||
583 | ||||||
584 | if (! cachedir) { | |||||
585 | tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1)malloc(((hl+strlen("/.compose-cache/")+1) == 0 ? 1 : (hl+strlen ("/.compose-cache/")+1))); | |||||
586 | strcpy (cachedir, home)__builtin___strcpy_chk (cachedir, home, __builtin_object_size (cachedir, 2 > 1 ? 1 : 0)); | |||||
587 | strcat (cachedir, XIM_HOME_CACHE_DIR)__builtin___strcat_chk (cachedir, "/.compose-cache/", __builtin_object_size (cachedir, 2 > 1 ? 1 : 0)); | |||||
588 | } | |||||
589 | cachefd = _XimCachedFileName (cachedir, name, intname, encoding, | |||||
590 | euid, 0, &cachename, &size); | |||||
591 | if (cachefd != -1) { | |||||
592 | if (_XimLoadCache (cachefd, intname, encoding, size, im)) { | |||||
593 | Xfree (tmpcachedir)free((tmpcachedir)); | |||||
594 | Xfree (tmpname)free((tmpname)); | |||||
595 | Xfree (cachename)free((cachename)); | |||||
596 | close (cachefd); | |||||
597 | return; | |||||
598 | } | |||||
599 | close (cachefd); | |||||
600 | } | |||||
601 | } | |||||
602 | #endif | |||||
603 | ||||||
604 | if (! (fp = _XFopenFile (name, "r")fopen(name,"r"))) { | |||||
605 | Xfree (tmpcachedir)free((tmpcachedir)); | |||||
606 | Xfree (tmpname)free((tmpname)); | |||||
607 | Xfree (cachename)free((cachename)); | |||||
608 | return; | |||||
609 | } | |||||
610 | _XimParseStringFile(fp, im); | |||||
611 | fclose(fp); | |||||
612 | ||||||
613 | #ifdef COMPOSECACHE1 | |||||
614 | if (cachename) { | |||||
615 | assert (euid != 0)(__builtin_expect(!(euid != 0), 0) ? __assert_rtn(__func__, "imLcIm.c" , 615, "euid != 0") : (void)0); | |||||
616 | _XimWriteCachedDefaultTree (intname, encoding, cachename, im); | |||||
617 | } | |||||
618 | #endif | |||||
619 | ||||||
620 | Xfree (tmpcachedir)free((tmpcachedir)); | |||||
621 | Xfree (tmpname)free((tmpname)); | |||||
622 | Xfree (cachename)free((cachename)); | |||||
623 | } | |||||
624 | ||||||
625 | static XIMMethodsRec Xim_im_local_methods = { | |||||
626 | _XimLocalCloseIM, /* close */ | |||||
627 | _XimLocalSetIMValues, /* set_values */ | |||||
628 | _XimLocalGetIMValues, /* get_values */ | |||||
629 | _XimLocalCreateIC, /* create_ic */ | |||||
630 | _XimLcctstombs, /* ctstombs */ | |||||
631 | _XimLcctstowcs, /* ctstowcs */ | |||||
632 | _XimLcctstoutf8 /* ctstoutf8 */ | |||||
633 | }; | |||||
634 | ||||||
635 | Boolint | |||||
636 | _XimLocalOpenIM( | |||||
637 | Xim im) | |||||
638 | { | |||||
639 | XLCd lcd = im->core.lcd; | |||||
640 | XlcConv conv; | |||||
641 | XimDefIMValues im_values; | |||||
642 | XimLocalPrivateRec* private = &im->private.local; | |||||
643 | ||||||
644 | _XimInitialResourceInfo(); | |||||
645 | if(_XimSetIMResourceList(&im->core.im_resources, | |||||
| ||||||
646 | &im->core.im_num_resources) == False0) { | |||||
647 | goto Open_Error; | |||||
648 | } | |||||
649 | if(_XimSetICResourceList(&im->core.ic_resources, | |||||
650 | &im->core.ic_num_resources) == False0) { | |||||
651 | goto Open_Error; | |||||
652 | } | |||||
653 | ||||||
654 | _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); | |||||
655 | ||||||
656 | _XimGetCurrentIMValues(im, &im_values); | |||||
657 | if(_XimSetLocalIMDefaults(im, (XPointer)&im_values, | |||||
658 | im->core.im_resources, im->core.im_num_resources) == False0) { | |||||
659 | goto Open_Error; | |||||
660 | } | |||||
661 | _XimSetCurrentIMValues(im, &im_values); | |||||
662 | ||||||
663 | if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText"compoundText", lcd, XlcNMultiByte"multiByte"))) | |||||
664 | goto Open_Error; | |||||
665 | private->ctom_conv = conv; | |||||
666 | ||||||
667 | if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText"compoundText", lcd, XlcNWideChar"wideChar"))) | |||||
668 | goto Open_Error; | |||||
669 | private->ctow_conv = conv; | |||||
670 | ||||||
671 | if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText"compoundText", lcd, XlcNUtf8String"utf8String"))) | |||||
672 | goto Open_Error; | |||||
673 | private->ctoutf8_conv = conv; | |||||
674 | ||||||
675 | if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet"charSet", lcd, XlcNMultiByte"multiByte"))) | |||||
676 | goto Open_Error; | |||||
677 | private->cstomb_conv = conv; | |||||
678 | ||||||
679 | if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet"charSet", lcd, XlcNWideChar"wideChar"))) | |||||
680 | goto Open_Error; | |||||
681 | private->cstowc_conv = conv; | |||||
682 | ||||||
683 | if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet"charSet", lcd, XlcNUtf8String"utf8String"))) | |||||
684 | goto Open_Error; | |||||
685 | private->cstoutf8_conv = conv; | |||||
686 | ||||||
687 | if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar"UCSchar", lcd, XlcNChar"char"))) | |||||
688 | goto Open_Error; | |||||
689 | private->ucstoc_conv = conv; | |||||
690 | ||||||
691 | if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar"UCSchar", lcd, XlcNUtf8String"utf8String"))) | |||||
692 | goto Open_Error; | |||||
693 | private->ucstoutf8_conv = conv; | |||||
694 | ||||||
695 | private->base.treeused = 1; | |||||
696 | private->base.mbused = 1; | |||||
697 | private->base.wcused = 1; | |||||
698 | private->base.utf8used = 1; | |||||
699 | ||||||
700 | _XimCreateDefaultTree(im); | |||||
701 | ||||||
702 | im->methods = &Xim_im_local_methods; | |||||
703 | private->current_ic = (XIC)NULL((void*)0); | |||||
704 | ||||||
705 | return(True1); | |||||
706 | ||||||
707 | Open_Error : | |||||
708 | _XimLocalIMFree(im); | |||||
709 | return(False0); | |||||
710 | } |