summaryrefslogtreecommitdiffstats
path: root/src/CLI/CLI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/CLI/CLI.cpp')
-rw-r--r--src/CLI/CLI.cpp240
1 files changed, 140 insertions, 100 deletions
diff --git a/src/CLI/CLI.cpp b/src/CLI/CLI.cpp
index cd530e75..d882161a 100644
--- a/src/CLI/CLI.cpp
+++ b/src/CLI/CLI.cpp
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2009 RedHat inc.
+ Copyright (C) 2009, 2010 Red Hat, 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
@@ -35,55 +35,54 @@
# define _(S) (S)
#endif
-/* Program options */
-enum
+/** Prints basic information about a crash to stdout. */
+static void print_crash(const map_crash_data_t &crash)
{
- OPT_VERSION,
- OPT_HELP,
- OPT_GET_LIST,
- OPT_GET_LIST_FULL,
- OPT_REPORT,
- OPT_REPORT_ALWAYS,
- OPT_DELETE
-};
+ /* Create a localized string from crash time. */
+ const char *timestr = get_crash_data_item_content(crash, FILENAME_TIME).c_str();
+ long time = xatou(timestr);
+ char timeloc[256];
+ int success = strftime(timeloc, 128, "%c", localtime(&time));
+ if (!success)
+ error_msg_and_die("Error while converting time to string.");
+
+ printf(_("\tUID : %s\n"
+ "\tUUID : %s\n"
+ "\tPackage : %s\n"
+ "\tExecutable : %s\n"
+ "\tCrash Time : %s\n"
+ "\tCrash Count: %s\n"),
+ get_crash_data_item_content(crash, CD_UID).c_str(),
+ get_crash_data_item_content(crash, CD_UUID).c_str(),
+ get_crash_data_item_content(crash, FILENAME_PACKAGE).c_str(),
+ get_crash_data_item_content(crash, FILENAME_EXECUTABLE).c_str(),
+ timeloc,
+ get_crash_data_item_content(crash, CD_COUNT).c_str());
+}
-static void print_crash_infos(vector_map_crash_data_t& pCrashInfos, int pMode)
+/**
+ * Prints a list containing "crashes" to stdout.
+ * @param include_reported
+ * Do not skip entries marked as already reported.
+ */
+static void print_crash_list(const vector_map_crash_data_t& crash_list, bool include_reported)
{
- unsigned int ii;
- for (ii = 0; ii < pCrashInfos.size(); ii++)
+ for (unsigned i = 0; i < crash_list.size(); ++i)
{
- map_crash_data_t& info = pCrashInfos[ii];
- if (pMode == OPT_GET_LIST_FULL || get_crash_data_item_content(info, CD_REPORTED) != "1")
- {
- const char *timestr = get_crash_data_item_content(info, FILENAME_TIME).c_str();
- long time = strtol(timestr, NULL, 10);
- if (time == 0)
- error_msg_and_die("Error while converting time string.");
-
- char timeloc[256];
- int success = strftime(timeloc, 128, "%c", localtime(&time));
- if (!success)
- error_msg_and_die("Error while converting time to string.");
+ const map_crash_data_t& crash = crash_list[i];
+ if (get_crash_data_item_content(crash, CD_REPORTED) == "1" && !include_reported)
+ continue;
- printf(_("%u.\n"
- "\tUID : %s\n"
- "\tUUID : %s\n"
- "\tPackage : %s\n"
- "\tExecutable : %s\n"
- "\tCrash Time : %s\n"
- "\tCrash Count: %s\n"),
- ii,
- get_crash_data_item_content(info, CD_UID).c_str(),
- get_crash_data_item_content(info, CD_UUID).c_str(),
- get_crash_data_item_content(info, FILENAME_PACKAGE).c_str(),
- get_crash_data_item_content(info, FILENAME_EXECUTABLE).c_str(),
- timeloc,
- get_crash_data_item_content(info, CD_COUNT).c_str()
- );
- }
+ printf("%u.\n", i);
+ print_crash(crash);
}
}
+/**
+ * Converts crash reference from user's input to unique crash identification
+ * in form UID:UUID.
+ * The returned string must be released by caller.
+ */
static char *guess_crash_id(const char *str)
{
vector_map_crash_data_t ci = call_GetCrashInfos();
@@ -122,16 +121,32 @@ static char *guess_crash_id(const char *str)
return result;
}
+/* Program options */
+enum
+{
+ OPT_GET_LIST,
+ OPT_REPORT,
+ OPT_DELETE
+};
+
+/**
+ * Long options.
+ * Do not use the has_arg field. Arguments are handled after parsing all options.
+ * The reason is that we want to use all the following combinations:
+ * --report ID
+ * --report ID --always
+ * --report --always ID
+ */
static const struct option longopts[] =
{
/* name, has_arg, flag, val */
- { "help" , no_argument , NULL, OPT_HELP },
- { "version" , no_argument , NULL, OPT_VERSION },
- { "get-list" , no_argument , NULL, OPT_GET_LIST },
- { "get-list-full", no_argument , NULL, OPT_GET_LIST_FULL },
- { "report" , required_argument, NULL, OPT_REPORT },
- { "report-always", required_argument, NULL, OPT_REPORT_ALWAYS },
- { "delete" , required_argument, NULL, OPT_DELETE },
+ { "help" , no_argument, NULL, '?' },
+ { "version", no_argument, NULL, 'V' },
+ { "list" , no_argument, NULL, 'l' },
+ { "full" , no_argument, NULL, 'f' },
+ { "always" , no_argument, NULL, 'y' },
+ { "report" , no_argument, NULL, 'r' },
+ { "delete" , no_argument, NULL, 'd' },
{ 0, 0, 0, 0 } /* prevents crashes for unknown options*/
};
@@ -144,7 +159,10 @@ static const char *progname(const char *argv0)
return argv0;
}
-/* Prints abrt-cli version and some help text. */
+/**
+ * Prints abrt-cli version and some help text.
+ * Then exits the program with return value 1.
+ */
static void usage(char *argv0)
{
const char *name = progname(argv0);
@@ -156,23 +174,27 @@ static void usage(char *argv0)
" -V, --version display the version of %s and exit\n"
" -?, --help print this help\n\n"
"Actions:\n"
- " --get-list print list of crashes which are not reported yet\n"
- " --get-list-full print list of all crashes\n"
- " --report CRASH_ID create and send a report\n"
- " --report-always CRASH_ID create and send a report without asking\n"
- " --delete CRASH_ID remove crash\n"
+ " -l, --list print list of crashes which are not reported yet\n"
+ " -f, --full list all crashes, including already reported ones\n"
+ " -r, --report CRASH_ID create and send a report\n"
+ " -y, --always create and send a report without asking\n"
+ " -d, --delete CRASH_ID remove crash\n"
"CRASH_ID can be:\n"
" UID:UUID pair,\n"
" unique UUID prefix - the crash with matching UUID will be acted upon\n"
- " @N - N'th crash (as displayed by --get-list-full) will be acted upon\n"
+ " @N - N'th crash (as displayed by --list --full) will be acted upon\n"
),
name, name);
+
+ exit(1);
}
int main(int argc, char** argv)
{
const char* crash_id = NULL;
int op = -1;
+ bool full = false;
+ bool always = false;
setlocale(LC_ALL, "");
#if ENABLE_NLS
@@ -183,70 +205,96 @@ int main(int argc, char** argv)
while (1)
{
int option_index;
- int c = getopt_long_only(argc, argv, "?V", longopts, &option_index);
+ /* Do not use colons, arguments are handled after parsing all options. */
+ int c = getopt_long_only(argc, argv, "?Vrdlfy",
+ longopts, &option_index);
+
+#define SET_OP(newop) \
+ if (op != -1 && op != newop) \
+ { \
+ error_msg(_("You must specify exactly one operation.")); \
+ return 1; \
+ } \
+ op = newop;
+
switch (c)
{
- case OPT_REPORT:
- case OPT_REPORT_ALWAYS:
- case OPT_DELETE:
- crash_id = optarg;
- /* fall through */
- case OPT_GET_LIST:
- case OPT_GET_LIST_FULL:
- if (op == -1)
- break;
- error_msg(_("You must specify exactly one operation."));
- return 1;
- case -1: /* end of options */
- if (op != -1) /* if some operation was specified... */
- break;
- /* fall through */
- default:
- case '?':
- case OPT_HELP:
- usage(argv[0]);
- return 1;
- case 'V':
- case OPT_VERSION:
- printf("%s "VERSION"\n", progname(argv[0]));
- return 0;
+ case 'r': SET_OP(OPT_REPORT); break;
+ case 'd': SET_OP(OPT_DELETE); break;
+ case 'l': SET_OP(OPT_GET_LIST); break;
+ case 'f': full = true; break;
+ case 'y': always = true; break;
+ case -1: /* end of options */ break;
+ default: /* some error */
+ case '?':
+ usage(argv[0]); /* exits app */
+ case 'V':
+ printf("%s "VERSION"\n", progname(argv[0]));
+ return 0;
}
+#undef SET_OP
if (c == -1)
break;
- op = c;
}
-#ifdef ENABLE_DBUS
+ /* Handle option arguments. */
+ int arg_count = argc - optind;
+ switch (arg_count)
+ {
+ case 0:
+ if (op == OPT_REPORT || op == OPT_DELETE)
+ usage(argv[0]);
+ break;
+ case 1:
+ if (op != OPT_REPORT && op != OPT_DELETE)
+ usage(argv[0]);
+ crash_id = argv[optind];
+ break;
+ default:
+ usage(argv[0]);
+ }
+
+ /* Check if we have an operation.
+ * Limit --full and --always to certain operations.
+ */
+ if ((full && op != OPT_GET_LIST) ||
+ (always && op != OPT_REPORT) ||
+ op == -1)
+ {
+ usage(argv[0]);
+ return 1;
+ }
+
DBusError err;
dbus_error_init(&err);
s_dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
handle_dbus_err(s_dbus_conn == NULL, &err);
-#elif ENABLE_SOCKET
- CABRTSocket ABRTDaemon;
- ABRTDaemon.Connect(VAR_RUN"/abrt.socket");
-#endif
+ /* Do the selected operation. */
int exitcode = 0;
switch (op)
{
case OPT_GET_LIST:
- case OPT_GET_LIST_FULL:
{
vector_map_crash_data_t ci = call_GetCrashInfos();
- print_crash_infos(ci, op);
+ print_crash_list(ci, full);
break;
}
case OPT_REPORT:
- case OPT_REPORT_ALWAYS:
- exitcode = report(crash_id, (op == OPT_REPORT_ALWAYS)*CLI_REPORT_BATCH + CLI_REPORT_SILENT_IF_NOT_FOUND);
+ {
+ int flags = CLI_REPORT_SILENT_IF_NOT_FOUND;
+ if (always)
+ flags |= CLI_REPORT_BATCH;
+ exitcode = report(crash_id, flags);
if (exitcode == -1) /* no such crash_id */
{
crash_id = guess_crash_id(crash_id);
- exitcode = report(crash_id, (op == OPT_REPORT_ALWAYS) * CLI_REPORT_BATCH);
+ exitcode = report(crash_id, always ? CLI_REPORT_BATCH : 0);
if (exitcode == -1)
error_msg_and_die("Crash '%s' not found", crash_id);
}
break;
+ }
case OPT_DELETE:
{
exitcode = call_DeleteDebugDump(crash_id);
@@ -255,21 +303,13 @@ int main(int argc, char** argv)
crash_id = guess_crash_id(crash_id);
exitcode = call_DeleteDebugDump(crash_id);
if (exitcode == ENOENT)
- {
error_msg_and_die("Crash '%s' not found", crash_id);
- }
}
if (exitcode != 0)
- {
error_msg_and_die("Can't delete debug dump '%s'", crash_id);
- }
break;
}
}
-#if ENABLE_SOCKET
- ABRTDaemon.Disconnect();
-#endif
-
return exitcode;
}