| 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 | } |