1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
29 #include <X11/keysym.h>
31 /* for symlink attack security fix -- Branden Robinson */
33 #include <sys/types.h>
41 #define DEBUG_VAR debugFlags
45 #include "parseutils.h"
48 #include <X11/extensions/XKBgeom.h>
61 #define lowbit(x) ((x) & (-(x)))
63 /***====================================================================***/
65 #define WANT_DEFAULT 0
66 #define WANT_XKM_FILE 1
68 #define WANT_XKB_FILE 3
69 #define WANT_X_SERVER 4
70 #define WANT_LISTING 5
72 #define INPUT_UNKNOWN 0
76 unsigned int debugFlags;
78 static const char *fileTypeExt[] = {
86 static unsigned inputFormat, outputFormat;
88 static char *inputFile;
89 static char *inputMap;
90 static char *outputFile;
91 static char *inDpyName;
92 static char *outDpyName;
93 static Display *inDpy;
94 static Display *outDpy;
95 static Bool showImplicit = False;
96 static Bool synch = False;
97 static Bool computeDflts = False;
98 static Bool xkblist = False;
99 unsigned warningLevel = 5;
100 unsigned verboseLevel = 0;
101 unsigned dirsToStrip = 0;
102 unsigned optionalParts = 0;
103 static char *preErrorMsg = NULL;
104 static char *postErrorMsg = NULL;
105 static char *errorPrefix = NULL;
106 static unsigned int device_id = XkbUseCoreKbd;
108 /***====================================================================***/
110 #define M(m) fprintf(stderr,(m))
111 #define M1(m,a) fprintf(stderr,(m),(a))
114 Usage(int argc, char *argv[])
117 M1("Usage: %s [options] input-file [ output-file ]\n", argv[0]);
119 M1("Usage: %s [options] file[(map)] ...\n", argv[0]);
120 M("Legal options:\n");
121 M("-?,-help Print this message\n");
124 M("-a Show all actions\n");
125 M("-C Create a C header file\n");
128 M("-d [flags] Report debugging information\n");
130 M("-em1 <msg> Print <msg> before printing first error message\n");
131 M("-emp <msg> Print <msg> at the start of each message line\n");
132 M("-eml <msg> If there were any errors, print <msg> before exiting\n");
135 M("-dflts Compute defaults for missing parts\n");
136 M("-I[<dir>] Specifies a top level directory for include\n");
137 M(" directives. Multiple directories are legal.\n");
138 M("-l [flags] List matching maps in the specified files\n");
139 M(" f: list fully specified names\n");
140 M(" h: also list hidden maps\n");
141 M(" l: long listing (show flags)\n");
142 M(" p: also list partial maps\n");
143 M(" R: recursively list subdirectories\n");
144 M(" default is all options off\n");
146 M("-i <deviceid> Specifies device ID (not name) to compile for\n");
147 M("-m[ap] <map> Specifies map to compile\n");
148 M("-o <file> Specifies output file name\n");
151 M("-opt[ional] <parts> Specifies optional components of keymap\n");
152 M(" Errors in optional parts are not fatal\n");
153 M(" <parts> can be any combination of:\n");
154 M(" c: compat map g: geometry\n");
155 M(" k: keycodes s: symbols\n");
160 M("-p <count> Specifies the number of slashes to be stripped\n");
161 M(" from the front of the map name on output\n");
163 M("-R[<DIR>] Specifies the root directory for\n");
164 M(" relative path names\n");
165 M("-synch Force synchronization\n");
168 M("-v [<flags>] Set level of detail for listing.\n");
169 M(" flags are as for the -l option\n");
171 M("-w [<lvl>] Set warning level (0=none, 10=all)\n");
174 M("-xkb Create an XKB source (.xkb) file\n");
175 M("-xkm Create a compiled key map (.xkm) file\n");
180 /***====================================================================***/
183 setVerboseFlags(char *str)
190 verboseLevel |= WantFullNames;
193 verboseLevel |= WantHiddenMaps;
196 verboseLevel |= WantLongListing;
199 verboseLevel |= WantPartialMaps;
202 verboseLevel |= ListRecursive;
205 if (warningLevel > 4)
207 WARN1("Unknown verbose option \"%c\"\n", (unsigned int) *str);
217 parseArgs(int argc, char *argv[])
222 tmp = strlen("xkblist");
223 if ((i >= tmp) && (strcmp(&argv[0][i - tmp], "xkblist") == 0))
227 for (i = 1; i < argc; i++)
230 if ((argv[i][0] != '-') || (uStringEqual(argv[i], "-")))
234 if (inputFile == NULL)
236 else if (outputFile == NULL)
237 outputFile = argv[i];
238 else if (warningLevel > 0)
240 WARN("Too many file names on command line\n");
242 ("Compiling %s, writing to %s, ignoring %s\n",
243 inputFile, outputFile, argv[i]);
246 else if (!AddMatchingFiles(argv[i]))
249 else if ((strcmp(argv[i], "-?") == 0)
250 || (strcmp(argv[i], "-help") == 0))
255 else if ((strcmp(argv[i], "-a") == 0) && (!xkblist))
259 else if ((strcmp(argv[i], "-C") == 0) && (!xkblist))
261 if ((outputFormat != WANT_DEFAULT)
262 && (outputFormat != WANT_C_HDR))
264 if (warningLevel > 0)
266 WARN("Multiple output file formats specified\n");
267 ACTION1("\"%s\" flag ignored\n", argv[i]);
271 outputFormat = WANT_C_HDR;
274 else if (strcmp(argv[i], "-d") == 0)
276 if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0])))
282 if (sscanf(argv[++i], "%i", &itmp) == 1)
285 INFO1("Setting debug flags to %d\n", debugFlags);
288 else if ((strcmp(argv[i], "-dflts") == 0) && (!xkblist))
292 else if (strcmp(argv[i], "-em1") == 0)
296 if (warningLevel > 0)
298 WARN("No pre-error message specified\n");
299 ACTION("Trailing \"-em1\" option ignored\n");
302 else if (preErrorMsg != NULL)
304 if (warningLevel > 0)
306 WARN("Multiple pre-error messsages specified\n");
307 ACTION2("Compiling %s, ignoring %s\n",
308 preErrorMsg, argv[i]);
312 preErrorMsg = argv[i];
314 else if (strcmp(argv[i], "-emp") == 0)
318 if (warningLevel > 0)
320 WARN("No error prefix specified\n");
321 ACTION("Trailing \"-emp\" option ignored\n");
324 else if (errorPrefix != NULL)
326 if (warningLevel > 0)
328 WARN("Multiple error prefixes specified\n");
329 ACTION2("Compiling %s, ignoring %s\n",
330 errorPrefix, argv[i]);
334 errorPrefix = argv[i];
336 else if (strcmp(argv[i], "-eml") == 0)
340 if (warningLevel > 0)
342 WARN("No post-error message specified\n");
343 ACTION("Trailing \"-eml\" option ignored\n");
346 else if (postErrorMsg != NULL)
348 if (warningLevel > 0)
350 WARN("Multiple post-error messages specified\n");
351 ACTION2("Compiling %s, ignoring %s\n",
352 postErrorMsg, argv[i]);
356 postErrorMsg = argv[i];
358 else if ((strncmp(argv[i], "-I", 2) == 0) && (!xkblist))
360 if (!XkbAddDirectoryToPath(&argv[i][2]))
366 else if ((strncmp(argv[i], "-i", 2) == 0) && (!xkblist))
370 if (warningLevel > 0)
371 WARN("No device ID specified\n");
373 device_id = atoi(argv[i]);
375 else if ((strncmp(argv[i], "-l", 2) == 0) && (!xkblist))
377 if (outputFormat != WANT_DEFAULT)
379 if (warningLevel > 0)
381 WARN("Multiple output file formats specified\n");
382 ACTION1("\"%s\" flag ignored\n", argv[i]);
387 if (argv[i][2] != '\0')
388 setVerboseFlags(&argv[i][2]);
390 if ((inputFile) && (!AddMatchingFiles(inputFile)))
394 if ((outputFile) && (!AddMatchingFiles(outputFile)))
400 else if ((strcmp(argv[i], "-m") == 0)
401 || (strcmp(argv[i], "-map") == 0))
405 if (warningLevel > 0)
407 WARN("No map name specified\n");
408 ACTION1("Trailing \"%s\" option ignored\n", argv[i - 1]);
413 if (!AddMapOnly(argv[i]))
416 else if (inputMap != NULL)
418 if (warningLevel > 0)
420 WARN("Multiple map names specified\n");
421 ACTION2("Compiling %s, ignoring %s\n", inputMap, argv[i]);
427 else if ((strcmp(argv[i], "-merge") == 0) && (!xkblist))
431 else if (strcmp(argv[i], "-o") == 0)
435 if (warningLevel > 0)
437 WARN("No output file specified\n");
438 ACTION("Trailing \"-o\" option ignored\n");
441 else if (outputFile != NULL)
443 if (warningLevel > 0)
445 WARN("Multiple output files specified\n");
446 ACTION2("Compiling %s, ignoring %s\n", outputFile,
451 outputFile = argv[i];
453 else if (((strcmp(argv[i], "-opt") == 0)
454 || (strcmp(argv[i], "optional") == 0)) && (!xkblist))
458 if (warningLevel > 0)
460 WARN("No optional components specified\n");
461 ACTION1("Trailing \"%s\" option ignored\n", argv[i - 1]);
467 for (tmp2 = argv[i]; (*tmp2 != '\0'); tmp2++)
473 optionalParts |= XkmCompatMapMask;
477 optionalParts |= XkmGeometryMask;
481 optionalParts |= XkmKeyNamesMask;
485 optionalParts |= XkmSymbolsMask;
489 optionalParts |= XkmTypesMask;
492 if (warningLevel > 0)
495 ("Illegal component for %s option\n",
498 ("Ignoring unknown specifier \"%c\"\n",
499 (unsigned int) *tmp2);
506 else if (strncmp(argv[i], "-p", 2) == 0)
508 if (isdigit(argv[i][2]))
510 if (sscanf(&argv[i][2], "%i", &itmp) == 1)
513 else if ((i < (argc - 1)) && (isdigit(argv[i + 1][0])))
515 if (sscanf(argv[++i], "%i", &itmp) == 1)
522 if (warningLevel > 5)
523 INFO1("Setting path count to %d\n", dirsToStrip);
525 else if (strncmp(argv[i], "-R", 2) == 0)
527 if (argv[i][2] == '\0')
529 if (warningLevel > 0)
531 WARN("No root directory specified\n");
532 ACTION("Ignoring -R option\n");
535 else if (rootDir != NULL)
537 if (warningLevel > 0)
539 WARN("Multiple root directories specified\n");
540 ACTION2("Using %s, ignoring %s\n", rootDir, argv[i]);
545 rootDir = &argv[i][2];
546 if (warningLevel > 8)
548 WARN1("Changing root directory to \"%s\"\n", rootDir);
550 if ((chdir(rootDir) < 0) && (warningLevel > 0))
552 WARN1("Couldn't change directory to \"%s\"\n", rootDir);
553 ACTION("Root directory (-R) option ignored\n");
558 else if ((strcmp(argv[i], "-synch") == 0)
559 || (strcmp(argv[i], "-s") == 0))
563 else if (strncmp(argv[i], "-v", 2) == 0)
566 if (argv[i][2] != '\0')
568 else if ((i < (argc - 1)) && (argv[i + 1][0] != '-'))
573 setVerboseFlags(str);
575 else if (strncmp(argv[i], "-w", 2) == 0)
577 if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0])))
580 if (isdigit(argv[i][1]))
581 if (sscanf(&argv[i][1], "%i", &itmp) == 1)
586 if (sscanf(argv[++i], "%i", &itmp) == 1)
590 else if ((strcmp(argv[i], "-xkb") == 0) && (!xkblist))
592 if ((outputFormat != WANT_DEFAULT)
593 && (outputFormat != WANT_XKB_FILE))
595 if (warningLevel > 0)
597 WARN("Multiple output file formats specified\n");
598 ACTION1("\"%s\" flag ignored\n", argv[i]);
602 outputFormat = WANT_XKB_FILE;
604 else if ((strcmp(argv[i], "-xkm") == 0) && (!xkblist))
606 if ((outputFormat != WANT_DEFAULT)
607 && (outputFormat != WANT_XKM_FILE))
609 if (warningLevel > 0)
611 WARN("Multiple output file formats specified\n");
612 ACTION1("\"%s\" flag ignored\n", argv[i]);
616 outputFormat = WANT_XKM_FILE;
620 ERROR1("Unknown flag \"%s\" on command line\n", argv[i]);
626 inputFormat = INPUT_XKB;
627 else if (inputFile == NULL)
629 ERROR("No input file specified\n");
632 else if (uStringEqual(inputFile, "-"))
634 inputFormat = INPUT_XKB;
637 else if (strchr(inputFile, ':') == NULL)
640 else if ((strchr(inputFile, ':') == NULL) || (strlen(inputFile) > 2 &&
641 isalpha(inputFile[0]) &&
643 && strchr(inputFile + 2,
648 len = strlen(inputFile);
649 if (inputFile[len - 1] == ')')
652 if ((tmp = strchr(inputFile, '(')) != NULL)
655 inputFile[len - 1] = '\0';
659 WARN("Empty map in filename\n");
662 else if (inputMap == NULL)
664 inputMap = uStringDup(tmp);
668 WARN("Map specified in filename and with -m flag\n");
669 ACTION1("map from name (\"%s\") ignored\n", tmp);
674 ERROR1("Illegal name \"%s\" for input file\n", inputFile);
678 if ((len > 4) && (strcmp(&inputFile[len - 4], ".xkm") == 0))
680 inputFormat = INPUT_XKM;
685 file = fopen(inputFile, "r");
689 inputFormat = INPUT_XKM;
691 inputFormat = INPUT_XKB;
696 fprintf(stderr, "Cannot open \"%s\" for reading\n",
704 inDpyName = inputFile;
706 inputFormat = INPUT_XKM;
709 if (outputFormat == WANT_DEFAULT)
712 outputFormat = WANT_LISTING;
713 else if (inputFormat == INPUT_XKB)
714 outputFormat = WANT_XKM_FILE;
716 outputFormat = WANT_XKB_FILE;
718 if ((outputFormat == WANT_LISTING) && (inputFormat != INPUT_XKB))
721 ERROR("Cannot generate a listing from a .xkm file (yet)\n");
723 ERROR("Cannot generate a listing from an X connection (yet)\n");
728 if (outputFile == NULL)
729 outputFile = uStringDup("-");
730 else if (strchr(outputFile, ':') != NULL)
732 ERROR("Cannot write a listing to an X connection\n");
736 else if ((!outputFile) && (inputFile) && uStringEqual(inputFile, "-"))
738 int len = strlen("stdin") + strlen(fileTypeExt[outputFormat]) + 2;
739 outputFile = uTypedCalloc(len, char);
740 if (outputFile == NULL)
742 WSGO("Cannot allocate space for output file name\n");
746 sprintf(outputFile, "stdin.%s", fileTypeExt[outputFormat]);
748 else if ((outputFile == NULL) && (inputFile != NULL))
753 if (inputMap == NULL)
755 base = strrchr(inputFile, '/');
764 len = strlen(base) + strlen(fileTypeExt[outputFormat]) + 2;
765 outputFile = uTypedCalloc(len, char);
766 if (outputFile == NULL)
768 WSGO("Cannot allocate space for output file name\n");
772 ext = strrchr(base, '.');
774 sprintf(outputFile, "%s.%s", base, fileTypeExt[outputFormat]);
777 strcpy(outputFile, base);
778 strcpy(&outputFile[ext - base + 1], fileTypeExt[outputFormat]);
781 else if (outputFile == NULL)
784 char *ch, *name, buf[128];
785 if (inDpyName[0] == ':')
786 snprintf(name = buf, sizeof(buf), "server%s", inDpyName);
790 len = strlen(name) + strlen(fileTypeExt[outputFormat]) + 2;
791 outputFile = uTypedCalloc(len, char);
792 if (outputFile == NULL)
794 WSGO("Cannot allocate space for output file name\n");
798 strcpy(outputFile, name);
799 for (ch = outputFile; (*ch) != '\0'; ch++)
807 strcpy(ch, fileTypeExt[outputFormat]);
810 else if (strlen(outputFile) > 2 &&
811 isalpha(outputFile[0]) &&
812 outputFile[1] == ':' && strchr(outputFile + 2, ':') == NULL)
816 else if (strchr(outputFile, ':') != NULL)
818 outDpyName = outputFile;
820 outputFormat = WANT_X_SERVER;
826 GetDisplay(char *program, char *dpyName)
831 mjr = XkbMajorVersion;
832 mnr = XkbMinorVersion;
833 dpy = XkbOpenDisplay(dpyName, NULL, NULL, &mjr, &mnr, &error);
838 case XkbOD_BadLibraryVersion:
839 INFO3("%s was compiled with XKB version %d.%02d\n",
840 program, XkbMajorVersion, XkbMinorVersion);
841 ERROR2("X library supports incompatible version %d.%02d\n",
844 case XkbOD_ConnectionRefused:
845 ERROR1("Cannot open display \"%s\"\n", dpyName);
847 case XkbOD_NonXkbServer:
848 ERROR1("XKB extension not present on %s\n", dpyName);
850 case XkbOD_BadServerVersion:
851 INFO3("%s was compiled with XKB version %d.%02d\n",
852 program, XkbMajorVersion, XkbMinorVersion);
853 ERROR3("Server %s uses incompatible version %d.%02d\n",
857 WSGO1("Unknown error %d from XkbOpenDisplay\n", error);
861 XSynchronize(dpy, True);
865 /***====================================================================***/
872 main(int argc, char *argv[])
874 FILE *file; /* input file (or stdin) */
882 uSetEntryFile(NullString);
883 uSetDebugFile(NullString);
884 uSetErrorFile(NullString);
886 XkbInitIncludePath();
887 if (!parseArgs(argc, argv))
890 if (debugFlags & 0x2)
894 uSetPreErrorMessage(preErrorMsg);
896 uSetErrorPrefix(errorPrefix);
898 uSetPostErrorMessage(postErrorMsg);
901 XkbAddDefaultDirectoriesToPath();
905 gotSome = GenerateListing(outputFile);
906 if ((warningLevel > 7) && (!gotSome))
910 if (inputFile != NULL)
912 if (uStringEqual(inputFile, "-"))
919 file = fopen(inputFile, "r");
922 else if (inDpyName != NULL)
924 inDpy = GetDisplay(argv[0], inDpyName);
931 if (outDpyName != NULL)
933 outDpy = GetDisplay(argv[0], outDpyName);
940 if ((inDpy == NULL) && (outDpy == NULL))
943 mjr = XkbMajorVersion;
944 mnr = XkbMinorVersion;
945 if (!XkbLibraryVersion(&mjr, &mnr))
947 INFO3("%s was compiled with XKB version %d.%02d\n",
948 argv[0], XkbMajorVersion, XkbMinorVersion);
949 ERROR2("X library supports incompatible version %d.%02d\n",
958 setScanState(inputFile, 1);
959 if ((inputFormat == INPUT_XKB) /* parse .xkb file */
960 && (XKBParseFile(file, &rtrn) && (rtrn != NULL)))
964 if (inputMap != NULL) /* map specified on cmdline? */
967 && (!uStringEqual(mapToUse->name, inputMap)))
969 mapToUse = (XkbFile *) mapToUse->common.next;
973 FATAL2("No map named \"%s\" in \"%s\"\n",
974 inputMap, inputFile);
978 else if (rtrn->common.next != NULL)
980 /* look for map with XkbLC_Default flag. */
982 for (; mapToUse; mapToUse = (XkbFile *) mapToUse->common.next)
984 if (mapToUse->flags & XkbLC_Default)
990 if (warningLevel > 4)
993 ("No map specified, but \"%s\" has several\n",
996 ("Using the first defined map, \"%s\"\n",
1001 bzero((char *) &result, sizeof(result));
1002 result.type = mapToUse->type;
1003 if ((result.xkb = XkbAllocKeyboard()) == NULL)
1005 WSGO("Cannot allocate keyboard description\n");
1008 switch (mapToUse->type)
1010 case XkmSemanticsFile:
1013 ok = CompileKeymap(mapToUse, &result, MergeReplace);
1015 case XkmKeyNamesIndex:
1016 ok = CompileKeycodes(mapToUse, &result, MergeReplace);
1019 ok = CompileKeyTypes(mapToUse, &result, MergeReplace);
1021 case XkmSymbolsIndex:
1022 /* if it's just symbols, invent key names */
1023 result.xkb->flags |= AutoKeyNames;
1026 case XkmCompatMapIndex:
1027 ok = CompileCompatMap(mapToUse, &result, MergeReplace, NULL);
1029 case XkmGeometryFile:
1030 case XkmGeometryIndex:
1031 /* if it's just a geometry, invent key names */
1032 result.xkb->flags |= AutoKeyNames;
1033 ok = CompileGeometry(mapToUse, &result, MergeReplace);
1036 WSGO1("Unknown file type %d\n", mapToUse->type);
1041 else if (inputFormat == INPUT_XKM) /* parse xkm file */
1044 bzero((char *) &result, sizeof(result));
1045 if ((result.xkb = XkbAllocKeyboard()) == NULL)
1047 WSGO("Cannot allocate keyboard description\n");
1050 tmp = XkmReadFile(file, 0, XkmKeymapLegal, &result);
1051 if (tmp == XkmKeymapLegal)
1053 ERROR1("Cannot read XKM file \"%s\"\n", inputFile);
1059 INFO1("Errors encountered in %s; not compiled.\n", inputFile);
1063 else if (inDpy != NULL)
1065 bzero((char *) &result, sizeof(result));
1066 result.type = XkmKeymapFile;
1067 result.xkb = XkbGetMap(inDpy, XkbAllMapComponentsMask, device_id);
1068 if (result.xkb == NULL)
1069 WSGO("Cannot load keyboard description\n");
1070 if (XkbGetIndicatorMap(inDpy, ~0, result.xkb) != Success)
1071 WSGO("Could not load indicator map\n");
1072 if (XkbGetControls(inDpy, XkbAllControlsMask, result.xkb) != Success)
1073 WSGO("Could not load keyboard controls\n");
1074 if (XkbGetCompatMap(inDpy, XkbAllCompatMask, result.xkb) != Success)
1075 WSGO("Could not load compatibility map\n");
1076 if (XkbGetNames(inDpy, XkbAllNamesMask, result.xkb) != Success)
1077 WSGO("Could not load names\n");
1078 if ((status = XkbGetGeometry(inDpy, result.xkb)) != Success)
1080 if (warningLevel > 3)
1084 XGetErrorText(inDpy, status, buf, 100);
1085 WARN1("Could not load keyboard geometry for %s\n", inDpyName);
1086 ACTION1("%s\n", buf);
1087 ACTION("Resulting keymap file will not describe geometry\n");
1091 ok = (ComputeKbdDefaults(result.xkb) == Success);
1097 fprintf(stderr, "Cannot open \"%s\" to compile\n", inputFile);
1103 if ((inDpy != outDpy) &&
1104 (XkbChangeKbdDisplay(outDpy, &result) != Success))
1106 WSGO2("Error converting keyboard display from %s to %s\n",
1107 inDpyName, outDpyName);
1110 if (outputFile != NULL)
1112 if (uStringEqual(outputFile, "-"))
1113 outputFile = "stdout";
1117 * fix to prevent symlink attack (e.g.,
1118 * ln -s /etc/passwd /var/tmp/server-0.xkm)
1121 * this patch may have POSIX, Linux, or GNU libc bias
1122 * -- Branden Robinson
1126 const char *openMode = "w";
1129 switch (outputFormat)
1141 open(outputFile, O_WRONLY | O_CREAT | O_EXCL,
1142 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
1143 | S_IWOTH | binMode);
1144 if (outputFileFd < 0)
1147 ("Cannot open \"%s\" to write keyboard description\n",
1149 ACTION("Exiting\n");
1153 out = fdopen(outputFileFd, openMode);
1155 close(outputFileFd);
1156 out = fopen(outputFile, "wb");
1162 ("Cannot open \"%s\" to write keyboard description\n",
1164 ACTION("Exiting\n");
1169 switch (outputFormat)
1172 ok = XkbWriteXKMFile(out, &result);
1175 ok = XkbWriteXKBFile(out, &result, showImplicit, NULL, NULL);
1178 ok = XkbWriteCFile(out, outputFile, &result);
1181 if (!(ok = XkbWriteToServer(&result)))
1183 ERROR2("%s in %s\n", _XkbErrMessages[_XkbErrCode],
1184 _XkbErrLocation ? _XkbErrLocation : "unknown");
1185 ACTION1("Couldn't write keyboard description to %s\n",
1190 WSGO1("Unknown output format %d\n", outputFormat);
1191 ACTION("No output file created\n");
1195 if (outputFormat != WANT_X_SERVER)
1199 ERROR1("Cannot close \"%s\" properly (not enough space?)\n",
1205 ERROR2("%s in %s\n", _XkbErrMessages[_XkbErrCode],
1206 _XkbErrLocation ? _XkbErrLocation : "unknown");
1210 ACTION1("Output file \"%s\" removed\n", outputFile);
1216 XCloseDisplay(inDpy);
1219 XCloseDisplay(outDpy);