~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/setxkbmap/setxkbmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************
 
2
 Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
 
3
 
 
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.
 
15
 
 
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.
 
24
 
 
25
 ********************************************************/
 
26
/* $XFree86: xc/programs/setxkbmap/setxkbmap.c,v 3.7 2003/01/20 04:15:08 dawes Exp $ */
 
27
 
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <locale.h>
 
31
#include <limits.h>
 
32
#include <ctype.h>
 
33
#include <X11/Xlib.h>
 
34
#include <X11/Xos.h>
 
35
#include <X11/XKBlib.h>
 
36
#include <X11/extensions/XKBfile.h>
 
37
#include <X11/extensions/XKBconfig.h>
 
38
#include <X11/extensions/XKBrules.h>
 
39
 
 
40
#ifndef PATH_MAX
 
41
#ifdef MAXPATHLEN
 
42
#define PATH_MAX MAXPATHLEN
 
43
#else
 
44
#define PATH_MAX 1024
 
45
#endif
 
46
#endif
 
47
 
 
48
#ifndef DFLT_XKB_CONFIG_ROOT
 
49
#define DFLT_XKB_CONFIG_ROOT "/usr/X11R6/lib/X11/xkb"
 
50
#endif
 
51
#ifndef DFLT_XKB_RULES_FILE
 
52
#define DFLT_XKB_RULES_FILE "xfree86"
 
53
#endif
 
54
#ifndef DFLT_XKB_LAYOUT
 
55
#define DFLT_XKB_LAYOUT "us"
 
56
#endif
 
57
#ifndef DFLT_XKB_MODEL
 
58
#define DFLT_XKB_MODEL "pc101"
 
59
#endif
 
60
 
 
61
#define UNDEFINED       0
 
62
#define FROM_SERVER     1
 
63
#define FROM_RULES      2
 
64
#define FROM_CONFIG     3
 
65
#define FROM_CMD_LINE   4
 
66
#define NUM_SOURCES     5
 
67
 
 
68
#define RULES_NDX       0
 
69
#define CONFIG_NDX      1
 
70
#define DISPLAY_NDX     2
 
71
#define LOCALE_NDX      3
 
72
#define MODEL_NDX       4
 
73
#define LAYOUT_NDX      5
 
74
#define VARIANT_NDX     6
 
75
#define KEYCODES_NDX    7
 
76
#define TYPES_NDX       8
 
77
#define COMPAT_NDX      9
 
78
#define SYMBOLS_NDX     10
 
79
#define GEOMETRY_NDX    11
 
80
#define KEYMAP_NDX      12
 
81
#define NUM_STRING_VALS 13
 
82
 
 
83
/***====================================================================***/
 
84
Bool                    print= False;
 
85
Bool                    synch= False;
 
86
int                     verbose= 5;
 
87
 
 
88
Display *               dpy;
 
89
 
 
90
char *  srcName[NUM_SOURCES] = {
 
91
        "undefined", "X server", "rules file", "config file", "command line"
 
92
};
 
93
 
 
94
char *  svName[NUM_STRING_VALS]= {
 
95
        "rules file", "config file", "X display", "locale",
 
96
        "keyboard model", "keyboard layout", "layout variant",
 
97
        "keycodes", "types", "compatibility map", "symbols", "geometry",
 
98
        "keymap"
 
99
};
 
100
int     svSrc[NUM_STRING_VALS];
 
101
char *  svValue[NUM_STRING_VALS];
 
102
 
 
103
XkbConfigFieldsRec      cfgDflts;
 
104
XkbConfigRtrnRec        cfgResult;
 
105
 
 
106
XkbRF_RulesPtr          rules= NULL;
 
107
XkbRF_VarDefsRec        rdefs;
 
108
 
 
109
Bool                    clearOptions= False;
 
110
int                     szOptions= 0;
 
111
int                     numOptions= 0;
 
112
char **                 options= NULL;
 
113
 
 
114
int                     szInclPath= 0;
 
115
int                     numInclPath= 0;
 
116
char **                 inclPath= NULL;
 
117
 
 
118
XkbDescPtr              xkb= NULL;
 
119
 
 
120
/***====================================================================***/
 
121
 
 
122
#define streq(s1,s2)    (strcmp(s1,s2)==0)
 
123
#define strpfx(s1,s2)   (strncmp(s1,s2,strlen(s2))==0)
 
124
 
 
125
#define MSG(s)          printf(s)
 
126
#define MSG1(s,a)       printf(s,a)
 
127
#define MSG2(s,a,b)     printf(s,a,b)
 
128
#define MSG3(s,a,b,c)   printf(s,a,b,c)
 
129
 
 
130
#define VMSG(l,s)       if (verbose>(l)) printf(s)
 
131
#define VMSG1(l,s,a)    if (verbose>(l)) printf(s,a)
 
132
#define VMSG2(l,s,a,b)  if (verbose>(l)) printf(s,a,b)
 
133
#define VMSG3(l,s,a,b,c) if (verbose>(l)) printf(s,a,b,c)
 
134
 
 
135
#define ERR(s)          fprintf(stderr,s)
 
136
#define ERR1(s,a)       fprintf(stderr,s,a)
 
137
#define ERR2(s,a,b)     fprintf(stderr,s,a,b)
 
138
#define ERR3(s,a,b,c)   fprintf(stderr,s,a,b,c)
 
139
 
 
140
/***====================================================================***/
 
141
 
 
142
Bool addToList ( int *sz, int *num, char ***listIn, char *newVal );
 
143
void usage ( int argc, char ** argv );
 
144
void dumpNames ( Bool wantRules, Bool wantCNames );
 
145
void trySetString ( int which, char * newVal, int src );
 
146
Bool setOptString ( int *arg, int argc, char **argv, int which, int src );
 
147
int parseArgs ( int argc, char ** argv );
 
148
Bool getDisplay ( int argc, char ** argv );
 
149
Bool getServerValues ( void );
 
150
FILE * findFileInPath ( char * name, char * subdir );
 
151
Bool addStringToOptions ( char * opt_str, int * sz_opts, int * num_opts, char *** opts );
 
152
char * stringFromOptions ( char * orig, int numNew, char ** newOpts );
 
153
Bool applyConfig ( char * name );
 
154
Bool applyRules ( void );
 
155
Bool applyComponentNames ( void );
 
156
void printKeymap( void );
 
157
 
 
158
/***====================================================================***/
 
159
 
 
160
Bool
 
161
#if NeedFunctionPrototypes
 
162
addToList(int *sz,int *num,char ***listIn,char *newVal)
 
163
#else
 
164
addToList(sz,num,listIn,newVal)
 
165
    int *       sz;
 
166
    int *       num;
 
167
    char ***    listIn;
 
168
    char *      newVal;
 
169
#endif
 
170
{
 
171
register int i;
 
172
char **list;
 
173
 
 
174
    if ((!newVal)||(!newVal[0])) {
 
175
        *num= 0;
 
176
        return True;
 
177
    }
 
178
    list= *listIn;
 
179
    for (i=0;i<*num;i++) {
 
180
        if (streq(list[i],newVal))
 
181
            return True;
 
182
    }
 
183
    if ((list==NULL)||(*sz<1)) {
 
184
        *num= 0;
 
185
        *sz= 4;
 
186
        list= (char **)calloc(*sz,sizeof(char *));
 
187
        *listIn= list;
 
188
    }
 
189
    else if (*num>=*sz) {
 
190
        *sz*= 2;
 
191
        list= (char **)realloc(list,(*sz)*sizeof(char *));
 
192
        *listIn= list;
 
193
    }
 
194
    if (!list) {
 
195
        ERR("Internal Error! Allocation failure in add to list!\n");
 
196
        ERR("                Exiting.\n");
 
197
        exit(-1);
 
198
    }
 
199
    list[*num]= strdup(newVal);
 
200
    (*num)= (*num)+1;
 
201
    return True;
 
202
}
 
203
 
 
204
/***====================================================================***/
 
205
 
 
206
void
 
207
#if NeedFunctionPrototypes
 
208
usage(int argc,char **argv)
 
209
#else
 
210
usage(argc,argv)
 
211
    int         argc;
 
212
    char **     argv;
 
213
#endif
 
214
{
 
215
    MSG1("Usage: %s [args] [<layout> [<variant> [<option> ... ]]]\n",argv[0]);
 
216
    MSG("Where legal args are:\n");
 
217
    MSG("-?,-help            Print this message\n");
 
218
    MSG("-compat <name>      Specifies compatibility map component name\n");
 
219
    MSG("-config <file>      Specifies configuration file to use\n");
 
220
    MSG("-display <dpy>      Specifies display to use\n");
 
221
    MSG("-geometry <name>    Specifies geometry component name\n");
 
222
    MSG("-I[<dir>]           Add <dir> to list of directories to be used\n");
 
223
    MSG("-keycodes <name>    Specifies keycodes component name\n");
 
224
    MSG("-keymap <name>      Specifies name of keymap to load\n");
 
225
    MSG("-layout <name>      Specifies layout used to choose component names\n");
 
226
    MSG("-model <name>       Specifies model used to choose component names\n");
 
227
    MSG("-option <name>      Adds an option used to choose component names\n");
 
228
    MSG("-print              Print a complete xkb_keymap description and exit\n");
 
229
    MSG("-rules <name>       Name of rules file to use\n");
 
230
    MSG("-symbols <name>     Specifies symbols component name\n");
 
231
    MSG("-synch              Synchronize request w/X server\n");
 
232
    MSG("-types <name>       Specifies types component name\n");
 
233
    MSG("-v[erbose] [<lvl>]  Sets verbosity (1..10).  Higher values yield\n");
 
234
    MSG("                    more messages\n");
 
235
    MSG("-variant <name>     Specifies layout variant used to choose component names\n");
 
236
}
 
237
 
 
238
void
 
239
#if NeedFunctionPrototypes
 
240
dumpNames(Bool wantRules,Bool wantCNames)
 
241
#else
 
242
dumpNames(wantRules,wantCNames)
 
243
    Bool        wantRules;
 
244
    Bool        wantCNames;
 
245
#endif
 
246
{
 
247
    if (wantRules) {
 
248
        if (svValue[MODEL_NDX])  MSG1("model:      %s\n",svValue[MODEL_NDX]);
 
249
        if (svValue[LAYOUT_NDX])  MSG1("layout:     %s\n",svValue[LAYOUT_NDX]);
 
250
        if (svValue[VARIANT_NDX]) MSG1("variant:    %s\n",svValue[VARIANT_NDX]);
 
251
        if (options) {
 
252
           char *opt_str=stringFromOptions(NULL, numOptions, options);
 
253
           MSG1("options:    %s\n", opt_str);
 
254
           free(opt_str);
 
255
        }
 
256
    }
 
257
    if (wantCNames) {
 
258
        if (svValue[KEYMAP_NDX])
 
259
            MSG1("keymap:     %s\n",svValue[KEYMAP_NDX]);
 
260
        if (svValue[KEYCODES_NDX])
 
261
            MSG1("keycodes:   %s\n",svValue[KEYCODES_NDX]);
 
262
        if (svValue[TYPES_NDX])
 
263
            MSG1("types:      %s\n",svValue[TYPES_NDX]);
 
264
        if (svValue[COMPAT_NDX])
 
265
            MSG1("compat:     %s\n",svValue[COMPAT_NDX]);
 
266
        if (svValue[SYMBOLS_NDX])
 
267
            MSG1("symbols:    %s\n",svValue[SYMBOLS_NDX]);
 
268
        if (svValue[GEOMETRY_NDX])
 
269
            MSG1("geometry:   %s\n",svValue[GEOMETRY_NDX]);
 
270
    }
 
271
    return;
 
272
}
 
273
 
 
274
/***====================================================================***/
 
275
 
 
276
void
 
277
#if NeedFunctionPrototypes
 
278
trySetString(int which,char *newVal,int src)
 
279
#else
 
280
trySetString(which,newVal,src)
 
281
    int         which;
 
282
    char *      newVal;
 
283
    int         src;
 
284
#endif
 
285
{
 
286
    if (svValue[which]!=NULL) {
 
287
        if (svSrc[which]==src) {
 
288
            VMSG2(0,"Warning! More than one %s from %s\n",
 
289
                                                svName[which],srcName[src]);
 
290
            VMSG2(0,"         Using \"%s\", ignoring \"%s\"\n",
 
291
                                                svValue[which],newVal);
 
292
            return;
 
293
        }
 
294
        else if (svSrc[which]>src) {
 
295
            VMSG1(5,"Warning! Multiple definitions of %s\n",svName[which]);
 
296
            VMSG2(5,"         Using %s, ignoring %s\n",srcName[svSrc[which]],
 
297
                                                srcName[src]);
 
298
            return;
 
299
        }
 
300
    }
 
301
    svSrc[which]= src;
 
302
    svValue[which]= newVal;
 
303
    return;
 
304
}
 
305
 
 
306
Bool
 
307
#if NeedFunctionPrototypes
 
308
setOptString(int *arg,int argc,char **argv,int which,int src)
 
309
#else
 
310
setOptString(arg,argc,argv,which,src)
 
311
    int *       arg;
 
312
    int         argc;
 
313
    char **     argv;
 
314
    int         what;
 
315
    int         src;
 
316
#endif
 
317
{
 
318
int     ndx;
 
319
char *  opt;
 
320
 
 
321
    ndx= *arg;
 
322
    opt= argv[ndx];
 
323
    if (ndx>=argc-1) {
 
324
        VMSG1(0,"No %s specified on the command line\n",svName[which]);
 
325
        VMSG1(0,"Trailing %s option ignored\n",opt);
 
326
        return True;
 
327
    }
 
328
    ndx++;
 
329
    *arg= ndx;
 
330
    if (svValue[which]!=NULL) {
 
331
        if (svSrc[which]==src) {
 
332
            VMSG2(0,"More than one %s on %s\n",svName[which],srcName[src]);
 
333
            VMSG2(0,"Using \"%s\", ignoring \"%s\"\n",svValue[which],argv[ndx]);
 
334
            return True;
 
335
        }
 
336
        else if (svSrc[which]>src) {
 
337
            VMSG1(5,"Multiple definitions of %s\n",svName[which]);
 
338
            VMSG2(5,"Using %s, ignoring %s\n",srcName[svSrc[which]],
 
339
                                                srcName[src]);
 
340
            return True;
 
341
        }
 
342
    }
 
343
    svSrc[which]= src;
 
344
    svValue[which]= argv[ndx];
 
345
    return True;
 
346
}
 
347
 
 
348
/***====================================================================***/
 
349
 
 
350
int
 
351
#if NeedFunctionPrototypes
 
352
parseArgs(int argc,char **argv)
 
353
#else
 
354
parseArgs(argc,argv)
 
355
    int         argc;
 
356
    char **     argv;
 
357
#endif
 
358
{
 
359
int     i;
 
360
Bool    ok;
 
361
unsigned        present;
 
362
 
 
363
    ok= True;
 
364
    addToList(&szInclPath,&numInclPath,&inclPath,".");
 
365
    addToList(&szInclPath,&numInclPath,&inclPath,DFLT_XKB_CONFIG_ROOT);
 
366
    for (i=1;(i<argc)&&ok;i++) {
 
367
        if (argv[i][0]!='-') {
 
368
            if (!svSrc[LAYOUT_NDX])
 
369
                 trySetString(LAYOUT_NDX,argv[i],FROM_CMD_LINE);
 
370
            else if (!svSrc[VARIANT_NDX])
 
371
                 trySetString(VARIANT_NDX,argv[i],FROM_CMD_LINE);
 
372
            else ok= addToList(&szOptions,&numOptions,&options,argv[i]);
 
373
        }
 
374
        else if (streq(argv[i],"-compat"))
 
375
            ok= setOptString(&i,argc,argv,COMPAT_NDX,FROM_CMD_LINE);
 
376
        else if (streq(argv[i],"-config"))
 
377
            ok= setOptString(&i,argc,argv,CONFIG_NDX,FROM_CMD_LINE);
 
378
        else if (streq(argv[i],"-display"))
 
379
            ok= setOptString(&i,argc,argv,DISPLAY_NDX,FROM_CMD_LINE);
 
380
        else if (streq(argv[i],"-geometry"))
 
381
            ok= setOptString(&i,argc,argv,GEOMETRY_NDX,FROM_CMD_LINE);
 
382
        else if (streq(argv[i],"-help")||streq(argv[i],"-?")) {
 
383
            usage(argc,argv);
 
384
            exit(0);
 
385
        }
 
386
        else if (strpfx(argv[i],"-I")) 
 
387
            ok= addToList(&szInclPath,&numInclPath,&inclPath,&argv[i][2]);
 
388
        else if (streq(argv[i],"-keycodes"))
 
389
            ok= setOptString(&i,argc,argv,KEYCODES_NDX,FROM_CMD_LINE);
 
390
        else if (streq(argv[i],"-keymap"))
 
391
            ok= setOptString(&i,argc,argv,KEYMAP_NDX,FROM_CMD_LINE);
 
392
        else if (streq(argv[i],"-layout"))
 
393
            ok= setOptString(&i,argc,argv,LAYOUT_NDX,FROM_CMD_LINE);
 
394
        else if (streq(argv[i],"-model"))
 
395
            ok= setOptString(&i,argc,argv,MODEL_NDX,FROM_CMD_LINE);
 
396
        else if (streq(argv[i],"-option")) {
 
397
            if ((i==argc-1)||(argv[i+1][0]=='\0')||(argv[i+1][0]=='-')) {
 
398
                clearOptions= True;
 
399
                ok= addToList(&szOptions,&numOptions,&options,"");
 
400
                if (i<argc-1 && argv[i+1][0]=='\0')
 
401
                   i++;
 
402
            }
 
403
            else {
 
404
                ok= addToList(&szOptions,&numOptions,&options,argv[++i]);
 
405
            }
 
406
        }
 
407
        else if (streq(argv[i],"-print"))
 
408
            print= True;
 
409
        else if (streq(argv[i],"-rules"))
 
410
            ok= setOptString(&i,argc,argv,RULES_NDX,FROM_CMD_LINE);
 
411
        else if (streq(argv[i],"-symbols"))
 
412
            ok= setOptString(&i,argc,argv,SYMBOLS_NDX,FROM_CMD_LINE);
 
413
        else if (streq(argv[i],"-synch"))
 
414
            synch= True;
 
415
        else if (streq(argv[i],"-types"))
 
416
            ok= setOptString(&i,argc,argv,TYPES_NDX,FROM_CMD_LINE);
 
417
        else if (streq(argv[i],"-verbose")||(streq(argv[i],"-v"))) {
 
418
            if ((i<argc-1)&&(isdigit(argv[i+1][0])))
 
419
                 verbose= atoi(argv[++i]);
 
420
            else verbose++;
 
421
            if (verbose<0) {
 
422
                ERR1("Illegal verbose level %d.  Reset to 0\n",verbose);
 
423
                verbose=0;
 
424
            }
 
425
            else if (verbose>10) {
 
426
                ERR1("Illegal verbose level %d.  Reset to 10\n",verbose);
 
427
                verbose= 10;
 
428
            }
 
429
            VMSG1(7,"Setting verbose level to %d\n",verbose);
 
430
        }
 
431
        else if (streq(argv[i],"-variant"))
 
432
            ok= setOptString(&i,argc,argv,VARIANT_NDX,FROM_CMD_LINE);
 
433
        else {
 
434
            ERR1("Error!   Option \"%s\" not recognized\n",argv[i]);
 
435
            ok= False;
 
436
        }
 
437
    }
 
438
 
 
439
    present= 0;
 
440
    if (svValue[TYPES_NDX])     present++;
 
441
    if (svValue[COMPAT_NDX])    present++;
 
442
    if (svValue[SYMBOLS_NDX])   present++;
 
443
    if (svValue[KEYCODES_NDX])  present++;
 
444
    if (svValue[GEOMETRY_NDX])  present++;
 
445
    if (svValue[CONFIG_NDX])    present++;
 
446
    if (svValue[MODEL_NDX])     present++;
 
447
    if (svValue[LAYOUT_NDX])    present++;
 
448
    if (svValue[VARIANT_NDX])   present++;
 
449
    if (svValue[KEYMAP_NDX] && present) {
 
450
        ERR("No other components can be specified when a keymap is present\n");
 
451
        return False;
 
452
    }
 
453
    return ok;
 
454
}
 
455
 
 
456
Bool
 
457
#if NeedFunctionPrototypes
 
458
getDisplay(int argc,char **argv)
 
459
#else
 
460
getDisplay(argc,argv)
 
461
    int         argc;
 
462
    char **     argv;
 
463
#endif
 
464
{
 
465
int     major,minor,why;
 
466
 
 
467
    major= XkbMajorVersion;
 
468
    minor= XkbMinorVersion;
 
469
    dpy= XkbOpenDisplay(svValue[DISPLAY_NDX],NULL,NULL,&major,&minor,&why);
 
470
    if (!dpy) {
 
471
        if (svValue[DISPLAY_NDX]==NULL) 
 
472
            svValue[DISPLAY_NDX]= getenv("DISPLAY");
 
473
        if (svValue[DISPLAY_NDX]==NULL)
 
474
            svValue[DISPLAY_NDX]= "default display";
 
475
        switch (why) {
 
476
            case XkbOD_BadLibraryVersion:
 
477
                ERR3("%s was compiled with XKB version %d.%02d\n",argv[0],
 
478
                                        XkbMajorVersion,XkbMinorVersion);
 
479
                ERR2("Xlib supports incompatible version %d.%02d\n",
 
480
                                        major,minor);
 
481
                break;
 
482
            case XkbOD_ConnectionRefused:
 
483
                ERR1("Cannot open display \"%s\"\n",svValue[DISPLAY_NDX]);
 
484
                break;
 
485
            case XkbOD_NonXkbServer:
 
486
                ERR1("XKB extension not present on %s\n",svValue[DISPLAY_NDX]);
 
487
                break;
 
488
            case XkbOD_BadServerVersion:
 
489
                ERR3("%s was compiled with XKB version %d.%02d\n",argv[0],
 
490
                                XkbMajorVersion,XkbMinorVersion);
 
491
                ERR3("Server %s uses incompatible version %d.%02d\n",
 
492
                                svValue[DISPLAY_NDX],major,minor);
 
493
                break;
 
494
            default:
 
495
                ERR1("Unknown error %d from XkbOpenDisplay\n",why);
 
496
                break;
 
497
        }
 
498
        return False;
 
499
    }
 
500
    if (synch)
 
501
        XSynchronize(dpy,True);
 
502
    return True;
 
503
}
 
504
 
 
505
/***====================================================================***/
 
506
 
 
507
Bool
 
508
#if NeedFunctionPrototypes
 
509
getServerValues(void)
 
510
#else
 
511
getServerValues()
 
512
#endif
 
513
{
 
514
XkbRF_VarDefsRec        vd;
 
515
char *                  tmp= NULL;
 
516
 
 
517
    if (!XkbRF_GetNamesProp(dpy,&tmp,&vd) || !tmp) {
 
518
        VMSG1(3,"Couldn't interpret %s property\n",_XKB_RF_NAMES_PROP_ATOM);
 
519
        tmp = DFLT_XKB_RULES_FILE;
 
520
        vd.model = DFLT_XKB_MODEL;
 
521
        vd.layout = DFLT_XKB_LAYOUT;
 
522
        VMSG3(3,"Use defaults: rules - '%s' model - '%s' layout - '%s'\n",
 
523
                tmp, vd.model, vd.layout);
 
524
    }
 
525
    if (tmp)
 
526
        trySetString(RULES_NDX,tmp,FROM_SERVER);
 
527
    if (vd.model)
 
528
        trySetString(MODEL_NDX,vd.model,FROM_SERVER);
 
529
    if (vd.layout)
 
530
        trySetString(LAYOUT_NDX,vd.layout,FROM_SERVER);
 
531
    if (vd.variant)
 
532
        trySetString(VARIANT_NDX,vd.variant,FROM_SERVER);
 
533
    if ((vd.options)&&(!clearOptions)) {
 
534
        addStringToOptions(vd.options,&szOptions,&numOptions,&options);
 
535
        XFree(vd.options);
 
536
    }
 
537
    return True;
 
538
}
 
539
 
 
540
/***====================================================================***/
 
541
 
 
542
FILE *
 
543
#if NeedFunctionPrototypes
 
544
findFileInPath(char *name,char *subdir)
 
545
#else
 
546
findFileInPath(name,subdir)
 
547
    char *      name;
 
548
    char *      subdir;
 
549
#endif
 
550
{
 
551
register int    i;
 
552
char            buf[PATH_MAX];
 
553
FILE *          fp;
 
554
 
 
555
    if (name[0]=='/') {
 
556
        fp= fopen(name,"r");
 
557
        if ((verbose>7)||((!fp)&&(verbose>0)))
 
558
            MSG2("%s file %s\n",(fp?"Found":"Didn't find"),name);
 
559
        return fp;
 
560
    }
 
561
    for (i=0;(i<numInclPath);i++) {
 
562
        if ((strlen(inclPath[i])+strlen(subdir)+strlen(name)+2)>PATH_MAX) {
 
563
            VMSG3(0,"Path too long (%s/%s%s). Ignored.\n",inclPath[i],subdir,
 
564
                                                                        name);
 
565
            continue;
 
566
        }
 
567
        sprintf(buf,"%s/%s%s",inclPath[i],subdir,name);
 
568
        fp= fopen(name,"r");
 
569
        if ((verbose>7)||((!fp)&&(verbose>5)))
 
570
            MSG2("%s file %s\n",(fp?"Found":"Didn't find"),buf);
 
571
        if (fp!=NULL)
 
572
            return fp;
 
573
    }
 
574
    return NULL;
 
575
}
 
576
 
 
577
/***====================================================================***/
 
578
 
 
579
Bool
 
580
#if NeedFunctionPrototypes
 
581
addStringToOptions(char *opt_str,int *sz_opts,int *num_opts,char ***opts)
 
582
#else
 
583
addStringToOptions(opt_str,sz_opts,num_opts,opts)
 
584
    char *      opt_str;
 
585
    int *       sz_opts;
 
586
    int *       num_opts;
 
587
    char ***    opts;
 
588
#endif
 
589
{
 
590
char    *tmp,*str,*next;
 
591
Bool    ok= True;
 
592
 
 
593
    if ((str= malloc(strlen(opt_str)+1))!=NULL)
 
594
         strcpy(str,opt_str);
 
595
    else return False;
 
596
    for (tmp= str,next=NULL;(tmp && *tmp!='\0')&&ok;tmp=next) {
 
597
        next= strchr(str,',');
 
598
        if (next) {
 
599
            *next= '\0';
 
600
            next++;
 
601
        }
 
602
        ok= addToList(sz_opts,num_opts,opts,tmp)&&ok;
 
603
    }
 
604
    free(str);
 
605
    return ok;
 
606
}
 
607
 
 
608
/***====================================================================***/
 
609
 
 
610
char *
 
611
#if NeedFunctionPrototypes
 
612
stringFromOptions(char *orig,int numNew,char **newOpts)
 
613
#else
 
614
stringFromOptions(orig,numNew,newOpts)
 
615
    char *      orig;
 
616
    int         numNew;
 
617
    char **     newOpts;
 
618
#endif
 
619
{
 
620
int     len,i,nOut;
 
621
 
 
622
    if (orig)   len= strlen(orig)+1;
 
623
    else        len= 0;
 
624
    for (i=0;i<numNew;i++) {
 
625
        if (newOpts[i])
 
626
            len+= strlen(newOpts[i])+1;
 
627
    }
 
628
    if (len<1)
 
629
        return NULL;
 
630
    if (orig) {
 
631
        orig= (char *)realloc(orig,len);
 
632
        nOut= 1;
 
633
    }
 
634
    else {
 
635
        orig= (char *)calloc(len,1);
 
636
        nOut= 0;
 
637
    }
 
638
    for (i=0;i<numNew;i++) {
 
639
        if (!newOpts[i])
 
640
            continue;
 
641
        if (nOut>0) {
 
642
             strcat(orig,",");
 
643
             strcat(orig,newOpts[i]);
 
644
        }
 
645
        else strcpy(orig,newOpts[i]);
 
646
        nOut++;
 
647
    }
 
648
    return orig;
 
649
}
 
650
 
 
651
/***====================================================================***/
 
652
 
 
653
Bool
 
654
#if NeedFunctionPrototypes
 
655
applyConfig(char *name)
 
656
#else
 
657
applyConfig(name)
 
658
    char *      name;
 
659
#endif
 
660
{
 
661
FILE *  fp;
 
662
Bool    ok;
 
663
    
 
664
    if ((fp=findFileInPath(name,""))==NULL)
 
665
        return False;
 
666
    ok= XkbCFParse(fp,XkbCFDflts,NULL,&cfgResult);
 
667
    fclose(fp);
 
668
    if (!ok) {
 
669
        ERR1("Couldn't find configuration file \"%s\"\n", name);
 
670
        return False;
 
671
    }
 
672
    if (cfgResult.rules_file) {
 
673
        trySetString(RULES_NDX,cfgResult.rules_file,FROM_CONFIG);
 
674
        cfgResult.rules_file= NULL;
 
675
    }
 
676
    if (cfgResult.model) {
 
677
        trySetString(MODEL_NDX,cfgResult.model,FROM_CONFIG);
 
678
        cfgResult.model= NULL;
 
679
    }
 
680
    if (cfgResult.layout) {
 
681
        trySetString(LAYOUT_NDX,cfgResult.layout,FROM_CONFIG);
 
682
        cfgResult.layout= NULL;
 
683
    }
 
684
    if (cfgResult.variant) {
 
685
        trySetString(VARIANT_NDX,cfgResult.variant,FROM_CONFIG);
 
686
        cfgResult.variant= NULL;
 
687
    }
 
688
    if (cfgResult.options) {
 
689
        addStringToOptions(cfgResult.options,&szOptions,&numOptions,&options);
 
690
        cfgResult.options= NULL;
 
691
    }
 
692
    if (cfgResult.keymap) {
 
693
        trySetString(KEYMAP_NDX,cfgResult.keymap,FROM_CONFIG);
 
694
        cfgResult.keymap= NULL;
 
695
    }
 
696
    if (cfgResult.keycodes) {
 
697
        trySetString(KEYCODES_NDX,cfgResult.keycodes,FROM_CONFIG);
 
698
        cfgResult.keycodes= NULL;
 
699
    }
 
700
    if (cfgResult.geometry) {
 
701
        trySetString(GEOMETRY_NDX,cfgResult.geometry,FROM_CONFIG);
 
702
        cfgResult.geometry= NULL;
 
703
    }
 
704
    if (cfgResult.symbols) {
 
705
        trySetString(SYMBOLS_NDX,cfgResult.symbols,FROM_CONFIG);
 
706
        cfgResult.symbols= NULL;
 
707
    }
 
708
    if (cfgResult.types) {
 
709
        trySetString(TYPES_NDX,cfgResult.types,FROM_CONFIG);
 
710
        cfgResult.types= NULL;
 
711
    }
 
712
    if (cfgResult.compat) {
 
713
        trySetString(COMPAT_NDX,cfgResult.compat,FROM_CONFIG);
 
714
        cfgResult.compat= NULL;
 
715
    }
 
716
    if (verbose>5) {
 
717
        MSG("After config file:\n");
 
718
        dumpNames(True,True);
 
719
    }
 
720
    return True;
 
721
}
 
722
 
 
723
Bool
 
724
#if NeedFunctionPrototypes
 
725
applyRules(void)
 
726
#else
 
727
applyRules()
 
728
#endif
 
729
{
 
730
int     i;
 
731
char *  rfName;
 
732
 
 
733
    if (svSrc[MODEL_NDX]||svSrc[LAYOUT_NDX]||svSrc[VARIANT_NDX]||options) {
 
734
        char                    buf[PATH_MAX];
 
735
        XkbComponentNamesRec    rnames;
 
736
 
 
737
        if(svSrc[VARIANT_NDX] < svSrc[LAYOUT_NDX])
 
738
            svValue[VARIANT_NDX] = NULL;
 
739
 
 
740
        rdefs.model= svValue[MODEL_NDX];
 
741
        rdefs.layout= svValue[LAYOUT_NDX];
 
742
        rdefs.variant= svValue[VARIANT_NDX];
 
743
        if (options)
 
744
            rdefs.options=stringFromOptions(rdefs.options,numOptions,options);
 
745
 
 
746
        if (svSrc[RULES_NDX])
 
747
             rfName= svValue[RULES_NDX];
 
748
        else rfName= DFLT_XKB_RULES_FILE;
 
749
 
 
750
        if (rfName[0]=='/') {
 
751
            rules= XkbRF_Load(rfName,svValue[LOCALE_NDX],True,True);
 
752
        }
 
753
        else {
 
754
            for (i=0;(i<numInclPath)&&(!rules);i++) {
 
755
                if ((strlen(inclPath[i])+strlen(rfName)+8)>PATH_MAX) {
 
756
                    VMSG2(0,"Path too long (%s/rules/%s). Ignored.\n",
 
757
                                                inclPath[i],rfName);
 
758
                    continue;
 
759
                }
 
760
                sprintf(buf,"%s/rules/%s",inclPath[i],svValue[RULES_NDX]);
 
761
                rules= XkbRF_Load(buf,svValue[LOCALE_NDX],True,True);
 
762
            }
 
763
        }
 
764
        if (!rules) {
 
765
            ERR1("Couldn't find rules file (%s) \n",svValue[RULES_NDX]);
 
766
            return False;
 
767
        }
 
768
        XkbRF_GetComponents(rules,&rdefs,&rnames);
 
769
        if (rnames.keycodes) {
 
770
            trySetString(KEYCODES_NDX,rnames.keycodes,FROM_RULES);
 
771
            rnames.keycodes= NULL;
 
772
        }
 
773
        if (rnames.symbols) {
 
774
            trySetString(SYMBOLS_NDX,rnames.symbols,FROM_RULES);
 
775
            rnames.symbols= NULL;
 
776
        }
 
777
        if (rnames.types) {
 
778
            trySetString(TYPES_NDX,rnames.types,FROM_RULES);
 
779
            rnames.types= NULL;
 
780
        }
 
781
        if (rnames.compat) {
 
782
            trySetString(COMPAT_NDX,rnames.compat,FROM_RULES);
 
783
            rnames.compat= NULL;
 
784
        }
 
785
        if (rnames.geometry) {
 
786
            trySetString(GEOMETRY_NDX,rnames.geometry,FROM_RULES);
 
787
            rnames.geometry= NULL;
 
788
        }
 
789
        if (rnames.keymap) {
 
790
            trySetString(KEYMAP_NDX,rnames.keymap,FROM_RULES);
 
791
            rnames.keymap= NULL;
 
792
        }
 
793
        if (verbose>6) {
 
794
            MSG1("Applied rules from %s:\n",svValue[RULES_NDX]);
 
795
            dumpNames(True,False);
 
796
        }
 
797
    }
 
798
    else if (verbose>6) {
 
799
        MSG("No rules variables specified.  Rules file ignored\n");
 
800
    }
 
801
    return True;
 
802
}
 
803
 
 
804
/* Primitive sanity check - filter out 'map names' (inside parenthesis) */
 
805
/* that can confuse xkbcomp parser */
 
806
Bool
 
807
#if NeedFunctionPrototypes
 
808
checkName(char *name, char* string)
 
809
#else
 
810
checkName()
 
811
    char *name;
 
812
    char *string;
 
813
#endif
 
814
{
 
815
   char *i = name, *opar = NULL;
 
816
   Bool ret = True;
 
817
 
 
818
   if(!name)
 
819
      return True;
 
820
 
 
821
   while (*i){
 
822
      if (opar == NULL) {
 
823
         if (*i == '(')
 
824
         opar = i;
 
825
      } else {
 
826
         if ((*i == '(') || (*i == '|') || (*i == '+')) {
 
827
             ret = False;
 
828
             break;
 
829
         }
 
830
         if (*i == ')')
 
831
             opar = NULL;
 
832
      }
 
833
      i++;
 
834
   }
 
835
   if (opar)
 
836
      ret = False;
 
837
   if (!ret) {
 
838
      char c;
 
839
      int n = 1;
 
840
      for(i = opar+1; *i && n; i++) {
 
841
         if (*i == '(') n++;
 
842
         if (*i == ')') n--;
 
843
      }
 
844
      if (*i) i++;
 
845
      c = *i;
 
846
      *i = '\0';
 
847
      ERR1("Illegal map name '%s' ", opar);
 
848
      *i = c;
 
849
      ERR2("in %s name '%s'\n", string, name);
 
850
   }
 
851
   return ret;
 
852
}
 
853
 
 
854
void
 
855
#if NeedFunctionPrototypes
 
856
printKeymap(void)
 
857
#else
 
858
printKeymap()
 
859
#endif
 
860
{
 
861
    MSG("xkb_keymap {\n");
 
862
    if (svValue[KEYCODES_NDX])
 
863
        MSG1("\txkb_keycodes  { include \"%s\"\t};\n",svValue[KEYCODES_NDX]);
 
864
    if (svValue[TYPES_NDX])
 
865
        MSG1("\txkb_types     { include \"%s\"\t};\n",svValue[TYPES_NDX]);
 
866
    if (svValue[COMPAT_NDX])
 
867
        MSG1("\txkb_compat    { include \"%s\"\t};\n",svValue[COMPAT_NDX]);
 
868
    if (svValue[SYMBOLS_NDX])
 
869
        MSG1("\txkb_symbols   { include \"%s\"\t};\n",svValue[SYMBOLS_NDX]);
 
870
    if (svValue[GEOMETRY_NDX])
 
871
        MSG1("\txkb_geometry  { include \"%s\"\t};\n",svValue[GEOMETRY_NDX]);
 
872
    MSG("};\n");
 
873
}
 
874
 
 
875
Bool
 
876
#if NeedFunctionPrototypes
 
877
applyComponentNames(void)
 
878
#else
 
879
applyComponentNames()
 
880
#endif
 
881
{
 
882
    if(!checkName(svValue[TYPES_NDX],    "types"))
 
883
        return False;
 
884
    if(!checkName(svValue[COMPAT_NDX],   "compat"))
 
885
        return False;
 
886
    if(!checkName(svValue[SYMBOLS_NDX],  "symbols"))
 
887
        return False;
 
888
    if(!checkName(svValue[KEYCODES_NDX], "keycodes"))
 
889
        return False;
 
890
    if(!checkName(svValue[GEOMETRY_NDX], "geometry"))
 
891
        return False;
 
892
    if(!checkName(svValue[KEYMAP_NDX],   "keymap"))
 
893
        return False;
 
894
 
 
895
    if (verbose>5) {
 
896
        MSG("Trying to build keymap using the following components:\n");
 
897
        dumpNames(False,True);
 
898
    }
 
899
    if (dpy && !print) {
 
900
        XkbComponentNamesRec    cmdNames;
 
901
        cmdNames.types= svValue[TYPES_NDX];
 
902
        cmdNames.compat= svValue[COMPAT_NDX];
 
903
        cmdNames.symbols= svValue[SYMBOLS_NDX];
 
904
        cmdNames.keycodes= svValue[KEYCODES_NDX];
 
905
        cmdNames.geometry= svValue[GEOMETRY_NDX];
 
906
        cmdNames.keymap= svValue[KEYMAP_NDX];
 
907
        xkb= XkbGetKeyboardByName(dpy,XkbUseCoreKbd,&cmdNames,
 
908
                        XkbGBN_AllComponentsMask, 
 
909
                        XkbGBN_AllComponentsMask&(~XkbGBN_GeometryMask),
 
910
                        True);
 
911
        if (!xkb) {
 
912
            ERR("Error loading new keyboard description\n");
 
913
            return False;
 
914
        }
 
915
        if (svValue[RULES_NDX] && (rdefs.model || rdefs.layout)) {
 
916
            if (!XkbRF_SetNamesProp(dpy,svValue[RULES_NDX],&rdefs)) {
 
917
                VMSG(0,"Error updating the XKB names property\n");
 
918
            }
 
919
        }
 
920
    }
 
921
    if (print) {
 
922
        printKeymap();
 
923
    }
 
924
    return True;
 
925
}
 
926
 
 
927
 
 
928
int
 
929
#if NeedFunctionPrototypes
 
930
main(int argc,char **argv)
 
931
#else
 
932
main(argc,argv)
 
933
    int         argc;
 
934
    char **     argv;
 
935
#endif
 
936
{
 
937
    if ((!parseArgs(argc,argv))||(!getDisplay(argc,argv)))
 
938
        exit(-1);
 
939
    svValue[LOCALE_NDX]= setlocale(LC_ALL,svValue[LOCALE_NDX]);
 
940
    svSrc[LOCALE_NDX]= FROM_SERVER;
 
941
    VMSG1(7,"locale is %s\n",svValue[LOCALE_NDX]);
 
942
    if (dpy)
 
943
        getServerValues();
 
944
    if (svValue[CONFIG_NDX] && (!applyConfig(svValue[CONFIG_NDX])))
 
945
        exit(-3);
 
946
    if (!applyRules())
 
947
        exit(-4);
 
948
    if (!applyComponentNames())
 
949
        exit(-5);
 
950
    if (dpy)
 
951
        XCloseDisplay(dpy);
 
952
    exit(0);
 
953
}