Simplified notification messages
[oweals/gnunet.git] / src / monkey / gdbmi_connect.c
1 /**[txh]********************************************************************
2
3   Copyright (c) 2004-2009 by Salvador E. Tropea.
4   Covered by the GPL license.
5
6   Module: Connect.
7   Comments:
8   This module handles the dialog with gdb, including starting and stopping
9 gdb.
10   @<p>
11
12 GDB Bug workaround for "file -readnow": I tried to workaround a bug using
13 it but looks like this option also have bugs!!!! so I have to use the
14 command line option --readnow.
15 It also have a bug!!!! when the binary is changed and gdb must reload it
16 this option is ignored. So it looks like we have no solution but 3 gdb bugs
17 in a row.
18
19 ***************************************************************************/
20
21 #include "platform.h"
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/wait.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <limits.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35
36 #include "gdbmi.h"
37 #ifndef _GNU_SOURCE
38 #define _GNU_SOURCE
39 #endif
40
41 #ifndef TEMP_FAILURE_RETRY
42  #define TEMP_FAILURE_RETRY(a) (a)
43 #endif
44
45 int mi_error=MI_OK;
46 char *mi_error_from_gdb=NULL;
47 static char *gdb_exe=NULL;
48 static char *xterm_exe=NULL;
49 static char *gdb_start=NULL;
50 static char *gdb_conn=NULL;
51 static char *main_func=NULL;
52 static char  disable_psym_search_workaround=0;
53
54 mi_h *mi_alloc_h()
55 {
56  mi_h *h=(mi_h *)calloc(1,sizeof(mi_h));
57  if (!h)
58    {
59     mi_error=MI_OUT_OF_MEMORY;
60     return NULL;
61    }
62  h->to_gdb[0]=h->to_gdb[1]=h->from_gdb[0]=h->from_gdb[1]=-1;
63  h->pid=-1;
64  return h;
65 }
66
67 int mi_check_running_pid(pid_t pid)
68 {
69  int status;
70
71  if (pid<=0)
72     return 0;
73  /* If waitpid returns the number of our child means it communicated
74     to as a termination status. */
75  if (waitpid(pid,&status,WNOHANG)==pid)
76    {
77     pid=0;
78     return 0;
79    }
80  return 1;
81 }
82
83 int mi_check_running(mi_h *h)
84 {
85  return !h->died && mi_check_running_pid(h->pid);
86 }
87
88 void mi_kill_child(pid_t pid)
89 {
90  kill(pid,SIGTERM);
91  usleep(100000);
92  if (mi_check_running_pid(pid))
93    {
94     int status;
95     kill(pid,SIGKILL);
96     waitpid(pid,&status,0);
97    }
98 }
99
100 void mi_free_h(mi_h **handle)
101 {
102  mi_h *h=*handle;
103  if (h->to_gdb[0]>=0)
104     close(h->to_gdb[0]);
105  if (h->to)
106     fclose(h->to);
107  else if (h->to_gdb[1]>=0)
108     close(h->to_gdb[1]);
109  if (h->from)
110     fclose(h->from);
111  else if (h->from_gdb[0]>=0)
112     close(h->from_gdb[0]);
113  if (h->from_gdb[1]>=0)
114     close(h->from_gdb[1]);
115  if (mi_check_running(h))
116    {/* GDB is running! */
117     mi_kill_child(h->pid);
118    }
119  if (h->line)
120     free(h->line);
121  mi_free_output(h->po);
122  free(h->catched_console);
123  free(h);
124  *handle=NULL;
125 }
126
127 void mi_set_nonblk(int h)
128 {
129  int flf;
130  flf=fcntl(h,F_GETFL,0);
131  flf=flf | O_NONBLOCK;
132  fcntl(h,F_SETFL,flf);
133 }
134
135 int mi_getline(mi_h *h)
136 {
137  char c;
138
139  while (read(h->from_gdb[0],&c,1)==1)
140    {
141     if (h->lread>=h->llen)
142       {
143        h->llen=h->lread+128;
144        h->line=(char *)realloc(h->line,h->llen);
145        if (!h->line)
146          {
147           h->llen=0;
148           h->lread=0;
149           return -1;
150          }
151       }
152     if (c=='\n')
153       {
154        int ret=h->lread;
155        h->line[ret]=0;
156        h->lread=0;
157        return ret;
158       }
159     h->line[h->lread]=c;
160     h->lread++;
161    }
162  return 0;
163 }
164
165 char *get_cstr(mi_output *o)
166 {
167  if (!o->c || o->c->type!=t_const)
168     return NULL;
169  return o->c->v.cstr;
170 }
171
172 int mi_get_response(mi_h *h)
173 {
174  int l=mi_getline(h);
175  if (!l)
176     return 0;
177
178  if (h->from_gdb_echo)
179     h->from_gdb_echo(h->line,h->from_gdb_echo_data);
180  if (strncmp(h->line,"(gdb)",5)==0)
181    {/* End of response. */
182     return 1;
183    }
184  else
185    {/* Add to the response. */
186     mi_output *o;
187     int add=1, is_exit=0;
188     o=mi_parse_gdb_output(h->line);
189
190     if (!o)
191        return 0;
192     /* Tunneled streams callbacks. */
193     if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_STREAM)
194       {
195        char *aux;
196        add=0;
197        switch (o->sstype)
198          {
199           case MI_SST_CONSOLE:
200                aux=get_cstr(o);
201                if (h->console)
202                   h->console(aux,h->console_data);
203                if (h->catch_console && aux)
204                  {
205                   h->catch_console--;
206                   if (!h->catch_console)
207                     {
208                      free(h->catched_console);
209                      h->catched_console=strdup(aux);
210                     }
211                  }
212                break;
213           case MI_SST_TARGET:
214                /* This one seems to be useless. */
215                if (h->target)
216                   h->target(get_cstr(o),h->target_data);
217                break;
218           case MI_SST_LOG:
219                if (h->log)
220                   h->log(get_cstr(o),h->log_data);
221                break;
222          }
223       }
224     else if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_ASYNC)
225       {
226        if (h->async)
227           h->async(o,h->async_data);
228       }
229     else if (o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_ERROR)
230       {/* Error from gdb, record it. */
231        mi_error=MI_FROM_GDB;
232        free(mi_error_from_gdb);
233        mi_error_from_gdb=NULL;
234        if (o->c && strcmp(o->c->var,"msg")==0 && o->c->type==t_const)
235           mi_error_from_gdb=strdup(o->c->v.cstr);
236       }
237     is_exit=(o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_EXIT);
238     /* Add to the list of responses. */
239     if (add)
240       {
241        if (h->last)
242           h->last->next=o;
243        else
244           h->po=o;
245        h->last=o;
246       }
247     else
248        mi_free_output(o);
249     /* Exit RR means gdb exited, we won't get a new prompt ;-) */
250     if (is_exit)
251        return 1;
252    }
253
254  return 0;
255 }
256
257 mi_output *mi_retire_response(mi_h *h)
258 {
259  mi_output *ret=h->po;
260  h->po=h->last=NULL;
261  return ret;
262 }
263
264 mi_output *mi_get_response_blk(mi_h *h)
265 {
266  int r;
267  /* Sometimes gdb dies. */
268  if (!mi_check_running(h))
269    {
270     h->died=1;
271     mi_error=MI_GDB_DIED;
272     return NULL;
273    }
274  do
275    {
276    /*
277     That's a must. If we just keep trying to read and failing things
278     become really sloooowwww. Instead we try and if it fails we wait
279     until something is available.
280     TODO: Implement something with the time out, a callback to ask the
281     application is we have to wait or not could be a good thing.
282    */
283    fd_set set;
284    struct timeval timeout;
285    int ret;
286
287    r=mi_get_response(h);
288    if (r)
289       return mi_retire_response(h);
290
291    FD_ZERO(&set);
292    FD_SET(h->from_gdb[0],&set);
293    timeout.tv_sec=h->time_out;
294    timeout.tv_usec=0;
295    ret=TEMP_FAILURE_RETRY(select(FD_SETSIZE,&set,NULL,NULL,&timeout));
296    if (!ret)
297      {
298       if (!mi_check_running(h))
299         {
300          h->died=1;
301          mi_error=MI_GDB_DIED;
302          return NULL;
303         }
304       if (h->time_out_cb)
305          ret=h->time_out_cb(h->time_out_cb_data);
306       if (!ret)
307         {
308          mi_error=MI_GDB_TIME_OUT;
309          return NULL;
310         }
311      }
312    }
313  while (!r);
314
315  return NULL;
316 }
317
318 void mi_send_commands(mi_h *h, const char *file)
319 {
320  FILE *f;
321  char b[PATH_MAX];
322
323  //printf("File: %s\n",file);
324  if (!file)
325     return;
326  f=fopen(file,"rt");
327  if (!f)
328     return;
329  while (!feof(f))
330    {
331     if (fgets(b,PATH_MAX,f))
332       {
333        //printf("Send: %s\n",b);
334        mi_send(h,b);
335        mi_res_simple_done(h);
336       }
337    }
338  fclose(f);
339 }
340
341 void mi_send_target_commands(mi_h *h)
342 {
343  mi_send_commands(h,gdb_conn);
344 }
345
346 /**[txh]********************************************************************
347
348   Description:
349   Connect to a local copy of gdb. Note that the mi_h structure is something
350 similar to a "FILE *" for stdio.
351   
352   Return: A new mi_h structure or NULL on error.
353   
354 ***************************************************************************/
355
356 mi_h *mi_connect_local()
357 {
358  mi_h *h;
359  const char *gdb=mi_get_gdb_exe();
360
361  /* Start without error. */
362  mi_error=MI_OK;
363  /* Verify we have a GDB binary. */
364  if (access(gdb,X_OK))
365    {
366     mi_error=MI_MISSING_GDB;
367     return NULL;
368    }
369  /* Alloc the handle structure. */
370  h=mi_alloc_h();
371  if (!h)
372     return h;
373  h->time_out=MI_DEFAULT_TIME_OUT;
374  /* Create the pipes to connect with the child. */
375  if (pipe(h->to_gdb) || pipe(h->from_gdb))
376    {
377     mi_error=MI_PIPE_CREATE;
378     mi_free_h(&h);
379     return NULL;
380    }
381  mi_set_nonblk(h->to_gdb[1]);
382  mi_set_nonblk(h->from_gdb[0]);
383  /* Associate streams to the file handles. */
384  h->to=fdopen(h->to_gdb[1],"w");
385  h->from=fdopen(h->from_gdb[0],"r");
386  if (!h->to || !h->from)
387    {
388     mi_error=MI_PIPE_CREATE;
389     mi_free_h(&h);
390     return NULL;
391    }
392  /* Create the child. */
393  h->pid=fork();
394  if (h->pid==0)
395    {/* We are the child. */
396     char *argv[5];
397     /* Connect stdin/out to the pipes. */
398     dup2(h->to_gdb[0],STDIN_FILENO);
399     dup2(h->from_gdb[1],STDOUT_FILENO);
400     /* Pass the control to gdb. */
401     argv[0]=(char *)gdb; /* Is that OK? */
402     argv[1]="--interpreter=mi";
403     argv[2]="--quiet";
404     argv[3]=disable_psym_search_workaround ? 0 : "--readnow";
405     argv[4]=0;
406     execvp(argv[0],argv);
407     /* We get here only if exec failed. */
408     _exit(127);
409    }
410  /* We are the parent. */
411  if (h->pid==-1)
412    {/* Fork failed. */
413     mi_error=MI_FORK;
414     mi_free_h(&h);
415     return NULL;
416    }
417  if (!mi_check_running(h))
418    {
419     mi_error=MI_DEBUGGER_RUN;
420     mi_free_h(&h);
421     return NULL;
422    }
423  /* Wait for the prompt. */
424  mi_get_response_blk(h);
425  /* Send the start-up commands */
426  mi_send_commands(h,gdb_start);
427
428  return h;
429 }
430
431 /**[txh]********************************************************************
432
433   Description:
434   Close connection. You should ask gdb to quit first gmi_gdb_exit.
435   
436 ***************************************************************************/
437
438 void mi_disconnect(mi_h *h)
439 {
440  mi_free_h(&h);
441  free(mi_error_from_gdb);
442  mi_error_from_gdb=NULL;
443 }
444
445 void mi_set_console_cb(mi_h *h, stream_cb cb, void *data)
446 {
447  h->console=cb;
448  h->console_data=data;
449 }
450
451 void mi_set_target_cb(mi_h *h, stream_cb cb, void *data)
452 {
453  h->target=cb;
454  h->target_data=data;
455 }
456
457 void mi_set_log_cb(mi_h *h, stream_cb cb, void *data)
458 {
459  h->log=cb;
460  h->log_data=data;
461 }
462
463 stream_cb mi_get_console_cb(mi_h *h, void **data)
464 {
465  if (data)
466     *data=h->console_data;
467  return h->console;
468 }
469
470 stream_cb mi_get_target_cb(mi_h *h, void **data)
471 {
472  if (data)
473     *data=h->target_data;
474  return h->target;
475 }
476
477 stream_cb mi_get_log_cb(mi_h *h, void **data)
478 {
479  if (data)
480     *data=h->log_data;
481  return h->log;
482 }
483
484 void mi_set_async_cb(mi_h *h, async_cb cb, void *data)
485 {
486  h->async=cb;
487  h->async_data=data;
488 }
489
490 async_cb mi_get_async_cb(mi_h *h, void **data)
491 {
492  if (data)
493     *data=h->async_data;
494  return h->async;
495 }
496
497 void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data)
498 {
499  h->to_gdb_echo=cb;
500  h->to_gdb_echo_data=data;
501 }
502
503 void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data)
504 {
505  h->from_gdb_echo=cb;
506  h->from_gdb_echo_data=data;
507 }
508
509 stream_cb mi_get_to_gdb_cb(mi_h *h, void **data)
510 {
511  if (data)
512     *data=h->to_gdb_echo_data;
513  return h->to_gdb_echo;
514 }
515
516 stream_cb mi_get_from_gdb_cb(mi_h *h, void **data)
517 {
518  if (data)
519     *data=h->from_gdb_echo_data;
520  return h->from_gdb_echo;
521 }
522
523 void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data)
524 {
525  h->time_out_cb=cb;
526  h->time_out_cb_data=data;
527 }
528
529 tm_cb mi_get_time_out_cb(mi_h *h, void **data)
530 {
531  if (data)
532     *data=h->time_out_cb_data;
533  return h->time_out_cb;
534 }
535
536 void mi_set_time_out(mi_h *h, int to)
537 {
538  h->time_out=to;
539 }
540
541 int mi_get_time_out(mi_h *h)
542 {
543  return h->time_out;
544 }
545
546 int mi_send(mi_h *h, const char *format, ...)
547 {
548  int ret;
549  char *str;
550  va_list argptr;
551
552  if (h->died)
553     return 0;
554
555  va_start(argptr,format);
556  ret=vasprintf(&str,format,argptr);
557  va_end(argptr);
558  fputs(str,h->to);
559  fflush(h->to);
560  if (h->to_gdb_echo)
561     h->to_gdb_echo(str,h->to_gdb_echo_data);
562  free(str);
563
564  return ret;
565 }
566
567 void mi_clean_up_globals()
568 {
569  free(gdb_exe);
570  gdb_exe=NULL;
571  free(xterm_exe);
572  xterm_exe=NULL;
573  free(gdb_start);
574  gdb_start=NULL;
575  free(gdb_conn);
576  gdb_conn=NULL;
577  free(main_func);
578  main_func=NULL;
579 }
580
581 void mi_register_exit()
582 {
583  static int registered=0;
584  if (!registered)
585    {
586     registered=1;
587     atexit(mi_clean_up_globals);
588    }
589 }
590
591 void mi_set_gdb_exe(const char *name)
592 {
593  free(gdb_exe);
594  gdb_exe=name ? strdup(name) : NULL;
595  mi_register_exit();
596 }
597
598 void mi_set_gdb_start(const char *name)
599 {
600  free(gdb_start);
601  gdb_start=name ? strdup(name) : NULL;
602  mi_register_exit();
603 }
604
605 void mi_set_gdb_conn(const char *name)
606 {
607  free(gdb_conn);
608  gdb_conn=name ? strdup(name) : NULL;
609  mi_register_exit();
610 }
611
612 static
613 char *mi_search_in_path(const char *file)
614 {
615  char *path, *pt, *r;
616  char test[PATH_MAX];
617  struct stat st;
618
619  path=getenv("PATH");
620  if (!path)
621     return NULL;
622  pt=strdup(path);
623  r=strtok(pt,PATH_SEPARATOR_STR);
624  while (r)
625    {
626     strcpy(test,r);
627     strcat(test,"/");
628     strcat(test,file);
629     if (stat(test,&st)==0 && S_ISREG(st.st_mode))
630       {
631        free(pt);
632        return strdup(test);
633       }
634     r=strtok(NULL,PATH_SEPARATOR_STR);
635    }
636  free(pt);
637  return NULL;
638 }
639
640 const char *mi_get_gdb_exe()
641 {
642  if (!gdb_exe)
643    {/* Look for gdb in path */
644     gdb_exe=mi_search_in_path("gdb");
645     if (!gdb_exe)
646        return "/usr/bin/gdb";
647    }
648  return gdb_exe;
649 }
650
651 const char *mi_get_gdb_start()
652 {
653  return gdb_start;
654 }
655
656 const char *mi_get_gdb_conn()
657 {
658  return gdb_conn;
659 }
660
661 void mi_set_xterm_exe(const char *name)
662 {
663  free(xterm_exe);
664  xterm_exe=name ? strdup(name) : NULL;
665  mi_register_exit();
666 }
667
668 const char *mi_get_xterm_exe()
669 {
670  if (!xterm_exe)
671    {/* Look for xterm in path */
672     xterm_exe=mi_search_in_path("xterm");
673     if (!xterm_exe)
674        return "/usr/bin/X11/xterm";
675    }
676  return xterm_exe;
677 }
678
679 void mi_set_main_func(const char *name)
680 {
681  free(main_func);
682  main_func=name ? strdup(name) : NULL;
683  mi_register_exit();
684 }
685
686 const char *mi_get_main_func()
687 {
688  if (main_func)
689     return main_func;
690  return "main";
691 }
692
693 /**[txh]********************************************************************
694
695   Description:
696   Opens a new xterm to be used by the child process to debug.
697   
698   Return: A new mi_aux_term structure, you can use gmi_end_aux_term to
699 release it.
700   
701 ***************************************************************************/
702
703 mi_aux_term *gmi_start_xterm()
704 {
705  char nsh[14]="/tmp/shXXXXXX";
706  char ntt[14]="/tmp/ttXXXXXX";
707  const char *xterm;
708  struct stat st;
709  int hsh, htt=-1;
710  mi_aux_term *res=NULL;
711  FILE *f;
712  pid_t pid;
713  char buf[PATH_MAX];
714
715  /* Verify we have an X terminal. */
716  xterm=mi_get_xterm_exe();
717  if (access(xterm,X_OK))
718    {
719     mi_error=MI_MISSING_XTERM;
720     return NULL;
721    }
722
723  /* Create 2 temporals. */
724  hsh=mkstemp(nsh);
725  if (hsh==-1)
726    {
727     mi_error=MI_CREATE_TEMPORAL;
728     return NULL;
729    }
730  htt=mkstemp(ntt);
731  if (htt==-1)
732    {
733     close(hsh);
734     unlink(nsh);
735     mi_error=MI_CREATE_TEMPORAL;
736     return NULL;
737    }
738  close(htt);
739  /* Create the script. */
740  f=fdopen(hsh,"w");
741  if (!f)
742    {
743     close(hsh);
744     unlink(nsh);
745     unlink(ntt);
746     mi_error=MI_CREATE_TEMPORAL;
747     return NULL;
748    }
749  fprintf(f,"#!/bin/sh\n");
750  fprintf(f,"tty > %s\n",ntt);
751  fprintf(f,"rm %s\n",nsh);
752  fprintf(f,"sleep 365d\n");
753  fclose(f);
754  /* Spawn xterm. */
755  /* Create the child. */
756  pid=fork();
757  if (pid==0)
758    {/* We are the child. */
759     char *argv[5];
760     /* Pass the control to gdb. */
761     argv[0]=(char *)mi_get_xterm_exe(); /* Is that ok? */
762     argv[1]="-e";
763     argv[2]="/bin/sh";
764     argv[3]=nsh;
765     argv[4]=0;
766     execvp(argv[0],argv);
767     /* We get here only if exec failed. */
768     unlink(nsh);
769     unlink(ntt);
770     _exit(127);
771    }
772  /* We are the parent. */
773  if (pid==-1)
774    {/* Fork failed. */
775     unlink(nsh);
776     unlink(ntt);
777     mi_error=MI_FORK;
778     return NULL;
779    }
780  /* Wait until the shell is deleted. */
781  while (stat(nsh,&st)==0)
782    usleep(1000);
783  /* Try to read the tty name. */
784  f=fopen(ntt,"rt");
785  if (f)
786    {
787     if (fgets(buf,PATH_MAX,f))
788       {
789        char *s; /* Strip the \n. */
790        for (s=buf; *s && *s!='\n'; s++);
791        *s=0;
792        res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
793        if (res)
794          {
795           res->pid=pid;
796           res->tty=strdup(buf);
797          }
798       }
799     fclose(f);
800    }
801  unlink(ntt);
802  return res;
803 }
804
805 void mi_free_aux_term(mi_aux_term *t)
806 {
807  if (!t)
808     return;
809  free(t->tty);
810  free(t);
811 }
812
813 /**[txh]********************************************************************
814
815   Description:
816   Closes the auxiliar terminal and releases the allocated memory.
817   
818 ***************************************************************************/
819
820 void gmi_end_aux_term(mi_aux_term *t)
821 {
822  if (!t)
823     return;
824  if (t->pid!=-1 && mi_check_running_pid(t->pid))
825     mi_kill_child(t->pid);
826  mi_free_aux_term(t);
827 }
828
829 /**[txh]********************************************************************
830
831   Description:
832   Forces the MI version. Currently the library can't detect it so you must
833 force it manually. GDB 5.x implemented MI v1 and 6.x v2.
834   
835 ***************************************************************************/
836
837 void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
838                       unsigned vMinor)
839 {
840  h->version=MI_VERSION2U(vMajor,vMiddle,vMinor);
841 }
842
843 /**[txh]********************************************************************
844
845   Description:
846   Dis/Enables the workaround for a bug in gdb.
847
848 ***************************************************************************/
849
850 void mi_set_workaround(unsigned wa, int enable)
851 {
852  switch (wa)
853    {
854     case MI_PSYM_SEARCH:
855          disable_psym_search_workaround=enable ? 0 : 1;
856          break;
857    }
858 }
859
860 /**[txh]********************************************************************
861
862   Description:
863   Finds if the workaround for a bug in gdb is enabled.
864   
865   Return: !=0 if enabled.
866   
867 ***************************************************************************/
868
869 int mi_get_workaround(unsigned wa)
870 {
871  switch (wa)
872    {
873     case MI_PSYM_SEARCH:
874          return disable_psym_search_workaround==0;
875    }
876  return 0;
877 }
878