#include "gnunet_monkey_action.h"
#include <libesmtp.h>
-
-#define DEBUG_MODE_GDB 0
-#define DEBUG_MODE_VALGRIND 1
-#define DEBUG_MODE_REPORT_READY 2
-
-extern void sendMail (const char *messageContents);
+extern void sendMail (const char *messageContents, const char *emailAddress);
static int async_c=0;
}
-static int wait_for_stop(mi_h *h)
+static int wait_for_stop(mi_h *h, struct GNUNET_MONKEY_ACTION_Context *cntxt)
{
- int res=1;
- mi_stop *sr;
- mi_frames *f;
-
while (!mi_get_response(h))
usleep(1000);
/* The end of the async. */
- sr=mi_res_stop(h);
- if (sr)
+ cntxt->gdb_stop_reason=mi_res_stop(h);
+ if (cntxt->gdb_stop_reason)
{
- f = gmi_stack_info_frame(h);
- if (NULL == f)
- printf("f is NULL!\n");
- if (NULL == f)
+ if (cntxt->gdb_stop_reason->reason == sr_exited_normally)
+ return GDB_STATE_EXIT_NORMALLY;
+
+ cntxt->gdb_frames = gmi_stack_info_frame(h);
+ if (NULL == cntxt->gdb_frames)
GNUNET_break(0);
- mi_free_stop(sr);
- res = 0;
- }
- else
- {
- res=0;
+ return GDB_STATE_STOPPED;
}
- return res;
+ return GDB_STATE_ERROR;
}
int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt)
{
if (cntxt->debug_mode == DEBUG_MODE_REPORT_READY)
- sendMail(cntxt->debug_report);
+ sendMail(cntxt->debug_report, cntxt->email_address);
return GNUNET_OK;
}
int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt)
{
cntxt->debug_mode = DEBUG_MODE_GDB;
- mi_aux_term *xterm_tty=NULL;
/* This is like a file-handle for fopen.
Here we have all the state of gdb "connection". */
- mi_h *h;
+ mi_set_gdb_exe("/tmp/gdb/bin/gdb");
+ mi_h *h;
+ int ret;
/* Connect to gdb child. */
h = mi_connect_local();
return GNUNET_NO;
}
/* Here we should be stopped when the program crashes */
- if (!wait_for_stop(h))
- {
- mi_disconnect(h);
- return GNUNET_NO;
- }
-
- /* Continue execution. */
- if (!gmi_exec_continue(h))
- {
- printf("Error in continue!\n");
- mi_disconnect(h);
- return GNUNET_NO;
- }
- /* Here we should be terminated. */
- if (!wait_for_stop(h))
- {
+ ret = wait_for_stop(h, cntxt);
+ if (ret != GDB_STATE_ERROR)
mi_disconnect(h);
- return GNUNET_NO;
- }
- /* Exit from gdb. */
- gmi_gdb_exit(h);
- /* Close the connection. */
- mi_disconnect(h);
- /* Wait 5 seconds and close the auxiliar terminal. */
- printf("Waiting 5 seconds\n");
- sleep(5);
- gmi_end_aux_term(xterm_tty);
-
- return GNUNET_OK;
+ return ret;
}
{
switch (cntxt->debug_mode) {
case DEBUG_MODE_GDB:
- GNUNET_asprintf(&cntxt->debug_report,
+ GNUNET_asprintf(&(cntxt->debug_report),
"Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n",
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);
break;
-/**[txh]********************************************************************
+/*
+ This file is part of GNUnet.
+ (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
- Copyright (c) 2004 by Salvador E. Tropea.
- Covered by the GPL license.
-
- Comment:
- X11 example/test of the libmigdb.
- Run it from an X11 terminal (xterm, Eterm, etc.).
-
-***************************************************************************/
+/**
+ * @file monkey/gnunet-monkey.c
+ * @brief Monkey: gnunet automated debugging tool
+ */
#include <stdio.h>
-#include <unistd.h> //usleep
-#include <libesmtp.h>
-#include "gdbmi.h"
#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_getopt_lib.h"
#include "gnunet_program_lib.h"
#include "gnunet_monkey_action.h"
-extern void sendMail (const char *messageContents);
static const char* mode;
static const char* dumpFileName;
static const char* binaryName;
+static const char* emailAddress;
static int ret = 0;
-void cb_console(const char *str, void *data)
-{
- printf("CONSOLE> %s\n",str);
-}
-
-/* Note that unlike what's documented in gdb docs it isn't usable. */
-void cb_target(const char *str, void *data)
-{
- printf("TARGET> %s\n",str);
-}
-
-void cb_log(const char *str, void *data)
-{
- printf("LOG> %s\n",str);
-}
-
-void cb_to(const char *str, void *data)
-{
- printf(">> %s",str);
-}
-
-void cb_from(const char *str, void *data)
-{
- printf("<< %s\n",str);
-}
-
-static int async_c=0;
-
-void cb_async(mi_output *o, void *data)
-{
- printf("ASYNC\n");
- async_c++;
-}
-
-
-static void dumpText(const char* message)
-{
- FILE* file = fopen(dumpFileName, "w");
- GNUNET_assert(NULL != file);
- fprintf(file,"%s", message);
- fclose(file);
-}
-
-
-void send_bug_mail(mi_stop* sr, mi_frames* f)
-{
- char *message;
- GNUNET_asprintf(&message,
- "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n",
- f->file, f->func, f->line, mi_reason_enum_to_str(sr->reason), sr->signal_name, sr->signal_meaning);
- if (strcasecmp(mode, "mail") == 0)
- sendMail(message);
- else
- dumpText(message);
-
- GNUNET_free (message);
-}
-
-
-int wait_for_stop(mi_h *h)
-{
- int res=1;
- mi_stop *sr;
- mi_frames *f;
-
- while (!mi_get_response(h))
- usleep(1000);
- /* The end of the async. */
- sr=mi_res_stop(h);
- if (sr)
- {
- f = gmi_stack_info_frame(h);
- if (f != NULL)
- send_bug_mail(sr, f);
- else
- GNUNET_break (0);
- mi_free_stop(sr);
- res = 0;
- }
- else
- {
- printf("Error while waiting\n");
- printf("mi_error: %d\nmi_error_from_gdb: %s\n",mi_error,mi_error_from_gdb);
- res=0;
- }
- return res;
-}
-
-
-
/**
- * Main function that will be run by the scheduler.
+ * Main function that will launch the action api.
*
* @param cls closure
* @param args remaining command-line arguments
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *c)
{
- struct GNUNET_MONKEY_ACTION_Context* cntxt =
- GNUNET_malloc(sizeof(struct GNUNET_MONKEY_ACTION_Context));
- cntxt->binary_name = binaryName;
- if (GNUNET_OK == GNUNET_MONKEY_ACTION_rerun_with_gdb(cntxt)) {
- GNUNET_MONKEY_ACTION_format_report(cntxt);
- GNUNET_MONKEY_ACTION_report_file(cntxt, dumpFileName);
+ int result;
+ struct GNUNET_MONKEY_ACTION_Context* cntxt;
+
+ if (strcasecmp(mode, "email") == 0) {
+ if (NULL == emailAddress) {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Working in email mode requires an email address!\n");
+ ret = 1;
+ return;
+ }
+ } else if (strcasecmp(mode, "text") == 0) {
+ if (NULL == dumpFileName) {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Working in text mode requires a path for the dump file!\n");
+ ret = 1;
+ return;
+ }
}
-// mi_aux_term *xterm_tty=NULL;
-//
-// /* This is like a file-handle for fopen.
-// Here we have all the state of gdb "connection". */
-// mi_h *h;
-//
-// /* Connect to gdb child. */
-// h=mi_connect_local();
-// if (!h)
-// {
-// printf("Connect failed\n");
-// ret = 1;
-// return;
-// }
-// printf("Connected to gdb!\n");
-//
-// /* Set all callbacks. */
-// mi_set_console_cb(h,cb_console,NULL);
-// mi_set_target_cb(h,cb_target,NULL);
-// mi_set_log_cb(h,cb_log,NULL);
-// mi_set_async_cb(h,cb_async,NULL);
-// mi_set_to_gdb_cb(h,cb_to,NULL);
-// mi_set_from_gdb_cb(h,cb_from,NULL);
-//
-// /* Set the name of the child and the command line aguments. */
-// if (!gmi_set_exec(h, binaryName, NULL))
-// {
-// printf("Error setting exec y args\n");
-// mi_disconnect(h);
-// ret = 1;
-// return;
-// }
-//
-// /* Tell gdb to attach the child to a terminal. */
-// if (!gmi_target_terminal(h, ttyname(STDIN_FILENO)))
-// {
-// printf("Error selecting target terminal\n");
-// mi_disconnect(h);
-// ret = 1;
-// return;
-// }
-//
-// /* Run the program. */
-// if (!gmi_exec_run(h))
-// {
-// printf("Error in run!\n");
-// mi_disconnect(h);
-// ret = 1;
-// return;
-// }
-// /* Here we should be stopped when the program crashes */
-// if (!wait_for_stop(h))
-// {
-// mi_disconnect(h);
-// ret = 1;
-// return;
-// }
-//
-// /* Continue execution. */
-// if (!gmi_exec_continue(h))
-// {
-// printf("Error in continue!\n");
-// mi_disconnect(h);
-// ret = 1;
-// return;
-// }
-// /* Here we should be terminated. */
-// if (!wait_for_stop(h))
-// {
-// mi_disconnect(h);
-// ret = 1;
-// return;
-// }
-//
-// /* Exit from gdb. */
-// gmi_gdb_exit(h);
-// /* Close the connection. */
-// mi_disconnect(h);
-// /* Wait 5 seconds and close the auxiliar terminal. */
-// printf("Waiting 5 seconds\n");
-// sleep(5);
-// gmi_end_aux_term(xterm_tty);
+ cntxt = GNUNET_malloc(sizeof(struct GNUNET_MONKEY_ACTION_Context));
+ cntxt->binary_name = binaryName;
+ result = GNUNET_MONKEY_ACTION_rerun_with_gdb(cntxt);
+ switch (result) {
+ case GDB_STATE_ERROR:
+ break;
+ case GDB_STATE_EXIT_NORMALLY:
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Debug with gdb, program exited normally!\n");
+ /*FIXME: Valgrind should be launched here */
+ break;
+ case GDB_STATE_STOPPED:
+ /*FIXME: Expression Database should be inspected here (before writing the report) */
+ if(GNUNET_OK != GNUNET_MONKEY_ACTION_format_report(cntxt)){
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in generating debug report!\n");
+ ret = 1;
+ }
+ if (strcasecmp(mode, "email") == 0) {
+ if (GNUNET_OK != GNUNET_MONKEY_ACTION_report_email(cntxt)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error sending email!\n");
+ ret = 1;
+ }
+ } else {
+ /* text mode */
+ if (GNUNET_OK != GNUNET_MONKEY_ACTION_report_file(cntxt, dumpFileName)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in saving debug file!\n");
+ ret = 1;
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
int main(int argc, char *argv[])
{
- /*
- * FIXME:
- * Command should accept email address to which monkey sends the debugging report.
- * The email address can also be read from the configuration file.
- */
static const struct GNUNET_GETOPT_CommandLineOption options[] = {
{'m', "mode", NULL, gettext_noop ("monkey's mode of operation: options are \"text\" or \"email\""),
GNUNET_YES, &GNUNET_GETOPT_set_string, &mode},
{'b', "binary", NULL, gettext_noop ("binary for program to debug with monkey"),
GNUNET_YES, &GNUNET_GETOPT_set_string, &binaryName},
- {'o', "output", NULL, gettext_noop ("path to file to dump monkey's output in case of working in text mode"),
+ {'o', "output", NULL, gettext_noop ("path to file to dump monkey's output in case of text mode"),
GNUNET_YES, &GNUNET_GETOPT_set_string, &dumpFileName},
+ {'a', "address", NULL, gettext_noop ("address to send email to in case of email mode"),
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &emailAddress},
GNUNET_GETOPT_OPTION_END
};