-/**[txh]********************************************************************
-
- 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.).
-
-***************************************************************************/
+/*
+ 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.
+*/
+
+/**
+ * @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"
-
-
-extern void sendMail (const char *messageContents);
-
-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);
-}
-
-volatile int async_c=0;
-
-void cb_async(mi_output *o, void *data)
-{
- printf("ASYNC\n");
- async_c++;
-}
-
-
-void send_bug_mail(mi_stop* sr, mi_frames* f)
+#include "gnunet_getopt_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_monkey_action.h"
+
+static const char* mode;
+static const char* dumpFileName;
+static const char* binaryName;
+static const char* emailAddress;
+static const char* edbFilePath;
+static const char* gdbBinaryPath;
+static int ret = 0;
+
+/**
+ * Main function that will launch the action api.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
{
- 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);
- sendMail(message);
- GNUNET_free (message);
+ 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;
+ }
+ }
+
+ /* Initialize context for the Action API */
+ cntxt = GNUNET_malloc(sizeof(struct GNUNET_MONKEY_ACTION_Context));
+ cntxt->binary_name = binaryName;
+ cntxt->expression_database_path = edbFilePath;
+ cntxt->gdb_binary_path = gdbBinaryPath;
+
+ 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_inspect_expression_database(cntxt)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error using Expression Database!\n");
+ ret = 1;
+ break;
+ }
+ 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 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);
- send_bug_mail(sr, f);
- 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;
-}
-
int main(int argc, char *argv[])
{
- mi_aux_term *xterm_tty=NULL;
- const char* binaryName;
+ 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 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},
+ {'d', "database", NULL, gettext_noop ("path to Expression Database file"),
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &edbFilePath},
+ {'g', "gdb", NULL, gettext_noop ("path to gdb binary in use; default is /usr/bin/gdb"),
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &gdbBinaryPath},
+ GNUNET_GETOPT_OPTION_END
+ };
- binaryName = argv[1];
- GNUNET_assert(NULL != binaryName);
+ if (argc < 2) {
+ printf("%s", "Monkey should take arguments: Use --help to get a list of options.\n");
+ return 1;
+ }
- /* 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");
- return 1;
- }
- 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);
- return 1;
- }
-
- /* 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);
- return 1;
- }
-
- /* Run the program. */
- if (!gmi_exec_run(h))
- {
- printf("Error in run!\n");
- mi_disconnect(h);
- return 1;
- }
- /* Here we should be stopped when the program crashes */
- if (!wait_for_stop(h))
- {
- mi_disconnect(h);
- return 1;
- }
-
- /* Continue execution. */
- if (!gmi_exec_continue(h))
- {
- printf("Error in continue!\n");
- mi_disconnect(h);
- return 1;
- }
- /* Here we should be terminated. */
- if (!wait_for_stop(h))
- {
- mi_disconnect(h);
- return 1;
- }
-
- /* 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 0;
+ if (GNUNET_OK == GNUNET_PROGRAM_run (argc,
+ argv,
+ "gnunet-monkey",
+ gettext_noop
+ ("Automatically debug a service"),
+ options, &run, NULL))
+ {
+ return ret;
+ }
+
+ return 1;
}
+