Bug Summary

File:handle.c
Location:line 672, column 24
Description:Potential leak of memory pointed to by 'kcs'

Annotated Source Code

1/*
2
3Copyright 1988, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29#ifdef HAVE_CONFIG_H1
30#include "config.h"
31#endif
32
33#include <X11/Xos.h>
34#include <X11/Xlib.h>
35#include <stdio.h>
36#include <ctype.h>
37#include "xmodmap.h"
38#include "wq.h"
39#include <stdlib.h>
40
41#ifdef HAVE_STRNCASECMP1
42#include <strings.h>
43#endif
44
45static XModifierKeymap *map = NULL((void*)0);
46
47
48/*
49 * The routines in this file manipulate a queue of intructions. Instead of
50 * executing each line as it is entered, we build up a list of actions to
51 * take and execute them all at the end. This allows us to find all errors
52 * at once, and to preserve the context in which we are looking up keysyms.
53 */
54
55struct wq work_queue = {NULL((void*)0), NULL((void*)0)};
56
57
58/*
59 * common utility routines
60 */
61
62static KeyCode *
63KeysymToKeycodes(Display *dpy, KeySym keysym, int *pnum_kcs)
64{
65 KeyCode *kcs = NULL((void*)0);
66 int i, j;
67
68 *pnum_kcs = 0;
69 for (i = min_keycode; i <= max_keycode; i++) {
15
Loop condition is true. Entering loop body
21
Loop condition is false. Execution continues on line 82
70 for (j = 0; j < 8; j++) {
16
Loop condition is true. Entering loop body
71 if (XKeycodeToKeysym(dpy, (KeyCode) i, j) == keysym) {
17
Taking true branch
72 if (!kcs)
18
Taking true branch
73 kcs = malloc(sizeof(KeyCode));
19
Memory is allocated
74 else
75 kcs = realloc(kcs, sizeof(KeyCode) * (*pnum_kcs + 1));
76 kcs[*pnum_kcs] = i;
77 *pnum_kcs += 1;
78 break;
20
Execution continues on line 69
79 }
80 }
81 }
82 return kcs;
83}
84
85static char *
86copy_to_scratch(const char *s, int len)
87{
88 static char *buf = NULL((void*)0);
89 static int buflen = 0;
90
91 if (len < 0)
92 len = 0;
93
94 if (len >= buflen) {
95 if (buf) free (buf);
96 buflen = (len < 40) ? 80 : (len * 2);
97 buf = malloc (buflen+1);
98 if (!buf) {
99 fprintf (stderr__stderrp, "attempt to allocate %d byte scratch buffer\n", buflen + 1);
100 return NULL((void*)0);
101 }
102 }
103
104 strncpy (buf, s, len)__builtin___strncpy_chk (buf, s, len, __builtin_object_size (
buf, 2 > 1 ? 1 : 0))
;
105 buf[len] = '\0';
106
107 return (buf);
108}
109
110static void
111badheader(void)
112{
113 fprintf (stderr__stderrp, "%s: %s:%d: bad ", ProgramName, inputFilename, lineno+1);
114 parse_errors++;
115}
116
117#define badmsg0(what){ badheader(); fprintf (__stderrp, what); putc ('\n', __stderrp
); }
{ badheader(); fprintf (stderr__stderrp, what); \
118 putc ('\n', stderr__stderrp); }
119
120#define badmsg(what,arg){ badheader(); fprintf (__stderrp, what, arg); putc ('\n', __stderrp
); }
{ badheader(); fprintf (stderr__stderrp, what, arg); \
121 putc ('\n', stderr__stderrp); }
122
123#define badmsgn(what,s,len){ badheader(); fprintf (__stderrp, what, copy_to_scratch (s, len
)); putc ('\n', __stderrp); }
badmsg (what, copy_to_scratch (s, len)){ badheader(); fprintf (__stderrp, what, copy_to_scratch (s, len
)); putc ('\n', __stderrp); }
124
125void
126initialize_map (void)
127{
128 map = XGetModifierMapping (dpy);
129 return;
130}
131
132static void do_keycode ( char *line, int len );
133static void do_keysym ( char *line, int len );
134static void finish_keycodes ( const char *line, int len, KeyCode *keycodes,
135 int count );
136static void do_add ( char *line, int len );
137static void do_remove ( char *line, int len );
138static void do_clear ( char *line, int len );
139static void do_pointer ( char *line, int len );
140static int get_keysym_list ( const char *line, int len, int *np, KeySym **kslistp );
141
142static void print_opcode(union op *op);
143
144static int skip_word ( const char *s, int len );
145static int skip_chars ( const char *s, int len );
146static int skip_space ( const char *s, int len );
147
148static struct dt {
149 const char *command; /* name of input command */
150 int length; /* length of command */
151 void (*proc)(char *, int); /* handler */
152} dispatch_table[] = {
153 { "keycode", 7, do_keycode },
154 { "keysym", 6, do_keysym },
155 { "add", 3, do_add },
156 { "remove", 6, do_remove },
157 { "clear", 5, do_clear },
158 { "pointer", 7, do_pointer },
159 { NULL((void*)0), 0, NULL((void*)0) }};
160
161/*
162 * handle_line - this routine parses the input line (which has had all leading
163 * and trailing whitespace removed) and builds up the work queue.
164 */
165
166void
167handle_line(char *line, /* string to parse */
168 int len) /* length of line */
169{
170 int n;
171 struct dt *dtp;
172
173 n = skip_chars (line, len);
174 if (n < 0) {
175 badmsg ("input line '%s'", line){ badheader(); fprintf (__stderrp, "input line '%s'", line); putc
('\n', __stderrp); }
;
176 return;
177 }
178
179 for (dtp = dispatch_table; dtp->command != NULL((void*)0); dtp++) {
180 if (n == dtp->length &&
181 strncmp (line, dtp->command, dtp->length) == 0) {
182
183 n += skip_space (line+n, len-n);
184 line += n, len -= n;
185
186 (*(dtp->proc)) (line, len);
187 return;
188 }
189 }
190
191 fprintf (stderr__stderrp, "%s: unknown command on line %s:%d\n",
192 ProgramName, inputFilename, lineno+1);
193 parse_errors++;
194}
195
196/*
197 * the following routines are useful for parsing
198 */
199
200static int
201skip_word (const char *s, int len)
202{
203 register int n;
204
205 n = skip_chars (s, len);
206 return (n + skip_space (s+n, len-n));
207}
208
209static int
210skip_chars(const char *s, int len)
211{
212 register int i;
213
214 if (len <= 0 || !s || *s == '\0') return (0);
215
216 for (i = 0; i < len; i++) {
217 if (isspace(s[i])) break;
218 }
219 return (i);
220}
221
222static int
223skip_space(const char *s, int len)
224{
225 register int i;
226
227 if (len <= 0 || !s || *s == '\0') return (0);
228
229 for (i = 0; i < len; i++) {
230 if (!s[i] || !isspace(s[i])) break;
231 }
232 return (i);
233}
234
235
236static int
237skip_until_char(const char *s, int len, char c)
238{
239 register int i;
240
241 for (i = 0; i < len; i++) {
242 if (s[i] == c) break;
243 }
244 return (i);
245}
246
247
248/*
249 * The action routines.
250 *
251 * This is where the real work gets done. Each routine is responsible for
252 * parsing its input (note that the command keyword has been stripped off)
253 * and adding to the work queue. They are also in charge of outputting
254 * error messages and returning non-zero if there is a problem.
255 *
256 * The following global variables are available:
257 * dpy the display descriptor
258 * work_queue linked list of opcodes
259 * inputFilename name of the file being processed
260 * lineno line number of current line in input file
261 */
262static void
263add_to_work_queue(union op *p) /* this can become a macro someday */
264{
265 if (work_queue.head == NULL((void*)0)) { /* nothing on the list */
266 work_queue.head = work_queue.tail = p; /* head, tail, no prev */
267 } else {
268 work_queue.tail->generic.next = p; /* head okay, prev */
269 work_queue.tail = p; /* tail */
270 }
271 p->generic.next = NULL((void*)0);
272
273 if (verbose) {
274 print_opcode (p);
275 }
276 return;
277}
278
279static Boolint
280parse_number(const char *str, unsigned long *val)
281{
282 const char *fmt = "%ld";
283
284 if (*str == '0') {
285 str++;
286 while (isspace(*str))
287 str++;
288 fmt = "%lo";
289 if (*str == '\0') {
290 *val = 0;
291 return 1;
292 }
293 if (*str == 'x' || *str == 'X') {
294 str++;
295 fmt = "%lx";
296 }
297 }
298 return (sscanf (str, fmt, val) == 1);
299}
300
301static Boolint
302parse_keysym(const char *line, int n, char **name, KeySym *keysym)
303{
304 *name = copy_to_scratch (line, n);
305 if (!strcmp(*name, "NoSymbol")) {
306 *keysym = NoSymbol0L;
307 return (True1);
308 }
309 *keysym = XStringToKeysym (*name);
310 if (*keysym == NoSymbol0L && '0' <= **name && **name <= '9')
311 return parse_number(*name, keysym);
312 return (*keysym != NoSymbol0L);
313}
314
315/*
316 * do_keycode - parse off lines of the form
317 *
318 * "keycode" number "=" [keysym ...]
319 * ^
320 *
321 * where number is in decimal, hex, or octal. Any number of keysyms may be
322 * listed.
323 */
324
325static void
326do_keycode(char *line, int len)
327{
328 int dummy;
329 const char *fmt = "%d";
330 KeyCode keycode;
331
332 if (len < 3 || !line || *line == '\0') { /* 5=a minimum */
333 badmsg0 ("keycode input line"){ badheader(); fprintf (__stderrp, "keycode input line"); putc
('\n', __stderrp); }
;
334 return;
335 }
336
337 /*
338 * We need not bother to advance line/len past the
339 * number (or the string 'any') as finish_keycodes() will
340 * first advance past the '='.
341 */
342 if (!strncmp("any", line, 3)) {
343 keycode = 0;
344 } else {
345 if (*line == '0') line++, len--, fmt = "%o";
346 if (*line == 'x' || *line == 'X') line++, len--, fmt = "%x";
347
348 dummy = 0;
349 if (sscanf (line, fmt, &dummy) != 1 || dummy == 0) {
350 badmsg0 ("keycode value"){ badheader(); fprintf (__stderrp, "keycode value"); putc ('\n'
, __stderrp); }
;
351 return;
352 }
353 keycode = (KeyCode) dummy;
354 if ((int)keycode < min_keycode || (int)keycode > max_keycode) {
355 badmsg0 ("keycode value (out of range)"){ badheader(); fprintf (__stderrp, "keycode value (out of range)"
); putc ('\n', __stderrp); }
;
356 return;
357 }
358 }
359
360 finish_keycodes (line, len, &keycode, 1);
361}
362
363
364/*
365 * do_keysym - parse off lines of the form
366 *
367 * "keysym" keysym "=" [keysym ...]
368 * ^
369 *
370 * The left keysyms has to be checked for validity and evaluated.
371 */
372
373static void
374do_keysym(char *line, int len)
375{
376 int n;
377 KeyCode *keycodes;
378 KeySym keysym;
379 char *tmpname;
380
381 if (len < 3 || !line || *line == '\0') { /* a=b minimum */
382 badmsg0 ("keysym input line"){ badheader(); fprintf (__stderrp, "keysym input line"); putc
('\n', __stderrp); }
;
383 return;
384 }
385
386 n = skip_chars (line, len);
387 if (n < 1) {
388 badmsg0 ("target keysym name"){ badheader(); fprintf (__stderrp, "target keysym name"); putc
('\n', __stderrp); }
;
389 return;
390 }
391 if (!parse_keysym(line, n, &tmpname, &keysym)) {
392 badmsg ("keysym target key symbol '%s'", tmpname){ badheader(); fprintf (__stderrp, "keysym target key symbol '%s'"
, tmpname); putc ('\n', __stderrp); }
;
393 return;
394 }
395
396 keycodes = KeysymToKeycodes (dpy, keysym, &n);
397 if (n == 0) {
398 badmsg ("keysym target keysym '%s', no corresponding keycodes",{ badheader(); fprintf (__stderrp, "keysym target keysym '%s', no corresponding keycodes"
, tmpname); putc ('\n', __stderrp); }
399 tmpname){ badheader(); fprintf (__stderrp, "keysym target keysym '%s', no corresponding keycodes"
, tmpname); putc ('\n', __stderrp); }
;
400 return;
401 }
402 if (verbose) {
403 int i;
404 printf ("! Keysym %s (0x%lx) corresponds to keycode(s)",
405 tmpname, (long) keysym);
406 for (i = 0; i < n; i++)
407 printf (" 0x%x", keycodes[i]);
408 printf("\n");
409 }
410
411 finish_keycodes (line, len, keycodes, n);
412}
413
414static void
415finish_keycodes(const char *line, int len, KeyCode *keycodes, int count)
416{
417 int n;
418 KeySym *kslist;
419 union op *uop;
420 struct op_keycode *opk;
421
422 n = skip_until_char (line, len, '=');
423 line += n, len -= n;
424
425 if (len < 1 || *line != '=') { /* = minimum */
426 badmsg0 ("keycode command (missing keysym list),"){ badheader(); fprintf (__stderrp, "keycode command (missing keysym list),"
); putc ('\n', __stderrp); }
;
427 return;
428 }
429 line++, len--; /* skip past the = */
430
431 n = skip_space (line, len);
432 line += n, len -= n;
433
434 /* allow empty list */
435 if (get_keysym_list (line, len, &n, &kslist) < 0)
436 return;
437
438 while (--count >= 0) {
439 uop = AllocStruct (union op)(malloc (sizeof (union op)));
440 if (!uop) {
441 badmsg ("attempt to allocate a %ld byte keycode opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte keycode opcode"
, (long) sizeof (struct op_keycode)); putc ('\n', __stderrp);
}
442 (long) sizeof (struct op_keycode)){ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte keycode opcode"
, (long) sizeof (struct op_keycode)); putc ('\n', __stderrp);
}
;
443 return;
444 }
445 opk = &uop->keycode;
446
447 opk->type = doKeycode;
448 opk->target_keycode = keycodes[count];
449 opk->count = n;
450 opk->keysyms = kslist;
451
452 add_to_work_queue (uop);
453 }
454
455#ifdef later
456 /* make sure we handle any special keys */
457 check_special_keys (keycode, n, kslist);
458#endif
459}
460
461
462/*
463 * parse_modifier - convert a modifier string name to its index
464 */
465
466struct modtab modifier_table[] = { /* keep in order so it can be index */
467 { "shift", 5, 0 },
468 { "lock", 4, 1 },
469 { "control", 7, 2 },
470 { "mod1", 4, 3 },
471 { "mod2", 4, 4 },
472 { "mod3", 4, 5 },
473 { "mod4", 4, 6 },
474 { "mod5", 4, 7 },
475 { "ctrl", 4, 2 },
476 { NULL((void*)0), 0, 0 }};
477
478static int
479parse_modifier(char *line, int n)
480{
481 register int i;
482 struct modtab *mt;
483
484 /* lowercase for comparison against table */
485 for (i = 0; i < n; i++) {
486 if (isupper (line[i])) line[i] = tolower (line[i]);
487 }
488
489 for (mt = modifier_table; mt->name; mt++) {
490 if (n == mt->length && strncmp (line, mt->name, n) == 0)
491 return (mt->value);
492 }
493 return (-1);
494}
495
496
497/*
498 * do_add - parse off lines of the form
499 *
500 * add MODIFIER = keysym ...
501 * ^
502 * where the MODIFIER is one of Shift, Lock, Control, Mod[1-5] where case
503 * is not important. There should also be an alias Ctrl for control.
504 */
505
506static void
507do_add(char *line, int len)
508{
509 int n;
510 int modifier;
511 KeySym *kslist;
512 union op *uop;
513 struct op_addmodifier *opam;
514
515 if (len < 6 || !line || *line == '\0') { /* Lock=a minimum */
516 badmsg0 ("add modifier input line"){ badheader(); fprintf (__stderrp, "add modifier input line")
; putc ('\n', __stderrp); }
;
517 return;
518 }
519
520 n = skip_chars (line, len);
521 if (n < 1) {
522 badmsg ("add modifier name %s", line){ badheader(); fprintf (__stderrp, "add modifier name %s", line
); putc ('\n', __stderrp); }
;
523 return;
524 }
525
526 modifier = parse_modifier (line, n);
527 if (modifier < 0) {
528 badmsgn ("add modifier name '%s', not allowed", line, n){ badheader(); fprintf (__stderrp, "add modifier name '%s', not allowed"
, copy_to_scratch (line, n)); putc ('\n', __stderrp); }
;
529 return;
530 }
531
532 line += n, len -= n;
533 n = skip_until_char (line, len, '=');
534 if (n < 0) {
535 badmsg0 ("add modifier = keysym"){ badheader(); fprintf (__stderrp, "add modifier = keysym"); putc
('\n', __stderrp); }
;
536 return;
537 }
538
539 n++; /* skip = */
540 n += skip_space (line+n, len-n);
541 line += n, len -= n;
542
543 if (get_keysym_list (line, len, &n, &kslist) < 0)
544 return;
545 if (n == 0) {
546 badmsg0 ("add modifier keysym list (empty)"){ badheader(); fprintf (__stderrp, "add modifier keysym list (empty)"
); putc ('\n', __stderrp); }
;
547 return;
548 }
549
550 uop = AllocStruct (union op)(malloc (sizeof (union op)));
551 if (!uop) {
552 badmsg ("attempt to allocate %ld byte addmodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode"
, (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp
); }
553 (long) sizeof (struct op_addmodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode"
, (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp
); }
;
554 return;
555 }
556 opam = &uop->addmodifier;
557
558 opam->type = doAddModifier;
559 opam->modifier = modifier;
560 opam->count = n;
561 opam->keysyms = kslist;
562
563 add_to_work_queue (uop);
564}
565
566#ifdef AUTO_ADD_REMOVE
567/*
568 * make_add - stick a single add onto the queue
569 */
570static void
571make_add(int modifier, KeySym keysym)
572{
573 union op *uop;
574 struct op_addmodifier *opam;
575
576 uop = AllocStruct (union op)(malloc (sizeof (union op)));
577 if (!uop) {
578 badmsg ("attempt to allocate %ld byte addmodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode"
, (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp
); }
579 (long) sizeof (struct op_addmodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode"
, (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp
); }
;
580 return;
581 }
582 opam = &uop->addmodifier;
583
584 opam->type = doAddModifier;
585 opam->modifier = modifier;
586 opam->count = 1;
587 opam->keysyms = malloc (sizeof (KeySym));
588 if (!opam->keysyms) {
589 badmsg ("attempt to allocate %ld byte KeySym", (long) sizeof (KeySym)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte KeySym"
, (long) sizeof (KeySym)); putc ('\n', __stderrp); }
;
590 free (opam);
591 return;
592 }
593 opam->keysyms[0] = keysym;
594
595 add_to_work_queue (uop);
596 return;
597}
598#endif /* AUTO_ADD_REMOVE */
599
600
601/*
602 * do_remove - parse off lines of the form
603 *
604 * remove MODIFIER = oldkeysym ...
605 * ^
606 * where the MODIFIER is one of Shift, Lock, Control, Mod[1-5] where case
607 * is not important. There should also be an alias Ctrl for control.
608 */
609
610static void
611do_remove(char *line, int len)
612{
613 int n;
614 int nc;
615 int i;
616 int tot;
617 int modifier;
618 KeySym *kslist;
619 KeyCode *kclist;
620 union op *uop;
621 struct op_removemodifier *oprm;
622
623 if (len < 6 || !line || *line == '\0') { /* Lock=a minimum */
1
Assuming 'len' is >= 6
2
Assuming 'line' is non-null
3
Taking false branch
624 badmsg0 ("remove modifier input line"){ badheader(); fprintf (__stderrp, "remove modifier input line"
); putc ('\n', __stderrp); }
;
625 return;
626 }
627
628 n = skip_chars (line, len);
629 if (n < 1) {
4
Assuming 'n' is >= 1
5
Taking false branch
630 badmsg ("remove modifier name %s", line){ badheader(); fprintf (__stderrp, "remove modifier name %s",
line); putc ('\n', __stderrp); }
;
631 return;
632 }
633
634 modifier = parse_modifier (line, n);
635 if (modifier < 0) {
6
Assuming 'modifier' is >= 0
7
Taking false branch
636 badmsgn ("remove modifier name '%s', not allowed", line, n){ badheader(); fprintf (__stderrp, "remove modifier name '%s', not allowed"
, copy_to_scratch (line, n)); putc ('\n', __stderrp); }
;
637 return;
638 }
639
640 line += n, len -= n;
641 n = skip_until_char (line, len, '=');
642 if (n < 0) {
8
Taking false branch
643 badmsg0 ("remove modifier = keysym"){ badheader(); fprintf (__stderrp, "remove modifier = keysym"
); putc ('\n', __stderrp); }
;
644 return;
645 }
646
647 n++;
648 n += skip_space (line+n, len-n);
649 line += n, len -= n;
650
651 if (get_keysym_list (line, len, &n, &kslist) < 0)
9
Taking false branch
652 return;
653 if (n == 0) {
10
Taking false branch
654 badmsg0 ("remove modifier keysym list (empty)"){ badheader(); fprintf (__stderrp, "remove modifier keysym list (empty)"
); putc ('\n', __stderrp); }
;
655 return;
656 }
657
658 /*
659 * unlike the add command, we have to now evaluate the keysyms
660 */
661
662 kclist = malloc (n * sizeof (KeyCode));
663 if (!kclist) {
11
Assuming 'kclist' is non-null
12
Taking false branch
664 badmsg ("attempt to allocate %ld byte keycode list",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list"
, (long) (n * sizeof (KeyCode))); putc ('\n', __stderrp); }
665 (long) (n * sizeof (KeyCode))){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list"
, (long) (n * sizeof (KeyCode))); putc ('\n', __stderrp); }
;
666 free (kslist);
667 return;
668 }
669
670 tot = n;
671 nc = 0;
672 for (i = 0; i < n; i++) {
13
Loop condition is true. Entering loop body
29
Potential leak of memory pointed to by 'kcs'
673 int num_kcs;
674 KeyCode *kcs;
675 kcs = KeysymToKeycodes (dpy, kslist[i], &num_kcs);
14
Calling 'KeysymToKeycodes'
22
Returned allocated memory
676 if (num_kcs == 0) {
23
Taking false branch
677 char *tmpname = XKeysymToString (kslist[i]);
678 badmsg ("keysym in remove modifier list '%s', no corresponding keycodes",{ badheader(); fprintf (__stderrp, "keysym in remove modifier list '%s', no corresponding keycodes"
, tmpname ? tmpname : "?"); putc ('\n', __stderrp); }
679 tmpname ? tmpname : "?"){ badheader(); fprintf (__stderrp, "keysym in remove modifier list '%s', no corresponding keycodes"
, tmpname ? tmpname : "?"); putc ('\n', __stderrp); }
;
680 continue;
681 }
682 if (verbose) {
24
Assuming 'verbose' is 0
25
Taking false branch
683 int j;
684 char *tmpname = XKeysymToString (kslist[i]);
685 printf ("! Keysym %s (0x%lx) corresponds to keycode(s)",
686 tmpname ? tmpname : "?", (long) kslist[i]);
687 for (j = 0; j < num_kcs; j++)
688 printf(" 0x%x", kcs[j]);
689 printf("\n");
690 }
691 if (nc + num_kcs > tot) {
26
Taking false branch
692 tot = nc + num_kcs;
693 kclist = realloc(kclist, tot * sizeof(KeyCode));
694 if (!kclist) {
695 badmsg ("attempt to allocate %ld byte keycode list",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list"
, (long) (tot * sizeof (KeyCode))); putc ('\n', __stderrp); }
696 (long) (tot * sizeof (KeyCode))){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list"
, (long) (tot * sizeof (KeyCode))); putc ('\n', __stderrp); }
;
697 free (kslist);
698 return;
699 }
700 }
701 while (--num_kcs >= 0)
27
Loop condition is true. Entering loop body
28
Loop condition is false. Execution continues on line 672
702 kclist[nc++] = *kcs++; /* okay, add it to list */
703 }
704
705 free (kslist); /* all done with it */
706
707 uop = AllocStruct (union op)(malloc (sizeof (union op)));
708 if (!uop) {
709 badmsg ("attempt to allocate %ld byte removemodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode"
, (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp
); }
710 (long) sizeof (struct op_removemodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode"
, (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp
); }
;
711 return;
712 }
713 oprm = &uop->removemodifier;
714
715 oprm->type = doRemoveModifier;
716 oprm->modifier = modifier;
717 oprm->count = nc;
718 oprm->keycodes = kclist;
719
720 add_to_work_queue (uop);
721}
722
723#ifdef AUTO_ADD_REMOVE
724/*
725 * make_remove - stick a single remove onto the queue
726 */
727static void
728make_remove(int modifier, KeyCode keycode)
729{
730 union op *uop;
731 struct op_removemodifier *oprm;
732
733 uop = AllocStruct (union op)(malloc (sizeof (union op)));
734 if (!uop) {
735 badmsg ("attempt to allocate %ld byte removemodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode"
, (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp
); }
736 (long) sizeof (struct op_removemodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode"
, (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp
); }
;
737 return;
738 }
739 oprm = &uop->removemodifier;
740
741 oprm->type = doRemoveModifier;
742 oprm->modifier = modifier;
743 oprm->count = 1;
744 oprm->keycodes = malloc (sizeof (KeyCode));
745 if (!oprm->keycodes) {
746 badmsg ("attempt to allocate %ld byte KeyCode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte KeyCode"
, (long) sizeof (KeyCode)); putc ('\n', __stderrp); }
747 (long) sizeof (KeyCode)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte KeyCode"
, (long) sizeof (KeyCode)); putc ('\n', __stderrp); }
;
748 free (oprm);
749 return;
750 }
751 oprm->keycodes[0] = keycode;
752
753 add_to_work_queue (uop);
754 return;
755}
756#endif /* AUTO_ADD_REMOVE */
757
758
759/*
760 * do_clear - parse off lines of the form
761 *
762 * clear MODIFIER
763 * ^
764 */
765
766static void
767do_clear(char *line, int len)
768{
769 int n;
770 int modifier;
771 union op *uop;
772 struct op_clearmodifier *opcm;
773
774 if (len < 4 || !line || *line == '\0') { /* Lock minimum */
775 badmsg0 ("clear modifier input line"){ badheader(); fprintf (__stderrp, "clear modifier input line"
); putc ('\n', __stderrp); }
;
776 return;
777 }
778
779 n = skip_chars (line, len);
780
781 modifier = parse_modifier (line, n);
782 if (modifier < 0) {
783 badmsgn ("clear modifier name '%s'", line, n){ badheader(); fprintf (__stderrp, "clear modifier name '%s'"
, copy_to_scratch (line, n)); putc ('\n', __stderrp); }
;
784 return;
785 }
786 n += skip_space (line+n, len-n);
787 if (n != len) {
788 badmsgn ("extra argument '%s' to clear modifier", line+n, len-n){ badheader(); fprintf (__stderrp, "extra argument '%s' to clear modifier"
, copy_to_scratch (line+n, len-n)); putc ('\n', __stderrp); }
;
789 /* okay to continue */
790 }
791
792 uop = AllocStruct (union op)(malloc (sizeof (union op)));
793 if (!uop) {
794 badmsg ("attempt to allocate %ld byte clearmodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte clearmodifier opcode"
, (long) sizeof (struct op_clearmodifier)); putc ('\n', __stderrp
); }
795 (long) sizeof (struct op_clearmodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte clearmodifier opcode"
, (long) sizeof (struct op_clearmodifier)); putc ('\n', __stderrp
); }
;
796 return;
797 }
798 opcm = &uop->clearmodifier;
799
800 opcm->type = doClearModifier;
801 opcm->modifier = modifier;
802
803 add_to_work_queue (uop);
804}
805
806#ifndef HAVE_STRNCASECMP1
807static int
808strncasecmp(const char *a, const char *b, int n)
809{
810 int i;
811 int a1, b1;
812
813 for (i = 0; i < n; i++, a++, b++) {
814 if (!*a) return -1;
815 if (!*b) return 1;
816
817 if (*a != *b) {
818 a1 = (isascii(*a) && isupper(*a)) ? tolower(*a) : *a;
819 b1 = (isascii(*b) && isupper(*b)) ? tolower(*b) : *b;
820 if (a1 != b1) return b1 - a1;
821 }
822 }
823 return 0;
824}
825#endif
826
827/*
828 * do_pointer = get list of numbers of the form
829 *
830 * buttons = NUMBER ...
831 * ^
832 */
833
834static void
835do_pointer(char *line, int len)
836{
837 int n;
838 int i;
839 unsigned long val;
840 union op *uop;
841 struct op_pointer *opp;
842 unsigned char buttons[MAXBUTTONCODES256];
843 int nbuttons;
844 char *strval;
845 Boolint ok;
846
847 if (len < 2 || !line || *line == '\0') { /* =1 minimum */
848 badmsg0 ("buttons input line"){ badheader(); fprintf (__stderrp, "buttons input line"); putc
('\n', __stderrp); }
;
849 return;
850 }
851
852 nbuttons = XGetPointerMapping (dpy, buttons, MAXBUTTONCODES256);
853
854 n = skip_space (line, len);
855 line += n, len -= n;
856
857 if (line[0] != '=') {
858 badmsg0 ("buttons pointer code list, missing equal sign"){ badheader(); fprintf (__stderrp, "buttons pointer code list, missing equal sign"
); putc ('\n', __stderrp); }
;
859 return;
860 }
861
862 line++, len--; /* skip = */
863 n = skip_space (line, len);
864 line += n, len -= n;
865
866 i = 0;
867 if (len < 7 || strncasecmp (line, "default", 7) != 0) {
868 while (len > 0) {
869 n = skip_space (line, len);
870 line += n, len -= n;
871 if (line[0] == '\0') break;
872 n = skip_word (line, len);
873 if (n < 1) {
874 badmsg ("skip of word in buttons line: %s", line){ badheader(); fprintf (__stderrp, "skip of word in buttons line: %s"
, line); putc ('\n', __stderrp); }
;
875 return;
876 }
877 strval = copy_to_scratch(line, n);
878 if (strval == NULL((void*)0))
879 /* copy_to_scratch already printed error message */
880 return;
881 ok = parse_number (strval, &val);
882 if (!ok || val >= MAXBUTTONCODES256) {
883 badmsg ("value %s given for buttons list", strval){ badheader(); fprintf (__stderrp, "value %s given for buttons list"
, strval); putc ('\n', __stderrp); }
;
884 return;
885 }
886 buttons[i++] = (unsigned char) val;
887 line += n, len -= n;
888 }
889 }
890
891 if (i > 0 && i != nbuttons) {
892 fprintf (stderr__stderrp, "Warning: Only changing the first %d of %d buttons.\n",
893 i, nbuttons);
894 i = nbuttons;
895 }
896
897 uop = AllocStruct (union op)(malloc (sizeof (union op)));
898 if (!uop) {
899 badmsg ("attempt to allocate a %ld byte pointer opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte pointer opcode"
, (long) sizeof (struct op_pointer)); putc ('\n', __stderrp);
}
900 (long) sizeof (struct op_pointer)){ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte pointer opcode"
, (long) sizeof (struct op_pointer)); putc ('\n', __stderrp);
}
;
901 return;
902 }
903 opp = &uop->pointer;
904
905 opp->type = doPointer;
906 opp->count = i;
907 for (i = 0; i < opp->count; i++) {
908 opp->button_codes[i] = buttons[i];
909 }
910
911 add_to_work_queue (uop);
912}
913
914
915/*
916 * get_keysym_list - parses the rest of the line into a keysyms assumes
917 * that the = sign has been parsed off but there may be leading whitespace
918 *
919 * keysym ...
920 * ^
921 *
922 * this involves getting the word containing the keysym, checking its range,
923 * and adding it to the list.
924 */
925
926static int
927get_keysym_list(const char *line, int len, int *np, KeySym **kslistp)
928{
929 int havesofar, maxcanhave;
930 KeySym *keysymlist;
931
932 *np = 0;
933 *kslistp = NULL((void*)0);
934
935 if (len == 0) return (0); /* empty list */
936
937 havesofar = 0;
938 maxcanhave = 4; /* most lists are small */
939 keysymlist = malloc (maxcanhave * sizeof (KeySym));
940 if (!keysymlist) {
941 badmsg ("attempt to allocate %ld byte initial keysymlist",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte initial keysymlist"
, (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp
); }
942 (long) (maxcanhave * sizeof (KeySym))){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte initial keysymlist"
, (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp
); }
;
943 return (-1);
944 }
945
946 while (len > 0) {
947 KeySym keysym;
948 int n;
949 char *tmpname;
950 Boolint ok;
951
952 n = skip_space (line, len);
953 line += n, len -= n;
954
955 n = skip_chars (line, len);
956 if (n < 0) {
957 badmsg0 ("keysym name list"){ badheader(); fprintf (__stderrp, "keysym name list"); putc (
'\n', __stderrp); }
;
958 free(keysymlist);
959 return (-1);
960 }
961
962 ok = parse_keysym (line, n, &tmpname, &keysym);
963 line += n, len -= n;
964 if (!ok) {
965 badmsg ("keysym name '%s' in keysym list", tmpname){ badheader(); fprintf (__stderrp, "keysym name '%s' in keysym list"
, tmpname); putc ('\n', __stderrp); }
;
966 /* do NOT return here, look for others */
967 continue;
968 }
969
970 /*
971 * Do NOT test to see if the keysym translates to a keycode or you
972 * won't be able to assign new ones....
973 */
974
975 /* grow the list bigger if necessary */
976 if (havesofar >= maxcanhave) {
977 KeySym *origkeysymlist = keysymlist;
978 maxcanhave *= 2;
979 keysymlist = realloc (keysymlist, maxcanhave * sizeof (KeySym));
980 if (!keysymlist) {
981 badmsg ("attempt to grow keysym list to %ld bytes",{ badheader(); fprintf (__stderrp, "attempt to grow keysym list to %ld bytes"
, (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp
); }
982 (long) (maxcanhave * sizeof (KeySym))){ badheader(); fprintf (__stderrp, "attempt to grow keysym list to %ld bytes"
, (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp
); }
;
983 free(origkeysymlist);
984 return (-1);
985 }
986 }
987
988 /* and add it to the list */
989 keysymlist[havesofar++] = keysym;
990 }
991
992 *kslistp = keysymlist;
993 *np = havesofar;
994 return (0);
995}
996
997
998#ifdef later
999/*
1000 * check_special_keys - run through list of keysyms and generate "add" or
1001 * "remove" commands for for any of the key syms that appear in the modifier
1002 * list. this involves running down the modifier map which is an array of
1003 * 8 by map->max_keypermod keycodes.
1004 */
1005
1006static void
1007check_special_keys(KeyCode keycode, int n, KeySym *kslist)
1008{
1009 int i; /* iterator variable */
1010 KeyCode *kcp; /* keycode pointer */
1011
1012 /*
1013 * walk the modifiermap array. since its dimensions are not known at
1014 * compile time, we have to walk it by hand instead of indexing. this
1015 * is why it is initialized outside the loop, but incremented inside the
1016 * second loop.
1017 */
1018
1019 kcp = map->modifiermap; /* start at beginning and iterate */
1020 for (i = 0; i < 8; i++) { /* there are 8 modifier keys */
1021 int j;
1022
1023 for (j = 0; j < map->max_keypermod; j++, kcp++) {
1024 KeySym keysym;
1025 int k;
1026
1027 if (!*kcp) continue; /* only non-zero entries significant */
1028
1029 /*
1030 * check to see if the target keycode is already a modifier; if so,
1031 * then we have to remove it
1032 */
1033 if (keycode == *kcp) {
1034 make_remove (i, keycode);
1035 }
1036
1037 /*
1038 * now, check to see if any of the keysyms map to keycodes
1039 * that are in the modifier list
1040 */
1041 for (k = 0; k < n; k++) {
1042 KeyCodes kc;
1043
1044 kc = XKeysymToKeycode (dpy, kslist[k]);
1045 if (kc == *kcp) { /* yup, found one */
1046 /*
1047 * have to generate a remove of the CURRENT keycode
1048 * and then an add of the new KEYCODE
1049 */
1050 make_remove (i, kc); /* modifier, keycode */
1051 make_add (i, kslist[k]); /* modifier, keysym */
1052 }
1053 }
1054 }
1055 }
1056 return;
1057}
1058#endif
1059
1060/*
1061 * print_work_queue - disassemble the work queue and print it on stdout
1062 */
1063
1064void
1065print_work_queue(void)
1066{
1067 union op *op;
1068
1069 printf ("! dump of work queue\n");
1070 for (op = work_queue.head; op; op = op->generic.next) {
1071 print_opcode (op);
1072 }
1073 return;
1074}
1075
1076static void
1077print_opcode(union op *op)
1078{
1079 int i;
1080
1081 printf (" ");
1082 switch (op->generic.type) {
1083 case doKeycode:
1084 if (op->keycode.target_keycode)
1085 printf ("keycode 0x%lx =", (long) op->keycode.target_keycode);
1086 else
1087 printf ("keycode any =");
1088 for (i = 0; i < op->keycode.count; i++) {
1089 char *name = XKeysymToString (op->keycode.keysyms[i]);
1090
1091 printf (" %s", name ? name : "BADKEYSYM");
1092 }
1093 printf ("\n");
1094 break;
1095 case doAddModifier:
1096 printf ("add %s =", modifier_table[op->addmodifier.modifier].name);
1097 for (i = 0; i < op->addmodifier.count; i++) {
1098 char *name = XKeysymToString (op->addmodifier.keysyms[i]);
1099 printf (" %s", name ? name : "BADKEYSYM");
1100 }
1101 printf ("\n");
1102 break;
1103 case doRemoveModifier:
1104 printf ("remove %s = ",
1105 modifier_table[op->removemodifier.modifier].name);
1106 for (i = 0; i < op->removemodifier.count; i++) {
1107 printf (" 0x%lx", (long) op->removemodifier.keycodes[i]);
1108 }
1109 printf ("\n");
1110 break;
1111 case doClearModifier:
1112 printf ("clear %s\n", modifier_table[op->clearmodifier.modifier].name);
1113 break;
1114 case doPointer:
1115 printf ("pointer = ");
1116 if (op->pointer.count == 0)
1117 printf(" default");
1118 else for (i=0; i < op->pointer.count; i++)
1119 printf(" %d", op->pointer.button_codes[i]);
1120 printf ("\n");
1121 break;
1122 default:
1123 printf ("! unknown opcode %d\n", op->generic.type);
1124 break;
1125 } /* end switch */
1126 return;
1127}
1128
1129/*
1130 * execute_work_queue - do the real meat and potatoes now that we know what
1131 * we need to do and that all of the input is correct.
1132 */
1133static int exec_keycode ( struct op_keycode *opk );
1134static int exec_add ( struct op_addmodifier *opam );
1135static int exec_remove ( struct op_removemodifier *oprm );
1136static int exec_clear ( struct op_clearmodifier *opcm );
1137static int exec_pointer ( struct op_pointer *opp );
1138
1139
1140int
1141execute_work_queue (void)
1142{
1143 union op *op;
1144 int errors;
1145 Boolint update_map = False0;
1146 int dosync;
1147
1148 if (verbose) {
1149 printf ("!\n");
1150 printf ("! executing work queue\n");
1151 printf ("!\n");
1152 }
1153
1154 errors = 0;
1155 dosync = 0;
1156
1157 for (op = work_queue.head; op; op = op->generic.next) {
1158 if (verbose) print_opcode (op);
1159
1160 /* check to see if we have to update the keyboard mapping */
1161 if (dosync &&
1162 (dosync < 0 ||
1163 op->generic.type != doKeycode ||
1164 !op->keycode.target_keycode)) {
1165 XSync (dpy, 0);
1166 while (XEventsQueued (dpy, QueuedAlready0) > 0) {
1167 XEvent event;
1168 XNextEvent (dpy, &event);
1169 if (event.type == MappingNotify34) {
1170 /* read all MappingNotify events */
1171 while (XCheckTypedEvent (dpy, MappingNotify34, &event)) ;
1172 XRefreshKeyboardMapping (&event.xmapping);
1173 } else {
1174 fprintf (stderr__stderrp, "%s: unknown event %ld\n",
1175 ProgramName, (long) event.type);
1176 }
1177 }
1178 }
1179 dosync = 0;
1180 switch (op->generic.type) {
1181 case doKeycode:
1182 if (exec_keycode (&op->keycode) < 0) errors++;
1183 if (op->keycode.target_keycode)
1184 dosync = 1;
1185 else
1186 dosync = -1;
1187 break;
1188 case doAddModifier:
1189 if (exec_add (&op->addmodifier) < 0) errors++;
1190 else update_map = True1;
1191 break;
1192 case doRemoveModifier:
1193 if (exec_remove (&op->removemodifier) < 0) errors++;
1194 else update_map = True1;
1195 break;
1196 case doClearModifier:
1197 if (exec_clear (&op->clearmodifier) < 0) errors++;
1198 else update_map = True1;
1199 break;
1200 case doPointer:
1201 if (exec_pointer (&op->pointer) < 0) errors++;
1202 break;
1203 default:
1204 fprintf (stderr__stderrp, "%s: unknown opcode %d\n",
1205 ProgramName, op->generic.type);
1206 break;
1207 }
1208 }
1209
1210 if (update_map) {
1211 if (UpdateModifierMapping (map) < 0) errors++;
1212 }
1213
1214 return (errors > 0 ? -1 : 0);
1215}
1216
1217static int
1218exec_keycode(struct op_keycode *opk)
1219{
1220 if (!opk->target_keycode) {
1221 int i, j;
1222 KeyCode free;
1223 if (!opk->count)
1224 return (0);
1225 free = 0;
1226 for (i = min_keycode; i <= max_keycode; i++) {
1227 for (j = 0; j < opk->count; j++) {
1228 if (XKeycodeToKeysym(dpy, (KeyCode) i, j) != opk->keysyms[j])
1229 break;
1230 }
1231 if (j >= opk->count)
1232 return (0);
1233 if (free)
1234 continue;
1235 for (j = 0; j < 8; j++) {
1236 if (XKeycodeToKeysym(dpy, (KeyCode) i, j) != None0L)
1237 break;
1238 }
1239 if (j >= 8)
1240 free = i;
1241 }
1242 if (!free) {
1243 fprintf(stderr__stderrp, "%s: no available keycode for assignment\n",
1244 ProgramName);
1245 return (-1);
1246 }
1247 XChangeKeyboardMapping (dpy, free, opk->count, opk->keysyms, 1);
1248 } else if (opk->count == 0) {
1249 KeySym dummy = NoSymbol0L;
1250 XChangeKeyboardMapping (dpy, opk->target_keycode, 1,
1251 &dummy, 1);
1252 } else {
1253 XChangeKeyboardMapping (dpy, opk->target_keycode, opk->count,
1254 opk->keysyms, 1);
1255 }
1256 return (0);
1257}
1258
1259static int
1260exec_add(struct op_addmodifier *opam)
1261{
1262 int i;
1263 int status;
1264
1265 status = 0;
1266 for (i = 0; i < opam->count; i++) {
1267 int num_kcs;
1268 KeyCode *kcs;
1269
1270 kcs = KeysymToKeycodes (dpy, opam->keysyms[i], &num_kcs);
1271 if (num_kcs == 0)
1272 status = -1;
1273 while (--num_kcs >= 0) {
1274 if (AddModifier (&map, *kcs++, opam->modifier) < 0)
1275 status = -1;
1276 }
1277 }
1278 return (status);
1279}
1280
1281static int
1282exec_remove(struct op_removemodifier *oprm)
1283{
1284 int i;
1285 int status;
1286
1287 status = 0;
1288 for (i = 0; i < oprm->count; i++) {
1289 if (RemoveModifier (&map, oprm->keycodes[i], oprm->modifier) < 0)
1290 status = -1;
1291 }
1292 return (status);
1293}
1294
1295static int
1296exec_clear(struct op_clearmodifier *opcm)
1297{
1298 return (ClearModifier (&map, opcm->modifier));
1299}
1300
1301
1302static int
1303exec_pointer(struct op_pointer *opp)
1304{
1305 return (SetPointerMap (opp->button_codes, opp->count));
1306}
1307
1308void
1309print_modifier_map(void)
1310{
1311 PrintModifierMapping (map, stdout__stdoutp);
1312 return;
1313}
1314
1315void
1316print_key_table(Boolint exprs)
1317{
1318 PrintKeyTable (exprs, stdout__stdoutp);
1319 return;
1320}
1321
1322void
1323print_pointer_map(void)
1324{
1325 PrintPointerMap (stdout__stdoutp);
1326 return;
1327}
1328
1329