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