WiP
[oweals/gnunet.git] / src / monkey / gnunet-monkey.c
index 3d93a51128a0c47a73ab6d5952daa64390aac0d6..7821936bf7d8df2f71cfd0f928f5403971e29d8d 100644 (file)
-/**[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"
-
-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)
+#include "platform.h"
+#include "gnunet_common.h"
+#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)
 {
- printf("ASYNC\n");
- async_c++;
+       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)
-   {
-    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
-    printf("Received signal name: %s\n", sr->signal_name);
-    printf("Received signal meaning: %s\n", sr->signal_meaning);
-    //printf("In file: %s\n", sr->frame->file);
-    //printf("Line Number: %d\n", sr->frame->line);
-    f = gmi_stack_info_frame(h);
-    mi_free_stop(sr);
-   }
- 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;
+ 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
+   };
  
- /* 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,"bug_null_pointer_exception", 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 (argc < 2) {
+        printf("%s", "Monkey should take arguments: Use --help to get a list of options.\n");
+        return 1;
+ }
+ if (GNUNET_OK == GNUNET_PROGRAM_run (argc,
+                       argv,
+                       "gnunet-monkey",
+                       gettext_noop
+                       ("Automatically debug a service"),
+                       options, &run, NULL))
+     {
+       return ret;
+     }
+
+     return 1;
 }
+