Bug Summary

File:property.c
Location:line 691, column 17
Description:Potential leak of memory pointed to by 'data.c'

Annotated Source Code

1/*
2 * Copyright © 2007 Peter Hutterer
3 * Copyright © 2009 Red Hat, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <ctype.h>
26#include <string.h>
27#include <stdlib.h>
28#include <stdint.h>
29#include <X11/Xatom.h>
30#include <X11/extensions/XIproto.h>
31
32#include "xinput.h"
33
34static Atom parse_atom(Display *dpy, char *name) {
35 Boolint is_atom = True1;
36 int i;
37
38 for (i = 0; name[i] != '\0'; i++) {
39 if (!isdigit(name[i])) {
40 is_atom = False0;
41 break;
42 }
43 }
44
45 if (is_atom)
46 return atoi(name);
47 else
48 return XInternAtom(dpy, name, False0);
49}
50
51static void
52print_property(Display *dpy, XDevice* dev, Atom property)
53{
54 Atom act_type;
55 char *name;
56 int act_format;
57 unsigned long nitems, bytes_after;
58 unsigned char *data, *ptr;
59 int j, done = False0, size = 0;
60
61 name = XGetAtomName(dpy, property);
62 printf("\t%s (%ld):\t", name, property);
63 XFree(name);
64
65 if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False0,
66 AnyPropertyType0L, &act_type, &act_format,
67 &nitems, &bytes_after, &data) == Success0)
68 {
69 Atom float_atom = XInternAtom(dpy, "FLOAT", True1);
70
71 ptr = data;
72
73 if (nitems == 0)
74 printf("<no items>");
75
76 switch(act_format)
77 {
78 case 8: size = sizeof(char); break;
79 case 16: size = sizeof(short); break;
80 case 32: size = sizeof(long); break;
81 }
82
83 for (j = 0; j < nitems; j++)
84 {
85 switch(act_type)
86 {
87 case XA_INTEGER((Atom) 19):
88 switch(act_format)
89 {
90 case 8:
91 printf("%d", *((char*)ptr));
92 break;
93 case 16:
94 printf("%d", *((short*)ptr));
95 break;
96 case 32:
97 printf("%ld", *((long*)ptr));
98 break;
99 }
100 break;
101 case XA_CARDINAL((Atom) 6):
102 switch(act_format)
103 {
104 case 8:
105 printf("%u", *((unsigned char*)ptr));
106 break;
107 case 16:
108 printf("%u", *((unsigned short*)ptr));
109 break;
110 case 32:
111 printf("%lu", *((unsigned long*)ptr));
112 break;
113 }
114 break;
115 case XA_STRING((Atom) 31):
116 if (act_format != 8)
117 {
118 printf("Unknown string format.\n");
119 done = True1;
120 break;
121 }
122 printf("\"%s\"", ptr);
123 j += strlen((char*)ptr); /* The loop's j++ jumps over the
124 terminating 0 */
125 ptr += strlen((char*)ptr); /* ptr += size below jumps over
126 the terminating 0 */
127 break;
128 case XA_ATOM((Atom) 4):
129 {
130 Atom a = *(Atom*)ptr;
131 name = (a) ? XGetAtomName(dpy, a) : NULL((void*)0);
132 printf("\"%s\" (%d)", name ? name : "None", (int)a);
133 XFree(name);
134 break;
135 }
136 default:
137 if (float_atom != None0L && act_type == float_atom)
138 {
139 printf("%f", *((float*)ptr));
140 break;
141 }
142
143 name = XGetAtomName(dpy, act_type);
144 printf("\t... of unknown type '%s'\n", name);
145 XFree(name);
146 done = True1;
147 break;
148 }
149
150 ptr += size;
151
152 if (done == True1)
153 break;
154 if (j < nitems - 1)
155 printf(", ");
156 }
157 printf("\n");
158 XFree(data);
159 } else
160 printf("\tFetch failure\n");
161
162}
163
164static int
165list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
166{
167 XDeviceInfo *info;
168 XDevice *dev;
169 int i;
170 int nprops;
171 Atom *props;
172 int rc = EXIT_SUCCESS0;
173
174 if (argc == 0)
175 {
176 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc);
177 return EXIT_FAILURE1;
178 }
179
180 for (i = 0; i < argc; i++)
181 {
182 info = find_device_info(dpy, argv[i], False0);
183 if (!info)
184 {
185 fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[i]);
186 rc = EXIT_FAILURE1;
187 continue;
188 }
189
190 dev = XOpenDevice(dpy, info->id);
191 if (!dev)
192 {
193 fprintf(stderr__stderrp, "unable to open device '%s'\n", info->name);
194 rc = EXIT_FAILURE1;
195 continue;
196 }
197
198 props = XListDeviceProperties(dpy, dev, &nprops);
199 if (!nprops)
200 {
201 printf("Device '%s' does not report any properties.\n", info->name);
202 continue;
203 }
204
205 printf("Device '%s':\n", info->name);
206 while(nprops--)
207 {
208 print_property(dpy, dev, props[nprops]);
209 }
210
211 XFree(props);
212 XCloseDevice(dpy, dev);
213 }
214 return rc;
215}
216
217
218int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc)
219{
220 XDevice *dev;
221 XDeviceInfo *info;
222 XEvent ev;
223 XDevicePropertyNotifyEvent *dpev;
224 char *name;
225 int type_prop;
226 XEventClass cls_prop;
227
228 if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS0)
229 return EXIT_FAILURE1;
230
231 info = find_device_info(dpy, argv[0], False0);
232 if (!info)
233 {
234 fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[0]);
235 return EXIT_FAILURE1;
236 }
237
238 dev = XOpenDevice(dpy, info->id);
239 if (!dev)
240 {
241 fprintf(stderr__stderrp, "unable to open device '%s'\n", info->name);
242 return EXIT_FAILURE1;
243 }
244
245 DevicePropertyNotify(dev, type_prop, cls_prop){ int _i; XInputClassInfo *_ip; type_prop = 0; cls_prop = 0; for
(_i=0, _ip= ((XDevice *) dev)->classes; _i< ((XDevice *
) dev)->num_classes; _i++, _ip++) if (_ip->input_class ==
6) {type_prop = _ip->event_type_base + 6; cls_prop = ((XDevice
*) dev)->device_id << 8 | type_prop;}}
;
246 XSelectExtensionEvent(dpy, DefaultRootWindow(dpy)((&((_XPrivDisplay)(dpy))->screens[(((_XPrivDisplay)(dpy
))->default_screen)])->root)
, &cls_prop, 1);
247
248 while(1)
249 {
250 XNextEvent(dpy, &ev);
251
252 dpev = (XDevicePropertyNotifyEvent*)&ev;
253 if (dpev->type != type_prop)
254 continue;
255
256 name = XGetAtomName(dpy, dpev->atom);
257 printf("Property '%s' changed.\n", name);
258 XFree(name);
259 print_property(dpy, dev, dpev->atom);
260 }
261
262 XCloseDevice(dpy, dev);
263}
264
265static int
266delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc)
267{
268 XDevice *dev;
269 XDeviceInfo *info;
270 char *name;
271 Atom prop;
272
273 info = find_device_info(dpy, argv[0], False0);
274 if (!info)
275 {
276 fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[0]);
277 return EXIT_FAILURE1;
278 }
279
280 dev = XOpenDevice(dpy, info->id);
281 if (!dev)
282 {
283 fprintf(stderr__stderrp, "unable to open device '%s'\n", info->name);
284 return EXIT_FAILURE1;
285 }
286
287 name = argv[1];
288
289 prop = parse_atom(dpy, name);
290
291 XDeleteDeviceProperty(dpy, dev, prop);
292
293 XCloseDevice(dpy, dev);
294 return EXIT_SUCCESS0;
295}
296
297static int
298do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
299{
300 XDeviceInfo *info;
301 XDevice *dev;
302 Atom prop;
303 Atom old_type;
304 char *name;
305 int i;
306 Atom float_atom;
307 int old_format, nelements = 0;
308 unsigned long act_nitems, bytes_after;
309 char *endptr;
310 union {
311 unsigned char *c;
312 short *s;
313 long *l;
314 Atom *a;
315 } data;
316
317 if (argc < 3)
318 {
319 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", n, desc);
320 return EXIT_FAILURE1;
321 }
322
323 info = find_device_info(dpy, argv[0], False0);
324 if (!info)
325 {
326 fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[0]);
327 return EXIT_FAILURE1;
328 }
329
330 dev = XOpenDevice(dpy, info->id);
331 if (!dev)
332 {
333 fprintf(stderr__stderrp, "unable to open device '%s'\n", argv[0]);
334 return EXIT_FAILURE1;
335 }
336
337 name = argv[1];
338
339 prop = parse_atom(dpy, name);
340
341 if (prop == None0L) {
342 fprintf(stderr__stderrp, "invalid property '%s'\n", name);
343 return EXIT_FAILURE1;
344 }
345
346 float_atom = XInternAtom(dpy, "FLOAT", False0);
347
348 nelements = argc - 2;
349 if (type == None0L || format == 0) {
350 if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False0, AnyPropertyType0L,
351 &old_type, &old_format, &act_nitems,
352 &bytes_after, &data.c) != Success0) {
353 fprintf(stderr__stderrp, "failed to get property type and format for '%s'\n",
354 name);
355 return EXIT_FAILURE1;
356 } else {
357 if (type == None0L)
358 type = old_type;
359 if (format == 0)
360 format = old_format;
361 }
362
363 XFree(data.c);
364 }
365
366 if (type == None0L) {
367 fprintf(stderr__stderrp, "property '%s' doesn't exist, you need to specify "
368 "its type and format\n", name);
369 return EXIT_FAILURE1;
370 }
371
372 data.c = calloc(nelements, sizeof(long));
373
374 for (i = 0; i < nelements; i++)
375 {
376 if (type == XA_INTEGER((Atom) 19) || type == XA_CARDINAL((Atom) 6)) {
377 switch (format)
378 {
379 case 8:
380 data.c[i] = atoi(argv[2 + i]);
381 break;
382 case 16:
383 data.s[i] = atoi(argv[2 + i]);
384 break;
385 case 32:
386 data.l[i] = atoi(argv[2 + i]);
387 break;
388 default:
389 fprintf(stderr__stderrp, "unexpected size for property '%s'", name);
390 return EXIT_FAILURE1;
391 }
392 } else if (type == float_atom) {
393 if (format != 32) {
394 fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n",
395 format, name);
396 return EXIT_FAILURE1;
397 }
398 *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
399 if (endptr == argv[2 + i]) {
400 fprintf(stderr__stderrp, "argument '%s' could not be parsed\n", argv[2 + i]);
401 return EXIT_FAILURE1;
402 }
403 } else if (type == XA_ATOM((Atom) 4)) {
404 if (format != 32) {
405 fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n",
406 format, name);
407 return EXIT_FAILURE1;
408 }
409 data.a[i] = parse_atom(dpy, argv[2 + i]);
410 } else {
411 fprintf(stderr__stderrp, "unexpected type for property '%s'\n", name);
412 return EXIT_FAILURE1;
413 }
414 }
415
416 XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace0,
417 data.c, nelements);
418 free(data.c);
419 XCloseDevice(dpy, dev);
420 return EXIT_SUCCESS0;
421}
422
423#if HAVE_XI21
424static void
425print_property_xi2(Display *dpy, int deviceid, Atom property)
426{
427 Atom act_type;
428 char *name;
429 int act_format;
430 unsigned long nitems, bytes_after;
431 unsigned char *data, *ptr;
432 int j, done = False0;
433
434 name = XGetAtomName(dpy, property);
435 printf("\t%s (%ld):\t", name, property);
436 XFree(name);
437
438 if (XIGetProperty(dpy, deviceid, property, 0, 1000, False0,
439 AnyPropertyType0L, &act_type, &act_format,
440 &nitems, &bytes_after, &data) == Success0)
441 {
442 Atom float_atom = XInternAtom(dpy, "FLOAT", True1);
443
444 ptr = data;
445
446 if (nitems == 0)
447 printf("<no items>");
448
449 for (j = 0; j < nitems; j++)
450 {
451 switch(act_type)
452 {
453 case XA_INTEGER((Atom) 19):
454 switch(act_format)
455 {
456 case 8:
457 printf("%d", *((int8_t*)ptr));
458 break;
459 case 16:
460 printf("%d", *((int16_t*)ptr));
461 break;
462 case 32:
463 printf("%d", *((int32_t*)ptr));
464 break;
465 }
466 break;
467 case XA_CARDINAL((Atom) 6):
468 switch(act_format)
469 {
470 case 8:
471 printf("%u", *((uint8_t*)ptr));
472 break;
473 case 16:
474 printf("%u", *((uint16_t*)ptr));
475 break;
476 case 32:
477 printf("%u", *((uint32_t*)ptr));
478 break;
479 }
480 break;
481 case XA_STRING((Atom) 31):
482 if (act_format != 8)
483 {
484 printf("Unknown string format.\n");
485 done = True1;
486 break;
487 }
488 printf("\"%s\"", ptr);
489 j += strlen((char*)ptr); /* The loop's j++ jumps over the
490 terminating 0 */
491 ptr += strlen((char*)ptr); /* ptr += size below jumps over
492 the terminating 0 */
493 break;
494 case XA_ATOM((Atom) 4):
495 {
496 Atom a = *(uint32_t*)ptr;
497 name = (a) ? XGetAtomName(dpy, a) : NULL((void*)0);
498 printf("\"%s\" (%ld)", name ? name : "None", a);
499 XFree(name);
500 break;
501 }
502 break;
503 default:
504 if (float_atom != None0L && act_type == float_atom)
505 {
506 printf("%f", *((float*)ptr));
507 break;
508 }
509
510 name = XGetAtomName(dpy, act_type);
511 printf("\t... of unknown type %s\n", name);
512 XFree(name);
513 done = True1;
514 break;
515 }
516
517 ptr += act_format/8;
518
519 if (done == True1)
520 break;
521 if (j < nitems - 1)
522 printf(", ");
523 }
524 printf("\n");
525 XFree(data);
526 } else
527 printf("\tFetch failure\n");
528
529}
530
531static int
532list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc)
533{
534 XIDeviceInfo *info;
535 int i;
536 int nprops;
537 Atom *props;
538 int rc = EXIT_SUCCESS0;
539
540 if (argc == 0)
541 {
542 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc);
543 return EXIT_FAILURE1;
544 }
545
546 for (i = 0; i < argc; i++)
547 {
548 info = xi2_find_device_info(dpy, argv[i]);
549 if (!info)
550 {
551 fprintf(stderr__stderrp, "unable to find device %s\n", argv[i]);
552 rc = EXIT_FAILURE1;
553 continue;
554 }
555
556 props = XIListProperties(dpy, info->deviceid, &nprops);
557 if (!nprops)
558 {
559 printf("Device '%s' does not report any properties.\n", info->name);
560 continue;
561 }
562
563 printf("Device '%s':\n", info->name);
564 while(nprops--)
565 {
566 print_property_xi2(dpy, info->deviceid, props[nprops]);
567 }
568
569 XFree(props);
570 }
571 return rc;
572}
573
574static int
575delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc)
576{
577 XIDeviceInfo *info;
578 char *name;
579 Atom prop;
580
581 info = xi2_find_device_info(dpy, argv[0]);
582 if (!info)
583 {
584 fprintf(stderr__stderrp, "unable to find device %s\n", argv[0]);
585 return EXIT_FAILURE1;
586 }
587
588 name = argv[1];
589
590 prop = parse_atom(dpy, name);
591
592 XIDeleteProperty(dpy, info->deviceid, prop);
593
594 return EXIT_SUCCESS0;
595}
596
597static int
598do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
599{
600 XIDeviceInfo *info;
601 Atom prop;
602 Atom old_type;
603 char *name;
604 int i;
605 Atom float_atom;
606 int old_format, nelements = 0;
607 unsigned long act_nitems, bytes_after;
608 char *endptr;
609 union {
610 unsigned char *c;
611 int16_t *s;
612 int32_t *l;
613 } data;
614
615 if (argc < 3)
4
Assuming 'argc' is >= 3
5
Taking false branch
616 {
617 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", n, desc);
618 return EXIT_FAILURE1;
619 }
620
621 info = xi2_find_device_info(dpy, argv[0]);
622 if (!info)
6
Assuming 'info' is non-null
7
Taking false branch
623 {
624 fprintf(stderr__stderrp, "unable to find device %s\n", argv[0]);
625 return EXIT_FAILURE1;
626 }
627
628 name = argv[1];
629
630 prop = parse_atom(dpy, name);
631
632 if (prop == None0L) {
8
Assuming 'prop' is not equal to 0
9
Taking false branch
633 fprintf(stderr__stderrp, "invalid property '%s'\n", name);
634 return EXIT_FAILURE1;
635 }
636
637 float_atom = XInternAtom(dpy, "FLOAT", False0);
638
639 nelements = argc - 2;
640 if (type == None0L || format == 0) {
10
Taking false branch
641 if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False0,
642 AnyPropertyType0L, &old_type, &old_format, &act_nitems,
643 &bytes_after, &data.c) != Success0) {
644 fprintf(stderr__stderrp, "failed to get property type and format for '%s'\n",
645 name);
646 return EXIT_FAILURE1;
647 } else {
648 if (type == None0L)
649 type = old_type;
650 if (format == 0)
651 format = old_format;
652 }
653
654 XFree(data.c);
655 }
656
657 if (type == None0L) {
11
Taking false branch
658 fprintf(stderr__stderrp, "property '%s' doesn't exist, you need to specify "
659 "its type and format\n", name);
660 return EXIT_FAILURE1;
661 }
662
663 data.c = calloc(nelements, sizeof(int32_t));
12
Memory is allocated
664
665 for (i = 0; i < nelements; i++)
13
Loop condition is true. Entering loop body
666 {
667 if (type == XA_INTEGER((Atom) 19) || type == XA_CARDINAL((Atom) 6)) {
14
Taking false branch
668 switch (format)
669 {
670 case 8:
671 data.c[i] = atoi(argv[2 + i]);
672 break;
673 case 16:
674 data.s[i] = atoi(argv[2 + i]);
675 break;
676 case 32:
677 data.l[i] = atoi(argv[2 + i]);
678 break;
679 default:
680 fprintf(stderr__stderrp, "unexpected size for property %s", name);
681 return EXIT_FAILURE1;
682 }
683 } else if (type == float_atom) {
15
Assuming 'type' is equal to 'float_atom'
16
Taking true branch
684 if (format != 32) {
17
Taking false branch
685 fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n",
686 format, name);
687 return EXIT_FAILURE1;
688 }
689 *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
690 if (endptr == argv[2 + i]) {
18
Taking true branch
691 fprintf(stderr__stderrp, "argument %s could not be parsed\n", argv[2 + i]);
19
Potential leak of memory pointed to by 'data.c'
692 return EXIT_FAILURE1;
693 }
694 } else if (type == XA_ATOM((Atom) 4)) {
695 if (format != 32) {
696 fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n",
697 format, name);
698 return EXIT_FAILURE1;
699 }
700 data.l[i] = parse_atom(dpy, argv[2 + i]);
701 } else {
702 fprintf(stderr__stderrp, "unexpected type for property '%s'\n", name);
703 return EXIT_FAILURE1;
704 }
705 }
706
707 XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace0,
708 data.c, nelements);
709 free(data.c);
710 return EXIT_SUCCESS0;
711}
712#endif
713
714int list_props(Display *display, int argc, char *argv[], char *name,
715 char *desc)
716{
717#ifdef HAVE_XI21
718 if (xinput_version(display) == XI_2_Major2)
719 return list_props_xi2(display, argc, argv, name, desc);
720#endif
721 return list_props_xi1(display, argc, argv, name, desc);
722
723}
724
725int delete_prop(Display *display, int argc, char *argv[], char *name,
726 char *desc)
727{
728#ifdef HAVE_XI21
729 if (xinput_version(display) == XI_2_Major2)
730 return delete_prop_xi2(display, argc, argv, name, desc);
731#endif
732 return delete_prop_xi1(display, argc, argv, name, desc);
733
734}
735
736static int
737do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc)
738{
739#ifdef HAVE_XI21
740 if (xinput_version(display) == XI_2_Major2)
2
Taking true branch
741 return do_set_prop_xi2(display, type, format, argc, argv, name, desc);
3
Calling 'do_set_prop_xi2'
742#endif
743 return do_set_prop_xi1(display, type, format, argc, argv, name, desc);
744}
745
746int
747set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
748{
749 return do_set_prop(dpy, XA_ATOM((Atom) 4), 32, argc, argv, n, desc);
1
Calling 'do_set_prop'
750}
751
752int
753set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
754{
755 int i;
756 int format;
757
758 if (argc < 3)
759 {
760 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", n, desc);
761 return EXIT_FAILURE1;
762 }
763
764 format = atoi(argv[2]);
765 if (format != 8 && format != 16 && format != 32)
766 {
767 fprintf(stderr__stderrp, "Invalid format %d\n", format);
768 return EXIT_FAILURE1;
769 }
770
771 for (i = 3; i < argc; i++)
772 argv[i - 1] = argv[i];
773
774 return do_set_prop(dpy, XA_INTEGER((Atom) 19), format, argc - 1, argv, n, desc);
775}
776
777int
778set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
779{
780 Atom float_atom = XInternAtom(dpy, "FLOAT", False0);
781
782 if (sizeof(float) != 4)
783 {
784 fprintf(stderr__stderrp, "sane FP required\n");
785 return EXIT_FAILURE1;
786 }
787
788 return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc);
789}
790
791int set_prop(Display *display, int argc, char *argv[], char *name,
792 char *desc)
793{
794 Atom type = None0L;
795 int format = 0;
796 int i = 0, j;
797
798 while (i < argc) {
799 char *option = strchr(argv[i], '=');
800 /* skip non-option arguments */
801 if (strncmp(argv[i], "--", 2) || !option) {
802 i++;
803 continue;
804 }
805
806 if (!strncmp(argv[i], "--type=", strlen("--type="))) {
807 if (!strcmp(option + 1, "int")) {
808 type = XA_INTEGER((Atom) 19);
809 } else if (!strcmp(option + 1, "float")) {
810 type = XInternAtom(display, "FLOAT", False0);
811 format = 32;
812 } else if (!strcmp(option + 1, "atom")) {
813 type = XA_ATOM((Atom) 4);
814 format = 32;
815 } else {
816 fprintf(stderr__stderrp, "unknown property type %s\n", option + 1);
817 return EXIT_FAILURE1;
818 }
819 } else if (!strncmp(argv[i], "--format=", strlen("--format="))) {
820 format = atoi(option + 1);
821 if (format != 8 && format != 16 && format != 32) {
822 fprintf(stderr__stderrp, "invalid property format '%s'\n", option + 1);
823 return EXIT_FAILURE1;
824 }
825 } else {
826 fprintf(stderr__stderrp, "invalid option '%s'\n", argv[i]);
827 return EXIT_FAILURE1;
828 }
829
830 for (j = i; j + 1 < argc; j++)
831 argv[j] = argv[j + 1];
832 argc--;
833 }
834
835 return do_set_prop(display, type, format, argc, argv, name, desc);
836}
837
838int disable(Display *display, int argc, char *argv[], char *name, char *desc)
839{
840 char *new_argv[3] = { NULL((void*)0), "Device Enabled", "0" };
841
842 if (argc != 1) {
843 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc);
844 return EXIT_FAILURE1;
845 }
846
847 new_argv[0] = argv[0];
848
849 return set_prop(display, 3, new_argv, name, desc);
850}
851
852int enable(Display *display, int argc, char *argv[], char *name, char *desc)
853{
854 char *new_argv[3] = { NULL((void*)0), "Device Enabled", "1" };
855
856 if (argc != 1) {
857 fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc);
858 return EXIT_FAILURE1;
859 }
860
861 new_argv[0] = argv[0];
862
863 return set_prop(display, 3, new_argv, name, desc);
864}