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