xkbcomp.c revision f46a6179
1/* $Xorg: xkbcomp.c,v 1.4 2000/08/17 19:54:33 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 4 5 Permission to use, copy, modify, and distribute this 6 software and its documentation for any purpose and without 7 fee is hereby granted, provided that the above copyright 8 notice appear in all copies and that both that copyright 9 notice and this permission notice appear in supporting 10 documentation, and that the name of Silicon Graphics not be 11 used in advertising or publicity pertaining to distribution 12 of the software without specific prior written permission. 13 Silicon Graphics makes no representation about the suitability 14 of this software for any purpose. It is provided "as is" 15 without any express or implied warranty. 16 17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 24 THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 26 ********************************************************/ 27/* $XFree86: xc/programs/xkbcomp/xkbcomp.c,v 3.20 2003/09/24 02:43:38 dawes Exp $ */ 28 29#include <stdio.h> 30#include <ctype.h> 31#include <X11/keysym.h> 32 33/* for symlink attack security fix -- Branden Robinson */ 34#include <sys/stat.h> 35#include <sys/types.h> 36#include <unistd.h> 37/* end BR */ 38 39#if defined(sgi) 40#include <malloc.h> 41#endif 42 43#define DEBUG_VAR_NOT_LOCAL 44#define DEBUG_VAR debugFlags 45#include "xkbcomp.h" 46#include <stdlib.h> 47#include "xkbpath.h" 48#include "parseutils.h" 49#include "misc.h" 50#include "tokens.h" 51#include <X11/extensions/XKBgeom.h> 52 53#ifdef __UNIXOS2__ 54#define chdir _chdir2 55#endif 56 57#ifdef WIN32 58#define S_IRGRP 0 59#define S_IWGRP 0 60#define S_IROTH 0 61#define S_IWOTH 0 62#endif 63 64#define lowbit(x) ((x) & (-(x))) 65 66/***====================================================================***/ 67 68#define WANT_DEFAULT 0 69#define WANT_XKM_FILE 1 70#define WANT_C_HDR 2 71#define WANT_XKB_FILE 3 72#define WANT_X_SERVER 4 73#define WANT_LISTING 5 74 75#define INPUT_UNKNOWN 0 76#define INPUT_XKB 1 77#define INPUT_XKM 2 78 79static const char *fileTypeExt[] = { 80 "XXX", 81 "xkm", 82 "h", 83 "xkb", 84 "dir" 85}; 86 87static unsigned inputFormat,outputFormat; 88 char * rootDir; 89static char * inputFile; 90static char * inputMap; 91static char * outputFile; 92static char * inDpyName; 93static char * outDpyName; 94static Display * inDpy; 95static Display * outDpy; 96static Bool showImplicit= False; 97static Bool synch= False; 98static Bool computeDflts= False; 99static Bool xkblist= False; 100 unsigned warningLevel= 5; 101 unsigned verboseLevel= 0; 102 unsigned dirsToStrip= 0; 103 unsigned optionalParts= 0; 104static char * preErrorMsg= NULL; 105static char * postErrorMsg= NULL; 106static char * errorPrefix= NULL; 107static unsigned int device_id = XkbUseCoreKbd; 108 109/***====================================================================***/ 110 111#define M(m) fprintf(stderr,(m)) 112#define M1(m,a) fprintf(stderr,(m),(a)) 113 114static void 115Usage(int argc,char *argv[]) 116{ 117 if (!xkblist) 118 M1("Usage: %s [options] input-file [ output-file ]\n",argv[0]); 119 else M1("Usage: %s [options] file[(map)] ...\n",argv[0]); 120 M("Legal options:\n"); 121 M("-?,-help Print this message\n"); 122 if (!xkblist) { 123 M("-a Show all actions\n"); 124 M("-C Create a C header file\n"); 125 } 126#ifdef DEBUG 127 M("-d [flags] Report debugging information\n"); 128#endif 129 M("-em1 <msg> Print <msg> before printing first error message\n"); 130 M("-emp <msg> Print <msg> at the start of each message line\n"); 131 M("-eml <msg> If there were any errors, print <msg> before exiting\n"); 132 if (!xkblist) { 133 M("-dflts Compute defaults for missing parts\n"); 134 M("-I[<dir>] Specifies a top level directory for include\n"); 135 M(" directives. Multiple directories are legal.\n"); 136 M("-l [flags] List matching maps in the specified files\n"); 137 M(" f: list fully specified names\n"); 138 M(" h: also list hidden maps\n"); 139 M(" l: long listing (show flags)\n"); 140 M(" p: also list partial maps\n"); 141 M(" R: recursively list subdirectories\n"); 142 M(" default is all options off\n"); 143 } 144 M("-i <deviceid> Specifies device ID (not name) to compile for\n"); 145 M("-m[ap] <map> Specifies map to compile\n"); 146 M("-o <file> Specifies output file name\n"); 147 if (!xkblist) { 148 M("-opt[ional] <parts> Specifies optional components of keymap\n"); 149 M(" Errors in optional parts are not fatal\n"); 150 M(" <parts> can be any combination of:\n"); 151 M(" c: compat map g: geometry\n"); 152 M(" k: keycodes s: symbols\n"); 153 M(" t: types\n"); 154 } 155 if (xkblist) { 156 M("-p <count> Specifies the number of slashes to be stripped\n"); 157 M(" from the front of the map name on output\n"); 158 } 159 M("-R[<DIR>] Specifies the root directory for\n"); 160 M(" relative path names\n"); 161 M("-synch Force synchronization\n"); 162 if (xkblist) { 163 M("-v [<flags>] Set level of detail for listing.\n"); 164 M(" flags are as for the -l option\n"); 165 } 166 M("-w [<lvl>] Set warning level (0=none, 10=all)\n"); 167 if (!xkblist) { 168 M("-xkb Create an XKB source (.xkb) file\n"); 169 M("-xkm Create a compiled key map (.xkm) file\n"); 170 } 171 return; 172} 173 174/***====================================================================***/ 175 176static void 177setVerboseFlags(char *str) 178{ 179 for (;*str;str++) { 180 switch (*str) { 181 case 'f': verboseLevel|= WantFullNames; break; 182 case 'h': verboseLevel|= WantHiddenMaps; break; 183 case 'l': verboseLevel|= WantLongListing; break; 184 case 'p': verboseLevel|= WantPartialMaps; break; 185 case 'R': verboseLevel|= ListRecursive; break; 186 default: 187 if (warningLevel>4) { 188 WARN1("Unknown verbose option \"%c\"\n",(unsigned int)*str); 189 ACTION("Ignored\n"); 190 } 191 break; 192 } 193 } 194 return; 195} 196 197static Bool 198parseArgs(int argc,char *argv[]) 199{ 200register int i,tmp; 201 202 i= strlen(argv[0]); 203 tmp= strlen("xkblist"); 204 if ((i>=tmp)&&(strcmp(&argv[0][i-tmp],"xkblist")==0)) { 205 xkblist= True; 206 } 207 for (i=1;i<argc;i++) { 208 int itmp; 209 if ((argv[i][0]!='-')||(uStringEqual(argv[i],"-"))) { 210 if (!xkblist) { 211 if (inputFile==NULL) 212 inputFile= argv[i]; 213 else if (outputFile==NULL) 214 outputFile= argv[i]; 215 else if (warningLevel>0) { 216 WARN("Too many file names on command line\n"); 217 ACTION3("Compiling %s, writing to %s, ignoring %s\n", 218 inputFile,outputFile,argv[i]); 219 } 220 } 221 else if (!AddMatchingFiles(argv[i])) 222 return False; 223 } 224 else if ((strcmp(argv[i],"-?")==0)||(strcmp(argv[i],"-help")==0)) { 225 Usage(argc,argv); 226 exit(0); 227 } 228 else if ((strcmp(argv[i],"-a")==0)&&(!xkblist)) { 229 showImplicit= True; 230 } 231 else if ((strcmp(argv[i],"-C")==0)&&(!xkblist)) { 232 if ((outputFormat!=WANT_DEFAULT)&&(outputFormat!=WANT_C_HDR)) { 233 if (warningLevel>0) { 234 WARN("Multiple output file formats specified\n"); 235 ACTION1("\"%s\" flag ignored\n",argv[i]); 236 } 237 } 238 else outputFormat= WANT_C_HDR; 239 } 240#ifdef DEBUG 241 else if (strcmp(argv[i],"-d")==0) { 242 if ((i>=(argc-1))||(!isdigit(argv[i+1][0]))) { 243 debugFlags= 1; 244 } 245 else { 246 if (sscanf(argv[++i],"%i",&itmp) == 1) 247 debugFlags = itmp; 248 } 249 INFO1("Setting debug flags to %d\n",debugFlags); 250 } 251#endif 252 else if ((strcmp(argv[i],"-dflts")==0)&&(!xkblist)) { 253 computeDflts= True; 254 } 255 else if (strcmp(argv[i],"-em1")==0) { 256 if (++i>=argc) { 257 if (warningLevel>0) { 258 WARN("No pre-error message specified\n"); 259 ACTION("Trailing \"-em1\" option ignored\n"); 260 } 261 } 262 else if (preErrorMsg!=NULL) { 263 if (warningLevel>0) { 264 WARN("Multiple pre-error messsages specified\n"); 265 ACTION2("Compiling %s, ignoring %s\n",preErrorMsg,argv[i]); 266 } 267 } 268 else preErrorMsg= argv[i]; 269 } 270 else if (strcmp(argv[i],"-emp")==0) { 271 if (++i>=argc) { 272 if (warningLevel>0) { 273 WARN("No error prefix specified\n"); 274 ACTION("Trailing \"-emp\" option ignored\n"); 275 } 276 } 277 else if (errorPrefix!=NULL) { 278 if (warningLevel>0) { 279 WARN("Multiple error prefixes specified\n"); 280 ACTION2("Compiling %s, ignoring %s\n",errorPrefix,argv[i]); 281 } 282 } 283 else errorPrefix= argv[i]; 284 } 285 else if (strcmp(argv[i],"-eml")==0) { 286 if (++i>=argc) { 287 if (warningLevel>0) { 288 WARN("No post-error message specified\n"); 289 ACTION("Trailing \"-eml\" option ignored\n"); 290 } 291 } 292 else if (postErrorMsg!=NULL) { 293 if (warningLevel>0) { 294 WARN("Multiple post-error messages specified\n"); 295 ACTION2("Compiling %s, ignoring %s\n",postErrorMsg,argv[i]); 296 } 297 } 298 else postErrorMsg= argv[i]; 299 } 300 else if ((strncmp(argv[i],"-I",2)==0)&&(!xkblist)) { 301 if (!XkbAddDirectoryToPath(&argv[i][2])) { 302 ACTION("Exiting\n"); 303 exit(1); 304 } 305 } 306 else if ((strncmp(argv[i], "-i", 2) == 0) && (!xkblist)) { 307 if (++i >= argc) { 308 if (warningLevel > 0) 309 WARN("No device ID specified\n"); 310 } 311 device_id = atoi(argv[i]); 312 } 313 else if ((strncmp(argv[i],"-l",2)==0)&&(!xkblist)) { 314 if (outputFormat!=WANT_DEFAULT) { 315 if (warningLevel>0) { 316 WARN("Multiple output file formats specified\n"); 317 ACTION1("\"%s\" flag ignored\n",argv[i]); 318 } 319 } 320 else { 321 if (argv[i][2]!='\0') 322 setVerboseFlags(&argv[i][2]); 323 xkblist= True; 324 if ((inputFile)&&(!AddMatchingFiles(inputFile))) 325 return False; 326 else inputFile= NULL; 327 if ((outputFile)&&(!AddMatchingFiles(outputFile))) 328 return False; 329 else outputFile= NULL; 330 } 331 } 332 else if ((strcmp(argv[i],"-m")==0)||(strcmp(argv[i],"-map")==0)) { 333 if (++i>=argc) { 334 if (warningLevel>0) { 335 WARN("No map name specified\n"); 336 ACTION1("Trailing \"%s\" option ignored\n",argv[i-1]); 337 } 338 } 339 else if (xkblist) { 340 if (!AddMapOnly(argv[i])) 341 return False; 342 } 343 else if (inputMap!=NULL) { 344 if (warningLevel>0) { 345 WARN("Multiple map names specified\n"); 346 ACTION2("Compiling %s, ignoring %s\n",inputMap,argv[i]); 347 } 348 } 349 else inputMap= argv[i]; 350 } 351 else if ((strcmp(argv[i],"-merge")==0)&&(!xkblist)) { 352 /* Ignored */ 353 } 354 else if (strcmp(argv[i],"-o")==0) { 355 if (++i>=argc) { 356 if (warningLevel>0) { 357 WARN("No output file specified\n"); 358 ACTION("Trailing \"-o\" option ignored\n"); 359 } 360 } 361 else if (outputFile!=NULL) { 362 if (warningLevel>0) { 363 WARN("Multiple output files specified\n"); 364 ACTION2("Compiling %s, ignoring %s\n",outputFile,argv[i]); 365 } 366 } 367 else outputFile= argv[i]; 368 } 369 else if (((strcmp(argv[i],"-opt")==0)||(strcmp(argv[i],"optional")==0)) 370 &&(!xkblist)) { 371 if (++i>=argc) { 372 if (warningLevel>0) { 373 WARN("No optional components specified\n"); 374 ACTION1("Trailing \"%s\" option ignored\n",argv[i-1]); 375 } 376 } 377 else { 378 char *tmp2; 379 for (tmp2=argv[i];(*tmp2!='\0');tmp2++) { 380 switch (*tmp2) { 381 case 'c': case 'C': 382 optionalParts|= XkmCompatMapMask; 383 break; 384 case 'g': case 'G': 385 optionalParts|= XkmGeometryMask; 386 break; 387 case 'k': case 'K': 388 optionalParts|= XkmKeyNamesMask; 389 break; 390 case 's': case 'S': 391 optionalParts|= XkmSymbolsMask; 392 break; 393 case 't': case 'T': 394 optionalParts|= XkmTypesMask; 395 break; 396 default: 397 if (warningLevel>0) { 398 WARN1("Illegal component for %s option\n", 399 argv[i-1]); 400 ACTION1("Ignoring unknown specifier \"%c\"\n", 401 (unsigned int)*tmp2); 402 } 403 break; 404 } 405 } 406 } 407 } 408 else if (strncmp(argv[i],"-p",2)==0) { 409 if (isdigit(argv[i][2])) { 410 if (sscanf(&argv[i][2],"%i",&itmp) == 1) 411 dirsToStrip = itmp; 412 } 413 else if ((i<(argc-1))&&(isdigit(argv[i+1][0]))) { 414 if (sscanf(argv[++i],"%i",&itmp) == 1) 415 dirsToStrip = itmp; 416 } 417 else { 418 dirsToStrip= 0; 419 } 420 if (warningLevel>5) 421 INFO1("Setting path count to %d\n",dirsToStrip); 422 } 423 else if (strncmp(argv[i],"-R",2)==0) { 424 if (argv[i][2]=='\0') { 425 if (warningLevel>0) { 426 WARN("No root directory specified\n"); 427 ACTION("Ignoring -R option\n"); 428 } 429 } 430 else if (rootDir!=NULL) { 431 if (warningLevel>0) { 432 WARN("Multiple root directories specified\n"); 433 ACTION2("Using %s, ignoring %s\n",rootDir,argv[i]); 434 } 435 } 436 else { 437 rootDir= &argv[i][2]; 438 if (warningLevel>8) { 439 WARN1("Changing root directory to \"%s\"\n",rootDir); 440 } 441 if ((chdir(rootDir)<0) && (warningLevel>0)) { 442 WARN1("Couldn't change directory to \"%s\"\n",rootDir); 443 ACTION("Root directory (-R) option ignored\n"); 444 rootDir= NULL; 445 } 446 } 447 } 448 else if ((strcmp(argv[i],"-synch")==0)||(strcmp(argv[i],"-s")==0)) { 449 synch= True; 450 } 451 else if (strncmp(argv[i],"-v",2)==0) { 452 char *str; 453 if (argv[i][2]!='\0') 454 str= &argv[i][2]; 455 else if ((i<(argc-1))&&(argv[i+1][0]!='-')) 456 str= argv[++i]; 457 else str= NULL; 458 if (str) 459 setVerboseFlags(str); 460 } 461 else if (strncmp(argv[i],"-w",2)==0) { 462 if ((i>=(argc-1))||(!isdigit(argv[i+1][0]))) { 463 warningLevel = 0; 464 if (isdigit(argv[i][1])) 465 if (sscanf(&argv[i][1],"%i",&itmp) == 1) 466 warningLevel = itmp; 467 } 468 else { 469 if (sscanf(argv[++i],"%i",&itmp) == 1) 470 warningLevel = itmp; 471 } 472 } 473 else if ((strcmp(argv[i],"-xkb")==0)&&(!xkblist)) { 474 if ((outputFormat!=WANT_DEFAULT)&&(outputFormat!=WANT_XKB_FILE)) { 475 if (warningLevel>0) { 476 WARN("Multiple output file formats specified\n"); 477 ACTION1("\"%s\" flag ignored\n",argv[i]); 478 } 479 } 480 else outputFormat= WANT_XKB_FILE; 481 } 482 else if ((strcmp(argv[i],"-xkm")==0)&&(!xkblist)) { 483 if ((outputFormat!=WANT_DEFAULT)&&(outputFormat!=WANT_XKM_FILE)) { 484 if (warningLevel>0) { 485 WARN("Multiple output file formats specified\n"); 486 ACTION1("\"%s\" flag ignored\n",argv[i]); 487 } 488 } 489 else outputFormat= WANT_XKM_FILE; 490 } 491 else { 492 ERROR1("Unknown flag \"%s\" on command line\n",argv[i]); 493 Usage(argc,argv); 494 return False; 495 } 496 } 497 if (xkblist) 498 inputFormat= INPUT_XKB; 499 else if (inputFile==NULL) { 500 ERROR("No input file specified\n"); 501 return False; 502 } 503 else if (uStringEqual(inputFile,"-")) { 504 inputFormat= INPUT_XKB; 505 } 506#ifndef WIN32 507 else if (strchr(inputFile,':')==0) { 508#else 509 else if ((strchr(inputFile,':')==0) || ( 510 strlen(inputFile) > 2 && 511 isalpha(inputFile[0]) && 512 inputFile[1] == ':' && strchr(inputFile + 2,':')==NULL)) { 513#endif 514 int len; 515 len= strlen(inputFile); 516 if (inputFile[len-1]==')') { 517 char *tmp; 518 if ((tmp=strchr(inputFile,'('))!=0) { 519 *tmp= '\0'; inputFile[len-1]= '\0'; 520 tmp++; 521 if (*tmp=='\0') { 522 WARN("Empty map in filename\n"); 523 ACTION("Ignored\n"); 524 } 525 else if (inputMap==NULL) { 526 inputMap= uStringDup(tmp); 527 } 528 else { 529 WARN("Map specified in filename and with -m flag\n"); 530 ACTION1("map from name (\"%s\") ignored\n",tmp); 531 } 532 } 533 else { 534 ERROR1("Illegal name \"%s\" for input file\n",inputFile); 535 return False; 536 } 537 } 538 if ((len>4)&&(strcmp(&inputFile[len-4],".xkm")==0)) { 539 inputFormat= INPUT_XKM; 540 } 541 else { 542 FILE *file; 543 file= fopen(inputFile,"r"); 544 if (file) { 545 if (XkmProbe(file)) inputFormat= INPUT_XKM; 546 else inputFormat= INPUT_XKB; 547 fclose(file); 548 } 549 else { 550 fprintf(stderr,"Cannot open \"%s\" for reading\n",inputFile); 551 return False; 552 } 553 } 554 } 555 else { 556 inDpyName= inputFile; 557 inputFile= NULL; 558 inputFormat= INPUT_XKM; 559 } 560 561 if (outputFormat==WANT_DEFAULT) { 562 if (xkblist) outputFormat= WANT_LISTING; 563 else if (inputFormat==INPUT_XKB) outputFormat= WANT_XKM_FILE; 564 else outputFormat= WANT_XKB_FILE; 565 } 566 if ((outputFormat==WANT_LISTING)&&(inputFormat!=INPUT_XKB)) { 567 if (inputFile) 568 ERROR("Cannot generate a listing from a .xkm file (yet)\n"); 569 else ERROR("Cannot generate a listing from an X connection (yet)\n"); 570 return False; 571 } 572 if (xkblist) { 573 if (outputFile==NULL) outputFile= uStringDup("-"); 574 else if (strchr(outputFile,':')!=NULL) { 575 ERROR("Cannot write a listing to an X connection\n"); 576 return False; 577 } 578 } 579 else if ((!outputFile) && (inputFile) && uStringEqual(inputFile,"-")) { 580 int len= strlen("stdin")+strlen(fileTypeExt[outputFormat])+2; 581 outputFile= uTypedCalloc(len,char); 582 if (outputFile==NULL) { 583 WSGO("Cannot allocate space for output file name\n"); 584 ACTION("Exiting\n"); 585 exit(1); 586 } 587 sprintf(outputFile,"stdin.%s",fileTypeExt[outputFormat]); 588 } 589 else if ((outputFile==NULL)&&(inputFile!=NULL)) { 590 int len; 591 char *base,*ext; 592 593 if (inputMap==NULL) { 594 base= strrchr(inputFile,'/'); 595 if (base==NULL) base= inputFile; 596 else base++; 597 } 598 else base= inputMap; 599 600 len= strlen(base)+strlen(fileTypeExt[outputFormat])+2; 601 outputFile= uTypedCalloc(len,char); 602 if (outputFile==NULL) { 603 WSGO("Cannot allocate space for output file name\n"); 604 ACTION("Exiting\n"); 605 exit(1); 606 } 607 ext= strrchr(base,'.'); 608 if (ext==NULL) 609 sprintf(outputFile,"%s.%s",base,fileTypeExt[outputFormat]); 610 else { 611 strcpy(outputFile,base); 612 strcpy(&outputFile[ext-base+1],fileTypeExt[outputFormat]); 613 } 614 } 615 else if (outputFile==NULL) { 616 int len; 617 char *ch,*name,buf[128]; 618 if (inDpyName[0]==':') 619 sprintf(name=buf,"server%s",inDpyName); 620 else name= inDpyName; 621 622 len= strlen(name)+strlen(fileTypeExt[outputFormat])+2; 623 outputFile= uTypedCalloc(len,char); 624 if (outputFile==NULL) { 625 WSGO("Cannot allocate space for output file name\n"); 626 ACTION("Exiting\n"); 627 exit(1); 628 } 629 strcpy(outputFile,name); 630 for (ch=outputFile;(*ch)!='\0';ch++) { 631 if (*ch==':') *ch= '-'; 632 else if (*ch=='.') *ch= '_'; 633 } 634 *ch++= '.'; 635 strcpy(ch,fileTypeExt[outputFormat]); 636 } 637#ifdef WIN32 638 else if (strlen(outputFile) > 2 && 639 isalpha(outputFile[0]) && 640 outputFile[1] == ':' && strchr(outputFile + 2,':')==NULL) { 641 } 642#endif 643 else if (strchr(outputFile,':')!=NULL) { 644 outDpyName= outputFile; 645 outputFile= NULL; 646 outputFormat= WANT_X_SERVER; 647 } 648 return True; 649} 650 651static Display * 652GetDisplay(char *program,char *dpyName) 653{ 654int mjr,mnr,error; 655Display *dpy; 656 657 mjr= XkbMajorVersion; 658 mnr= XkbMinorVersion; 659 dpy= XkbOpenDisplay(dpyName,NULL,NULL,&mjr,&mnr,&error); 660 if (dpy==NULL) { 661 switch (error) { 662 case XkbOD_BadLibraryVersion: 663 INFO3("%s was compiled with XKB version %d.%02d\n", 664 program,XkbMajorVersion,XkbMinorVersion); 665 ERROR2("X library supports incompatible version %d.%02d\n", 666 mjr,mnr); 667 break; 668 case XkbOD_ConnectionRefused: 669 ERROR1("Cannot open display \"%s\"\n",dpyName); 670 break; 671 case XkbOD_NonXkbServer: 672 ERROR1("XKB extension not present on %s\n",dpyName); 673 break; 674 case XkbOD_BadServerVersion: 675 INFO3("%s was compiled with XKB version %d.%02d\n", 676 program,XkbMajorVersion,XkbMinorVersion); 677 ERROR3("Server %s uses incompatible version %d.%02d\n", 678 dpyName,mjr,mnr); 679 break; 680 default: 681 WSGO1("Unknown error %d from XkbOpenDisplay\n",error); 682 } 683 } 684 else if (synch) 685 XSynchronize(dpy,True); 686 return dpy; 687} 688 689/***====================================================================***/ 690 691extern int yydebug; 692 693int 694main(int argc,char *argv[]) 695{ 696FILE * file; 697XkbFile * rtrn; 698XkbFile * mapToUse; 699int ok; 700XkbFileInfo result; 701Status status; 702 703 yyin = stdin; 704 uSetEntryFile(NullString); 705 uSetDebugFile(NullString); 706 uSetErrorFile(NullString); 707 708 XkbInitIncludePath(); 709 if (!parseArgs(argc,argv)) 710 exit(1); 711#ifdef DEBUG 712 if (debugFlags&0x2) 713 yydebug= 1; 714#endif 715 if (preErrorMsg) 716 uSetPreErrorMessage(preErrorMsg); 717 if (errorPrefix) 718 uSetErrorPrefix(errorPrefix); 719 if (postErrorMsg) 720 uSetPostErrorMessage(postErrorMsg); 721 file= NULL; 722 XkbInitAtoms(NULL); 723 XkbAddDefaultDirectoriesToPath(); 724 if (xkblist) { 725 Bool gotSome; 726 gotSome= GenerateListing(outputFile); 727 if ((warningLevel>7)&&(!gotSome)) 728 return -1; 729 return 0; 730 } 731 if (inputFile!=NULL) { 732 if (uStringEqual(inputFile,"-")) { 733 file= stdin; 734 inputFile= "stdin"; 735 } 736 else { 737 file= fopen(inputFile,"r"); 738 } 739 } 740 else if (inDpyName!=NULL) { 741 inDpy= GetDisplay(argv[0],inDpyName); 742 if (!inDpy) { 743 ACTION("Exiting\n"); 744 exit(1); 745 } 746 } 747 if (outDpyName!=NULL) { 748 outDpy= GetDisplay(argv[0],outDpyName); 749 if (!outDpy) { 750 ACTION("Exiting\n"); 751 exit(1); 752 } 753 } 754 if ((inDpy==NULL) && (outDpy==NULL)) { 755 int mjr,mnr; 756 mjr= XkbMajorVersion; 757 mnr= XkbMinorVersion; 758 if (!XkbLibraryVersion(&mjr,&mnr)) { 759 INFO3("%s was compiled with XKB version %d.%02d\n", 760 argv[0],XkbMajorVersion,XkbMinorVersion); 761 ERROR2("X library supports incompatible version %d.%02d\n", 762 mjr,mnr); 763 ACTION("Exiting\n"); 764 exit(1); 765 } 766 } 767 if (file) { 768 ok= True; 769 setScanState(inputFile,1); 770 if ((inputFormat==INPUT_XKB)&&(XKBParseFile(file,&rtrn)&&(rtrn!=NULL))){ 771 fclose(file); 772 mapToUse= rtrn; 773 if (inputMap!=NULL) { 774 while ((mapToUse)&&(!uStringEqual(mapToUse->name,inputMap))) { 775 mapToUse= (XkbFile *)mapToUse->common.next; 776 } 777 if (!mapToUse) { 778 FATAL2("No map named \"%s\" in \"%s\"\n",inputMap, 779 inputFile); 780 /* NOTREACHED */ 781 } 782 } 783 else if (rtrn->common.next!=NULL) { 784 mapToUse= rtrn; 785 for (;mapToUse;mapToUse= (XkbFile*)mapToUse->common.next) { 786 if (mapToUse->flags&XkbLC_Default) 787 break; 788 } 789 if (!mapToUse) { 790 mapToUse= rtrn; 791 if (warningLevel>4) { 792 WARN1("No map specified, but \"%s\" has several\n", 793 inputFile); 794 ACTION1("Using the first defined map, \"%s\"\n", 795 mapToUse->name); 796 } 797 } 798 } 799 bzero((char *)&result,sizeof(result)); 800 result.type= mapToUse->type; 801 if ((result.xkb= XkbAllocKeyboard())==NULL) { 802 WSGO("Cannot allocate keyboard description\n"); 803 /* NOTREACHED */ 804 } 805 switch (mapToUse->type) { 806 case XkmSemanticsFile: 807 case XkmLayoutFile: 808 case XkmKeymapFile: 809 ok= CompileKeymap(mapToUse,&result,MergeReplace); 810 break; 811 case XkmKeyNamesIndex: 812 ok= CompileKeycodes(mapToUse,&result,MergeReplace); 813 break; 814 case XkmTypesIndex: 815 ok= CompileKeyTypes(mapToUse,&result,MergeReplace); 816 break; 817 case XkmSymbolsIndex: 818 /* if it's just symbols, invent key names */ 819 result.xkb->flags|= AutoKeyNames; 820 ok= False; 821 break; 822 case XkmCompatMapIndex: 823 ok= CompileCompatMap(mapToUse,&result,MergeReplace,NULL); 824 break; 825 case XkmGeometryFile: 826 case XkmGeometryIndex: 827 /* if it's just a geometry, invent key names */ 828 result.xkb->flags|= AutoKeyNames; 829 ok= CompileGeometry(mapToUse,&result,MergeReplace); 830 break; 831 default: 832 WSGO1("Unknown file type %d\n",mapToUse->type); 833 ok= False; 834 break; 835 } 836 } 837 else if (inputFormat==INPUT_XKM) { 838 unsigned tmp; 839 bzero((char *)&result,sizeof(result)); 840 if ((result.xkb= XkbAllocKeyboard())==NULL) { 841 WSGO("Cannot allocate keyboard description\n"); 842 /* NOTREACHED */ 843 } 844 tmp= XkmReadFile(file,0,XkmKeymapLegal,&result); 845 if (tmp==XkmKeymapLegal) { 846 ERROR1("Cannot read XKM file \"%s\"\n",inputFile); 847 ok= False; 848 } 849 } 850 else { 851 INFO1("Errors encountered in %s; not compiled.\n",inputFile); 852 ok= False; 853 } 854 } 855 else if (inDpy!=NULL) { 856 bzero((char *)&result,sizeof(result)); 857 result.type= XkmKeymapFile; 858 result.xkb= XkbGetMap(inDpy,XkbAllMapComponentsMask,device_id); 859 if (result.xkb==NULL) 860 WSGO("Cannot load keyboard description\n"); 861 if (XkbGetIndicatorMap(inDpy,~0,result.xkb)!=Success) 862 WSGO("Could not load indicator map\n"); 863 if (XkbGetControls(inDpy,XkbAllControlsMask,result.xkb)!=Success) 864 WSGO("Could not load keyboard controls\n"); 865 if (XkbGetCompatMap(inDpy,XkbAllCompatMask,result.xkb)!=Success) 866 WSGO("Could not load compatibility map\n"); 867 if (XkbGetNames(inDpy,XkbAllNamesMask,result.xkb)!=Success) 868 WSGO("Could not load names\n"); 869 if ((status=XkbGetGeometry(inDpy,result.xkb))!=Success) { 870 if (warningLevel>3) { 871 char buf[100]; 872 buf[0]= '\0'; 873 XGetErrorText(inDpy,status,buf,100); 874 WARN1("Could not load keyboard geometry for %s\n",inDpyName); 875 ACTION1("%s\n",buf); 876 ACTION("Resulting keymap file will not describe geometry\n"); 877 } 878 } 879 if (computeDflts) 880 ok= (ComputeKbdDefaults(result.xkb)==Success); 881 else ok= True; 882 } 883 else { 884 fprintf(stderr,"Cannot open \"%s\" to compile\n",inputFile); 885 ok= 0; 886 } 887 if (ok) { 888 FILE *out = stdout; 889 if ((inDpy!=outDpy)&& 890 (XkbChangeKbdDisplay(outDpy,&result)!=Success)) { 891 WSGO2("Error converting keyboard display from %s to %s\n", 892 inDpyName,outDpyName); 893 exit(1); 894 } 895 if (outputFile!=NULL) { 896 if (uStringEqual(outputFile,"-")) 897 outputFile= "stdout"; 898 else { 899 /* 900 * fix to prevent symlink attack (e.g., 901 * ln -s /etc/passwd /var/tmp/server-0.xkm) 902 */ 903 /* 904 * this patch may have POSIX, Linux, or GNU libc bias 905 * -- Branden Robinson 906 */ 907 int outputFileFd; 908 int binMode = 0; 909 const char *openMode = "w"; 910 unlink(outputFile); 911#ifdef O_BINARY 912 switch (outputFormat) { 913 case WANT_XKM_FILE: 914 binMode = O_BINARY; 915 openMode = "wb"; 916 break; 917 default: 918 binMode = 0; 919 break; 920 } 921#endif 922 outputFileFd= open(outputFile, O_WRONLY|O_CREAT|O_EXCL, 923 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH|binMode); 924 if (outputFileFd<0) { 925 ERROR1("Cannot open \"%s\" to write keyboard description\n", 926 outputFile); 927 ACTION("Exiting\n"); 928 exit(1); 929 } 930#ifndef WIN32 931 out= fdopen(outputFileFd, openMode); 932#else 933 close(outputFileFd); 934 out= fopen(outputFile, "wb"); 935#endif 936 /* end BR */ 937 if (out==NULL) { 938 ERROR1("Cannot open \"%s\" to write keyboard description\n", 939 outputFile); 940 ACTION("Exiting\n"); 941 exit(1); 942 } 943 } 944 } 945 switch (outputFormat) { 946 case WANT_XKM_FILE: 947 ok= XkbWriteXKMFile(out,&result); 948 break; 949 case WANT_XKB_FILE: 950 ok= XkbWriteXKBFile(out,&result,showImplicit,NULL,NULL); 951 break; 952 case WANT_C_HDR: 953 ok= XkbWriteCFile(out,outputFile,&result); 954 break; 955 case WANT_X_SERVER: 956 if (!(ok= XkbWriteToServer(&result))) { 957 ERROR2("%s in %s\n",_XkbErrMessages[_XkbErrCode], 958 _XkbErrLocation?_XkbErrLocation:"unknown"); 959 ACTION1("Couldn't write keyboard description to %s\n", 960 outDpyName); 961 } 962 break; 963 default: 964 WSGO1("Unknown output format %d\n",outputFormat); 965 ACTION("No output file created\n"); 966 ok= False; 967 break; 968 } 969 if (outputFormat!=WANT_X_SERVER) { 970 fclose(out); 971 if (!ok) { 972 ERROR2("%s in %s\n",_XkbErrMessages[_XkbErrCode], 973 _XkbErrLocation?_XkbErrLocation:"unknown"); 974 ACTION1("Output file \"%s\" removed\n",outputFile); 975 unlink(outputFile); 976 } 977 } 978 } 979 if (inDpy) 980 XCloseDisplay(inDpy); 981 inDpy= NULL; 982 if (outDpy) 983 XCloseDisplay(outDpy); 984 uFinishUp(); 985 return (ok==0); 986} 987