fixing error message -- 1635
[oweals/gnunet.git] / src / monkey / gnunet-monkey.c
1 /**[txh]********************************************************************
2
3   Copyright (c) 2004 by Salvador E. Tropea.
4   Covered by the GPL license.
5
6   Comment:
7   X11 example/test of the libmigdb.
8   Run it from an X11 terminal (xterm, Eterm, etc.).
9   
10 ***************************************************************************/
11
12 #include <stdio.h>
13 #include <unistd.h> //usleep
14 #include <libesmtp.h>
15 #include "gdbmi.h"
16 #include "platform.h"
17 #include "gnunet_common.h"
18 #include "gnunet_getopt_lib.h"
19 #include "gnunet_program_lib.h"
20
21 extern void sendMail (const char *messageContents);
22 static const char* mode;
23 static const char* dumpFileName;
24 static const char* binaryName;
25 static int ret = 0;
26
27 void cb_console(const char *str, void *data)
28 {
29  printf("CONSOLE> %s\n",str);
30 }
31
32 /* Note that unlike what's documented in gdb docs it isn't usable. */
33 void cb_target(const char *str, void *data)
34 {
35  printf("TARGET> %s\n",str);
36 }
37
38 void cb_log(const char *str, void *data)
39 {
40  printf("LOG> %s\n",str);
41 }
42
43 void cb_to(const char *str, void *data)
44 {
45  printf(">> %s",str);
46 }
47
48 void cb_from(const char *str, void *data)
49 {
50  printf("<< %s\n",str);
51 }
52
53 static int async_c=0;
54
55 void cb_async(mi_output *o, void *data)
56 {
57  printf("ASYNC\n");
58  async_c++;
59 }
60
61
62 static void dumpText(const char* message)
63 {
64         FILE* file = fopen(dumpFileName, "w");
65         GNUNET_assert(NULL != file);
66         fprintf(file,"%s", message);
67         fclose(file);
68 }
69
70
71 void send_bug_mail(mi_stop* sr, mi_frames* f)
72 {
73         char *message;
74         GNUNET_asprintf(&message, 
75                         "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n",
76                         f->file, f->func, f->line, mi_reason_enum_to_str(sr->reason), sr->signal_name, sr->signal_meaning);
77         if (strcasecmp(mode, "mail") == 0)
78                 sendMail(message);
79         else
80                 dumpText(message);
81         
82         GNUNET_free (message);
83 }
84
85
86 int wait_for_stop(mi_h *h)
87 {
88  int res=1;
89  mi_stop *sr;
90  mi_frames *f;
91
92  while (!mi_get_response(h))
93     usleep(1000);
94  /* The end of the async. */
95  sr=mi_res_stop(h);
96  if (sr)
97    {
98     f = gmi_stack_info_frame(h);
99     if (f != NULL)
100       send_bug_mail(sr, f);
101     else
102       GNUNET_break (0);
103     mi_free_stop(sr);
104     res = 0;
105    }
106  else
107    {
108     printf("Error while waiting\n");
109     printf("mi_error: %d\nmi_error_from_gdb: %s\n",mi_error,mi_error_from_gdb);
110     res=0;
111    }
112  return res;
113 }
114
115
116
117 /**
118  * Main function that will be run by the scheduler.
119  *
120  * @param cls closure
121  * @param args remaining command-line arguments
122  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
123  * @param c configuration
124  */
125 static void
126 run (void *cls,
127      char *const *args,
128      const char *cfgfile,
129      const struct GNUNET_CONFIGURATION_Handle *c)
130 {
131         mi_aux_term *xterm_tty=NULL;
132         
133         /* This is like a file-handle for fopen.
134             Here we have all the state of gdb "connection". */
135          mi_h *h;
136
137          /* Connect to gdb child. */
138          h=mi_connect_local();
139          if (!h)
140            {
141             printf("Connect failed\n");
142             ret = 1;
143             return;
144            }
145          printf("Connected to gdb!\n");
146
147          /* Set all callbacks. */
148          mi_set_console_cb(h,cb_console,NULL);
149          mi_set_target_cb(h,cb_target,NULL);
150          mi_set_log_cb(h,cb_log,NULL);
151          mi_set_async_cb(h,cb_async,NULL);
152          mi_set_to_gdb_cb(h,cb_to,NULL);
153          mi_set_from_gdb_cb(h,cb_from,NULL);
154
155          /* Set the name of the child and the command line aguments. */
156          if (!gmi_set_exec(h, binaryName, NULL))
157            {
158             printf("Error setting exec y args\n");
159             mi_disconnect(h);
160             ret = 1;
161             return;
162            }
163
164          /* Tell gdb to attach the child to a terminal. */
165          if (!gmi_target_terminal(h, ttyname(STDIN_FILENO)))
166            {
167             printf("Error selecting target terminal\n");
168             mi_disconnect(h);
169             ret = 1;
170             return;
171            }
172
173          /* Run the program. */
174          if (!gmi_exec_run(h))
175            {
176             printf("Error in run!\n");
177             mi_disconnect(h);
178             ret = 1;
179             return;
180            }
181          /* Here we should be stopped when the program crashes */
182          if (!wait_for_stop(h))
183            {
184             mi_disconnect(h);
185             ret = 1;
186             return;
187            }
188
189          /* Continue execution. */
190          if (!gmi_exec_continue(h))
191            {
192             printf("Error in continue!\n");
193             mi_disconnect(h);
194             ret = 1;
195             return;
196            }
197          /* Here we should be terminated. */
198          if (!wait_for_stop(h))
199            {
200             mi_disconnect(h);
201             ret = 1;
202             return;
203            }
204
205          /* Exit from gdb. */
206          gmi_gdb_exit(h);
207          /* Close the connection. */
208          mi_disconnect(h);
209          /* Wait 5 seconds and close the auxiliar terminal. */
210          printf("Waiting 5 seconds\n");
211          sleep(5);
212          gmi_end_aux_term(xterm_tty);
213 }
214
215
216 int main(int argc, char *argv[])
217 {
218         /*
219          * FIXME: 
220          * Command should accept email address to which monkey sends the debugging report.
221          * The email address can also be read from the configuration file.
222          */
223  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
224      {'m', "mode", NULL, gettext_noop ("monkey's mode of operation: options are \"text\" or \"email\""),
225       GNUNET_YES, &GNUNET_GETOPT_set_string, &mode},
226      {'b', "binary", NULL, gettext_noop ("binary for program to debug with monkey"),
227       GNUNET_YES, &GNUNET_GETOPT_set_string, &binaryName},
228      {'o', "output", NULL, gettext_noop ("path to file to dump monkey's output in case of working in text mode"),
229       GNUNET_YES, &GNUNET_GETOPT_set_string, &dumpFileName},
230       GNUNET_GETOPT_OPTION_END
231    };
232  
233  if (argc < 2) {
234          printf("%s", "Monkey should take arguments: Use --help to get a list of options.\n");
235          return 1;
236  }
237  
238  if (GNUNET_OK == GNUNET_PROGRAM_run (argc,
239                        argv,
240                        "gnunet-monkey",
241                        gettext_noop
242                        ("Automatically debug a service"),
243                        options, &run, NULL))
244      {
245        return ret;
246      }
247
248      return 1;
249 }