From c9f43d22c5bf1d1bb392ee426c72d383b2241bbe Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Mon, 19 Oct 2009 12:02:25 +0200 Subject: ABRTSocket renamed DisConnect to Disconnect, CLI added localization support and commandline editor work in progress --- src/CLI/ABRTSocket.cpp | 9 +- src/CLI/ABRTSocket.h | 2 +- src/CLI/CLI.cpp | 219 ++++++++++++++++++++++++++++++++++++------------- src/CLI/Makefile.am | 1 + 4 files changed, 169 insertions(+), 62 deletions(-) (limited to 'src/CLI') diff --git a/src/CLI/ABRTSocket.cpp b/src/CLI/ABRTSocket.cpp index 1f90f63a..d31c7a4f 100644 --- a/src/CLI/ABRTSocket.cpp +++ b/src/CLI/ABRTSocket.cpp @@ -8,13 +8,12 @@ #include #include -CABRTSocket::CABRTSocket() : - m_nSocket(-1) +CABRTSocket::CABRTSocket() : m_nSocket(-1) {} CABRTSocket::~CABRTSocket() { - DisConnect(); + Disconnect(); } void CABRTSocket::Send(const std::string& pMessage) @@ -91,12 +90,10 @@ void CABRTSocket::Connect(const std::string& pPath) } } -void CABRTSocket::DisConnect() +void CABRTSocket::Disconnect() { if (m_nSocket != -1) - { close(m_nSocket); - } } vector_crash_infos_t CABRTSocket::GetCrashInfos() diff --git a/src/CLI/ABRTSocket.h b/src/CLI/ABRTSocket.h index d476411c..5d5383fa 100644 --- a/src/CLI/ABRTSocket.h +++ b/src/CLI/ABRTSocket.h @@ -18,7 +18,7 @@ class CABRTSocket ~CABRTSocket(); void Connect(const std::string& pPath); - void DisConnect(); + void Disconnect(); vector_crash_infos_t GetCrashInfos(); map_crash_report_t CreateReport(const std::string& pUUID); diff --git a/src/CLI/CLI.cpp b/src/CLI/CLI.cpp index 33272df5..d4e2bb4b 100644 --- a/src/CLI/CLI.cpp +++ b/src/CLI/CLI.cpp @@ -24,6 +24,15 @@ #if HAVE_CONFIG_H #include #endif +#if HAVE_LOCALE_H + #include +#endif +#if ENABLE_NLS + #include + #define _(S) gettext(S) +#else + #define _(S) (S) +#endif /* Program options */ enum @@ -47,25 +56,54 @@ static void print_crash_infos(vector_crash_infos_t& pCrashInfos, int pMode) map_crash_info_t& info = pCrashInfos[ii]; if (pMode == OPT_GET_LIST_FULL || info.find(CD_REPORTED)->second[CD_CONTENT] != "1") { - printf("%u.\n" - "\tUID : %s\n" - "\tUUID : %s\n" - "\tPackage : %s\n" - "\tExecutable: %s\n" - "\tCrash time: %s\n" - "\tCrash Rate: %s\n", - ii, - info[CD_UID][CD_CONTENT].c_str(), - info[CD_UUID][CD_CONTENT].c_str(), - info[CD_PACKAGE][CD_CONTENT].c_str(), - info[CD_EXECUTABLE][CD_CONTENT].c_str(), - info[CD_TIME][CD_CONTENT].c_str(), - info[CD_COUNT][CD_CONTENT].c_str() - ); + const char *timestr = info[CD_TIME][CD_CONTENT].c_str(); + long time = strtol(timestr, 0, 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."); + + printf(_("%u.\n" + "\tUID : %s\n" + "\tUUID : %s\n" + "\tPackage : %s\n" + "\tExecutable : %s\n" + "\tCrash Time : %s\n" + "\tCrash Count: %s\n"), + ii, + info[CD_UID][CD_CONTENT].c_str(), + info[CD_UUID][CD_CONTENT].c_str(), + info[CD_PACKAGE][CD_CONTENT].c_str(), + info[CD_EXECUTABLE][CD_CONTENT].c_str(), + timeloc, + info[CD_COUNT][CD_CONTENT].c_str() + ); } } } +/* Saves the crash report to a file. + * Fp must be opened before write_crash_report is called. + * Returned Value: + * If the report is successfully stored to the file, a zero value is returned. + * On failure, nonzero value is returned. + */ +static int write_crash_report(const map_crash_report_t& report, FILE *fp) +{ + for (map_crash_report_t::const_iterator it = report.begin(); it != report.end(); it++) + { + if (it->second[CD_TYPE] == CD_SYS) + continue; + + fprintf(fp, "\n%s\n-----\n%s\n", it->first.c_str(), it->second[CD_CONTENT].c_str()); + } + + return 0; +} + static void print_crash_report(const map_crash_report_t& pCrashReport) { map_crash_report_t::const_iterator it = pCrashReport.begin(); @@ -92,6 +130,7 @@ static DBusMessage* new_call_msg(const char* method) die_out_of_memory(); return msg; } + static DBusMessage* send_get_reply_and_unref(DBusMessage* msg) { DBusError err; @@ -99,7 +138,7 @@ static DBusMessage* send_get_reply_and_unref(DBusMessage* msg) DBusMessage *reply = dbus_connection_send_with_reply_and_block(s_dbus_conn, msg, /*timeout*/ -1, &err); if (reply == NULL) { -//TODO: analyse err + //TODO: analyse err error_msg_and_die("Error sending DBus message"); } dbus_message_unref(msg); @@ -109,7 +148,6 @@ static DBusMessage* send_get_reply_and_unref(DBusMessage* msg) static vector_crash_infos_t call_GetCrashInfos() { DBusMessage* msg = new_call_msg("GetCrashInfos"); - DBusMessage *reply = send_get_reply_and_unref(msg); vector_crash_infos_t argout; @@ -189,6 +227,76 @@ static void handle_dbus_err(bool error_flag, DBusError *err) CC_DBUS_NAME); } +int launch_editor(const char *path, const char *report, char **output) +{ + const char *editor, *terminal; + + editor = getenv("VISUAL"); + if (!editor) + editor = getenv("EDITOR"); + + terminal = getenv("TERM"); + if (!editor && (!terminal || !strcmp(terminal, "dumb"))) + { + error_msg(_("Terminal is dumb but no VISUAL nor EDITOR defined.")); + return 1; + } + + if (!editor) + editor = "vi"; + + return 0; +} + +/* Reports the crash with corresponding uuid over DBus. */ +int report(const char *uuid, bool always) +{ + map_crash_report_t cr = call_CreateReport(uuid); + + if (always) + { + call_Report(cr); + return 0; + } + + print_crash_report(cr); + + /* Open a temporary file and write the crash report to it. */ + char filename[] = "/tmp/abrt-report.XXXXXX"; + int fd = mkstemp(filename); + if (fd == -1) + { + error_msg("could not generate temporary file name"); + return 1; + } + + FILE *fp = fdopen(fd, "w"); + if (!fp) + { + error_msg("could not open '%s' to save the crash report", filename); + return 1; + } + + write_crash_report(cr, fp); + + if (fclose(fp)) + { + error_msg("could not close '%s'", filename); + return 2; + } + + printf(_("\nDo you want to send the report? [y/n]: ")); + fflush(NULL); + char answer[16] = "n"; + fgets(answer, sizeof(answer), stdin); + if (answer[0] == 'Y' || answer[0] == 'y') + { + call_Report(cr); + } + + return 0; +} + static const struct option longopts[] = { /* name, has_arg, flag, val */ @@ -202,7 +310,7 @@ static const struct option longopts[] = { 0, 0, 0, 0 } /* prevents crashes for unknown options*/ }; -/* Gets program name from command line argument. */ +/* Gets the program name from the first command line argument. */ static char *progname(char *argv0) { char* name = strrchr(argv0, '/'); @@ -212,12 +320,38 @@ static char *progname(char *argv0) return argv0; } +/* Prints abrt-cli version and some help text. */ +static void usage(char *argv0) +{ + char *name = progname(argv0); + printf("%s " VERSION "\n\n", name); + + /* Message has embedded tabs. */ + printf(_("Usage: %s [OPTION]\n\n" + "Startup:\n" + " -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 UUID create and send a report\n" + " --report-always UUID create and send a report without asking\n" + " --delete UUID remove crash\n"), + name, name); +} + int main(int argc, char** argv) { char* uuid = NULL; int op = -1; char *name; + setlocale(LC_ALL,""); +#if ENABLE_NLS + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +#endif + while (1) { int option_index; @@ -233,7 +367,7 @@ int main(int argc, char** argv) case OPT_GET_LIST_FULL: if (op == -1) break; - error_msg("You must specify exactly one operation."); + error_msg(_("You must specify exactly one operation.")); return 1; case -1: /* end of options */ if (op != -1) /* if some operation was specified... */ @@ -242,25 +376,12 @@ int main(int argc, char** argv) default: case '?': case OPT_HELP: - name = progname(argv[0]); - printf("%s " VERSION "\n\n", name); - /* note: message has embedded tabs */ - printf("Usage: %s [OPTION]\n\n" - "Startup:\n" - " -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 UUID create and send a report\n" - " --report-always UUID create and send a report without asking\n" - " --delete UUID remove crash\n", - name, name); - return 1; + usage(argv[0]); + return 1; case 'V': case OPT_VERSION: - printf("%s " VERSION "\n", progname(argv[0])); - return 0; + printf("%s " VERSION "\n", progname(argv[0])); + return 0; } if (c == -1) break; @@ -276,6 +397,7 @@ int main(int argc, char** argv) CABRTSocket ABRTDaemon; ABRTDaemon.Connect(VAR_RUN"/abrt.socket"); #endif + switch (op) { case OPT_GET_LIST: @@ -286,33 +408,20 @@ int main(int argc, char** argv) break; } case OPT_REPORT: - { - map_crash_report_t cr = call_CreateReport(uuid); - print_crash_report(cr); - printf("\nDo you want to send the report? [y/n]: "); - fflush(NULL); - char answer[16] = "n"; - fgets(answer, sizeof(answer), stdin); - if (answer[0] == 'Y' || answer[0] == 'y') - { - call_Report(cr); - } - break; - } + report(uuid, false); + break; case OPT_REPORT_ALWAYS: - { - map_crash_report_t cr = call_CreateReport(uuid); - call_Report(cr); - break; - } + report(uuid, true); + break; case OPT_DELETE: { call_DeleteDebugDump(uuid); break; } } + #if ENABLE_SOCKET - ABRTDaemon.DisConnect(); + ABRTDaemon.Disconnect(); #endif return 0; diff --git a/src/CLI/Makefile.am b/src/CLI/Makefile.am index 0167149b..68109534 100644 --- a/src/CLI/Makefile.am +++ b/src/CLI/Makefile.am @@ -22,3 +22,4 @@ EXTRA_DIST = $(man_MANS) completiondir = $(sysconfdir)/bash_completion.d completion_DATA = abrt-cli.bash +DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ -- cgit