Simplified notification messages
[oweals/gnunet.git] / src / monkey / action_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file monkey/action_api.c
23  * @brief Monkey API for actions taken by Monkey while debugging
24  */
25
26 #include "platform.h"
27 #include "gnunet_common.h"
28 #include "gnunet_monkey_action.h"
29 #include <libesmtp.h>
30
31 extern void sendMail (const char *messageContents, const char *emailAddress);
32
33
34 static int async_c=0;
35
36
37 static void cb_console(const char *str, void *data)
38 {
39  printf("CONSOLE> %s\n",str);
40 }
41
42
43 /* Note that unlike what's documented in gdb docs it isn't usable. */
44 static void cb_target(const char *str, void *data)
45 {
46  printf("TARGET> %s\n",str);
47 }
48
49
50 static void cb_log(const char *str, void *data)
51 {
52  printf("LOG> %s\n",str);
53 }
54
55
56 static void cb_to(const char *str, void *data)
57 {
58  printf(">> %s",str);
59 }
60
61
62 static void cb_from(const char *str, void *data)
63 {
64  printf("<< %s\n",str);
65 }
66
67
68 static void cb_async(mi_output *o, void *data)
69 {
70  printf("ASYNC\n");
71  async_c++;
72 }
73
74
75 static int wait_for_stop(mi_h *h, struct GNUNET_MONKEY_ACTION_Context *cntxt)
76 {
77         while (!mi_get_response(h))
78                 usleep(1000);
79         /* The end of the async. */
80         cntxt->gdb_stop_reason=mi_res_stop(h);
81         if (cntxt->gdb_stop_reason)
82         {
83                 if (cntxt->gdb_stop_reason->reason == sr_exited_normally)
84                         return GDB_STATE_EXIT_NORMALLY;
85
86                 cntxt->gdb_frames = gmi_stack_info_frame(h);
87                 if (NULL == cntxt->gdb_frames)
88                   GNUNET_break(0);
89
90                 return GDB_STATE_STOPPED;
91         }
92         return GDB_STATE_ERROR;
93 }
94
95
96 int GNUNET_MONKEY_ACTION_report_file(struct GNUNET_MONKEY_ACTION_Context* cntxt, const char* dumpFileName)
97 {
98         FILE* file = fopen(dumpFileName, "w");
99         GNUNET_assert(NULL != file);
100         fprintf(file,"%s", cntxt->debug_report);
101         fclose(file);
102         return GNUNET_OK;
103 }
104
105
106 int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt)
107 {
108         if (cntxt->debug_mode == DEBUG_MODE_REPORT_READY)
109                 sendMail(cntxt->debug_report, cntxt->email_address);
110
111         return GNUNET_OK;
112 }
113
114
115
116 int GNUNET_MONKEY_ACTION_rerun_with_valgrind()
117 {
118         return GNUNET_OK;
119 }
120
121
122 int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt)
123 {
124         cntxt->debug_mode = DEBUG_MODE_GDB;
125
126         /* This is like a file-handle for fopen.
127             Here we have all the state of gdb "connection". */
128         mi_set_gdb_exe("/tmp/gdb/bin/gdb");
129         mi_h *h;
130         int ret;
131
132          /* Connect to gdb child. */
133          h = mi_connect_local();
134          if (!h)
135            {
136             printf("Connect failed\n");
137             return GNUNET_NO;
138            }
139          printf("Connected to gdb!\n");
140
141          /* Set all callbacks. */
142          mi_set_console_cb(h,cb_console,NULL);
143          mi_set_target_cb(h,cb_target,NULL);
144          mi_set_log_cb(h,cb_log,NULL);
145          mi_set_async_cb(h,cb_async,NULL);
146          mi_set_to_gdb_cb(h,cb_to,NULL);
147          mi_set_from_gdb_cb(h,cb_from,NULL);
148
149          /* Set the name of the child and the command line aguments. */
150          if (!gmi_set_exec(h, cntxt->binary_name, NULL))
151            {
152             printf("Error setting exec y args\n");
153             mi_disconnect(h);
154             return GNUNET_NO;
155            }
156
157          /* Tell gdb to attach the child to a terminal. */
158          if (!gmi_target_terminal(h, ttyname(STDIN_FILENO)))
159            {
160             printf("Error selecting target terminal\n");
161             mi_disconnect(h);
162             return GNUNET_NO;
163            }
164
165          /* Run the program. */
166          if (!gmi_exec_run(h))
167            {
168             printf("Error in run!\n");
169             mi_disconnect(h);
170             return GNUNET_NO;
171            }
172          /* Here we should be stopped when the program crashes */
173          ret = wait_for_stop(h, cntxt);
174          if (ret != GDB_STATE_ERROR)
175             mi_disconnect(h);
176
177         return ret;
178 }
179
180
181 int GNUNET_MONKEY_ACTION_format_report(struct GNUNET_MONKEY_ACTION_Context* cntxt)
182 {
183         switch (cntxt->debug_mode) {
184         case DEBUG_MODE_GDB:
185                 GNUNET_asprintf(&(cntxt->debug_report),
186                         "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n",
187                         cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning);
188                 break;
189         case DEBUG_MODE_VALGRIND:
190                 break;
191         default:
192                 break;
193         }
194
195         cntxt->debug_mode = DEBUG_MODE_REPORT_READY;
196         return GNUNET_OK;
197 }
198
199
200 int GNUNET_MONKEY_ACTION_check_bug_redundancy()
201 {
202         return GNUNET_OK;
203 }