1 /*****
2 * Xnee's Not an Event Emulator
3 *
4 * Xnee enables recording and replaying of X protocol data
5 *
6 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
7 * 2005, 2006, 2007, 2009, 2010
8 * Henrik Sandklef
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 3
13 * of the License, or any later version.
14 *
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Boston,
24 * MA 02110-1301, USA.
25 ****/
26
27
28
29
30
31
32 /* Standard includes */
33 #include <stdio.h>
34
35 #include "libxnee/xnee.h"
36 #include "libxnee/print.h"
37 #include "libxnee/xnee_dl.h"
38 #include "libxnee/xnee_sem.h"
39 #include "libxnee/xnee_setget.h"
40 #include "libxnee/xnee_resolution.h"
41 #include "libxnee/xnee_resource.h"
42 #include "libxnee/xnee_grab.h"
43 #include "libxnee/xnee_km.h"
44 #include "libxnee/datastrings.h"
45 #include "libxnee/xnee_range.h"
46 #include "libxnee/xnee_session.h"
47 #include "libxnee/xnee_alloc.h"
48
49
50 static struct xnee_ranges myxrs ;
51 static int need_init = 1 ;
52 static int added_reparent = 0 ;
53 struct xnee_ranges *xrs = &myxrs ;
54
55 static int
56 xnee_add_to_list2(xnee_data *xd, int type, int ev);
57
58 int
59 xnee_add_range (xnee_data* xd, int type,
60 int start, int stop);
61 int
62 xnee_rem_from_list(xnee_data *xd, int type, int ev);
63
64 static int
xnee_do_workaround(xnee_data * xd)65 xnee_do_workaround(xnee_data *xd)
66 {
67 int ret = XNEE_OK;
68 int active_state;
69
70 if ( xnee_is_type_nr_set(xd, XNEE_DELIVERED_EVENT, ReparentNotify))
71 {
72 xnee_set_new_window_pos(xd);
73 }
74 else
75 {
76 active_state = xd->record_setup->active;
77
78 xnee_add_to_list2(xd, XNEE_DELIVERED_EVENT, ReparentNotify);
79 /* Reset active state, since we don't want to record anything
80 * if nothing specified.
81 * We don't want to record the ReparentNotify (as added to
82 * achieve new window pos only)....
83 */
84 xd->record_setup->active = active_state ;
85 added_reparent = 1 ;
86 }
87 return ret;
88 }
89
90 static int
xnee_undo_workaround(xnee_data * xd)91 xnee_undo_workaround(xnee_data *xd)
92 {
93 int ret = XNEE_OK;
94 int w_pos= xnee_get_new_window_pos(xd);
95
96 if (added_reparent)
97 {
98 xnee_rem_from_list(xd, XNEE_DELIVERED_EVENT, ReparentNotify);
99 added_reparent = 0 ;
100 }
101
102 if (w_pos > 0)
103 {
104 xnee_unset_new_window_pos(xd);
105 }
106
107 return ret;
108 }
109
110
111 /**************************************************************
112 * *
113 * xnee_null_range *
114 * *
115 * *
116 **************************************************************/
117 void
xnee_null_range(XRecordRange * range)118 xnee_null_range ( XRecordRange *range)
119 {
120 memset (range, 0, sizeof(XRecordRange));
121 /* There seems to be something spooky about setting
122 errors to first=last=0
123 This solves the X server crashes that has been around for a while */
124 /*
125 range->errors.first = BadCursor;
126 range->errors.last = BadCursor;
127 */
128 }
129
130 static int
xnee_bsort(int * numbers,int size)131 xnee_bsort(int *numbers, int size)
132 {
133 int i;
134 int j;
135 int temp;
136
137 for (i = (size - 1); i >= 0; i--)
138 {
139 for (j = 1; j <= i; j++)
140 {
141 if (numbers[j-1] > numbers[j])
142 {
143 temp = numbers[j-1];
144 numbers[j-1] = numbers[j];
145 numbers[j] = temp;
146 }
147 }
148 }
149 return XNEE_OK;
150 }
151
152 static int
xnee_bsort_all(void)153 xnee_bsort_all(void)
154 {
155 int i ;
156 for (i=0;i<XNEE_NR_OF_TYPES;i++)
157 {
158 xnee_bsort (xrs->type[i].data, xrs->type[i].index);
159 }
160 return XNEE_OK;
161 }
162
163
164 static int
xnee_init_list(struct xnee_range * xr,int size)165 xnee_init_list(struct xnee_range *xr, int size)
166 {
167 /* printf ("\t'%s' need=%d\n", */
168 /* __func__, need_init); */
169 xr->index = 0;
170 xr->size = size;
171 xr->data = (int*) malloc (xr->size*sizeof(int));
172 /* printf (" xr->data = %d\n", xr->data); */
173 return XNEE_OK;
174 }
175
176 int
xnee_free_ranges(xnee_data * xd)177 xnee_free_ranges(xnee_data *xd)
178 {
179 int i ;
180
181 xnee_verbose((xd, " -- xnee_free_ranges\n"));
182
183 for (i=0;i<XNEE_NR_OF_TYPES;i++)
184 {
185 XNEE_FREE_AND_NULL(xrs->type[i].data);
186 xrs->type[i].data = NULL;
187 xrs->type[i].index = 0;
188 }
189 need_init = 1 ;
190
191 return XNEE_OK;
192 }
193
194 int
xnee_init_ranges()195 xnee_init_ranges()
196 {
197 int i ;
198 xrs->alloc_size = 5;
199
200 /* printf ("--->'%s' init ranges need=%d\n", */
201 /* __func__, need_init); */
202
203 for (i=0;i<XNEE_NR_OF_TYPES;i++)
204 {
205 xnee_init_list (&xrs->type[i], xrs->alloc_size);
206 }
207 need_init = 0 ;
208 /* printf ("<---'%s' init ranges need=%d\n", */
209 /* __func__, need_init); */
210 return XNEE_OK;
211 }
212
213
214 int
xnee_refresh_ranges(xnee_data * xd)215 xnee_refresh_ranges(xnee_data *xd)
216 {
217 xnee_verbose((xd, "-->xnee_refresh_ranges\n"));
218 xnee_free_ranges(xd);
219 xnee_init_ranges();
220 xrs->nr_of_data = 0;
221 xnee_verbose((xd, "<--xnee_refresh_ranges\n"));
222 return XNEE_OK;
223 }
224
225 int
xnee_print_list(void)226 xnee_print_list(void)
227 {
228 int i ;
229 int j ;
230
231 for (i=0;i<XNEE_NR_OF_TYPES;i++)
232 {
233 printf ("%d:[", i);
234 for (j=0; j<xrs->type[i].index ;j++)
235 {
236 printf ("%.3d", xrs->type[i].data[j]);
237
238 if (j!=xrs->type[i].index-1)
239 printf (",");
240 }
241 printf ("]\n");
242 }
243 printf ("\n");
244 return XNEE_OK;
245 }
246
247
248 static int
xnee_add_to_list2(xnee_data * xd,int type,int ev)249 xnee_add_to_list2(xnee_data *xd, int type, int ev)
250 {
251 int i ;
252 struct xnee_range *xrp;
253
254 /* An item is added, set recording active */
255 xd->record_setup->active = 1;
256
257 if (type==XNEE_EVENT)
258 {
259 if ((ev>=KeyPress)&&(ev<=MotionNotify))
260 {
261 type=XNEE_DEVICE_EVENT;
262 }
263 else
264 {
265 type=XNEE_DELIVERED_EVENT;
266 }
267 }
268 xrp = &xrs->type[type];
269
270 if (need_init==1)
271 {
272 xnee_init_ranges();
273 }
274
275 for (i=0;i<xrp->index;i++)
276 {
277 if (xrp->data[i]==ev)
278 {
279 return XNEE_OK;
280 }
281 }
282
283 if (xrp->index >=(xrp->size-1) )
284 {
285 xrp->size+=xrp->size;
286
287 xrp->data = (int*) realloc (xrp->data,
288 xrp->size*sizeof(int));
289 if (xrp->data==NULL)
290 {
291 fprintf (stderr, " PANIC in xnee_add_to_list2 ....\n") ;
292 fflush(stdout);
293 return XNEE_MEMORY_FAULT;
294 }
295 }
296 xrp->data[xrp->index++]=ev;
297
298 return XNEE_OK;
299 }
300
301 /**************************************************************
302 * *
303 * xnee_add_range_str *
304 * *
305 * *
306 **************************************************************/
307 int
xnee_add_range_str(xnee_data * xd,int type,char * range)308 xnee_add_range_str (xnee_data *xd, int type, char *range)
309 {
310 char start_str[XNEE_RANGE_STRING_SIZE] ;
311 char *second;
312 int start=0;
313 int stop=0;
314 int str_len=0;
315 int ret=0;
316 int i ;
317 xnee_verbose((xd, " --> add_range_str (%p, %d, %s)\n",
318 (void*)xd,type, range));
319 str_len=strspn(range, "1234567890-");
320
321
322 if ( str_len > XNEE_RANGE_STRING_SIZE )
323 {
324 fprintf (stderr, "The string you wanted to add is too long\n");
325 fprintf (stderr, "Ranges can't be longer then %d characters\n",
326 XNEE_RANGE_STRING_SIZE);
327 return -1;
328 }
329
330 if (str_len==0)
331 {
332 str_len=
333 strspn(range,
334 "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_");
335 strncpy(start_str,range,str_len);
336 start_str[str_len]='\0';
337 start=xnee_data2int (type, start_str);
338 if (start==-1)
339 {
340 fprintf(stderr,
341 "Could not convert \"%s\" to an integer\nleaving",
342 start_str);
343 return -1;
344 }
345 }
346 else
347 {
348 strncpy(start_str,range,str_len);
349 start_str[str_len]='\0';
350 sscanf(start_str,"%d",&start);
351 }
352 xnee_verbose((xd,
353 " -- add_range_str first string=\"%s\" (%d)\n",
354 start_str, start));
355
356
357 second=strchr ( range, '-' ) ;
358 if (second)
359 {
360 int ret;
361 second++;
362 ret=sscanf(second,"%d",&stop);
363 if (ret==0)
364 {
365 stop=xnee_data2int (type, second);
366 if (stop==-1)
367 {
368 fprintf(stderr,
369 "Could not convert \"%s\" to an integer\nleaving",
370 second);
371 return -1;
372 }
373 }
374 xnee_verbose((xd, " -- add_range_str second string=\"%s\" ret=%d\n",
375 second, ret));
376 }
377
378 xnee_verbose((xd, " -- add_range_str 1 %d %d \n" ,
379 start, stop));
380 if ( (start>=0) && (stop>=0) )
381 {
382 if ( (start!=stop) && (start<stop) )
383 {
384 for (i=start;i<=stop;i++)
385 {
386 ret = xnee_add_to_list2(xd, type, i);
387 }
388 }
389 else if (start!=0)
390 {
391 xnee_verbose((xd, " -- add_range_str 4\n" ));
392 ret = xnee_add_to_list2(xd, type, start);
393 }
394 else if ( (start==0) && (stop==0) )
395 {
396 ret = XNEE_OK;
397 }
398 else
399 {
400 ret = XNEE_RANGE_FAILURE ;
401 }
402 }
403
404 xnee_verbose((xd, " <-- add_range_str (%p, %d, %s) max range=%d\n",
405 (void*)xd,type, range, xnee_get_max_range(xd)));
406
407 return (ret);
408 }
409
410
411 static int
xnee_device_as_delivered(xnee_data * xd)412 xnee_device_as_delivered(xnee_data *xd)
413 {
414 int ret_val = 0;
415
416 if (xd!=NULL)
417 {
418 if ( (xd->x_vendor_name != NULL ) &&
419 (strstr(xd->x_vendor_name, "X.Org") ))
420 {
421 if ( ( xd->x_version_major == 1 ) &&
422 ( xd->x_version_minor >= 6 ) &&
423 ( xd->x_version_minor < 9 ) )
424 {
425 ret_val = 1;
426 }
427 }
428 }
429 return ret_val;
430 }
431
432
433
434 static int
is_dangerous_xserver(xnee_data * xd)435 is_dangerous_xserver(xnee_data *xd)
436 {
437 int ret_val = 1;
438 if (xd==NULL)
439 {
440 return XNEE_MEMORY_FAULT;
441 }
442
443 if (xd->x_vendor_name==NULL)
444 {
445 xnee_set_x_server_version(xd);
446 }
447
448 if (strstr(xd->x_vendor_name, "X.Org") )
449 {
450
451 if ( ( ( xd->x_version_major == 7 ) ||
452 ( xd->x_version_major == 1 ) ) &&
453 ( xd->x_version_minor >= 1 ) )
454 {
455 ret_val = 0;
456 }
457 }
458 return ret_val;
459 }
460
461
462
463 /**************************************************************
464 * *
465 * xnee_add_range *
466 * *
467 * *
468 **************************************************************/
469 int
xnee_add_range(xnee_data * xd,int type,int start,int stop)470 xnee_add_range (xnee_data* xd,
471 int type,
472 int start,
473 int stop)
474 {
475 XRecordRange *range;
476 int max_index=0;
477 int alloc_nr=0;
478
479 XRecordRange *r_range;
480 xnee_verbose((xd, "---> xnee_add_range %d %d %d\n", type, start, stop));
481
482 /* increment the counter to ensure we allocate enough memory */
483 alloc_nr=xd->xnee_info.data_ranges[type] ;
484 max_index=xnee_get_max_range(xd) - 1 ;
485
486 xnee_verbose((xd, " MAX %d ALLOC %d\n", max_index, alloc_nr));
487
488 if (alloc_nr>max_index)
489 {
490 xnee_verbose((xd, " -- Allocating a new range of size %d\n",
491 alloc_nr+1));
492
493 if ( alloc_nr == 0 )
494 {
495 xd->record_setup->range_array =
496 (XRecordRange**) Xcalloc (1, sizeof(XRecordRange*));
497 }
498 else
499 {
500 xd->record_setup->range_array =
501 (XRecordRange**) Xrealloc (xd->record_setup->range_array,
502 (alloc_nr+1)*sizeof(XRecordRange*));
503 }
504 r_range = XRecordAllocRange();
505
506 xnee_null_range (r_range);
507 xd->record_setup->range_array[alloc_nr] = r_range;
508 }
509
510
511 /* is it single value */
512 if (stop==0)
513 {
514 stop=start;
515 }
516 xnee_verbose((xd,
517 "Adding %d range %d - %d at range %d\n",
518 type, start, stop, alloc_nr));
519
520 range = xd->record_setup->range_array[alloc_nr];
521
522 if ( type == XNEE_DELIVERED_EVENT )
523 {
524 range->delivered_events.first = start;
525 range->delivered_events.last = stop;
526
527
528 if ( is_dangerous_xserver(xd) )
529 {
530 fprintf(stderr, "Workaround: Adding some errors to recored to prevent crash\n");
531 fprintf(stderr, " You can ignore this message\n");
532 /* Workaround for problem with crashing X server */
533 xd->xnee_info.data_ranges[XNEE_ERROR]++;
534 range->errors.first = BadCursor;
535 range->errors.last = BadCursor;
536 }
537 }
538 else if ( type == XNEE_REQUEST )
539 {
540 range->core_requests.first = start;
541 range->core_requests.last = stop;
542 }
543 else if ( type == XNEE_ERROR )
544 {
545 range->errors.first = start;
546 range->errors.last = stop;
547
548 /* Workaround for problem with crashing X server*/
549 range->delivered_events.first =33 ;
550 range->delivered_events.last = 33;
551 xd->xnee_info.data_ranges[XNEE_DELIVERED_EVENT]++;
552 }
553 else if ( type == XNEE_REPLY )
554 {
555 range->core_replies.first = start;
556 range->core_replies.last = stop;
557 }
558 else if ( type == XNEE_EXT_REQUEST_MAJOR )
559 {
560 range->ext_requests.ext_major.first = start;
561 range->ext_requests.ext_major.last = stop;
562 }
563 else if ( type == XNEE_EXT_REQUEST_MINOR )
564 {
565 range->ext_requests.ext_minor.first = start;
566 range->ext_requests.ext_minor.last = stop;
567 }
568 else if ( type == XNEE_EXT_REPLY_MAJOR )
569 {
570 range->ext_replies.ext_major.first = start;
571 range->ext_replies.ext_major.last = stop;
572 }
573 else if ( type == XNEE_EXT_REPLY_MINOR )
574 {
575 range->ext_replies.ext_minor.first = start;
576 range->ext_replies.ext_minor.last = stop;
577 }
578 else if ( type == XNEE_DEVICE_EVENT )
579 {
580 range->device_events.first = start;
581 range->device_events.last = stop;
582
583 /*
584 * WORKAROUND
585 *
586 * xnee doesn't record on some servers
587 * unless device evs are added as deliv. evs :(
588 *
589 */
590 if ( xnee_device_as_delivered(xd))
591 {
592 fprintf(stderr, "Workaround: Adding your device events as delivered events to get them recorded.\n");
593 fprintf(stderr, " You can ignore this message\n");
594 xnee_add_range(xd,
595 XNEE_DELIVERED_EVENT,
596 start ,
597 stop);
598 }
599 else
600 {
601 /* the work around above should probably be removed any time ... errrh */
602 fprintf(stderr, "NOTIFICATION: If you have problem with Xnee and recording device events: File a bug report including this text.\n");
603 }
604
605 }
606
607
608 /*
609 * Used when debugging
610 * print_data_range_count (xnee_info, rec_range);
611 *
612 */
613 xd->xnee_info.data_ranges[type]++;
614 xnee_verbose((xd, "<--- xnee_add_range\n"));
615
616 /* xnee_record_print_record_range(xd, stderr); */
617
618 return (XNEE_OK);
619 }
620
621
622 /**************************************************************
623 * *
624 * xnee_parse_range *
625 * *
626 * *
627 **************************************************************/
628 int
xnee_parse_range(xnee_data * xd,int type,char * range)629 xnee_parse_range (xnee_data *xd,int type, char *range)
630 {
631 char buf[DATA_NAME_SIZE_MAX];
632 int next;
633 int ret=0;
634 int range_len=strlen(range);
635
636 /* */
637
638 xnee_verbose ((xd, "int arg=%p\n", (void*)xd));
639 xnee_verbose ((xd, "nt arg=%d\n", type));
640 xnee_verbose ((xd, "string arg=%s\n", range));
641
642 while ( 1 )
643 {
644 next=strspn (range, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_");
645 if (next==0)
646 {
647 ret = XNEE_RANGE_FAILURE;
648 break;
649 }
650 strncpy(buf,range,next);
651 buf[next]='\0';
652 range+=next+1;
653 range_len=range_len - next - 1;
654 xnee_verbose((xd, " -- calling xnee_add_range_str (%p, %d, %s) \n" , (void*)xd, type, buf));
655
656 ret=xnee_add_range_str (xd, type, buf);
657
658 if (ret == XNEE_RANGE_FAILURE )
659 {
660 ret = XNEE_RANGE_FAILURE;
661 break;
662 }
663 if (range_len<=0)
664 {
665 break;
666 }
667 if (ret!=XNEE_OK) return (ret);
668 }
669
670 xnee_verbose((xd, "<-- parse_range()\n"));
671 return ret;
672 }
673
674
675
676
677
678 int
xnee_get_nr_of_data(int type)679 xnee_get_nr_of_data (int type)
680 {
681 if (xrs->type==NULL)
682 {
683 return -1;
684 }
685 else
686 {
687 /*
688 * We're not going to record if only ReparentNotify are recorded
689 */
690 if ( ( type == XNEE_DELIVERED_EVENT )
691 &&
692 ( xrs->type[type].index == 1)
693 &&
694 ( xrs->type[type].data[0] == ReparentNotify))
695 {
696 return 0;
697 }
698 else
699 {
700 return xrs->type[type].index;
701 }
702 }
703 }
704
705 int *
xnee_get_data(int type)706 xnee_get_data (int type)
707 {
708 if (xrs->type==NULL)
709 {
710 return NULL;
711 }
712 else
713 {
714 return xrs->type[type].data;
715 }
716 }
717
718 int
xnee_is_type_nr_set(xnee_data * xd,int type,int nr)719 xnee_is_type_nr_set(xnee_data *xd, int type, int nr)
720 {
721 int i ;
722
723 xnee_verbose((xd, " -- xnee_is_type_nr_set\n"));
724 for (i=0; i<xrs->type[type].index ;i++)
725 {
726 if ( xrs->type[type].data[i] == nr )
727 {
728 return True;
729 }
730 }
731
732 return False;
733 }
734
735
736 int
xnee_set_ranges(xnee_data * xd)737 xnee_set_ranges(xnee_data *xd)
738 {
739 int i ;
740 int j ;
741 int first = -1;
742 int last = -1;
743 int this ;
744
745
746 xnee_bsort_all();
747
748 if (xnee_is_replayer(xd))
749 {
750 xnee_undo_workaround(xd);
751 xnee_do_workaround(xd);
752 }
753
754 for (j=0; j<XNEE_NR_OF_TYPES ;j++)
755 {
756 first = -1;
757 last = -1;
758
759 for (i=0; i<xrs->type[j].index ;i++)
760 {
761
762 this = xrs->type[j].data[i] ;
763
764 if (first == -1)
765 {
766 first=this;
767 last=this;
768 }
769 else if ( this == last + 1 )
770 {
771 last = this;
772 }
773 else
774 {
775 xnee_add_range (xd, j,
776 first,
777 last);
778
779 first=this;
780 last=this;
781 }
782 }
783 if (first!=-1)
784 {
785 if (last!=-1)
786 {
787 xnee_add_range (xd, j,
788 first,
789 last);
790 }
791 else
792 {
793 xnee_add_range (xd, j,
794 first,
795 first);
796 }
797 }
798 }
799
800 return XNEE_OK;
801 }
802
803
804
805 int
xnee_rem_from_list(xnee_data * xd,int type,int ev)806 xnee_rem_from_list(xnee_data *xd, int type, int ev)
807 {
808 int i ;
809 int j ;
810
811 struct xnee_range *xrp;
812
813 xnee_verbose((xd, " -- xnee_rem_from_list\n"));
814
815 if (need_init==1)
816 {
817 return XNEE_OK;
818 }
819
820 xrp = &xrs->type[type];
821
822
823 for (i=0;i<xrp->index;i++)
824 {
825 if ( xrp->data[i] == ev )
826 {
827 for (j=i;j<xrp->index;j++)
828 {
829 if (j==xrp->index-1)
830 {
831 xrp->data[j]=0;
832 }
833 else
834 {
835 xrp->data[j]=xrp->data[j+1];
836 }
837 }
838 xrp->index--;
839 }
840 }
841
842 return XNEE_OK;
843 }
844
845
846 int*
xnee_get_list(int type)847 xnee_get_list(int type)
848 {
849 if (need_init==1)
850 return NULL;
851
852 if (type==0)
853 {
854 return xrs->type[type].data;
855 }
856 return XNEE_OK;
857 }
858
859
860
861 int
xnee_rem_data_from_range_str(xnee_data * xd,int type,char * name)862 xnee_rem_data_from_range_str (xnee_data *xd,
863 int type,
864 char *name)
865 {
866 int rem_data ;
867 int my_type;
868
869 if (type == -1)
870 {
871 rem_data = xnee_data2int_special(&my_type, name);
872 type = my_type ;
873 }
874 else
875 {
876 rem_data = xnee_data2int(type, name);
877 }
878
879 if (rem_data == -1)
880 {
881 return -1;
882 }
883
884 xnee_verbose ((xd, "xnee range removing : %d of type %d\n",
885 rem_data, type ));
886 xnee_rem_from_list(xd, type, rem_data);
887
888
889 return XNEE_OK;
890 }
891
892
893
894
895