abrt-cli uses commands now instead of switches for main purpose.
Usage string for abrt-cli:
abrt-cli [--version] [--base-dir=DUMP_DIR] <command> [<args>]
--base-dir - change base dir for dump directories
--version - print out version and die
commands are:
list
delete
report
Each command can take it's own arguments.
list command takes two switches -d -f, where -d behaves as old --info switch. Show
more detailed information about crash (all if not specified exactly dump-dir) and
with -f switch shows even multiline files from dump-dir
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
abrt.spec.in | 4 +-
configure.ac | 1 +
src/Makefile.am | 2 +-
src/cli/Makefile.am | 25 ++++++
src/cli/abrt-cli.c | 146 ++++++++++++++++++++++++++++++++++
src/cli/builtin-cmd.h | 27 +++++++
src/cli/list.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++
src/cli/report.c | 45 +++++++++++
src/cli/rm.c | 53 +++++++++++++
9 files changed, 506 insertions(+), 3 deletions(-)
create mode 100644 src/cli/Makefile.am
create mode 100644 src/cli/abrt-cli.c
create mode 100644 src/cli/builtin-cmd.h
create mode 100644 src/cli/list.c
create mode 100644 src/cli/report.c
create mode 100644 src/cli/rm.c
diff --git a/abrt.spec.in b/abrt.spec.in
index 2f53f76..351eb5e 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -235,8 +235,6 @@ mkdir -p $RPM_BUILD_ROOT/var/cache/abrt-di
mkdir -p $RPM_BUILD_ROOT/var/run/abrt
mkdir -p $RPM_BUILD_ROOT/var/spool/abrt
mkdir -p $RPM_BUILD_ROOT/var/spool/abrt-upload
-# compat before we split abrt-cli and report-cli
-ln -s %{_bindir}/report-cli $RPM_BUILD_ROOT/%{_bindir}/abrt-cli
desktop-file-install \
--dir ${RPM_BUILD_ROOT}%{_datadir}/applications \
@@ -513,6 +511,8 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null ||
:
%files cli
%defattr(-,root,root,-)
%{_bindir}/abrt-cli
+# provide asap
+#% {_mandir}/man1/report-cli.1.gz
%files desktop
%defattr(-,root,root,-)
diff --git a/configure.ac b/configure.ac
index baf0f01..3b2a669 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,6 +145,7 @@ AC_CONFIG_FILES([
src/hooks/abrt-install-ccpp-hook
src/applet/Makefile
src/gui-gtk/Makefile
+ src/cli/Makefile
po/Makefile.in
icons/Makefile
])
diff --git a/src/Makefile.am b/src/Makefile.am
index b41b939..ab95ef7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1 +1 @@
-SUBDIRS = include lib hooks daemon applet gui-gtk plugins
+SUBDIRS = include lib hooks daemon applet gui-gtk plugins cli
diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am
new file mode 100644
index 0000000..c5ebc14
--- /dev/null
+++ b/src/cli/Makefile.am
@@ -0,0 +1,25 @@
+-include ../../config.mak
+
+bin_PROGRAMS = abrt-cli
+
+CLI_C =
+CLI_C += abrt-cli.c
+
+BUILTIN_C =
+BUILTIN_C += list.c
+BUILTIN_C += rm.c
+BUILTIN_C += report.c
+
+abrt_cli_SOURCES = $(CLI_C) $(BUILTIN_C) builtin-cmd.h
+
+abrt_cli_CFLAGS = \
+ -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
+ $(LIBREPORT_CFLAGS) \
+ -Wwrite-strings -Werror
+
+abrt_cli_LDADD = \
+ $(LIBREPORT_LIBS)
+
+DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
diff --git a/src/cli/abrt-cli.c b/src/cli/abrt-cli.c
new file mode 100644
index 0000000..79d17bb
--- /dev/null
+++ b/src/cli/abrt-cli.c
@@ -0,0 +1,146 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "abrtlib.h"
+#include "builtin-cmd.h"
+
+#define USAGE_OPTS_WIDTH 12
+#define USAGE_GAP 2
+
+/* TODO: add --pager(default) and --no-pager */
+
+/* better way to set <base-dir> as environ variable? */
+GList *D_list = NULL;
+
+const char abrt_cli_usage_string[] =
+ "abrt-cli [--version] [--base-dir=DUMP_DIR] <command>
[<args>]";
+
+struct cmd_struct {
+ const char *cmd;
+ int (*fn)(int, const char **);
+ const char *help;
+};
+
+static void list_cmds_help(const struct cmd_struct *commands)
+{
+ for (const struct cmd_struct *p = commands; p->cmd; ++p)
+ {
+ size_t pos;
+ int pad;
+
+ pos = fprintf(stderr, " ");
+ pos += fprintf(stderr, "%s", p->cmd);
+
+ if (pos <= USAGE_OPTS_WIDTH)
+ pad = USAGE_OPTS_WIDTH - pos;
+ else
+ {
+ fputc('\n', stderr);
+ pad = USAGE_OPTS_WIDTH;
+ }
+
+ fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", p->help);
+ }
+}
+
+static void handle_internal_options(int *argc, const char ***argv)
+{
+ while (*argc > 0)
+ {
+ const char *cmd = (*argv)[0];
+ if (cmd[0] != '-')
+ break;
+
+ if (strcmp(cmd, "--version") == 0)
+ {
+ puts(PACKAGE_VERSION);
+ exit(0);
+ }
+ else if (prefixcmp(cmd, "--base-dir=") == 0)
+ D_list = g_list_append(D_list, xstrdup(cmd +
strlen("--base-dir=")));
+#if 0
+ else if (prefixcmp(cmd, "--list-events") == 0)
+ {
+ const char *pfx = cmd + strlen("--list-events");
+ if (pfx && *pfx)
+ pfx += 1; /* skip '=' */
+
+ char *events = list_possible_events(NULL, dump_dir_name, pfx);
+ if (!events)
+ exit(1); /* error msg is already logged */
+
+ fputs(events, stdout);
+ free(events);
+
+ exit(0);
+ }
+#endif
+ else
+ error_msg_and_die("usage: %s", abrt_cli_usage_string);
+
+ (*argv)++;
+ (*argc)--;
+ }
+}
+
+static void handle_internal_command(int argc, const char **argv,
+ const struct cmd_struct *commands)
+{
+ const char *cmd = argv[0];
+
+ for (const struct cmd_struct *p = commands; p->cmd; ++p)
+ {
+ if (strcmp(p->cmd, cmd))
+ continue;
+
+ exit(p->fn(argc, argv));
+ }
+}
+
+int main(int argc, const char **argv)
+{
+ abrt_init((char **)argv);
+
+ setlocale(LC_ALL, "");
+#if ENABLE_NLS
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
+
+ argv++;
+ argc--;
+
+ const struct cmd_struct commands[] = {
+ {"list", cmd_list, _("List not yet reported problems")},
+ {"rm", cmd_rm, _("Remove files from problem directory")},
+ {"report", cmd_report, _("Analyze and report problem data in
problem directory")},
+ {NULL, NULL, NULL}
+ };
+
+ handle_internal_options(&argc, &argv);
+ if (argc > 0)
+ handle_internal_command(argc, argv, commands);
+
+ /* user didn't specify command; print out help */
+ printf("%s\n\n", abrt_cli_usage_string);
+ list_cmds_help(commands);
+ printf("\n%s\n", _("See 'abrt-cli <command> -h' for more
information"));
+
+ return 0;
+}
diff --git a/src/cli/builtin-cmd.h b/src/cli/builtin-cmd.h
new file mode 100644
index 0000000..28aa753
--- /dev/null
+++ b/src/cli/builtin-cmd.h
@@ -0,0 +1,27 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef _BUILTIN_CMD_H_
+#define _BUILTIN_CMD_H_
+
+extern int cmd_list(int argc, const char **argv);
+extern int cmd_rm(int argc, const char **argv);
+extern int cmd_report(int argc, const char **argv);
+
+#endif /* _BUILTIN-CMD_H_ */
diff --git a/src/cli/list.c b/src/cli/list.c
new file mode 100644
index 0000000..bdb371f
--- /dev/null
+++ b/src/cli/list.c
@@ -0,0 +1,206 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "abrtlib.h"
+#include "builtin-cmd.h"
+
+extern GList *D_list;
+
+/* TODO: npajkovs
+ * add --since
+ * add --until
+ * add --pretty=oneline|raw|normal|format="%a %b %c"
+ * add wildcard e.g. *-2011-04-01-10-* (list all problems in specific day)
+ *
+ * TODO?: remove base dir from list of crashes? is there a way that same crash can be in
+ * ~/.abrt/spool and /var/spool/abrt? needs more _meditation_.
+ */
+
+/* Vector of problems: */
+/* problem_data_vector[i] = { "name" = { "content", CD_FLAG_foo_bits
} } */
+typedef GPtrArray vector_of_problem_data_t;
+
+static inline problem_data_t *get_problem_data(vector_of_problem_data_t *vector, unsigned
i)
+{
+ return (problem_data_t *)g_ptr_array_index(vector, i);
+}
+
+static void free_vector_of_problem_data(vector_of_problem_data_t *vector)
+{
+ if (vector)
+ g_ptr_array_free(vector, TRUE);
+}
+
+static vector_of_problem_data_t *new_vector_of_problem_data(void)
+{
+ return g_ptr_array_new_with_free_func((void (*)(void*)) &free_problem_data);
+}
+
+static problem_data_t *fill_crash_info(const char *dump_dir_name)
+{
+ int sv_logmode = logmode;
+ logmode = 0; /* suppress EPERM/EACCES errors in opendir */
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ DD_OPEN_READONLY);
+ logmode = sv_logmode;
+
+ if (!dd)
+ return NULL;
+
+ problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
+ dd_close(dd);
+ add_to_problem_data_ext(problem_data, CD_DUMPDIR, dump_dir_name,
+ CD_FLAG_TXT + CD_FLAG_ISNOTEDITABLE + CD_FLAG_LIST);
+
+ return problem_data;
+}
+
+static void get_all_crash_infos(vector_of_problem_data_t *retval, const char *dir_name)
+{
+ VERB1 log("Loading dumps from '%s'", dir_name);
+
+ DIR *dir = opendir(dir_name);
+ if (dir != NULL)
+ {
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ char *dump_dir_name = concat_path_file(dir_name, dent->d_name);
+
+ struct stat statbuf;
+ if (stat(dump_dir_name, &statbuf) == 0
+ && S_ISDIR(statbuf.st_mode))
+ {
+ problem_data_t *problem_data = fill_crash_info(dump_dir_name);
+ if (problem_data)
+ g_ptr_array_add(retval, problem_data);
+ }
+ free(dump_dir_name);
+ }
+ closedir(dir);
+ }
+}
+
+/** Prints basic information about a crash to stdout. */
+static void print_crash(problem_data_t *problem_data, int detailed)
+{
+ char *desc;
+ if (detailed)
+ {
+ int show_multiline = (detailed ? MAKEDESC_SHOW_MULTILINE : 0);
+ desc = make_description(problem_data,
+ /*names_to_skip:*/ NULL,
+ /*max_text_size:*/ CD_TEXT_ATT_SIZE,
+ MAKEDESC_SHOW_FILES | show_multiline);
+ }
+ else
+ {
+ desc = make_description(problem_data,
+ /*names_to_skip:*/ NULL,
+ /*max_text_size:*/ CD_TEXT_ATT_SIZE,
+ MAKEDESC_SHOW_ONLY_LIST);
+ }
+ fputs(desc, stdout);
+ free(desc);
+}
+
+/**
+ * Prints a list containing "crashes" to stdout.
+ * @param include_reported
+ * Do not skip entries marked as already reported.
+ */
+static void print_crash_list(vector_of_problem_data_t *crash_list, int include_reported,
+ int detailed)
+{
+ unsigned i;
+ for (i = 0; i < crash_list->len; ++i)
+ {
+ problem_data_t *crash = get_problem_data(crash_list, i);
+ if (!include_reported)
+ {
+ const char *msg = get_problem_item_content_or_NULL(crash,
FILENAME_REPORTED_TO);
+ if (msg)
+ continue;
+ }
+ puts("");
+ print_crash(crash, detailed);
+ }
+}
+
+int cmd_list(int argc, const char **argv)
+{
+ const char *program_usage_string = _(
+ "\b list [options] [<dump-dir>]..."
+ );
+
+ static int opt_full, opt_detailed;
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_GROUP(""),
+ OPT_BOOL('f', "full" , &opt_full, _("List
even reported problems")),
+ /* deprecate -d option with --pretty=full*/
+ OPT_BOOL('d', "detailed" , &opt_detailed, _("Show
detailed report")),
+ OPT_END()
+ };
+
+ parse_opts(argc, (char **)argv, program_options, program_usage_string);
+
+ if (optind < argc)
+ {
+ while (optind < argc)
+ {
+ problem_data_t *problem = fill_crash_info(argv[optind++]);
+ print_crash(problem, opt_detailed);
+ free_problem_data(problem);
+ printf("\n");
+ }
+ exit(0);
+ }
+
+ if (!D_list)
+ {
+ char *home = getenv("HOME");
+ if (home)
+ D_list = g_list_append(D_list, concat_path_file(home,
".abrt/spool"));
+ D_list = g_list_append(D_list, xstrdup((void*)DEBUG_DUMPS_DIR));
+ }
+
+ VERB2
+ {
+ log("Base directory");
+ for (GList *li = D_list; li; li = li->next)
+ log("\t %s", (char *) li->data);
+ }
+
+ vector_of_problem_data_t *ci = new_vector_of_problem_data();
+ while (D_list)
+ {
+ char *dir = (char *)D_list->data;
+ get_all_crash_infos(ci, dir);
+ D_list = g_list_remove(D_list, dir);
+ free(dir);
+ }
+ print_crash_list(ci, opt_full, opt_detailed);
+ free_vector_of_problem_data(ci);
+ g_list_free(D_list);
+
+ return 0;
+}
diff --git a/src/cli/report.c b/src/cli/report.c
new file mode 100644
index 0000000..8d9f006
--- /dev/null
+++ b/src/cli/report.c
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "abrtlib.h"
+#include "builtin-cmd.h"
+
+int cmd_report(int argc, const char **argv)
+{
+ const char *program_usage_string = _(
+ "\b report [options] [<dump-dir>]..."
+ );
+
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_END()
+ };
+
+ parse_opts(argc, (char **)argv, program_options, program_usage_string);
+ if (optind < argc)
+ {
+ while (optind < argc)
+ {
+ report_problem_in_dir(argv[optind++], LIBREPORT_ANALYZE | LIBREPORT_NOWAIT);
+ log("report '%s'", argv[optind++]);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/cli/rm.c b/src/cli/rm.c
new file mode 100644
index 0000000..eac01af
--- /dev/null
+++ b/src/cli/rm.c
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "abrtlib.h"
+#include "builtin-cmd.h"
+
+/* TODO npajkovs:
+ * add -n, --dry-run
+ * add -q, --quite
+ */
+
+int cmd_rm(int argc, const char **argv)
+{
+ const char *program_usage_string = _(
+ "\b rm [options] [<dump-dir>]..."
+ );
+
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_END()
+ };
+
+ parse_opts(argc, (char **)argv, program_options, program_usage_string);
+ if (optind < argc)
+ {
+ int status;
+ while (optind < argc)
+ {
+ const char *rm_dir = argv[optind++];
+ status = delete_dump_dir_possibly_using_abrtd(rm_dir);
+ if (!status)
+ log("rm '%s'", rm_dir);
+ }
+ }
+
+ return 0;
+}
--
1.7.6.rc3