1 /*****
2 * Xnee's Not an Event Emulator
3 *
4 * Xnee enables recording and replaying of X protocol data
5 *
6 * Copyright (C) 1999-2004, 2009-2011, 2013, 2014 Henrik Sandklef
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 3
11 * of the License, or any later version.
12 *
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Boston,
22 * MA 02110-1301, USA.
23 ****/
24
25 #include "libxnee/xnee.h"
26 #include "libxnee/xnee_internal.h"
27 #include "libxnee/xnee_error.h"
28 #include "libxnee/print_varargs.h"
29 #include "libxnee/xnee_range.h"
30 #include "libxnee/xnee_setget.h"
31 #include "libxnee/xnee_resource.h"
32 #include "libxnee/xnee_settings.h"
33 #include "libxnee/xnee_utils.h"
34
35
36
37
38 /**************************************************************
39 * *
40 * xnee_write_settings_to_file *
41 * *
42 * *
43 **************************************************************/
44 int
xnee_write_settings_to_file(xnee_data * xd,FILE * fp)45 xnee_write_settings_to_file (xnee_data *xd, FILE *fp)
46 {
47 int ret;
48
49 ret = xnee_set_ranges(xd);
50 XNEE_RETURN_IF_ERR(ret);
51
52 xnee_print_xnee_resource_settings (xd, fp) ;
53 xnee_print_xnee_settings (xd, fp) ;
54 xnee_print_ranges (xd, fp);
55 return XNEE_OK;
56 }
57
58
59
60
61 /**************************************************************
62 * *
63 * xnee_delay *
64 * *
65 * *
66 **************************************************************/
67 void
xnee_delay(int secs,char * mess)68 xnee_delay (int secs, char *mess)
69 {
70 int i;
71 int j;
72 int bytes_written = 0 ;
73 int last_written = 0 ;
74 size_t len = strlen (mess);
75 unsigned int sleep_int = 1 ;
76 unsigned int ret;
77
78 for ( i=secs ; i>-1 ; i-- )
79 {
80 if (len>0)
81 {
82 (void) fflush(stderr);
83 last_written= bytes_written ;
84 bytes_written = fprintf (stderr,
85 "\r%s delayed start, time left: "
86 "%d seconds left", mess, i );
87 (void) fflush(stderr);
88 for ( j=0 ; j < ( last_written -bytes_written) ; j++ )
89 {
90 fprintf (stderr," \b");
91 }
92 (void) fflush(stderr);
93 }
94 ret = sleep (sleep_int);
95 if (ret!=0)
96 {
97 sleep_int = sleep_int + ret;
98 }
99 else
100 {
101 sleep_int = 1 ;
102 }
103 }
104
105
106 fprintf (stderr,"\r");
107 for ( j=0 ; j < bytes_written ; j++ )
108 {
109 fprintf (stderr, " ");
110 }
111 /* We can typecast these to void safely, since this is not
112 * in any way an obstacle if it fails.... */
113 (void) fprintf (stderr, "\r");
114 (void) fflush(stderr);
115 }
116
117
118
119
120
121 /**************************************************************
122 * *
123 * xnee_strip *
124 * *
125 * *
126 **************************************************************/
127 int
xnee_strip(xnee_data * xd,char * str)128 xnee_strip(xnee_data *xd, char *str)
129 {
130 int i;
131 int j;
132 int blanks=0;
133 size_t len ;
134 len = strlen (str);
135
136 xnee_verbose ((xd," --> xnee_strip \"%s\"\n", str));
137 /*
138 * how many blanks do we have */
139 for (i=0 ; i<=(int)len ; i++)
140 {
141 if (str[i]==' ' )
142 {
143 blanks++;
144 for (j=i ; j<=(int)len ; j++)
145 {
146 str[j]=str[j+1];
147 len--;
148 }
149 i--;
150 }
151 }
152 str[len-blanks]='\0';
153 xnee_verbose ((xd," <-- xnee_strip \"%s\"\n", str));
154 return 1;
155 }
156
157
158
159
160 /**************************************************************
161 * *
162 * xnee_rem_comment_start *
163 * *
164 * *
165 **************************************************************/
166 int
xnee_rem_comment_start(xnee_data * xd,char * str)167 xnee_rem_comment_start(xnee_data *xd, char *str)
168 {
169 int i ;
170 int j ;
171 int comms=0;
172 size_t len ;
173
174 if (str==NULL)
175 {
176 return 1;
177 }
178 xnee_verbose ((xd," --> xnee_rem_comment_start \"%s\"\n", str));
179
180
181 len = strlen (str);
182
183 /*
184 * how many comments do we have */
185 for (i=0 ; i<=(int)len ; i++)
186 {
187 if ( str[i]==XNEE_COMMENT_START_CHAR )
188 {
189 comms++;
190 for (j=i ; j<=(int)len ; j++)
191 {
192 str[j]=str[j+1];
193 }
194 i--;
195 }
196 }
197
198 str[len-comms]='\0';
199 xnee_verbose ((xd," <-- xnee_rem_comment_start \"%s\"\n", str));
200 return 0;
201 }
202
203
204
205
206
207
208 /**************************************************************
209 * *
210 * rem_blanks *
211 * *
212 * *
213 **************************************************************/
214 int
rem_blanks(char * array,int size)215 rem_blanks (char *array, int size)
216 {
217 int i=0;
218 int j=0;
219 for (i=0;i<size;i++)
220 {
221 if ( (array[i]==' ') || (array[i]=='\t') || (array[i]=='\n') )
222 {
223 for (j=i;j<size-1;j++)
224 {
225 array[j]=array[j+1];
226 }
227 array[j]='\0';
228 }
229 }
230 return XNEE_OK;
231 }
232
233
234 /**************************************************************
235 * *
236 * rem_begin_blanks *
237 * *
238 * *
239 **************************************************************/
240 int
rem_begin_blanks(char * array,int size)241 rem_begin_blanks (char *array, int size)
242 {
243 int i=0;
244 int j=0;
245 for (i=0;i<size;i++)
246 {
247 if ( (array[i]==' ') || (array[i]=='\t') || (array[i]=='\n') )
248 {
249 for (j=i;j<size-1;j++)
250 {
251 array[j]=array[j+1];
252 }
253 i--;
254 array[j]='\0';
255 }
256 else
257 {
258 return 0;
259 }
260 }
261 return XNEE_OK;
262 }
263
264
265 /**************************************************************
266 * *
267 * rem_all_blanks *
268 * *
269 * *
270 **************************************************************/
271 int
rem_all_blanks(char * array,size_t size)272 rem_all_blanks (char *array, size_t size)
273 {
274 int i=0;
275 int j=0;
276 int zeros=0;
277
278
279 for (i=0;i<(int)size;i++)
280 {
281 if ( (array[i]==' ') || (array[i]=='\t') || (array[i]=='\n') )
282 {
283 zeros++;
284 for (j=i;j<(int)size;j++)
285 {
286 array[j]=array[j+1];
287 }
288 i--;
289 array[j-zeros]='\0';
290 }
291 }
292 return XNEE_OK;
293 }
294
295
296
297
298
299 /**************************************************************
300 * *
301 * xnee_client_id *
302 * *
303 * *
304 **************************************************************/
305 XID
xnee_client_id(Display * dpy)306 xnee_client_id (Display *dpy)
307 {
308 return dpy->resource_base ;
309 }
310
311
312
313
314
315
316
317
318 char **
xnee_str2strptr(char * tmp,int fill_option)319 xnee_str2strptr (char *tmp, int fill_option)
320 {
321 int size=0;
322 int str_size=0 ;
323 char **ret ;
324 char *blank_ptr1;
325 char *str;
326 ret = NULL;
327
328 while (*tmp)
329 {
330 /* rem leading blanks */
331 while(tmp[0]==' ')
332 {
333 if (tmp[0]==' ')
334 {
335 tmp++;
336 }
337 }
338
339 /* Find next blank (or newline) */
340 blank_ptr1 = strstr(tmp, " ");
341 if (blank_ptr1==NULL)
342 {
343 blank_ptr1 = strstr(tmp, "\n");
344 }
345
346 ret= (char**) realloc(ret,(size+2)*sizeof(char*));
347
348 if (ret == NULL )
349 {
350 break;
351 }
352
353 if (blank_ptr1 != NULL)
354 {
355 str_size = strlen(tmp) - strlen(blank_ptr1) + 1 ;
356 }
357 else
358 {
359 str_size = strlen(tmp) + 1;
360 }
361
362 if ( (size==0) && (fill_option==XNEE_CLI_SYNTAX) )
363 {
364 str = (char*) calloc(str_size, sizeof(char)+2);
365 strcpy (str, "--");
366 strncat(str, tmp, str_size-1);
367 }
368 else
369 {
370 str = (char*) calloc(str_size, sizeof(char));
371 strncpy(str, tmp, str_size-1);
372 }
373
374 ret[size] = str;
375 ret[size+1] = NULL;
376 size++;
377
378 tmp = blank_ptr1;
379 if (tmp==NULL)
380 {
381 break;
382 }
383 tmp++;
384 }
385
386 return ret;
387 }
388
389
390 void
xnee_print_strptr(xnee_data * xd,char ** strptr)391 xnee_print_strptr(xnee_data *xd, char **strptr)
392 {
393 int i = 0 ;
394
395 if ( (xd==NULL) || ( xd->verbose == 0 ) )
396 {
397 return;
398 }
399
400 if (strptr==NULL)
401 {
402 return;
403 }
404
405 fprintf (xd->err_file, "Option: '%s'\n", strptr[0]);
406
407 for (i=1; strptr[i] != NULL ; i++)
408 {
409 if ( strptr[i] != NULL )
410 {
411 fprintf (xd->err_file, "\targument: '%s'\n", strptr[i]);
412 }
413 else break;
414 }
415 }
416
417 int
xnee_free_strptr(char ** strptr)418 xnee_free_strptr(char **strptr)
419 {
420 int i = 0 ;
421
422 if (strptr==NULL)
423 {
424 return XNEE_OK;
425 }
426
427 for (i=0; strptr[i] != NULL ; i++)
428 {
429 if ( strptr[i] != NULL )
430 {
431 free(strptr[i]);
432 }
433 else
434 {
435 break;
436 }
437 }
438 free(strptr);
439
440 return XNEE_OK;
441 }
442
443 int
xnee_boolstr2int(xnee_data * xd,char * str)444 xnee_boolstr2int(xnee_data *xd, char *str)
445 {
446 int ret;
447
448 XNEE_VERBOSE_ENTER_FUNCTION();
449 if (str==NULL)
450 {
451 ret = XNEE_BOOL_IMPLICIT_TRUE;
452 }
453 else if (xnee_check_true(str))
454 {
455 ret = XNEE_BOOL_EXPLICIT_TRUE;
456 }
457 else if (xnee_check_false(str))
458 {
459 ret = XNEE_BOOL_EXPLICIT_FALSE;
460 }
461 else
462 {
463 ret = XNEE_BOOL_ERROR;
464 }
465 XNEE_VERBOSE_LEAVE_FUNCTION();
466 return ret;
467 }
468
469
470 int
xnee_str2int(xnee_data * xd,char * str)471 xnee_str2int(xnee_data *xd, char *str)
472 {
473 int ret=XNEE_OK;
474
475 xnee_verbose((xd, " xnee_str2int\n"));
476
477 if (str==NULL)
478 {
479 /* Set return value to error */
480 ret = INT_MAX;
481 }
482 else
483 {
484 /* scan the string */
485 if ( !sscanf(str, "%d", &ret) == 1 )
486 {
487 /* If scan failed, set return value to error */
488 ret = INT_MAX;
489 }
490 }
491 return ret;
492 }
493
494
495 int
xnee_record_from_data_display(xnee_data * xd)496 xnee_record_from_data_display(xnee_data *xd)
497 {
498 int ret_val = 0;
499
500
501 /* fprintf (stderr,"X info: %s %d %d %d\n", */
502 /* xd->x_vendor_name, */
503 /* xd->x_version_major, */
504 /* xd->x_version_minor, */
505 /* xd->x_version_minor_sub); */
506
507 if ( (xd != NULL) && (xd->x_vendor_name != NULL ) )
508 {
509
510
511 /*
512 * Xorg
513 *
514 * Fedora 13 (X.org 1.8.2), 14 (X.org 1.9.1) calls the server "Fedora project"
515 * (thanks to William Bader, and Olf Astrand)
516 */
517 if (strstr(xd->x_vendor_name, "X.Org") ||
518 strstr(xd->x_vendor_name, "Fedora Project") ||
519 strstr(xd->x_vendor_name, "Red Hat, Inc.") )
520 {
521 /*
522 * Version 1
523 */
524 if ( xd->x_version_major == 1 )
525 {
526 /*
527 * versions
528 */
529 if ( xd->x_version_minor >= 3 )
530 {
531 /* Old check removed. Seems as if all version follow
532 same pattern, so let's go for all future. Let's skip:
533 ( xd->x_version_minor <= 14 )
534 /*
535 * Once the XLIB fix is in place
536 * this should be enabled
537 *
538 if ( ( xd->x_version_minor == 7 ) &&
539 ( xd->x_version_minor_sub > 6 ))
540 {
541 ;
542 }
543 else
544 {
545 */
546 /*
547 }
548 */
549 ret_val=1;
550 }
551 else
552 {
553 ret_val=0;
554 }
555 }
556 else if ( xd->x_version_major == 6 )
557 {
558 if ( xd->x_version_minor == 9 )
559 {
560 /*
561 * NoMachine (nxserver-3.4.0-8)
562 * returns "The X.Org Foundation" 6.9.0
563 */
564 ret_val = 1;
565 }
566 else
567 {
568 fprintf(stderr, " WARNING\n");
569 fprintf(stderr, "You seem to be running NoMachine X server\n");
570 fprintf(stderr, "with a X server version unkown to " PACKAGE " \n");
571 fprintf(stderr, "We will assume that it works similar to nxserver-3.4.0-8\n");
572 ret_val = 1;
573 }
574 }
575 else if ( xd->x_version_major == 7 )
576 {
577 ret_val = 1;
578 }
579 }
580 else if (strstr(xd->x_vendor_name, "Sun Microsystems") )
581 {
582
583 if ( ( xd->x_version_major == 1 ) &&
584 ( xd->x_version_minor >= 3 ) )
585 {
586 ret_val = 1;
587 }
588 }
589 /* N900 */
590 else if (strstr(xd->x_vendor_name, "Nokia") )
591 {
592 if ( ( xd->x_version_major == 1 ) &&
593 ( xd->x_version_minor >= 1 ) )
594 {
595 ret_val = 1;
596 }
597 }
598 else
599 {
600 ;
601 }
602 }
603 xnee_verbose((xd, " -- xnee_record_from_data_display() using the following X serv data\n"));
604 xnee_verbose((xd, " using the following X serv data\n"));
605 xnee_verbose((xd, "X info: %s %d %d %d\n",
606 xd->x_vendor_name,
607 xd->x_version_major,
608 xd->x_version_minor,
609 xd->x_version_minor_sub));
610 xnee_verbose((xd, "<-- %d \n", ret_val));
611
612 return ret_val ;
613 }
614
615
616
617 Display *
xnee_get_display_for_recordcontext(xnee_data * xd)618 xnee_get_display_for_recordcontext(xnee_data *xd)
619 {
620 Display *context_display;
621 int override_mode;
622
623 if (xd==NULL)
624 {
625 return NULL;
626 }
627
628 override_mode = xnee_get_override_display(xd);
629 if (override_mode == XNEE_OVERRIDE_DISPLAY_DATA)
630 {
631 context_display = xd->data ;
632 }
633 else if (override_mode == XNEE_OVERRIDE_DISPLAY_CONTROL)
634 {
635 context_display = xd->control ;
636 }
637 else if ( xnee_record_from_data_display(xd))
638 {
639 /*
640 * From X.org 1.6.0 to ????
641 *
642 * there seem to be something strange about
643 * the XRecordCreateContext call
644 * which causes the XRecordEnableContextAsync
645 * to fail ... ugly fix, but it works
646 *
647 */
648 fprintf(stderr, "Workaround: Creating context on data display instead of control \n");
649 fprintf(stderr, " You can ignore this message\n");
650 context_display = xd->data ;
651 }
652 else
653 {
654 context_display = xd->control ;
655 }
656 return context_display;
657 }
658
659
660 int
xnee_is_screen_ok(xnee_data * xd,int screen)661 xnee_is_screen_ok(xnee_data *xd, int screen)
662 {
663 int ret;
664
665 ret = 0 ;
666 if ( (screen >= 0 ) &&
667 (screen < 100))
668 {
669 ret = 1;
670 }
671 else
672 {
673 if ( (xd != NULL) && (xd->x_vendor_name != NULL ) )
674 {
675
676 if (strstr(xd->x_vendor_name, "Nokia") )
677 {
678 if ( ( xd->x_version_major == 1 ) &&
679 ( xd->x_version_minor >= 1 ) )
680 {
681 ret = 1;
682 }
683 }
684 }
685 }
686
687 return ret ;
688 }
689
690
691
692 int
xnee_check_true(char * expr)693 xnee_check_true(char *expr)
694 {
695 return (int) ( (strncmp(expr,XNEE_TRUE_STRING,strlen(XNEE_TRUE_STRING))==0)
696 ||
697 (strncmp(expr,XNEE_1_STRING,strlen(XNEE_1_STRING))==0) );
698 }
699
700 int
xnee_check_false(char * expr)701 xnee_check_false(char *expr)
702 {
703 return (int)( (strncmp(expr,XNEE_FALSE_STRING,strlen(XNEE_FALSE_STRING))==0)
704 ||
705 (strncmp(expr,XNEE_0_STRING,strlen(XNEE_0_STRING))==0) );
706 }
707