From 2cf0d770b66b6c6ce50af2767f575db552cd784c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 Nov 2010 15:29:24 +0100 Subject: move inc/ and lib/ to src/. No code changes Signed-off-by: Denys Vlasenko --- Makefile.am | 2 +- configure.ac | 5 +- inc/Makefile.am | 18 -- inc/abrt_exception.h | 57 ---- inc/abrt_types.h | 50 ---- inc/abrtlib.h | 269 ------------------ inc/action.h | 44 --- inc/analyzer.h | 34 --- inc/comm_layer_inner.h | 61 ---- inc/crash_types.h | 133 --------- inc/database.h | 134 --------- inc/dbus_common.h | 28 -- inc/dump_dir.h | 65 ----- inc/observer.h | 32 --- inc/plugin.h | 135 --------- inc/reporter.h | 48 ---- inc/xfuncs.h | 95 ------- lib/Makefile.am | 1 - lib/utils/ABRTException.cpp | 33 --- lib/utils/CommLayerInner.cpp | 94 ------- lib/utils/CrashTypes.cpp | 254 ----------------- lib/utils/Makefile.am | 109 -------- lib/utils/Plugin.cpp | 116 -------- lib/utils/Polkit.cpp | 102 ------- lib/utils/Polkit.h | 42 --- lib/utils/abrt_curl.c | 375 ------------------------- lib/utils/abrt_curl.h | 96 ------- lib/utils/abrt_dbus.c | 430 ----------------------------- lib/utils/abrt_dbus.h | 324 ---------------------- lib/utils/abrt_packages.c | 43 --- lib/utils/abrt_packages.h | 33 --- lib/utils/abrt_xmlrpc.cpp | 97 ------- lib/utils/abrt_xmlrpc.h | 48 ---- lib/utils/append_to_malloced_string.c | 27 -- lib/utils/concat_path_file.c | 25 -- lib/utils/copyfd.c | 172 ------------ lib/utils/daemon.c | 139 ---------- lib/utils/database.c | 73 ----- lib/utils/dirsize.c | 110 -------- lib/utils/dump_dir.c | 504 ---------------------------------- lib/utils/encbase64.c | 78 ------ lib/utils/hash_md5.c | 444 ------------------------------ lib/utils/hash_md5.h | 29 -- lib/utils/hash_sha1.c | 213 -------------- lib/utils/hash_sha1.h | 40 --- lib/utils/hooklib.c | 138 ---------- lib/utils/hooklib.h | 29 -- lib/utils/logging.c | 148 ---------- lib/utils/logging.h | 78 ------ lib/utils/make_descr.cpp | 287 ------------------- lib/utils/numtoa.cpp | 34 --- lib/utils/overlapping_strcpy.c | 22 -- lib/utils/parse_options.c | 182 ------------ lib/utils/parse_options.h | 53 ---- lib/utils/parse_release.cpp | 59 ---- lib/utils/read_write.c | 105 ------- lib/utils/read_write.h | 49 ---- lib/utils/run_event.c | 276 ------------------- lib/utils/skip_whitespace.c | 22 -- lib/utils/spawn.c | 156 ----------- lib/utils/stdio_helpers.c | 69 ----- lib/utils/strbuf.c | 147 ---------- lib/utils/strbuf.h | 103 ------- lib/utils/stringops.cpp | 57 ---- lib/utils/test.cpp | 105 ------- lib/utils/time.c | 65 ----- lib/utils/xatonum.c | 50 ---- lib/utils/xconnect.c | 415 ---------------------------- lib/utils/xfuncs.c | 400 --------------------------- scripts/dbg_rpminst | 10 +- scripts/dbg_rpmuninst | 2 +- src/Makefile.am | 2 +- src/applet/Makefile.am | 6 +- src/btparser/Makefile.am | 4 +- src/cli/Makefile.am | 8 +- src/daemon/Makefile.am | 28 +- src/hooks/Makefile.am | 12 +- src/include/Makefile.am | 18 ++ src/include/abrt_exception.h | 57 ++++ src/include/abrt_types.h | 50 ++++ src/include/abrtlib.h | 269 ++++++++++++++++++ src/include/action.h | 44 +++ src/include/analyzer.h | 34 +++ src/include/comm_layer_inner.h | 61 ++++ src/include/crash_types.h | 133 +++++++++ src/include/database.h | 134 +++++++++ src/include/dbus_common.h | 28 ++ src/include/dump_dir.h | 65 +++++ src/include/observer.h | 32 +++ src/include/plugin.h | 135 +++++++++ src/include/reporter.h | 48 ++++ src/include/xfuncs.h | 95 +++++++ src/lib/ABRTException.cpp | 33 +++ src/lib/CommLayerInner.cpp | 94 +++++++ src/lib/CrashTypes.cpp | 254 +++++++++++++++++ src/lib/Makefile.am | 109 ++++++++ src/lib/Plugin.cpp | 116 ++++++++ src/lib/Polkit.cpp | 102 +++++++ src/lib/Polkit.h | 42 +++ src/lib/abrt_curl.c | 375 +++++++++++++++++++++++++ src/lib/abrt_curl.h | 96 +++++++ src/lib/abrt_dbus.c | 430 +++++++++++++++++++++++++++++ src/lib/abrt_dbus.h | 324 ++++++++++++++++++++++ src/lib/abrt_packages.c | 43 +++ src/lib/abrt_packages.h | 33 +++ src/lib/abrt_xmlrpc.cpp | 97 +++++++ src/lib/abrt_xmlrpc.h | 48 ++++ src/lib/append_to_malloced_string.c | 27 ++ src/lib/concat_path_file.c | 25 ++ src/lib/copyfd.c | 172 ++++++++++++ src/lib/daemon.c | 139 ++++++++++ src/lib/database.c | 73 +++++ src/lib/dirsize.c | 110 ++++++++ src/lib/dump_dir.c | 504 ++++++++++++++++++++++++++++++++++ src/lib/encbase64.c | 78 ++++++ src/lib/hash_md5.c | 444 ++++++++++++++++++++++++++++++ src/lib/hash_md5.h | 29 ++ src/lib/hash_sha1.c | 213 ++++++++++++++ src/lib/hash_sha1.h | 40 +++ src/lib/hooklib.c | 138 ++++++++++ src/lib/hooklib.h | 29 ++ src/lib/logging.c | 148 ++++++++++ src/lib/logging.h | 78 ++++++ src/lib/make_descr.cpp | 287 +++++++++++++++++++ src/lib/numtoa.cpp | 34 +++ src/lib/overlapping_strcpy.c | 22 ++ src/lib/parse_options.c | 182 ++++++++++++ src/lib/parse_options.h | 53 ++++ src/lib/parse_release.cpp | 59 ++++ src/lib/read_write.c | 105 +++++++ src/lib/read_write.h | 49 ++++ src/lib/run_event.c | 276 +++++++++++++++++++ src/lib/skip_whitespace.c | 22 ++ src/lib/spawn.c | 156 +++++++++++ src/lib/stdio_helpers.c | 69 +++++ src/lib/strbuf.c | 147 ++++++++++ src/lib/strbuf.h | 103 +++++++ src/lib/stringops.cpp | 57 ++++ src/lib/test.cpp | 105 +++++++ src/lib/time.c | 65 +++++ src/lib/xatonum.c | 50 ++++ src/lib/xconnect.c | 415 ++++++++++++++++++++++++++++ src/lib/xfuncs.c | 400 +++++++++++++++++++++++++++ src/plugins/Makefile.am | 85 +++--- tests/atlocal.in | 2 +- 145 files changed, 8385 insertions(+), 8386 deletions(-) delete mode 100644 inc/Makefile.am delete mode 100644 inc/abrt_exception.h delete mode 100644 inc/abrt_types.h delete mode 100644 inc/abrtlib.h delete mode 100644 inc/action.h delete mode 100644 inc/analyzer.h delete mode 100644 inc/comm_layer_inner.h delete mode 100644 inc/crash_types.h delete mode 100644 inc/database.h delete mode 100644 inc/dbus_common.h delete mode 100644 inc/dump_dir.h delete mode 100644 inc/observer.h delete mode 100644 inc/plugin.h delete mode 100644 inc/reporter.h delete mode 100644 inc/xfuncs.h delete mode 100644 lib/Makefile.am delete mode 100644 lib/utils/ABRTException.cpp delete mode 100644 lib/utils/CommLayerInner.cpp delete mode 100644 lib/utils/CrashTypes.cpp delete mode 100644 lib/utils/Makefile.am delete mode 100644 lib/utils/Plugin.cpp delete mode 100644 lib/utils/Polkit.cpp delete mode 100644 lib/utils/Polkit.h delete mode 100644 lib/utils/abrt_curl.c delete mode 100644 lib/utils/abrt_curl.h delete mode 100644 lib/utils/abrt_dbus.c delete mode 100644 lib/utils/abrt_dbus.h delete mode 100644 lib/utils/abrt_packages.c delete mode 100644 lib/utils/abrt_packages.h delete mode 100644 lib/utils/abrt_xmlrpc.cpp delete mode 100644 lib/utils/abrt_xmlrpc.h delete mode 100644 lib/utils/append_to_malloced_string.c delete mode 100644 lib/utils/concat_path_file.c delete mode 100644 lib/utils/copyfd.c delete mode 100644 lib/utils/daemon.c delete mode 100644 lib/utils/database.c delete mode 100644 lib/utils/dirsize.c delete mode 100644 lib/utils/dump_dir.c delete mode 100644 lib/utils/encbase64.c delete mode 100644 lib/utils/hash_md5.c delete mode 100644 lib/utils/hash_md5.h delete mode 100644 lib/utils/hash_sha1.c delete mode 100644 lib/utils/hash_sha1.h delete mode 100644 lib/utils/hooklib.c delete mode 100644 lib/utils/hooklib.h delete mode 100644 lib/utils/logging.c delete mode 100644 lib/utils/logging.h delete mode 100644 lib/utils/make_descr.cpp delete mode 100644 lib/utils/numtoa.cpp delete mode 100644 lib/utils/overlapping_strcpy.c delete mode 100644 lib/utils/parse_options.c delete mode 100644 lib/utils/parse_options.h delete mode 100644 lib/utils/parse_release.cpp delete mode 100644 lib/utils/read_write.c delete mode 100644 lib/utils/read_write.h delete mode 100644 lib/utils/run_event.c delete mode 100644 lib/utils/skip_whitespace.c delete mode 100644 lib/utils/spawn.c delete mode 100644 lib/utils/stdio_helpers.c delete mode 100644 lib/utils/strbuf.c delete mode 100644 lib/utils/strbuf.h delete mode 100644 lib/utils/stringops.cpp delete mode 100644 lib/utils/test.cpp delete mode 100644 lib/utils/time.c delete mode 100644 lib/utils/xatonum.c delete mode 100644 lib/utils/xconnect.c delete mode 100644 lib/utils/xfuncs.c create mode 100644 src/include/Makefile.am create mode 100644 src/include/abrt_exception.h create mode 100644 src/include/abrt_types.h create mode 100644 src/include/abrtlib.h create mode 100644 src/include/action.h create mode 100644 src/include/analyzer.h create mode 100644 src/include/comm_layer_inner.h create mode 100644 src/include/crash_types.h create mode 100644 src/include/database.h create mode 100644 src/include/dbus_common.h create mode 100644 src/include/dump_dir.h create mode 100644 src/include/observer.h create mode 100644 src/include/plugin.h create mode 100644 src/include/reporter.h create mode 100644 src/include/xfuncs.h create mode 100644 src/lib/ABRTException.cpp create mode 100644 src/lib/CommLayerInner.cpp create mode 100644 src/lib/CrashTypes.cpp create mode 100644 src/lib/Makefile.am create mode 100644 src/lib/Plugin.cpp create mode 100644 src/lib/Polkit.cpp create mode 100644 src/lib/Polkit.h create mode 100644 src/lib/abrt_curl.c create mode 100644 src/lib/abrt_curl.h create mode 100644 src/lib/abrt_dbus.c create mode 100644 src/lib/abrt_dbus.h create mode 100644 src/lib/abrt_packages.c create mode 100644 src/lib/abrt_packages.h create mode 100644 src/lib/abrt_xmlrpc.cpp create mode 100644 src/lib/abrt_xmlrpc.h create mode 100644 src/lib/append_to_malloced_string.c create mode 100644 src/lib/concat_path_file.c create mode 100644 src/lib/copyfd.c create mode 100644 src/lib/daemon.c create mode 100644 src/lib/database.c create mode 100644 src/lib/dirsize.c create mode 100644 src/lib/dump_dir.c create mode 100644 src/lib/encbase64.c create mode 100644 src/lib/hash_md5.c create mode 100644 src/lib/hash_md5.h create mode 100644 src/lib/hash_sha1.c create mode 100644 src/lib/hash_sha1.h create mode 100644 src/lib/hooklib.c create mode 100644 src/lib/hooklib.h create mode 100644 src/lib/logging.c create mode 100644 src/lib/logging.h create mode 100644 src/lib/make_descr.cpp create mode 100644 src/lib/numtoa.cpp create mode 100644 src/lib/overlapping_strcpy.c create mode 100644 src/lib/parse_options.c create mode 100644 src/lib/parse_options.h create mode 100644 src/lib/parse_release.cpp create mode 100644 src/lib/read_write.c create mode 100644 src/lib/read_write.h create mode 100644 src/lib/run_event.c create mode 100644 src/lib/skip_whitespace.c create mode 100644 src/lib/spawn.c create mode 100644 src/lib/stdio_helpers.c create mode 100644 src/lib/strbuf.c create mode 100644 src/lib/strbuf.h create mode 100644 src/lib/stringops.cpp create mode 100644 src/lib/test.cpp create mode 100644 src/lib/time.c create mode 100644 src/lib/xatonum.c create mode 100644 src/lib/xconnect.c create mode 100644 src/lib/xfuncs.c diff --git a/Makefile.am b/Makefile.am index 9447c975..a536b7c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = lib src inc po icons tests +SUBDIRS = src po icons tests DISTCHECK_CONFIGURE_FLAGS = \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) diff --git a/configure.ac b/configure.ac index 5818b4b0..1ed908b8 100644 --- a/configure.ac +++ b/configure.ac @@ -118,8 +118,8 @@ AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([ Makefile abrt.pc - lib/Makefile - lib/utils/Makefile + src/include/Makefile + src/lib/Makefile src/plugins/Makefile src/Makefile src/btparser/Makefile @@ -128,7 +128,6 @@ AC_CONFIG_FILES([ src/applet/Makefile src/gui/Makefile src/cli/Makefile - inc/Makefile po/Makefile.in icons/Makefile tests/btparser/Makefile diff --git a/inc/Makefile.am b/inc/Makefile.am deleted file mode 100644 index 993fa62a..00000000 --- a/inc/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -HEADER_FILES = \ - abrt_exception.h \ - abrtlib.h \ - abrt_types.h \ - action.h \ - analyzer.h \ - comm_layer_inner.h \ - crash_types.h \ - database.h \ - dbus_common.h \ - dump_dir.h \ - observer.h \ - plugin.h \ - reporter.h \ - xfuncs.h - -lib_includedir=$(includedir)/abrt/ -lib_include_HEADERS = $(HEADER_FILES) diff --git a/inc/abrt_exception.h b/inc/abrt_exception.h deleted file mode 100644 index b826bfa8..00000000 --- a/inc/abrt_exception.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 ABRTEXCEPTION_H_ -#define ABRTEXCEPTION_H_ - -#include "abrtlib.h" - -typedef enum { - EXCEP_UNKNOW, - EXCEP_DD_OPEN, - EXCEP_DD_LOAD, - EXCEP_DD_SAVE, - EXCEP_DD_DELETE, - EXCEP_DL, - EXCEP_PLUGIN, - EXCEP_ERROR, -} abrt_exception_t; - -/* std::exception is a class with virtual members. - * deriving from it makes our ctor/dtor much more heavy, - * and those are inlined in every throw and catch site! - */ -class CABRTException /*: public std::exception*/ -{ - private: - abrt_exception_t m_type; - char *m_what; - - /* Not defined. You can't use it */ - CABRTException& operator= (const CABRTException&); - - public: - ~CABRTException() { free(m_what); } - CABRTException(abrt_exception_t type, const char* fmt, ...); - CABRTException(const CABRTException& rhs); - - abrt_exception_t type() { return m_type; } - const char* what() const { return m_what; } -}; - -#endif diff --git a/inc/abrt_types.h b/inc/abrt_types.h deleted file mode 100644 index 38804895..00000000 --- a/inc/abrt_types.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2009 Denys Vlasenko (dvlasenk@redhat.com) - Copyright (C) 2009 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 ABRT_TYPES_H_ -#define ABRT_TYPES_H_ - -#ifdef __cplusplus - -#include -#include -#include -#include - -typedef std::vector vector_string_t; -typedef std::set set_string_t; -typedef std::pair pair_string_string_t; -typedef std::map map_string_t; - -typedef std::vector vector_pair_string_string_t; -typedef std::vector vector_map_string_t; -typedef std::map map_map_string_t; -typedef std::map map_vector_string_t; -typedef std::map map_vector_pair_string_string_t; - -/* Report() method return type */ -typedef map_vector_string_t report_status_t; -/* map_vector_string_t's vector element meaning: */ -#define REPORT_STATUS_IDX_FLAG 0 -#define REPORT_STATUS_IDX_MSG 1 -/* Holds result of .conf file section parsing: map["name"] = "value" */ -typedef map_string_t map_plugin_settings_t; - -#endif /* __cplusplus */ - -#endif diff --git a/inc/abrtlib.h b/inc/abrtlib.h deleted file mode 100644 index 4d565644..00000000 --- a/inc/abrtlib.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Utility routines. - * - * Licensed under GPLv2, see file COPYING in this tarball for details. - */ -#ifndef ABRTLIB_H_ -#define ABRTLIB_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* sockaddr_in, sockaddr_in6 etc */ -#include -#include -#include -/* Try to pull in PATH_MAX */ -#include -#include -#ifndef PATH_MAX -# define PATH_MAX 256 -#endif -#include -#include -/* C++ bits */ -#ifdef __cplusplus -# include -#endif - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -/* Must be after #include "config.h" */ -#if ENABLE_NLS -# include -# define _(S) gettext(S) -#else -# define _(S) (S) -#endif - -/* Some libc's forget to declare these, do it ourself */ -extern char **environ; -#if defined(__GLIBC__) && __GLIBC__ < 2 -int vdprintf(int d, const char *format, va_list ap); -#endif - -#undef NORETURN -#define NORETURN __attribute__ ((noreturn)) - -#undef ERR_PTR -#define ERR_PTR ((void*)(uintptr_t)1) - -#undef ARRAY_SIZE -#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) - -#include "xfuncs.h" -#include "logging.h" -#include "read_write.h" -#include "strbuf.h" -#include "hash_sha1.h" -#include "hash_md5.h" - -#include "crash_types.h" -#include "dump_dir.h" -#include "abrt_types.h" -#include "abrt_packages.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -int prefixcmp(const char *str, const char *prefix); -int suffixcmp(const char *str, const char *suffix); -char *concat_path_file(const char *path, const char *filename); -char *append_to_malloced_string(char *mstr, const char *append); -char* skip_whitespace(const char *s); -char* skip_non_whitespace(const char *s); -/* Like strcpy but can copy overlapping strings. */ -void overlapping_strcpy(char *dst, const char *src); - -/* A-la fgets, but malloced and of unlimited size */ -char *xmalloc_fgets(FILE *file); -/* Similar, but removes trailing \n */ -char *xmalloc_fgetline(FILE *file); - -/* On error, copyfd_XX prints error messages and returns -1 */ -enum { - COPYFD_SPARSE = 1 << 0, -}; -off_t copyfd_eof(int src_fd, int dst_fd, int flags); -off_t copyfd_size(int src_fd, int dst_fd, off_t size, int flags); -void copyfd_exact_size(int src_fd, int dst_fd, off_t size); -off_t copy_file(const char *src_name, const char *dst_name, int mode); - -/* Returns malloc'ed block */ -char *encode_base64(const void *src, int length); - -unsigned xatou(const char *numstr); -int xatoi(const char *numstr); -/* Using xatoi() instead of naive atoi() is not always convenient - - * in many places people want *non-negative* values, but store them - * in signed int. Therefore we need this one: - * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc */ -int xatoi_u(const char *numstr); - -unsigned long long monotonic_ns(void); -unsigned long long monotonic_us(void); -unsigned monotonic_sec(void); - -enum { - /* on return, pipefds[1] is fd to which parent may write - * and deliver data to child's stdin: */ - EXECFLG_INPUT = 1 << 0, - /* on return, pipefds[0] is fd from which parent may read - * child's stdout: */ - EXECFLG_OUTPUT = 1 << 1, - /* open child's stdin to /dev/null: */ - EXECFLG_INPUT_NUL = 1 << 2, - /* open child's stdout to /dev/null: */ - EXECFLG_OUTPUT_NUL = 1 << 3, - /* redirect child's stderr to stdout: */ - EXECFLG_ERR2OUT = 1 << 4, - /* open child's stderr to /dev/null: */ - EXECFLG_ERR_NUL = 1 << 5, - /* suppress perror_msg("Can't execute 'foo'") if exec fails */ - EXECFLG_QUIET = 1 << 6, - EXECFLG_SETGUID = 1 << 7, - EXECFLG_SETSID = 1 << 8, -}; -/* Returns pid */ -pid_t fork_execv_on_steroids(int flags, - char **argv, - int *pipefds, - char **unsetenv_vec, - const char *dir, - uid_t uid); -/* Returns malloc'ed string. NULs are retained, and extra one is appended - * after the last byte (this NUL is not accounted for in *size_p) */ -char *run_in_shell_and_save_output(int flags, - const char *cmd, - const char *dir, - size_t *size_p); - -/* Networking helpers */ -typedef struct len_and_sockaddr { - socklen_t len; - union { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - } u; -} len_and_sockaddr; -enum { - LSA_LEN_SIZE = offsetof(len_and_sockaddr, u), - LSA_SIZEOF_SA = sizeof(struct sockaddr) > sizeof(struct sockaddr_in6) ? - sizeof(struct sockaddr) : sizeof(struct sockaddr_in6), -}; -void setsockopt_reuseaddr(int fd); -int setsockopt_broadcast(int fd); -int setsockopt_bindtodevice(int fd, const char *iface); -len_and_sockaddr* get_sock_lsa(int fd); -void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen); -unsigned lookup_port(const char *port, const char *protocol, unsigned default_port); -int get_nport(const struct sockaddr *sa); -void set_nport(len_and_sockaddr *lsa, unsigned port); -len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af); -len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t af); -len_and_sockaddr* host2sockaddr(const char *host, int port); -len_and_sockaddr* xhost2sockaddr(const char *host, int port); -len_and_sockaddr* xdotted2sockaddr(const char *host, int port); -int xsocket_type(len_and_sockaddr **lsap, int family, int sock_type); -int xsocket_stream(len_and_sockaddr **lsap); -int create_and_bind_stream_or_die(const char *bindaddr, int port); -int create_and_bind_dgram_or_die(const char *bindaddr, int port); -int create_and_connect_stream_or_die(const char *peer, int port); -int xconnect_stream(const len_and_sockaddr *lsa); -char* xmalloc_sockaddr2host(const struct sockaddr *sa); -char* xmalloc_sockaddr2host_noport(const struct sockaddr *sa); -char* xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa); -char* xmalloc_sockaddr2dotted(const struct sockaddr *sa); -char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa); - -/* Random utility functions */ - -double get_dirsize(const char *pPath); -double get_dirsize_find_largest_dir( - const char *pPath, - char **worst_dir, /* can be NULL */ - const char *excluded /* can be NULL */ -); - -/* Returns command line of running program. - * Caller is responsible to free() the returned value. - * If the pid is not valid or command line can not be obtained, - * empty string is returned. - */ -char* get_cmdline(pid_t pid); - -/* Returns 1 if abrtd daemon is running, 0 otherwise. */ -int daemon_is_ok(); - -struct run_event_state { - int (*post_run_callback)(const char *dump_dir_name, void *param); - void *post_run_param; - char* (*logging_callback)(char *log_line, void *param); - void *logging_param; -}; -static inline struct run_event_state *new_run_event_state() - { return (struct run_event_state*)xzalloc(sizeof(struct run_event_state)); } -static inline void free_run_event_state(struct run_event_state *state) - { free(state); } -int run_event(struct run_event_state *state, const char *dump_dir_name, const char *event); -char *list_possible_events(struct dump_dir *dd, const char *dump_dir_name, const char *pfx); - -#ifdef __cplusplus -} -#endif - - -/* C++ style stuff */ -#ifdef __cplusplus -std::string unsigned_to_string(unsigned long long x); -std::string signed_to_string(long long x); -template inline -std::string to_string(T x) -{ - if ((T)~(T)0 < (T)0) /* T is a signed type */ - return signed_to_string(x); - return unsigned_to_string(x); -} - -void parse_args(const char *psArgs, vector_string_t& pArgs, int quote = -1); -void parse_release(const char *pRelease, char **product, char **version); - -// TODO: npajkovs: full rewrite ssprintf -> xasprintf -static inline std::string ssprintf(const char *format, ...) -{ - va_list p; - char *string_ptr; - - va_start(p, format); - string_ptr = xvasprintf(format, p); - va_end(p); - - std::string res = string_ptr; - free(string_ptr); - return res; -} -#endif - -#endif diff --git a/inc/action.h b/inc/action.h deleted file mode 100644 index 21183366..00000000 --- a/inc/action.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Action.h - header file for action plugin - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 ACTION_H_ -#define ACTION_H_ - -#include "plugin.h" - -/** - * An abstract class. The class defines an action plugin interface. - */ -class CAction : public CPlugin -{ - public: - /** - * A Method which performs particular action. As the first parameter it - * takes an action directory. It could be either a directory of actual - * crash or it could be a directory contains all crashes. It depends on - * who call the plugin. The plugin can takes arguments, but the plugin - * has to parse them by itself. - * @param pActionDir An actual directory. - * @param pArgs Plugin's arguments. - */ - virtual void Run(const char *pActionDir, const char *pArgs, int force) = 0; -}; - -#endif diff --git a/inc/analyzer.h b/inc/analyzer.h deleted file mode 100644 index 1d78d576..00000000 --- a/inc/analyzer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Analyzer.h - header file for analyzer plugin - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 ANALYZER_H_ -#define ANALYZER_H_ - -#include -#include "plugin.h" - -/** - * An abstract class. The class defines an analyzer plugin interface. - */ -class CAnalyzer : public CPlugin -{ -}; - -#endif /*ANALYZER_H_*/ diff --git a/inc/comm_layer_inner.h b/inc/comm_layer_inner.h deleted file mode 100644 index 2cca9add..00000000 --- a/inc/comm_layer_inner.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 COMMLAYERINNER_H_ -#define COMMLAYERINNER_H_ - -#ifdef __cplusplus - -#include "observer.h" - -void init_daemon_logging(CObserver *pObs); - -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Set client's name (dbus ID). NULL unsets it. - */ -void set_client_name(const char* name); - -/* - * Ask a client to warn the user about a non-fatal, but unexpected condition. - * In GUI, it will usually be presented as a popup message. - * Usually there is no need to call it directly, just use [p]error_msg(). - */ -//now static: -//void warn_client(const char *msg); -//use [p]error_msg[_and_die] instead, it sends the message as a warning to client -//as well as to the log. - -/* - * Logs a message to a client. - * In UI, it will usually appear as a new status line message in GUI, - * or as a new message line in CLI. - */ -void update_client(const char *fmt, ...); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/inc/crash_types.h b/inc/crash_types.h deleted file mode 100644 index de9f7bf2..00000000 --- a/inc/crash_types.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright (C) 2009 Abrt team. - Copyright (C) 2009 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 CRASHTYPES_H_ -#define CRASHTYPES_H_ - -#include "abrt_types.h" - -// Keep in sync with CCDump.py: - -// Filenames in dump directory: -// filled by a hook: -#define FILENAME_ANALYZER "analyzer" -#define FILENAME_EXECUTABLE "executable" -#define FILENAME_BINARY "binary" -#define FILENAME_CMDLINE "cmdline" -#define FILENAME_REASON "reason" -#define FILENAME_COREDUMP "coredump" -#define FILENAME_BACKTRACE "backtrace" -#define FILENAME_MEMORYMAP "memorymap" -#define FILENAME_DUPHASH "global_uuid" /* name is compat, to be renamed to "duphash" */ -// Name of the function where the application crashed. -// Optional. -#define FILENAME_CRASH_FUNCTION "crash_function" -// filled by CDebugDump::Create() (which also fills CD_UID): -#define FILENAME_ARCHITECTURE "architecture" -#define FILENAME_KERNEL "kernel" -#define FILENAME_TIME "time" -#define FILENAME_RELEASE "release" /* from /etc/redhat-release */ -// filled by -#define FILENAME_PACKAGE "package" -#define FILENAME_COMPONENT "component" -#define FILENAME_DESCRIPTION "description" /* package descr (not crash descr) */ -#define FILENAME_COMMENT "comment" -#define FILENAME_REPRODUCE "reproduce" -#define FILENAME_RATING "rating" -#define FILENAME_HOSTNAME "hostname" -// Optional. Set to "1" by abrt-handle-upload for every unpacked crashdump -#define FILENAME_REMOTE "remote" -// TODO: TicketUploader also has open-coded "TICKET", "CUSTOMER" files - -// Apart from CD_UID, which is also stored as a file in dump directory, -// these items only exist in db. (CD_UID is also a file because -// dump directory is created before its DB entry, and DB has to learn -// CD_UID from _somewhere_ in order to be able to store it in DB record, -// right?) -#define CD_UID "uid" -// Now uuid also is saved as a file (but is still stored in database too): -#define CD_UUID "uuid" -#define CD_INFORMALL "InformAll" -#define CD_DUMPDIR "DumpDir" -#define CD_COUNT "Count" -#define CD_REPORTED "Reported" -#define CD_MESSAGE "Message" -// "Which events are possible (make sense) on this crash dump?" -// (a string with "\n" terminated event names) -#define CD_EVENTS "Events" - - -// Crash data is a map of 3-element vectors of strings: type, editable, content -#define CD_TYPE 0 -#define CD_EDITABLE 1 -#define CD_CONTENT 2 - -// SYS - system value, should not be displayed -// BIN - binary data -// TXT - text data, can be displayed -#define CD_SYS "s" -#define CD_BIN "b" -#define CD_TXT "t" -// Text bigger than this usually is attached, not added inline -#define CD_TEXT_ATT_SIZE (2*1024) - -#define CD_ISEDITABLE "y" -#define CD_ISNOTEDITABLE "n" - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const char *const must_have_files[]; - -bool is_editable_file(const char *file_name); - -#ifdef __cplusplus -} -#endif - - -#ifdef __cplusplus - -// -typedef map_vector_string_t map_crash_data_t; -typedef std::vector vector_map_crash_data_t; - -void add_to_crash_data_ext(map_crash_data_t& pCrashData, - const char *pItem, - const char *pType, - const char *pEditable, - const char *pContent); -// Uses type:CD_TXT, editable:CD_ISNOTEDITABLE -void add_to_crash_data(map_crash_data_t& pCrashData, - const char *pItem, - const char *pContent); - -void load_crash_data_from_debug_dump(struct dump_dir *dd, map_crash_data_t& data); - -const char *get_crash_data_item_content_or_NULL(const map_crash_data_t& crash_data, const char *key); -// Aborts if key is not found: -const std::string& get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key); - -void log_map_crash_data(const map_crash_data_t& data, const char *name); - -#endif /* __cplusplus */ - - -#endif diff --git a/inc/database.h b/inc/database.h deleted file mode 100644 index 5eaceed7..00000000 --- a/inc/database.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - Database.h - header file for database plugin - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 DATABASE_H_ -#define DATABASE_H_ - -#include - -/** - * Table - * ===== - * UUID | UID| DebugDumpPath | Count | Reported | Time | Message - * - * primary key (UUID, UID) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * A struct contains one database row. - */ -struct db_row -{ - char *db_uuid; /**< A local UUID.*/ - char *db_uid; /**< An UID of an user.*/ - char *db_inform_all; - char *db_dump_dir; /**< A debugdump directory of a crash.*/ - char *db_count; /**< Crash rate.*/ - char *db_reported; /**< Is a row reported?*/ - char *db_message; /**< if a row is reported, then there can be store message abotu that*/ - char *db_time; /**< Time of last occurred crash with same local UUID*/ -}; - -void db_row_free(struct db_row *row); - -void db_list_free(GList *list); - -struct db_row *db_rowcpy_from_list(GList* list); - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -#include -#include - -#include "plugin.h" - -/** - * An abstract class. The class defines a database plugin interface. - */ -class CDatabase : public CPlugin -{ - public: - /** - * A method, which connects to a database. - */ - virtual void Connect() = 0; - /** - * A method, which disconnects from a database. - */ - virtual void DisConnect() = 0; - /** - * A method, which inserts one row to a database. - * @param pUUID A local UUID of a crash. - * @param pUID An UID of an user. - * @param pDebugDumpPath A debugdump path. - * @param pTime Time when a crash occurs. - */ - virtual void Insert_or_Update(const char *crash_id, - bool inform_all_users, - const char *pDebugDumpPath, - const char *pTime) = 0; - /** - * A method, which deletes one row in a database. - * @param pUUID A lodal UUID of a crash. - * @param pUID An UID of an user. - */ - virtual void DeleteRow(const char *crash_id) = 0; - virtual void DeleteRows_by_dir(const char *dump_dir) = 0; - /** - * A method, which sets that particular row was reported. - * @param pUUID A local UUID of a crash. - * @param pUID An UID of an user. - * @param pMessage A text explanation of reported problem - * (where it is stored etc)... - */ - virtual void SetReported(const char *crash_id, - const char *pMessage) = 0; - virtual void SetReportedPerReporter(const char *crash_id, - const char *reporter, - const char *pMessage) = 0; - /** - * A method, which gets all rows which belongs to particular user. - * If the user is root, then all rows are returned. If there are no - * rows, empty vector is returned. - * @param pUID An UID of an user. - * @return A vector of matched rows. - */ - virtual GList *GetUIDData(long caller_uid) = 0; - /** - * A method, which returns one row accordind to UUID of a crash and - * UID of an user. If there are no row, empty row is returned. - * @param pUUID A UUID of a crash. - * @param pUID An UID of an user. - * @return A matched row. - */ - virtual struct db_row *GetRow(const char *crash_id) = 0; - virtual struct db_row *GetRow_by_dir(const char *dir) = 0; -}; -#endif - -#endif diff --git a/inc/dbus_common.h b/inc/dbus_common.h deleted file mode 100644 index 63053cc9..00000000 --- a/inc/dbus_common.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) - Copyright (C) 2009 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 DBUSCOMMON_H_ -#define DBUSCOMMON_H_ - -#include "crash_types.h" - -#define ABRTD_DBUS_NAME "com.redhat.abrt" -#define ABRTD_DBUS_PATH "/com/redhat/abrt" -#define ABRTD_DBUS_IFACE "com.redhat.abrt" - -#endif diff --git a/inc/dump_dir.h b/inc/dump_dir.h deleted file mode 100644 index aeaa3180..00000000 --- a/inc/dump_dir.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - DebugDump.h - header file for the library caring of writing new reports - to the specific directory - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 DEBUGDUMP_H_ -#define DEBUGDUMP_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - DD_FAIL_QUIETLY = (1 << 0), -}; - -struct dump_dir { - char *dd_dir; - DIR *next_dir; - int locked; - uid_t dd_uid; - gid_t dd_gid; -}; - -void dd_close(struct dump_dir *dd); - -struct dump_dir *dd_opendir(const char *dir, int flags); -struct dump_dir *dd_create(const char *dir, uid_t uid); -int dd_exist(struct dump_dir *dd, const char *path); -DIR *dd_init_next_file(struct dump_dir *dd); -int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name); - -enum { - /* DD_FAIL_QUIETLY bit is valid for dd_load_text_ext too, */ - DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE = (1 << 1), -}; -char* dd_load_text_ext(const struct dump_dir *dd, const char* name, unsigned flags); -char* dd_load_text(const struct dump_dir *dd, const char* name); -void dd_save_text(struct dump_dir *dd, const char *name, const char *data); -void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, unsigned size); -void dd_delete(struct dump_dir *dd); - -void delete_debug_dump_dir(const char *dd_dir); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/inc/observer.h b/inc/observer.h deleted file mode 100644 index 1c8f2355..00000000 --- a/inc/observer.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 OBSERVER_H_ -#define OBSERVER_H_ - -#include -#include "dbus_common.h" - -class CObserver { - public: - virtual ~CObserver() {} - virtual void Status(const char *pMessage, const char* peer) = 0; - virtual void Warning(const char *pMessage, const char* peer) = 0; -}; - -#endif diff --git a/inc/plugin.h b/inc/plugin.h deleted file mode 100644 index e0f45b6c..00000000 --- a/inc/plugin.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - Plugin.h - header file for plugin. It contains mandatory macros - and common function for plugins - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 PLUGIN_H_ -#define PLUGIN_H_ - -#include "abrt_types.h" -#include "crash_types.h" - -#define PLUGINS_MAGIC_NUMBER 6 - -#define PLUGINS_CONF_EXTENSION "conf" -#define PLUGINS_LIB_EXTENSION "so" -#define PLUGINS_LIB_PREFIX "lib" - -/** - * An abstract class. The class defines a common plugin interface. If a plugin - * has some settings, then a *Settings(*) method has to be written. - */ -class CPlugin -{ - protected: - map_plugin_settings_t m_pSettings; - - public: - CPlugin(); - /** - * A destructor. - */ - virtual ~CPlugin(); - /** - * A method, which initializes a plugin. It is not mandatory method. - */ - virtual void Init(); - /** - * A method, which deinitializes a plugin. It is not mandatory method. - */ - virtual void DeInit(); - /** - * A method, which takes a settings and apply them. It is not a mandatory method. - * @param pSettings Plugin's settings - */ - virtual void SetSettings(const map_plugin_settings_t& pSettings); - /** - * A method, which return current settings. It is not mandatory method. - * @return Plugin's settings - */ -/// -// virtual const map_plugin_settings_t& GetSettings(); -}; - -/** - * An enum of plugin types. - */ -typedef enum { - ANALYZER, /**< An analyzer plugin*/ - ACTION, /**< An action plugin*/ - REPORTER, /**< A reporter plugin*/ - DATABASE, /**< A database plugin*/ - MAX_PLUGIN_TYPE = DATABASE, -} plugin_type_t; - -/** - * A struct contains all needed data about particular plugin. - */ -typedef struct SPluginInfo -{ - const plugin_type_t m_Type; /**< Plugin type.*/ - const char *const m_sName; /**< Plugin name.*/ - const char *const m_sVersion; /**< Plugin version.*/ - const char *const m_sDescription; /**< Plugin description.*/ - const char *const m_sEmail; /**< Plugin author's email.*/ - const char *const m_sWWW; /**< Plugin's home page.*/ - const char *const m_sGTKBuilder; /**< Plugin's gui description.*/ - const int m_nMagicNumber; /**< Plugin magical number.*/ -} plugin_info_t; - -#define PLUGIN_INFO(type, plugin_class, name, version, description, email, www, gtk_builder)\ - extern "C" CPlugin* plugin_new()\ - {\ - return new plugin_class();\ - }\ - extern "C" const plugin_info_t plugin_info =\ - {\ - type,\ - name,\ - version,\ - description,\ - email,\ - www,\ - gtk_builder,\ - PLUGINS_MAGIC_NUMBER,\ - }; - -/* helper functions */ -char* make_description_bz(const map_crash_data_t& pCrashData); -char* make_description_reproduce_comment(const map_crash_data_t& pCrashData); -char* make_description_logger(const map_crash_data_t& pCrashData); -char* make_dsc_mailx(const map_crash_data_t& pCrashData); - -/** - * Loads settings and stores it in second parameter. On success it - * returns true, otherwise returns false. - * - * @param path A path of config file. - * Config file consists of "key=value" lines. - * @param settings A readed plugin's settings. - * @param skipKeysWithoutValue - * If true, lines in format "key=" (without value) are skipped. - * Otherwise empty value "" is inserted into pSettings. - * @return if it success it returns true, otherwise it returns false. - */ -extern bool LoadPluginSettings(const char *pPath, - map_plugin_settings_t& pSettings, - bool skipKeysWithoutValue = true); - -#endif diff --git a/inc/reporter.h b/inc/reporter.h deleted file mode 100644 index 469e828e..00000000 --- a/inc/reporter.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Reporter.h - header file for reporter plugin - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 REPORTER_H_ -#define REPORTER_H_ - -#include -#include "plugin.h" -#include "crash_types.h" - -/** - * An abstract class. The class defines a reporter plugin interface. - */ -class CReporter : public CPlugin -{ - public: - /** - * A method, which reports a crash report to particular receiver. - * The plugin can takes arguments, but the plugin has to parse them - * by itself. - * @param pCrashData A crash report. - * @param pArgs Plugin's arguments. - * @retun A message which can be displayed after a report is created. - */ -/// -// virtual std::string Report(const map_crash_data_t& pCrashData, -// const map_plugin_settings_t& pSettings, -// const char *pArgs) = 0; -}; - -#endif /* REPORTER_H_ */ diff --git a/inc/xfuncs.h b/inc/xfuncs.h deleted file mode 100644 index 20284564..00000000 --- a/inc/xfuncs.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 ABRT_XFUNCS_H -#define ABRT_XFUNCS_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int ndelay_on(int fd); -int ndelay_off(int fd); -int close_on_exec_on(int fd); - -void* xcalloc(size_t nmemb, size_t size); -void* xmalloc(size_t size); -void* xrealloc(void *ptr, size_t size); -void* xzalloc(size_t size); -char* xstrdup(const char *s); -char* xstrndup(const char *s, int n); - -void xpipe(int filedes[2]); -void xdup(int from); -void xdup2(int from, int to); -void xmove_fd(int from, int to); - -void xwrite(int fd, const void *buf, size_t count); -void xwrite_str(int fd, const char *str); - -off_t xlseek(int fd, off_t offset, int whence); - -void xchdir(const char *path); - -char* xvasprintf(const char *format, va_list p); -char* xasprintf(const char *format, ...); - -void xsetenv(const char *key, const char *value); -int xsocket(int domain, int type, int protocol); -void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); -void xlisten(int s, int backlog); -ssize_t xsendto(int s, const void *buf, size_t len, - const struct sockaddr *to, socklen_t tolen); - -void xstat(const char *name, struct stat *stat_buf); - -int xopen3(const char *pathname, int flags, int mode); -int xopen(const char *pathname, int flags); -void xunlink(const char *pathname); - -/* Just testing dent->d_type == DT_REG is wrong: some filesystems - * do not report the type, they report DT_UNKNOWN for every dirent - * (and this is not a bug in filesystem, this is allowed by standards). - * This function handles this case. Note: it returns 0 on symlinks - * even if they point to regular files. - */ -int is_regular_file(struct dirent *dent, const char *dirname); -bool dot_or_dotdot(const char *filename); -char *last_char_is(const char *s, int c); - -bool string_to_bool(const char *s); - -void xseteuid(uid_t euid); -void xsetegid(gid_t egid); -void xsetreuid(uid_t ruid, uid_t euid); -void xsetregid(gid_t rgid, gid_t egid); - -/* Returns getpwuid(uid)->pw_dir or NULL */ -const char *get_home_dir(uid_t uid); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index 97b7b2b3..00000000 --- a/lib/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = utils diff --git a/lib/utils/ABRTException.cpp b/lib/utils/ABRTException.cpp deleted file mode 100644 index 0ae5d452..00000000 --- a/lib/utils/ABRTException.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 "abrt_exception.h" - -CABRTException::CABRTException(abrt_exception_t type, const char* fmt, ...) -{ - m_type = type; - va_list ap; - va_start(ap, fmt); - m_what = xvasprintf(fmt, ap); - va_end(ap); -} - -CABRTException::CABRTException(const CABRTException& rhs): - m_type(rhs.m_type), - m_what(xstrdup(rhs.m_what)) -{} diff --git a/lib/utils/CommLayerInner.cpp b/lib/utils/CommLayerInner.cpp deleted file mode 100644 index 3c102d6e..00000000 --- a/lib/utils/CommLayerInner.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 -#include -#include "abrtlib.h" -#include "comm_layer_inner.h" - -static CObserver *s_pObs; - -typedef std::map map_uint_str_t; -static map_uint_str_t s_mapClientID; -static pthread_mutex_t s_map_mutex; -static bool s_map_mutex_inited; - -/* called via [p]error_msg() */ -static void warn_client(const char *msg) -{ - if (!s_pObs) - return; - - uint64_t key = uint64_t(pthread_self()); - - pthread_mutex_lock(&s_map_mutex); - map_uint_str_t::const_iterator ki = s_mapClientID.find(key); - const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); - pthread_mutex_unlock(&s_map_mutex); - - if (peer) - s_pObs->Warning(msg, peer); -} - -void init_daemon_logging(CObserver *pObs) -{ - s_pObs = pObs; - if (!s_map_mutex_inited) - { - s_map_mutex_inited = true; - pthread_mutex_init(&s_map_mutex, NULL); - g_custom_logger = &warn_client; - } -} - -void set_client_name(const char *name) -{ - uint64_t key = uint64_t(pthread_self()); - - pthread_mutex_lock(&s_map_mutex); - if (!name) { - s_mapClientID.erase(key); - } else { - s_mapClientID[key] = name; - } - pthread_mutex_unlock(&s_map_mutex); -} - -void update_client(const char *fmt, ...) -{ - if (!s_pObs) - return; - - uint64_t key = uint64_t(pthread_self()); - - pthread_mutex_lock(&s_map_mutex); - map_uint_str_t::const_iterator ki = s_mapClientID.find(key); - const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); - pthread_mutex_unlock(&s_map_mutex); - - if (!peer) - return; - - va_list p; - va_start(p, fmt); - char *msg = xvasprintf(fmt, p); - va_end(p); - - s_pObs->Status(msg, peer); - free(msg); -} diff --git a/lib/utils/CrashTypes.cpp b/lib/utils/CrashTypes.cpp deleted file mode 100644 index acacda5e..00000000 --- a/lib/utils/CrashTypes.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - Copyright (C) 2010 Denys Vlasenko (dvlasenk@redhat.com) - Copyright (C) 2010 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 "crash_types.h" - -const char *const must_have_files[] = { - FILENAME_ARCHITECTURE, - FILENAME_KERNEL , - FILENAME_PACKAGE , - FILENAME_COMPONENT , - FILENAME_RELEASE , - FILENAME_EXECUTABLE , - NULL -}; - -static const char *const editable_files[] = { - FILENAME_DESCRIPTION, - FILENAME_COMMENT , - FILENAME_REPRODUCE , - FILENAME_BACKTRACE , - NULL -}; - -static bool is_editable(const char *name, const char *const *v) -{ - while (*v) { - if (strcmp(*v, name) == 0) - return true; - v++; - } - return false; -} - -bool is_editable_file(const char *file_name) -{ - return is_editable(file_name, editable_files); -} - - -void add_to_crash_data_ext(map_crash_data_t& pCrashData, - const char *pItem, - const char *pType, - const char *pEditable, - const char *pContent) -{ - map_crash_data_t::iterator it = pCrashData.find(pItem); - if (it == pCrashData.end()) { - vector_string_t& v = pCrashData[pItem]; /* create empty vector */ - v.push_back(pType); - v.push_back(pEditable); - v.push_back(pContent); - return; - } - vector_string_t& v = it->second; - while (v.size() < 3) - v.push_back(""); - v[CD_TYPE] = pType; - v[CD_EDITABLE] = pEditable; - v[CD_CONTENT] = pContent; -} - -void add_to_crash_data(map_crash_data_t& pCrashData, - const char *pItem, - const char *pContent) -{ - add_to_crash_data_ext(pCrashData, pItem, CD_TXT, CD_ISNOTEDITABLE, pContent); -} - -static char* is_text_file(const char *name, ssize_t *sz) -{ - /* We were using magic.h API to check for file being text, but it thinks - * that file containing just "0" is not text (!!) - * So, we do it ourself. - */ - - int fd = open(name, O_RDONLY); - if (fd < 0) - return NULL; /* it's not text (because it does not exist! :) */ - - /* Maybe 64k limit is small. But _some_ limit is necessary: - * fields declared "text" may end up in editing fields and such. - * We don't want to accidentally end up with 100meg text in a textbox! - * So, don't remove this. If you really need to, raise the limit. - */ - off_t size = lseek(fd, 0, SEEK_END); - if (size < 0 || size > 64*1024) - { - close(fd); - return NULL; /* it's not a SMALL text */ - } - lseek(fd, 0, SEEK_SET); - - char *buf = (char*)xmalloc(*sz); - ssize_t r = *sz = full_read(fd, buf, *sz); - close(fd); - if (r < 0) - { - free(buf); - return NULL; /* it's not text (because we can't read it) */ - } - - /* Some files in our dump directories are known to always be textual */ - const char *base = strrchr(name, '/'); - if (base) - { - base++; - if (strcmp(base, FILENAME_BACKTRACE) == 0 - || strcmp(base, FILENAME_CMDLINE) == 0 - ) { - return buf; - } - } - - /* Every once in a while, even a text file contains a few garbled - * or unexpected non-ASCII chars. We should not declare it "binary". - */ - const unsigned RATIO = 50; - unsigned total_chars = r + RATIO; - unsigned bad_chars = 1; /* 1 prevents division by 0 later */ - while (--r >= 0) - { - if (buf[r] >= 0x7f - /* among control chars, only '\t','\n' etc are allowed */ - || (buf[r] < ' ' && !isspace(buf[r])) - ) { - if (buf[r] == '\0') - { - /* We don't like NULs very much. Not text for sure! */ - free(buf); - return NULL; - } - bad_chars++; - } - } - - if ((total_chars / bad_chars) >= RATIO) - return buf; /* looks like text to me */ - - free(buf); - return NULL; /* it's binary */ -} - -void load_crash_data_from_debug_dump(struct dump_dir *dd, map_crash_data_t& data) -{ - char *short_name; - char *full_name; - - dd_init_next_file(dd); - while (dd_get_next_file(dd, &short_name, &full_name)) - { - ssize_t sz = 4*1024; - char *text = NULL; - bool editable = is_editable_file(short_name); - - if (!editable) - { - text = is_text_file(full_name, &sz); - if (!text) - { - add_to_crash_data_ext(data, - short_name, - CD_BIN, - CD_ISNOTEDITABLE, - full_name - ); - - free(short_name); - free(full_name); - continue; - } - } - - char *content; - if (sz < 4*1024) /* is_text_file did read entire file */ - content = xstrndup(text, sz); //TODO: can avoid this copying if is_text_file() adds NUL - else /* no, need to read it all */ - content = dd_load_text(dd, short_name); - free(text); - - add_to_crash_data_ext(data, - short_name, - CD_TXT, - editable ? CD_ISEDITABLE : CD_ISNOTEDITABLE, - content - ); - free(short_name); - free(full_name); - free(content); - } -} - -static const std::string* helper_get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key) -{ - map_crash_data_t::const_iterator it = crash_data.find(key); - if (it == crash_data.end()) { - return NULL; - } - if (it->second.size() <= CD_CONTENT) { - return NULL; - } - return &it->second[CD_CONTENT]; -} - -const std::string& get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key) -{ - const std::string* sp = helper_get_crash_data_item_content(crash_data, key); - if (sp == NULL) { - if (crash_data.find(key) == crash_data.end()) - error_msg_and_die("Error accessing crash data: no ['%s']", key); - error_msg_and_die("Error accessing crash data: no ['%s'][%d]", key, CD_CONTENT); - } - return *sp; -} - -const char *get_crash_data_item_content_or_NULL(const map_crash_data_t& crash_data, const char *key) -{ - const std::string* sp = helper_get_crash_data_item_content(crash_data, key); - if (!sp) { - return NULL; - } - return sp->c_str(); -} - -void log_map_crash_data(const map_crash_data_t& data, const char *name) -{ - map_crash_data_t::const_iterator it = data.begin(); - while (it != data.end()) - { - ssize_t sz = it->second.size(); - log("%s[%s]:%s/%s/'%.20s'", - name, it->first.c_str(), - sz > 0 ? it->second[0].c_str() : "", - sz > 1 ? it->second[1].c_str() : "", - sz > 2 ? it->second[2].c_str() : "" - ); - it++; - } -} diff --git a/lib/utils/Makefile.am b/lib/utils/Makefile.am deleted file mode 100644 index 37508ee7..00000000 --- a/lib/utils/Makefile.am +++ /dev/null @@ -1,109 +0,0 @@ -# ABRTUtils has small set of deps. This reduces deps of smaller abrt binaries -# ABRTdUtils has much more. It is used by daemon and plugins only -# ABRT_web_utils is used only by some abrt-action-foo programs, not by daemon -lib_LTLIBRARIES = \ - libABRTUtils.la \ - libABRTdUtils.la \ - libABRT_web_utils.la -HEADER_DIR = $(srcdir)/../../inc -AM_CPPFLAGS = -I$(HEADER_DIR) - -# Not used just yet: -# time.cpp -# xconnect.cpp - -libABRTUtils_la_SOURCES = \ - xfuncs.c \ - concat_path_file.c \ - append_to_malloced_string.c \ - overlapping_strcpy.c \ - encbase64.c \ - stdio_helpers.c \ - hash_md5.c hash_md5.h \ - hash_sha1.c hash_sha1.h \ - read_write.c read_write.h \ - logging.c logging.h \ - copyfd.c \ - daemon.c \ - skip_whitespace.c \ - xatonum.c numtoa.cpp \ - spawn.c \ - stringops.cpp \ - dirsize.c \ - dump_dir.c \ - strbuf.c strbuf.h \ - abrt_dbus.c abrt_dbus.h \ - CrashTypes.cpp \ - ABRTException.cpp \ - run_event.c \ - abrt_packages.c abrt_packages.h \ - hooklib.c hooklib.h \ - database.c \ - parse_options.c parse_options.h -libABRTUtils_la_CPPFLAGS = \ - -Wall -Werror \ - -I$(srcdir)/../../inc \ - -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ - -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ - -DCONF_DIR=\"$(CONF_DIR)\" \ - -DVAR_RUN=\"$(VAR_RUN)\" \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ - -D_GNU_SOURCE -libABRTUtils_la_LDFLAGS = \ - -version-info 0:1:0 -libABRTUtils_la_LIBADD = \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) \ - -ldl - -libABRTdUtils_la_SOURCES = \ - parse_release.cpp \ - make_descr.cpp \ - $(HEADER_DIR)/comm_layer_inner.h CommLayerInner.cpp \ - $(HEADER_DIR)/plugin.h Plugin.cpp \ - Polkit.h Polkit.cpp -libABRTdUtils_la_CPPFLAGS = \ - -Wall -Werror \ - -I$(srcdir)/../../inc \ - -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ - -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ - -DCONF_DIR=\"$(CONF_DIR)\" \ - -DVAR_RUN=\"$(VAR_RUN)\" \ - $(POLKIT_CFLAGS) \ - -D_GNU_SOURCE -libABRTdUtils_la_LDFLAGS = \ - -version-info 0:1:0 -libABRTdUtils_la_LIBADD = \ - $(POLKIT_LIBS) \ - -ldl - -libABRT_web_utils_la_SOURCES = \ - abrt_curl.h abrt_curl.c \ - abrt_xmlrpc.h abrt_xmlrpc.cpp -libABRT_web_utils_la_CPPFLAGS = \ - -Wall -Werror \ - -I$(srcdir)/../../inc \ - -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ - -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ - -DCONF_DIR=\"$(CONF_DIR)\" \ - -DVAR_RUN=\"$(VAR_RUN)\" \ - $(CURL_CFLAGS) \ - $(LIBXML_CFLAGS) \ - $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \ - -D_GNU_SOURCE -libABRT_web_utils_la_LDFLAGS = \ - -version-info 0:1:0 -libABRT_web_utils_la_LIBADD = \ - $(CURL_LIBS) \ - $(LIBXML_LIBS) \ - $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) - -$(DESTDIR)/$(DEBUG_DUMPS_DIR): - $(mkdir_p) '$@' -# no need to chmod it here -#chmod 1777 '$@' -install-data-local: $(DESTDIR)/$(DEBUG_DUMPS_DIR) diff --git a/lib/utils/Plugin.cpp b/lib/utils/Plugin.cpp deleted file mode 100644 index bf237959..00000000 --- a/lib/utils/Plugin.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 "plugin.h" -#include "abrtlib.h" - -CPlugin::CPlugin() {} - -/* class CPlugin's virtuals */ -CPlugin::~CPlugin() {} -void CPlugin::Init() {} -void CPlugin::DeInit() {} -void CPlugin::SetSettings(const map_plugin_settings_t& pSettings) -{ - m_pSettings = pSettings; - VERB3 - { - log("SetSettings:"); - map_plugin_settings_t::const_iterator it = m_pSettings.begin(); - while (it != m_pSettings.end()) - { - log(" settings[%s]='%s'", it->first.c_str(), it->second.c_str()); - it++; - } - } -} - -bool LoadPluginSettings(const char *pPath, map_plugin_settings_t& pSettings, - bool skipKeysWithoutValue /*= true*/) -{ - FILE *fp = stdin; - if (strcmp(pPath, "-") != 0) - { - fp = fopen(pPath, "r"); - if (!fp) - return false; - } - - char *line; - while ((line = xmalloc_fgetline(fp)) != NULL) - { - unsigned ii; - bool is_value = false; - bool valid = false; - bool in_quote = false; - std::string key; - std::string value; - for (ii = 0; line[ii] != '\0'; ii++) - { - if (line[ii] == '"') - { - in_quote = !in_quote; - } - if (isspace(line[ii]) && !in_quote) - { - continue; - } - if (line[ii] == '#' && !in_quote && key == "") - { - break; - } - if (line[ii] == '=' && !in_quote) - { - is_value = true; - valid = true; - continue; - } - if (!is_value) - { - key += line[ii]; - } - else - { - value += line[ii]; - } - } - - /* Skip broken or empty lines. */ - if (!valid) - goto free_line; - - /* Skip lines with empty key. */ - if (key.length() == 0) - goto free_line; - - if (skipKeysWithoutValue && value.length() == 0) - goto free_line; - - /* Skip lines with unclosed quotes. */ - if (in_quote) - goto free_line; - - pSettings[key] = value; - free_line: - free(line); - } - - if (fp != stdin) - fclose(fp); - return true; -} diff --git a/lib/utils/Polkit.cpp b/lib/utils/Polkit.cpp deleted file mode 100644 index a5e07760..00000000 --- a/lib/utils/Polkit.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - Polkit.cpp - PolicyKit integration for ABRT - - Copyright (C) 2009 Daniel Novotny (dnovotny@redhat.com) - Copyright (C) 2009 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 -#include -#include -#include - -#include "Polkit.h" -#include "abrtlib.h" - -/*number of seconds: timeout for the authorization*/ -#define POLKIT_TIMEOUT 20 - -static gboolean do_cancel(GCancellable* cancellable) -{ - log("Timer has expired; cancelling authorization check\n"); - g_cancellable_cancel(cancellable); - return FALSE; -} - - -static PolkitResult do_check(PolkitSubject *subject, const char *action_id) -{ - PolkitAuthority *authority; - PolkitAuthorizationResult *result; - GError *error = NULL; - GCancellable * cancellable; - - authority = polkit_authority_get(); - cancellable = g_cancellable_new(); - - guint cancel_timeout = g_timeout_add(POLKIT_TIMEOUT * 1000, - (GSourceFunc) do_cancel, - cancellable); - - result = polkit_authority_check_authorization_sync(authority, - subject, - action_id, - NULL, - POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, - cancellable, - &error); - g_object_unref(authority); - g_source_remove(cancel_timeout); - if (error) - { - g_error_free(error); - return PolkitUnknown; - } - - if (result) - { - if (polkit_authorization_result_get_is_challenge(result)) - { - /* Can't happen (happens only with - * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */ - g_object_unref(result); - return PolkitChallenge; - } - if (polkit_authorization_result_get_is_authorized(result)) - { - g_object_unref(result); - return PolkitYes; - } - g_object_unref(result); - return PolkitNo; - } - - return PolkitUnknown; -} - -PolkitResult polkit_check_authorization(const char *dbus_name, const char *action_id) -{ - g_type_init(); - PolkitSubject *subject = polkit_system_bus_name_new(dbus_name); - return do_check(subject, action_id); -} - -PolkitResult polkit_check_authorization(pid_t pid, const char *action_id) -{ - g_type_init(); - PolkitSubject *subject = polkit_unix_process_new(pid); - return do_check(subject, action_id); -} diff --git a/lib/utils/Polkit.h b/lib/utils/Polkit.h deleted file mode 100644 index d9e097ac..00000000 --- a/lib/utils/Polkit.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Polkit.h - header file for PolicyKit integration - - Copyright (C) 2009 Daniel Novotny (dnovotny@redhat.com) - Copyright (C) 2009 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 ABRT_POLKIT_H -#define ABRT_POLKIT_H - -#include -#include - -typedef enum { -/* Authorization status is unknown */ - PolkitUnknown = 0x0, - /* Subject is authorized for the action */ - PolkitYes = 0x01, - /* Subject is not authorized for the action */ - PolkitNo = 0x02, - /* Challenge is needed for this action, only when flag is - * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE */ - PolkitChallenge = 0x03 -} PolkitResult; - -PolkitResult polkit_check_authorization(const char *dbus_name, const char *action_id); -PolkitResult polkit_check_authorization(pid_t pid, const char *action_id); - -#endif diff --git a/lib/utils/abrt_curl.c b/lib/utils/abrt_curl.c deleted file mode 100644 index f23d3949..00000000 --- a/lib/utils/abrt_curl.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 "abrt_curl.h" - -/* - * Utility functions - */ -CURL* xcurl_easy_init() -{ - CURL* curl = curl_easy_init(); - if (!curl) - { - error_msg_and_die("Can't create curl handle"); - } - return curl; -} - -static char* -check_curl_error(CURLcode err, const char* msg) -{ - if (err) - return xasprintf("%s: %s", msg, curl_easy_strerror(err)); - return NULL; -} - -static void -die_if_curl_error(CURLcode err) -{ - if (err) { - char *msg = check_curl_error(err, "curl"); - error_msg_and_die("%s", msg); - } -} - -static void -xcurl_easy_setopt_ptr(CURL *handle, CURLoption option, const void *parameter) -{ - CURLcode err = curl_easy_setopt(handle, option, parameter); - if (err) { - char *msg = check_curl_error(err, "curl"); - error_msg_and_die("%s", msg); - } -} -static inline void -xcurl_easy_setopt_long(CURL *handle, CURLoption option, long parameter) -{ - xcurl_easy_setopt_ptr(handle, option, (void*)parameter); -} - -/* - * post_state utility functions - */ - -abrt_post_state_t *new_abrt_post_state(int flags) -{ - abrt_post_state_t *state = (abrt_post_state_t *)xzalloc(sizeof(*state)); - state->flags = flags; - return state; -} - -void free_abrt_post_state(abrt_post_state_t *state) -{ - char **headers = state->headers; - if (headers) - { - while (*headers) - free(*headers++); - free(state->headers); - } - free(state->curl_error_msg); - free(state->body); - free(state); -} - -char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char *str) -{ - char **headers = state->headers; - if (headers) - { - unsigned len = strlen(str); - while (*headers) - { - if (strncmp(*headers, str, len) == 0) - return skip_whitespace(*headers + len); - headers++; - } - } - return NULL; -} - -/* - * abrt_post: perform HTTP POST transaction - */ - -/* "save headers" callback */ -static size_t -save_headers(void *buffer_pv, size_t count, size_t nmemb, void *ptr) -{ - abrt_post_state_t* state = (abrt_post_state_t*)ptr; - size_t size = count * nmemb; - - char *h = xstrndup((char*)buffer_pv, size); - strchrnul(h, '\r')[0] = '\0'; - strchrnul(h, '\n')[0] = '\0'; - - unsigned cnt = state->header_cnt; - - /* Check for the case when curl follows a redirect: - * header 0: 'HTTP/1.1 301 Moved Permanently' - * header 1: 'Connection: close' - * header 2: 'Location: NEW_URL' - * header 3: '' - * header 0: 'HTTP/1.1 200 OK' <-- we need to forget all hdrs and start anew - */ - if (cnt != 0 - && strncmp(h, "HTTP/", 5) == 0 - && state->headers[cnt-1][0] == '\0' /* prev header is an empty string */ - ) { - char **headers = state->headers; - if (headers) - { - while (*headers) - free(*headers++); - } - cnt = 0; - } - - VERB3 log("save_headers: header %d: '%s'", cnt, h); - state->headers = (char**)xrealloc(state->headers, (cnt+2) * sizeof(state->headers[0])); - state->headers[cnt] = h; - state->header_cnt = ++cnt; - state->headers[cnt] = NULL; - - return size; -} - -/* "read local data from a file" callback */ -static size_t fread_with_reporting(void *ptr, size_t size, size_t nmemb, void *userdata) -{ - static time_t last_t; // hack - - FILE *fp = (FILE*)userdata; - time_t t = time(NULL); - - // Report current file position every 16 seconds - if (!(t & 0xf) && last_t != t) - { - last_t = t; - off_t cur_pos = ftello(fp); - fseeko(fp, 0, SEEK_END); - off_t sz = ftello(fp); - fseeko(fp, cur_pos, SEEK_SET); - log(_("Uploaded: %llu of %llu kbytes"), - (unsigned long long)cur_pos / 1024, - (unsigned long long)sz / 1024); - } - - return fread(ptr, size, nmemb, fp); -} - -int -abrt_post(abrt_post_state_t *state, - const char *url, - const char *content_type, - const char *data, - off_t data_size) -{ - CURLcode curl_err; - long response_code; - abrt_post_state_t localstate; - - VERB3 log("abrt_post('%s','%s')", url, data); - - if (!state) - { - memset(&localstate, 0, sizeof(localstate)); - state = &localstate; - } - - state->http_resp_code = response_code = -1; - - CURL *handle = xcurl_easy_init(); - - // Buffer[CURL_ERROR_SIZE] curl stores human readable error messages in. - // This may be more helpful than just return code from curl_easy_perform. - // curl will need it until curl_easy_cleanup. - state->errmsg[0] = '\0'; - xcurl_easy_setopt_ptr(handle, CURLOPT_ERRORBUFFER, state->errmsg); - // "Display a lot of verbose information about its operations. - // Very useful for libcurl and/or protocol debugging and understanding. - // The verbose information will be sent to stderr, or the stream set - // with CURLOPT_STDERR" - //xcurl_easy_setopt_long(handle, CURLOPT_VERBOSE, 1); - // Shut off the built-in progress meter completely - xcurl_easy_setopt_long(handle, CURLOPT_NOPROGRESS, 1); - - // TODO: do we need to check for CURLE_URL_MALFORMAT error *here*, - // not in curl_easy_perform? - xcurl_easy_setopt_ptr(handle, CURLOPT_URL, url); - - // Auth if configured - if (state->username) { - // bitmask of allowed auth methods - xcurl_easy_setopt_long(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - xcurl_easy_setopt_ptr(handle, CURLOPT_USERNAME, state->username); - xcurl_easy_setopt_ptr(handle, CURLOPT_PASSWORD, (state->password ? state->password : "")); - } - - // Do a regular HTTP post. This also makes curl use - // a "Content-Type: application/x-www-form-urlencoded" header. - // (This is by far the most commonly used POST method). - xcurl_easy_setopt_long(handle, CURLOPT_POST, 1); - // Supply POST data... - struct curl_httppost* post = NULL; - struct curl_httppost* last = NULL; - FILE* data_file = NULL; - if (data_size == ABRT_POST_DATA_FROMFILE) { - // ...from a file - data_file = fopen(data, "r"); - if (!data_file) -//FIXME: - perror_msg_and_die("can't open '%s'", data); - xcurl_easy_setopt_ptr(handle, CURLOPT_READDATA, data_file); - // Want to use custom read function - xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const void*)fread_with_reporting); - } else if (data_size == ABRT_POST_DATA_FROMFILE_AS_FORM_DATA) { - // ...from a file, in multipart/formdata format - const char *basename = strrchr(data, '/'); - if (basename) basename++; - else basename = data; -#if 0 - // Simple way, without custom reader function - CURLFORMcode curlform_err = curl_formadd(&post, &last, - CURLFORM_PTRNAME, "file", // element name - CURLFORM_FILE, data, // filename to read from - CURLFORM_CONTENTTYPE, content_type, - CURLFORM_FILENAME, basename, // filename to put in the form - CURLFORM_END); -#else - data_file = fopen(data, "r"); - if (!data_file) -//FIXME: - perror_msg_and_die("can't open '%s'", data); - // Want to use custom read function - xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const void*)fread_with_reporting); - // Need to know file size - fseeko(data_file, 0, SEEK_END); - off_t sz = ftello(data_file); - fseeko(data_file, 0, SEEK_SET); - // Create formdata - CURLFORMcode curlform_err = curl_formadd(&post, &last, - CURLFORM_PTRNAME, "file", // element name - // use CURLOPT_READFUNCTION for reading, pass data_file as its last param: - CURLFORM_STREAM, data_file, - CURLFORM_CONTENTSLENGTH, (long)sz, // a must if we use CURLFORM_STREAM option - CURLFORM_CONTENTTYPE, content_type, - CURLFORM_FILENAME, basename, // filename to put in the form - CURLFORM_END); -#endif - if (curlform_err != 0) -//FIXME: - error_msg_and_die("out of memory or read error (curl_formadd error code: %d)", (int)curlform_err); - xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post); - } else { - // .. from a blob in memory - xcurl_easy_setopt_ptr(handle, CURLOPT_POSTFIELDS, data); - // note1: if data_size == ABRT_POST_DATA_STRING == -1, curl will use strlen(data) - xcurl_easy_setopt_long(handle, CURLOPT_POSTFIELDSIZE, data_size); - // note2: CURLOPT_POSTFIELDSIZE_LARGE can't be used: xcurl_easy_setopt_long() - // truncates data_size on 32-bit arch. Need xcurl_easy_setopt_long_long()? - // Also, I'm not sure CURLOPT_POSTFIELDSIZE_LARGE special-cases -1. - } - // Override "Content-Type:" - struct curl_slist *httpheader_list = NULL; - if (data_size != ABRT_POST_DATA_FROMFILE_AS_FORM_DATA) - { - char *content_type_header = xasprintf("Content-Type: %s", content_type); - // Note: curl_slist_append() copies content_type_header - httpheader_list = curl_slist_append(httpheader_list, content_type_header); - if (!httpheader_list) - error_msg_and_die("out of memory"); - free(content_type_header); - xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPHEADER, httpheader_list); - } - -// Disabled: was observed to also handle "305 Use proxy" redirect, -// apparently with POST->GET remapping - which server didn't like at all. -// Attempted to suppress remapping on 305 using CURLOPT_POSTREDIR of -1, -// but it still did not work. -#if 0 - // Please handle 301/302 redirects for me - xcurl_easy_setopt_long(handle, CURLOPT_FOLLOWLOCATION, 1); - xcurl_easy_setopt_long(handle, CURLOPT_MAXREDIRS, 10); - // Bitmask to control how libcurl acts on redirects after POSTs. - // Bit 0 set (value CURL_REDIR_POST_301) makes libcurl - // not convert POST requests into GET requests when following - // a 301 redirection. Bit 1 (value CURL_REDIR_POST_302) makes libcurl - // maintain the request method after a 302 redirect. - // CURL_REDIR_POST_ALL is a convenience define that sets both bits. - // The non-RFC behaviour is ubiquitous in web browsers, so the library - // does the conversion by default to maintain consistency. - // However, a server may require a POST to remain a POST. - xcurl_easy_setopt_long(handle, CURLOPT_POSTREDIR, -1L /*CURL_REDIR_POST_ALL*/ ); -#endif - - // Prepare for saving information - if (state->flags & ABRT_POST_WANT_HEADERS) - { - xcurl_easy_setopt_ptr(handle, CURLOPT_HEADERFUNCTION, (void*)save_headers); - xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEHEADER, state); - } - FILE* body_stream = NULL; - if (state->flags & ABRT_POST_WANT_BODY) - { - body_stream = open_memstream(&state->body, &state->body_size); - if (!body_stream) - error_msg_and_die("out of memory"); - xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEDATA, body_stream); - } - if (!(state->flags & ABRT_POST_WANT_SSL_VERIFY)) - { - xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYPEER, 0); - xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYHOST, 0); - } - - // This is the place where everything happens. - // Here errors are not limited to "out of memory", can't just die. - curl_err = curl_easy_perform(handle); - if (curl_err) - { - VERB2 log("curl_easy_perform: error %d", (int)curl_err); - if (state->flags & ABRT_POST_WANT_ERROR_MSG) - { - state->curl_error_msg = check_curl_error(curl_err, "curl_easy_perform"); - VERB3 log("curl_easy_perform: error_msg: %s", state->curl_error_msg); - } - goto ret; - } - - // Headers/body are already saved (if requested), extract more info - curl_err = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code); - die_if_curl_error(curl_err); - state->http_resp_code = response_code; - VERB3 log("after curl_easy_perform: http code %ld body:'%s'", response_code, state->body); - - ret: - curl_easy_cleanup(handle); - if (httpheader_list) - curl_slist_free_all(httpheader_list); - if (body_stream) - fclose(body_stream); - if (data_file) - fclose(data_file); - if (post) - curl_formfree(post); - - return response_code; -} diff --git a/lib/utils/abrt_curl.h b/lib/utils/abrt_curl.h deleted file mode 100644 index 77b4605c..00000000 --- a/lib/utils/abrt_curl.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 ABRT_CURL_H_ -#define ABRT_CURL_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -CURL* xcurl_easy_init(); - -typedef struct abrt_post_state { - /* Supplied by caller: */ - int flags; - const char *username; - const char *password; - /* Results of POST transaction: */ - int http_resp_code; - unsigned header_cnt; - char **headers; - char *curl_error_msg; - char *body; - size_t body_size; - char errmsg[CURL_ERROR_SIZE]; -} abrt_post_state_t; - -abrt_post_state_t *new_abrt_post_state(int flags); -void free_abrt_post_state(abrt_post_state_t *state); -char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char *str); - -enum { - ABRT_POST_WANT_HEADERS = (1 << 0), - ABRT_POST_WANT_ERROR_MSG = (1 << 1), - ABRT_POST_WANT_BODY = (1 << 2), - ABRT_POST_WANT_SSL_VERIFY = (1 << 3), -}; -enum { - /* Must be -1! CURLOPT_POSTFIELDSIZE interprets -1 as "use strlen" */ - ABRT_POST_DATA_STRING = -1, - ABRT_POST_DATA_FROMFILE = -2, - ABRT_POST_DATA_FROMFILE_AS_FORM_DATA = -3, -}; -int -abrt_post(abrt_post_state_t *state, - const char *url, - const char *content_type, - const char *data, - off_t data_size); -static inline int -abrt_post_string(abrt_post_state_t *state, - const char *url, - const char *content_type, - const char *str) -{ - return abrt_post(state, url, content_type, str, ABRT_POST_DATA_STRING); -} -static inline int -abrt_post_file(abrt_post_state_t *state, - const char *url, - const char *content_type, - const char *filename) -{ - return abrt_post(state, url, content_type, filename, ABRT_POST_DATA_FROMFILE); -} -static inline int -abrt_post_file_as_form(abrt_post_state_t *state, - const char *url, - const char *content_type, - const char *filename) -{ - return abrt_post(state, url, content_type, filename, ABRT_POST_DATA_FROMFILE_AS_FORM_DATA); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/utils/abrt_dbus.c b/lib/utils/abrt_dbus.c deleted file mode 100644 index 6bc155e3..00000000 --- a/lib/utils/abrt_dbus.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 -#include -#include "abrtlib.h" -#include "abrt_dbus.h" - -DBusConnection* g_dbus_conn; - - -/* - * Helpers for building DBus messages - */ - -//void store_bool(DBusMessageIter* iter, bool val) -//{ -// dbus_bool_t db = val; -// if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &db)) -// die_out_of_memory(); -//} -void store_int32(DBusMessageIter* iter, int32_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &val)) - die_out_of_memory(); -} -void store_uint32(DBusMessageIter* iter, uint32_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &val)) - die_out_of_memory(); -} -void store_int64(DBusMessageIter* iter, int64_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &val)) - die_out_of_memory(); -} -void store_uint64(DBusMessageIter* iter, uint64_t val) -{ - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &val)) - die_out_of_memory(); -} - -/* dbus daemon will simply close our connection if we send broken utf8. - * Therefore we must never do that. - */ -static char *sanitize_utf8(const char *src) -{ - const char *initial_src = src; - char *sanitized = NULL; - unsigned sanitized_pos = 0; - - while (*src) - { - int bytes = 0; - - unsigned c = (unsigned char) *src; - if (c <= 0x7f) - { - bytes = 1; - goto good_byte; - } - - /* Unicode -> utf8: */ - /* 80-7FF -> 110yyyxx 10xxxxxx */ - /* 800-FFFF -> 1110yyyy 10yyyyxx 10xxxxxx */ - /* 10000-1FFFFF -> 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx */ - /* 200000-3FFFFFF -> 111110tt 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx */ - /* 4000000-FFFFFFFF -> 111111tt 10tttttt 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx */ - do { - c <<= 1; - bytes++; - } while ((c & 0x80) && bytes < 6); - if (bytes == 1) - { - /* A bare "continuation" byte. Say, 80 */ - goto bad_byte; - } - - c = (uint8_t)(c) >> bytes; - { - const char *pp = src; - int cnt = bytes; - while (--cnt) - { - unsigned ch = (unsigned char) *++pp; - if ((ch & 0xc0) != 0x80) /* Missing "continuation" byte. Example: e0 80 */ - { - goto bad_byte; - } - c = (c << 6) + (ch & 0x3f); - } - } - /* TODO */ - /* Need to check that c isn't produced by overlong encoding */ - /* Example: 11000000 10000000 converts to NUL */ - /* 11110000 10000000 10000100 10000000 converts to 0x100 */ - /* correct encoding: 11000100 10000000 */ - if (c <= 0x7f) /* crude check: only catches bad encodings which map to chars <= 7f */ - { - goto bad_byte; - } - - good_byte: - while (--bytes >= 0) - { - c = (unsigned char) *src++; - if (sanitized) - { - sanitized = (char*) xrealloc(sanitized, sanitized_pos + 2); - sanitized[sanitized_pos++] = c; - sanitized[sanitized_pos] = '\0'; - } - } - continue; - - bad_byte: - if (!sanitized) - { - sanitized_pos = src - initial_src; - sanitized = xstrndup(initial_src, sanitized_pos); - } - sanitized = (char*) xrealloc(sanitized, sanitized_pos + 5); - sanitized[sanitized_pos++] = '['; - c = (unsigned char) *src++; - sanitized[sanitized_pos++] = "0123456789ABCDEF"[c >> 4]; - sanitized[sanitized_pos++] = "0123456789ABCDEF"[c & 0xf]; - sanitized[sanitized_pos++] = ']'; - sanitized[sanitized_pos] = '\0'; - } - - if (sanitized) - VERB2 log("note: bad utf8, converted '%s' -> '%s'", initial_src, sanitized); - - return sanitized; /* usually NULL: the whole string is ok */ -} -void store_string(DBusMessageIter* iter, const char* val) -{ - const char *sanitized = sanitize_utf8(val); - if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, sanitized ? &sanitized : &val)) - die_out_of_memory(); - free((char*)sanitized); -} - - -/* - * Helpers for parsing DBus messages - */ - -//int load_bool(DBusMessageIter* iter, bool& val) -//{ -// int type = dbus_message_iter_get_arg_type(iter); -// if (type != DBUS_TYPE_BOOLEAN) -// error_msg_and_die("%s expected in dbus message, but not found ('%c')", "bool", type); -// dbus_bool_t db; -// dbus_message_iter_get_basic(iter, &db); -// val = db; -// return dbus_message_iter_next(iter); -//} -int load_int32(DBusMessageIter* iter, int32_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_INT32) - { - error_msg("%s expected in dbus message, but not found ('%c')", "int32", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_uint32(DBusMessageIter* iter, uint32_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_UINT32) - { - error_msg("%s expected in dbus message, but not found ('%c')", "uint32", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_int64(DBusMessageIter* iter, int64_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_INT64) - { - error_msg("%s expected in dbus message, but not found ('%c')", "int64", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_uint64(DBusMessageIter* iter, uint64_t *val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_UINT64) - { - error_msg("%s expected in dbus message, but not found ('%c')", "uint64", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); - return dbus_message_iter_next(iter); -} -int load_charp(DBusMessageIter* iter, const char** val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_STRING) - { - error_msg("%s expected in dbus message, but not found ('%c')", "string", type); - return -1; - } - dbus_message_iter_get_basic(iter, val); -//log("load_charp:'%s'", *val); - return dbus_message_iter_next(iter); -} - - -/* - * Glib integration machinery - */ - -/* Callback: "glib says dbus fd is active" */ -static gboolean handle_dbus_fd(GIOChannel *gio, GIOCondition condition, gpointer data) -{ - DBusWatch *watch = (DBusWatch*)data; - - VERB3 log("%s(gio, condition:%x [bits:IN/PRI/OUT/ERR/HUP...], data)", __func__, (int)condition); - - /* Notify the D-Bus library when a previously-added watch - * is ready for reading or writing, or has an exception such as a hangup. - */ - int glib_flags = (int)condition; - int dbus_flags = 0; - if (glib_flags & G_IO_IN) dbus_flags |= DBUS_WATCH_READABLE; - if (glib_flags & G_IO_OUT) dbus_flags |= DBUS_WATCH_WRITABLE; - if (glib_flags & G_IO_ERR) dbus_flags |= DBUS_WATCH_ERROR; - if (glib_flags & G_IO_HUP) dbus_flags |= DBUS_WATCH_HANGUP; - /* - * TODO: - * If dbus_watch_handle returns FALSE, then the file descriptor - * may still be ready for reading or writing, but more memory - * is needed in order to do the reading or writing. If you ignore - * the FALSE return, your application may spin in a busy loop - * on the file descriptor until memory becomes available, - * but nothing more catastrophic should happen. - */ - dbus_watch_handle(watch, dbus_flags); - - while (dbus_connection_dispatch(g_dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) - VERB3 log("%s: more data to process, looping", __func__); - return TRUE; /* "glib, do not remove this event source!" */ -} - -typedef struct watch_app_info_t -{ - GIOChannel *channel; - guint event_source_id; - bool watch_enabled; -} watch_app_info_t; -/* Callback: "dbus_watch_get_enabled() may return a different value than it did before" */ -static void toggled_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s(watch:%p, data)", __func__, watch); - - watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); - if (dbus_watch_get_enabled(watch)) - { - if (!app_info->watch_enabled) - { - app_info->watch_enabled = true; - int dbus_flags = dbus_watch_get_flags(watch); - int glib_flags = 0; - if (dbus_flags & DBUS_WATCH_READABLE) glib_flags |= G_IO_IN; - if (dbus_flags & DBUS_WATCH_WRITABLE) glib_flags |= G_IO_OUT; - VERB3 log(" adding watch to glib main loop. dbus_flags:%x glib_flags:%x", dbus_flags, glib_flags); - app_info->event_source_id = g_io_add_watch(app_info->channel, (GIOCondition)glib_flags, handle_dbus_fd, watch); - } - /* else: it was already enabled */ - } else { - if (app_info->watch_enabled) - { - app_info->watch_enabled = false; - /* does it free the hidden GSource too? */ - VERB3 log(" removing watch from glib main loop"); - g_source_remove(app_info->event_source_id); - } - /* else: it was already disabled */ - } -} -/* Callback: "libdbus needs a new watch to be monitored by the main loop" */ -static dbus_bool_t add_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s(watch:%p, data)", __func__, watch); - - watch_app_info_t* app_info = (watch_app_info_t*)xzalloc(sizeof(*app_info)); - dbus_watch_set_data(watch, app_info, free); - - int fd = dbus_watch_get_unix_fd(watch); - VERB3 log(" dbus_watch_get_unix_fd():%d", fd); - app_info->channel = g_io_channel_unix_new(fd); - /* _unconditionally_ adding it to event loop would be an error */ - toggled_watch(watch, data); - return TRUE; -} -/* Callback: "libdbus no longer needs a watch to be monitored by the main loop" */ -static void remove_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s()", __func__); - watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); - if (app_info->watch_enabled) - { - app_info->watch_enabled = false; - g_source_remove(app_info->event_source_id); - } - g_io_channel_unref(app_info->channel); -} - -/* Callback: "libdbus needs a new timeout to be monitored by the main loop" */ -static dbus_bool_t add_timeout(DBusTimeout *timeout, void* data) -{ - VERB3 log("%s()", __func__); - return TRUE; -} -/* Callback: "libdbus no longer needs a timeout to be monitored by the main loop" */ -static void remove_timeout(DBusTimeout *timeout, void* data) -{ - VERB3 log("%s()", __func__); -} -/* Callback: "dbus_timeout_get_enabled() may return a different value than it did before" */ -static void timeout_toggled(DBusTimeout *timeout, void* data) -{ -//seems to be never called, let's make it noisy - error_msg_and_die("%s(): FIXME: some dbus machinery is missing here", __func__); -} - -/* Callback: "DBusObjectPathVTable is unregistered (or its connection is freed)" */ -static void unregister_vtable(DBusConnection *conn, void* data) -{ - VERB3 log("%s()", __func__); -} - -/* - * Initialization works as follows: - * - * we have a DBusConnection* (say, obtained with dbus_bus_get) - * we call dbus_connection_set_watch_functions - * libdbus calls back add_watch(watch:0x2341090, data), this watch is for writing - * we call toggled_watch, but it finds that watch is not to be enabled yet - * libdbus calls back add_watch(watch:0x23410e0, data), this watch is for reading - * we call toggled_watch, it adds watch's fd to glib main loop with POLLIN - * (note: these watches are different objects, but they have the same fd) - * we call dbus_connection_set_timeout_functions - * we call dbus_connection_register_object_path - * - * Note: if user will later call dbus_bus_request_name(conn, ...): - * libdbus calls back add_timeout() - * libdbus calls back remove_timeout() - * note - no callback to timeout_toggled()! - * (therefore there is no code yet in timeout_toggled (see above), it's not used) - */ -void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, - const char* object_path, - DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) -) { - if (g_dbus_conn) - error_msg_and_die("Internal bug: can't connect to more than one dbus"); - g_dbus_conn = conn; - -//do we need this? why? -//log("dbus_connection_set_dispatch_status_function"); -// dbus_connection_set_dispatch_status_function(conn, -// dispatch, /* void dispatch(DBusConnection *conn, DBusDispatchStatus new_status, void* data) */ -// NULL, /* data */ -// NULL /* free_data_function */ -// ) - VERB3 log("dbus_connection_set_watch_functions"); - if (!dbus_connection_set_watch_functions(conn, - add_watch, - remove_watch, - toggled_watch, - NULL, /* data */ - NULL /* free_data_function */ - ) - ) { - die_out_of_memory(); - } - VERB3 log("dbus_connection_set_timeout_functions"); - if (!dbus_connection_set_timeout_functions(conn, - add_timeout, - remove_timeout, - timeout_toggled, - NULL, /* data */ - NULL /* free_data_function */ - ) - ) { - die_out_of_memory(); - } - - if (object_path && message_received_func) - { - /* Table */ - const DBusObjectPathVTable vtable = { - /* .unregister_function = */ unregister_vtable, - /* .message_function = */ message_received_func, - }; - VERB3 log("dbus_connection_register_object_path"); - if (!dbus_connection_register_object_path(conn, - object_path, - &vtable, - NULL /* data */ - ) - ) { - die_out_of_memory(); - } - } -} diff --git a/lib/utils/abrt_dbus.h b/lib/utils/abrt_dbus.h deleted file mode 100644 index cdc963ca..00000000 --- a/lib/utils/abrt_dbus.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 ABRT_DBUS_H -#define ABRT_DBUS_H - -#include -#include "abrtlib.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -extern DBusConnection* g_dbus_conn; - -/* - * Glib integration machinery - */ - -/* Hook up to DBus and to glib main loop. - * Usage cases: - * - * - server: - * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err); - * attach_dbus_conn_to_glib_main_loop(conn, "/some/path", handler_of_calls_to_some_path); - * rc = dbus_bus_request_name(conn, "server.name", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); - * - * - client which does not receive signals (only makes calls and emits signals): - * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err); - * // needed only if you need to use async dbus calls (not shown below): - * attach_dbus_conn_to_glib_main_loop(conn, NULL, NULL); - * // syncronous method call: - * msg = dbus_message_new_method_call("some.serv", "/path/on/serv", "optional.iface.on.serv", "method_name"); - * reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout, &err); - * // emitting signal: - * msg = dbus_message_new_signal("/path/sig/emitted/from", "iface.sig.emitted.from", "sig_name"); - * // (note: "iface.sig.emitted.from" is not optional for signals!) - * dbus_message_set_destination(msg, "peer"); // optional - * dbus_connection_send(conn, msg, &serial); // &serial can be NULL - * - * - client which receives and processes signals: - * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err); - * attach_dbus_conn_to_glib_main_loop(conn, NULL, NULL); - * dbus_connection_add_filter(conn, handle_message, NULL, NULL) - * dbus_bus_add_match(system_conn, "type='signal',...", &err); - * // signal is a dbus message which looks like this: - * // sender=XXX dest=YYY(or null) path=/path/sig/emitted/from interface=iface.sig.emitted.from member=sig_name - * // and handler_for_signals(conn,msg,opaque) will be called by glib - * // main loop to process received signals (and other messages - * // if you ask for them in dbus_bus_add_match[es], but this - * // would turn you into a server if you handle them too) ;] - */ -void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, - /* NULL if you are just a client */ - const char* object_path_to_register, - /* makes sense only if you use object_path_to_register: */ - DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) -); - -/* - * Helpers for building DBus messages - */ -//void store_bool(DBusMessageIter* iter, bool val); -void store_int32(DBusMessageIter* iter, int32_t val); -void store_uint32(DBusMessageIter* iter, uint32_t val); -void store_int64(DBusMessageIter* iter, int64_t val); -void store_uint64(DBusMessageIter* iter, uint64_t val); -void store_string(DBusMessageIter* iter, const char* val); - -/* - * Helpers for parsing DBus messages - */ -enum { - ABRT_DBUS_ERROR = -1, - ABRT_DBUS_LAST_FIELD = 0, - ABRT_DBUS_MORE_FIELDS = 1, - /* note that dbus_message_iter_next() returns FALSE on last field - * and TRUE if there are more fields. - * It maps exactly on the above constants. */ -}; -/* Checks type, loads data, advances to the next arg. - * Returns TRUE if next arg exists. - */ -//int load_bool(DBusMessageIter* iter, bool& val); -int load_int32(DBusMessageIter* iter, int32_t *val); -int load_uint32(DBusMessageIter* iter, uint32_t *val); -int load_int64(DBusMessageIter* iter, int64_t *val); -int load_uint64(DBusMessageIter* iter, uint64_t *val); -int load_charp(DBusMessageIter* iter, const char **val); - -#ifdef __cplusplus -} -#endif - - -/* C++ style stuff */ -#ifdef __cplusplus - -#include -#include - -/* - * Helpers for building DBus messages - */ - -//static inline void store_val(DBusMessageIter* iter, bool val) { store_bool(iter, val); } -static inline void store_val(DBusMessageIter* iter, int32_t val) { store_int32(iter, val); } -static inline void store_val(DBusMessageIter* iter, uint32_t val) { store_uint32(iter, val); } -static inline void store_val(DBusMessageIter* iter, int64_t val) { store_int64(iter, val); } -static inline void store_val(DBusMessageIter* iter, uint64_t val) { store_uint64(iter, val); } -static inline void store_val(DBusMessageIter* iter, const char* val) { store_string(iter, val); } -static inline void store_val(DBusMessageIter* iter, const std::string& val) { store_string(iter, val.c_str()); } - -/* Templates for vector and map */ -template struct abrt_dbus_type {}; -//template <> struct abrt_dbus_type { static const char* csig() { return "b"; } }; -template <> struct abrt_dbus_type { static const char* csig() { return "i"; } static std::string sig(); }; -template <> struct abrt_dbus_type { static const char* csig() { return "u"; } static std::string sig(); }; -template <> struct abrt_dbus_type { static const char* csig() { return "x"; } static std::string sig(); }; -template <> struct abrt_dbus_type { static const char* csig() { return "t"; } static std::string sig(); }; -template <> struct abrt_dbus_type { static const char* csig() { return "s"; } static std::string sig(); }; -#define ABRT_DBUS_SIG(T) (abrt_dbus_type::csig() ? abrt_dbus_type::csig() : abrt_dbus_type::sig().c_str()) -template -struct abrt_dbus_type< std::vector > { - static const char* csig() { return NULL; } - static std::string sig() { return ssprintf("a%s", ABRT_DBUS_SIG(E)); } -}; -template -struct abrt_dbus_type< std::map > { - static const char* csig() { return NULL; } - static std::string sig() { return ssprintf("a{%s%s}", ABRT_DBUS_SIG(K), ABRT_DBUS_SIG(V)); } -}; - -template -static void store_vector(DBusMessageIter* iter, const std::vector& val) -{ - DBusMessageIter sub_iter; - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, ABRT_DBUS_SIG(E), &sub_iter)) - die_out_of_memory(); - - typename std::vector::const_iterator vit = val.begin(); - for (; vit != val.end(); ++vit) - { - store_val(&sub_iter, *vit); - } - - if (!dbus_message_iter_close_container(iter, &sub_iter)) - die_out_of_memory(); -} -/* -template<> -static void store_vector(DBus::MessageIter &iter, const std::vector& val) -{ - if we use such vector, MUST add specialized code here (see in dbus-c++ source) -} -*/ -template -static void store_map(DBusMessageIter* iter, const std::map& val) -{ - DBusMessageIter sub_iter; - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, - ssprintf("{%s%s}", ABRT_DBUS_SIG(K), ABRT_DBUS_SIG(V)).c_str(), - &sub_iter)) - die_out_of_memory(); - - typename std::map::const_iterator mit = val.begin(); - for (; mit != val.end(); ++mit) - { - DBusMessageIter sub_sub_iter; - if (!dbus_message_iter_open_container(&sub_iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub_sub_iter)) - die_out_of_memory(); - store_val(&sub_sub_iter, mit->first); - store_val(&sub_sub_iter, mit->second); - if (!dbus_message_iter_close_container(&sub_iter, &sub_sub_iter)) - die_out_of_memory(); - } - - if (!dbus_message_iter_close_container(iter, &sub_iter)) - die_out_of_memory(); -} - -template -static inline void store_val(DBusMessageIter* iter, const std::vector& val) { store_vector(iter, val); } -template -static inline void store_val(DBusMessageIter* iter, const std::map& val) { store_map(iter, val); } - - -/* - * Helpers for parsing DBus messages - */ - -//static inline int load_val(DBusMessageIter* iter, bool &val) { return load_bool(iter, &val); } -static inline int load_val(DBusMessageIter* iter, int32_t &val) { return load_int32(iter, &val); } -static inline int load_val(DBusMessageIter* iter, uint32_t &val) { return load_uint32(iter, &val); } -static inline int load_val(DBusMessageIter* iter, int64_t &val) { return load_int64(iter, &val); } -static inline int load_val(DBusMessageIter* iter, uint64_t &val) { return load_uint64(iter, &val); } -static inline int load_val(DBusMessageIter* iter, const char*& val) { return load_charp(iter, &val); } -static inline int load_val(DBusMessageIter* iter, std::string& val) -{ - const char* str; - int r = load_charp(iter, &str); - val = str; - return r; -} - -/* Templates for vector and map */ -template -static int load_vector(DBusMessageIter* iter, std::vector& val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_ARRAY) - { - error_msg("array expected in dbus message, but not found ('%c')", type); - return -1; - } - - DBusMessageIter sub_iter; - dbus_message_iter_recurse(iter, &sub_iter); - - int r; -//int cnt = 0; - /* When the vector has 0 elements, we see DBUS_TYPE_INVALID here */ - type = dbus_message_iter_get_arg_type(&sub_iter); - if (type != DBUS_TYPE_INVALID) - { - do { - E elem; -//cnt++; - r = load_val(&sub_iter, elem); - if (r < 0) - return r; - val.push_back(elem); - } while (r == ABRT_DBUS_MORE_FIELDS); - } -//log("%s: %d elems", __func__, cnt); - - return dbus_message_iter_next(iter); -} -/* -template<> -static int load_vector(DBusMessageIter* iter, std::vector& val) -{ - if we use such vector, MUST add specialized code here (see in dbus-c++ source) -} -*/ -template -static int load_map(DBusMessageIter* iter, std::map& val) -{ - int type = dbus_message_iter_get_arg_type(iter); - if (type != DBUS_TYPE_ARRAY) - { - error_msg("array expected in dbus message, but not found ('%c')", type); - return -1; - } - - DBusMessageIter sub_iter; - dbus_message_iter_recurse(iter, &sub_iter); - - bool next_exists; - int r; -//int cnt = 0; - do { - type = dbus_message_iter_get_arg_type(&sub_iter); - if (type != DBUS_TYPE_DICT_ENTRY) - { - /* When the map has 0 elements, we see DBUS_TYPE_INVALID (on the first iteration) */ - if (type == DBUS_TYPE_INVALID) - break; - error_msg("sub_iter type is not DBUS_TYPE_DICT_ENTRY (%c)!", type); - return -1; - } - - DBusMessageIter sub_sub_iter; - dbus_message_iter_recurse(&sub_iter, &sub_sub_iter); - - K key; - r = load_val(&sub_sub_iter, key); - if (r != ABRT_DBUS_MORE_FIELDS) - { - if (r == ABRT_DBUS_LAST_FIELD) - error_msg("malformed map element in dbus message"); - return -1; - } - V value; - r = load_val(&sub_sub_iter, value); - if (r != ABRT_DBUS_LAST_FIELD) - { - if (r == ABRT_DBUS_MORE_FIELDS) - error_msg("malformed map element in dbus message"); - return -1; - } - val[key] = value; -//cnt++; - next_exists = dbus_message_iter_next(&sub_iter); - } while (next_exists); -//log("%s: %d elems", __func__, cnt); - - return dbus_message_iter_next(iter); -} - -template -static inline int load_val(DBusMessageIter* iter, std::vector& val) { return load_vector(iter, val); } -template -static inline int load_val(DBusMessageIter* iter, std::map& val) { return load_map(iter, val); } - -#endif /* __cplusplus */ - -#endif diff --git a/lib/utils/abrt_packages.c b/lib/utils/abrt_packages.c deleted file mode 100644 index bbf0e729..00000000 --- a/lib/utils/abrt_packages.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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" - -/* cuts the name from the NVR format: foo-1.2.3-1.el6 - returns a newly allocated string -*/ -char* get_package_name_from_NVR_or_NULL(const char* packageNVR) -{ - char* package_name = NULL; - if (packageNVR != NULL) - { - VERB1 log("packageNVR %s", packageNVR); - package_name = xstrdup(packageNVR); - char *pos = strrchr(package_name, '-'); - if (pos != NULL) - { - *pos = 0; - pos = strrchr(package_name, '-'); - if (pos != NULL) - { - *pos = 0; - } - } - } - return package_name; -} diff --git a/lib/utils/abrt_packages.h b/lib/utils/abrt_packages.h deleted file mode 100644 index 6a952f5e..00000000 --- a/lib/utils/abrt_packages.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 ABRT_PACKAGES_H -#define ABRT_PACKAGES_H - -#ifdef __cplusplus -extern "C" { -#endif - -char* get_package_name_from_NVR_or_NULL(const char* packageNVR); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/utils/abrt_xmlrpc.cpp b/lib/utils/abrt_xmlrpc.cpp deleted file mode 100644 index bf74f05b..00000000 --- a/lib/utils/abrt_xmlrpc.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 "abrt_xmlrpc.h" -#include "abrt_exception.h" - -void throw_xml_fault(xmlrpc_env *env) -{ - std::string errmsg = ssprintf("XML-RPC Fault(%d): %s", env->fault_code, env->fault_string); - xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred - xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env - error_msg("%s", errmsg.c_str()); // show error in daemon log - throw CABRTException(EXCEP_PLUGIN, errmsg.c_str()); -} - -void throw_if_xml_fault_occurred(xmlrpc_env *env) -{ - if (env->fault_occurred) - { - throw_xml_fault(env); - } -} - -void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool ssl_verify) -{ - m_pClient = NULL; - m_pServer_info = NULL; - - xmlrpc_env env; - xmlrpc_env_init(&env); - - /* This should be done at program startup, once. - * We do it in abrtd's main */ - /* xmlrpc_client_setup_global_const(&env); */ - - struct xmlrpc_curl_xportparms curlParms; - memset(&curlParms, 0, sizeof(curlParms)); - /* curlParms.network_interface = NULL; - done by memset */ - curlParms.no_ssl_verifypeer = !ssl_verify; - curlParms.no_ssl_verifyhost = !ssl_verify; -#ifdef VERSION - curlParms.user_agent = PACKAGE_NAME"/"VERSION; -#else - curlParms.user_agent = "abrt"; -#endif - - struct xmlrpc_clientparms clientParms; - memset(&clientParms, 0, sizeof(clientParms)); - clientParms.transport = "curl"; - clientParms.transportparmsP = &curlParms; - clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent); - - xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, - PACKAGE_NAME, VERSION, - &clientParms, XMLRPC_CPSIZE(transportparm_size), - &m_pClient); - if (env.fault_occurred) - throw_xml_fault(&env); - - m_pServer_info = xmlrpc_server_info_new(&env, url); - if (env.fault_occurred) - { - xmlrpc_client_destroy(m_pClient); - m_pClient = NULL; - throw_xml_fault(&env); - } -} - -void abrt_xmlrpc_conn::destroy_xmlrpc_client() -{ - if (m_pServer_info) - { - xmlrpc_server_info_free(m_pServer_info); - m_pServer_info = NULL; - } - if (m_pClient) - { - xmlrpc_client_destroy(m_pClient); - m_pClient = NULL; - } -} diff --git a/lib/utils/abrt_xmlrpc.h b/lib/utils/abrt_xmlrpc.h deleted file mode 100644 index ad1a87d3..00000000 --- a/lib/utils/abrt_xmlrpc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 ABRT_XMLRPC_H_ -#define ABRT_XMLRPC_H_ 1 - -#include -#include -#include - -/* - * Simple class holding XMLRPC connection data. - * Used mainly to ensure we always destroy xmlrpc client and server_info - * on return or throw. - */ - -struct abrt_xmlrpc_conn { - xmlrpc_client* m_pClient; - xmlrpc_server_info* m_pServer_info; - - abrt_xmlrpc_conn(const char* url, bool ssl_verify) { new_xmlrpc_client(url, ssl_verify); } - /* this never throws exceptions - calls C functions only */ - ~abrt_xmlrpc_conn() { destroy_xmlrpc_client(); } - - void new_xmlrpc_client(const char* url, bool ssl_verify); - void destroy_xmlrpc_client(); -}; - -/* Utility functions */ -void throw_xml_fault(xmlrpc_env *env); -void throw_if_xml_fault_occurred(xmlrpc_env *env); - -#endif diff --git a/lib/utils/append_to_malloced_string.c b/lib/utils/append_to_malloced_string.c deleted file mode 100644 index 430cef0b..00000000 --- a/lib/utils/append_to_malloced_string.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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" - -char *append_to_malloced_string(char *mstr, const char *append) -{ - unsigned mlen = strlen(mstr); - mstr = (char*) xrealloc(mstr, mlen + strlen(append) + 1); - strcpy(mstr + mlen, append); - return mstr; -} diff --git a/lib/utils/concat_path_file.c b/lib/utils/concat_path_file.c deleted file mode 100644 index 4c946628..00000000 --- a/lib/utils/concat_path_file.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Utility routines. - * - * Copyright (C) 2001 Erik Andersen - * - * Licensed under GPLv2 or later. - */ - -/* Concatenate path and filename to new allocated buffer. - * Add '/' only as needed (no duplicate // are produced). - * If path is NULL, it is assumed to be "/". - * filename should not be NULL. - */ - -#include "abrtlib.h" - -char *concat_path_file(const char *path, const char *filename) -{ - if (!path) - path = ""; - const char *end = path + strlen(path); - while (*filename == '/') - filename++; - return xasprintf("%s%s%s", path, (end != path && end[-1] != '/' ? "/" : ""), filename); -} diff --git a/lib/utils/copyfd.c b/lib/utils/copyfd.c deleted file mode 100644 index bfe0fa49..00000000 --- a/lib/utils/copyfd.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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. -*/ - -/* - * Utility routines. - * - */ -#include "abrtlib.h" - -#define CONFIG_FEATURE_COPYBUF_KB 4 - -static const char msg_write_error[] = "write error"; -static const char msg_read_error[] = "read error"; - -static off_t full_fd_action(int src_fd, int dst_fd, off_t size, int flags) -{ - int status = -1; - off_t total = 0; - int last_was_seek = 0; -#if CONFIG_FEATURE_COPYBUF_KB <= 4 - char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; - enum { buffer_size = sizeof(buffer) }; -#else - char *buffer; - int buffer_size; - - /* We want page-aligned buffer, just in case kernel is clever - * and can do page-aligned io more efficiently */ - buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - /* ignored: */ -1, 0); - buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; - if (buffer == MAP_FAILED) { - buffer = alloca(4 * 1024); - buffer_size = 4 * 1024; - } -#endif - - if (src_fd < 0) - goto out; - - if (!size) { - size = buffer_size; - status = 1; /* copy until eof */ - } - - while (1) { - ssize_t rd; - - rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); - - if (!rd) { /* eof - all done */ - if (last_was_seek) { - if (lseek(dst_fd, -1, SEEK_CUR) < 0 - || safe_write(dst_fd, "", 1) != 1 - ) { - perror_msg("%s", msg_write_error); - break; - } - } - status = 0; - break; - } - if (rd < 0) { - perror_msg("%s", msg_read_error); - break; - } - /* dst_fd == -1 is a fake, else... */ - if (dst_fd >= 0) { - if (flags & COPYFD_SPARSE) { - ssize_t cnt = rd; - while (--cnt >= 0) - if (buffer[cnt] != 0) - goto need2write; - if (lseek(dst_fd, rd, SEEK_CUR) < 0) { - flags &= ~COPYFD_SPARSE; - goto need2write; - } - last_was_seek = 1; - } else { - need2write: - { - ssize_t wr = full_write(dst_fd, buffer, rd); - if (wr < rd) { - perror_msg("%s", msg_write_error); - break; - } - last_was_seek = 0; - } - } - } - total += rd; - if (status < 0) { /* if we aren't copying till EOF... */ - size -= rd; - if (!size) { - /* 'size' bytes copied - all done */ - status = 0; - break; - } - } - } - out: - -#if CONFIG_FEATURE_COPYBUF_KB > 4 - if (buffer_size != 4 * 1024) - munmap(buffer, buffer_size); -#endif - return status ? -1 : total; -} - -off_t copyfd_size(int fd1, int fd2, off_t size, int flags) -{ - if (size) { - return full_fd_action(fd1, fd2, size, flags); - } - return 0; -} - -void copyfd_exact_size(int fd1, int fd2, off_t size) -{ - off_t sz = copyfd_size(fd1, fd2, size, /*flags:*/ 0); - if (sz == size) - return; - if (sz != -1) - error_msg_and_die("short read"); - /* if sz == -1, copyfd_XX already complained */ - xfunc_die(); -} - -off_t copyfd_eof(int fd1, int fd2, int flags) -{ - return full_fd_action(fd1, fd2, 0, flags); -} - -off_t copy_file(const char *src_name, const char *dst_name, int mode) -{ - off_t r; - int src = open(src_name, O_RDONLY); - if (src < 0) - { - perror_msg("Can't open '%s'", src_name); - return -1; - } - int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, mode); - if (dst < 0) - { - close(src); - perror_msg("Can't open '%s'", dst_name); - return -1; - } - r = copyfd_eof(src, dst, /*flags:*/ 0); - close(src); - close(dst); - return r; -} diff --git a/lib/utils/daemon.c b/lib/utils/daemon.c deleted file mode 100644 index 944aef0c..00000000 --- a/lib/utils/daemon.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - Copyright (C) 2009 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" - -#define VAR_RUN_PID_FILE VAR_RUN"/abrtd.pid" - -static char *append_escaped(char *start, const char *s) -{ - char hex_char_buf[] = "\\x00"; - - *start++ = ' '; - char *dst = start; - const unsigned char *p = (unsigned char *)s; - - while (1) - { - const unsigned char *old_p = p; - while (*p > ' ' && *p <= 0x7e && *p != '\"' && *p != '\'' && *p != '\\') - p++; - if (dst == start) - { - if (p != (unsigned char *)s && *p == '\0') - { - /* entire word does not need escaping and quoting */ - strcpy(dst, s); - dst += strlen(s); - return dst; - } - *dst++ = '\''; - } - - strncpy(dst, (char *)old_p, (p - old_p)); - dst += (p - old_p); - - if (*p == '\0') - { - *dst++ = '\''; - *dst = '\0'; - return dst; - } - const char *a; - switch (*p) - { - case '\r': a = "\\r"; break; - case '\n': a = "\\n"; break; - case '\t': a = "\\t"; break; - case '\'': a = "\\\'"; break; - case '\"': a = "\\\""; break; - case '\\': a = "\\\\"; break; - case ' ': a = " "; break; - default: - hex_char_buf[2] = "0123456789abcdef"[*p >> 4]; - hex_char_buf[3] = "0123456789abcdef"[*p & 0xf]; - a = hex_char_buf; - } - strcpy(dst, a); - dst += strlen(a); - p++; - } -} - -// taken from kernel -#define COMMAND_LINE_SIZE 2048 -char* get_cmdline(pid_t pid) -{ - char path[sizeof("/proc/%lu/cmdline") + sizeof(long)*3]; - char cmdline[COMMAND_LINE_SIZE]; - char escaped_cmdline[COMMAND_LINE_SIZE*4 + 4]; - - escaped_cmdline[1] = '\0'; - sprintf(path, "/proc/%lu/cmdline", (long)pid); - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - int len = read(fd, cmdline, sizeof(cmdline) - 1); - close(fd); - - if (len > 0) - { - cmdline[len] = '\0'; - char *src = cmdline; - char *dst = escaped_cmdline; - while ((src - cmdline) < len) - { - dst = append_escaped(dst, src); - src += strlen(src) + 1; - } - } - } - - return xstrdup(escaped_cmdline + 1); /* +1 skips extraneous leading space */ -} - -int daemon_is_ok() -{ - int fd = open(VAR_RUN_PID_FILE, O_RDONLY); - if (fd < 0) - { - return 0; - } - - char pid[sizeof(pid_t)*3 + 2]; - int len = read(fd, pid, sizeof(pid)-1); - close(fd); - if (len <= 0) - return 0; - - pid[len] = '\0'; - *strchrnul(pid, '\n') = '\0'; - /* paranoia: we don't want to check /proc//stat or /proc///stat */ - if (pid[0] == '\0' || pid[0] == '/') - return 0; - - /* TODO: maybe readlink and check that it is "xxx/abrt"? */ - char path[sizeof("/proc/%s/stat") + sizeof(pid)]; - sprintf(path, "/proc/%s/stat", pid); - struct stat sb; - if (stat(path, &sb) == -1) - { - return 0; - } - - return 1; -} diff --git a/lib/utils/database.c b/lib/utils/database.c deleted file mode 100644 index 2b742ebf..00000000 --- a/lib/utils/database.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 "database.h" - -struct db_row *db_rowcpy_from_list(GList* list) -{ - GList *first = g_list_first(list); - struct db_row *row = (struct db_row*)xzalloc(sizeof(struct db_row)); - struct db_row *src_row = (struct db_row*)first->data; - /* All fields are initialized below, copying is not needed - * memcpy(row, (struct db_row*)first->data, sizeof(struct db_row)); - */ - - row->db_uuid = xstrdup(src_row->db_uuid); - row->db_uid = xstrdup(src_row->db_uid); - row->db_inform_all = xstrdup(src_row->db_inform_all); - row->db_dump_dir = xstrdup(src_row->db_dump_dir); - row->db_count = xstrdup(src_row->db_count); - row->db_reported = xstrdup(src_row->db_reported); - row->db_message = xstrdup(src_row->db_message); - row->db_time = xstrdup(src_row->db_time); - - return row; -} - -void db_row_free(struct db_row *row) -{ - if (!row) - return; - - free(row->db_uuid); - free(row->db_uid); - free(row->db_inform_all); - free(row->db_dump_dir); - free(row->db_count); - free(row->db_reported); - free(row->db_message); - free(row->db_time); - - free(row); -} - -void db_list_free(GList *list) -{ - if (!list) - return; - - for (GList *li = list; li != NULL; li = g_list_next(li)) - { - struct db_row *row = (struct db_row*)li->data; - db_row_free(row); - } - g_list_free(list); -} - diff --git a/lib/utils/dirsize.c b/lib/utils/dirsize.c deleted file mode 100644 index be927ad5..00000000 --- a/lib/utils/dirsize.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) - Copyright (C) 2009 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" - -double get_dirsize(const char *pPath) -{ - DIR *dp = opendir(pPath); - if (dp == NULL) - return 0; - - struct dirent *ep; - struct stat statbuf; - double size = 0; - while ((ep = readdir(dp)) != NULL) - { - if (dot_or_dotdot(ep->d_name)) - continue; - char *dname = concat_path_file(pPath, ep->d_name); - if (lstat(dname, &statbuf) != 0) - { - free(dname); - continue; - } - if (S_ISDIR(statbuf.st_mode)) - { - size += get_dirsize(dname); - } - else if (S_ISREG(statbuf.st_mode)) - { - size += statbuf.st_size; - } - free(dname); - } - closedir(dp); - return size; -} - -double get_dirsize_find_largest_dir( - const char *pPath, - char **worst_dir, - const char *excluded) -{ - if (worst_dir) - *worst_dir = NULL; - - DIR *dp = opendir(pPath); - if (dp == NULL) - return 0; - - struct dirent *ep; - struct stat statbuf; - double size = 0; - double maxsz = 0; - while ((ep = readdir(dp)) != NULL) - { - if (dot_or_dotdot(ep->d_name)) - continue; - char *dname = concat_path_file(pPath, ep->d_name); - if (lstat(dname, &statbuf) != 0) - { - free(dname); - continue; - } - if (S_ISDIR(statbuf.st_mode)) - { - double sz = get_dirsize(dname); - size += sz; - - if (worst_dir && (!excluded || strcmp(excluded, ep->d_name) != 0)) - { - /* Calculate "weighted" size and age - * w = sz_kbytes * age_mins */ - sz /= 1024; - long age = (time(NULL) - statbuf.st_mtime) / 60; - if (age > 0) - sz *= age; - - if (sz > maxsz) - { - maxsz = sz; - free(*worst_dir); - *worst_dir = xstrdup(ep->d_name); - } - } - } - else if (S_ISREG(statbuf.st_mode)) - { - size += statbuf.st_size; - } - free(dname); - } - closedir(dp); - return size; -} diff --git a/lib/utils/dump_dir.c b/lib/utils/dump_dir.c deleted file mode 100644 index 0328bb26..00000000 --- a/lib/utils/dump_dir.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - DebugDump.cpp - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 -#include "abrtlib.h" -#include "strbuf.h" - -// TODO: -// -// Perhaps dd_opendir should do some sanity checking like -// "if there is no "uid" file in the directory, it's not a crash dump", -// and fail. - -static char *load_text_file(const char *path, unsigned flags); - -static bool isdigit_str(const char *str) -{ - do - { - if (*str < '0' || *str > '9') return false; - str++; - } while (*str); - return true; -} - -static bool exist_file_dir(const char *path) -{ - struct stat buf; - if (stat(path, &buf) == 0) - { - if (S_ISDIR(buf.st_mode) || S_ISREG(buf.st_mode)) - { - return true; - } - } - return false; -} - -static bool get_and_set_lock(const char* lock_file, const char* pid) -{ - while (symlink(pid, lock_file) != 0) - { - if (errno != EEXIST) - perror_msg_and_die("Can't create lock file '%s'", lock_file); - - char pid_buf[sizeof(pid_t)*3 + 4]; - ssize_t r = readlink(lock_file, pid_buf, sizeof(pid_buf) - 1); - if (r < 0) - { - if (errno == ENOENT) - { - /* Looks like lock_file was deleted */ - usleep(10 * 1000); /* avoid CPU eating loop */ - continue; - } - perror_msg_and_die("Can't read lock file '%s'", lock_file); - } - pid_buf[r] = '\0'; - - if (strcmp(pid_buf, pid) == 0) - { - log("Lock file '%s' is already locked by us", lock_file); - return false; - } - if (isdigit_str(pid_buf)) - { - char pid_str[sizeof("/proc/") + strlen(pid_buf)]; - sprintf(pid_str, "/proc/%s", pid_buf); - if (access(pid_str, F_OK) == 0) - { - log("Lock file '%s' is locked by process %s", lock_file, pid_buf); - return false; - } - log("Lock file '%s' was locked by process %s, but it crashed?", lock_file, pid_buf); - } - /* The file may be deleted by now by other process. Ignore ENOENT */ - if (unlink(lock_file) != 0 && errno != ENOENT) - { - perror_msg_and_die("Can't remove stale lock file '%s'", lock_file); - } - } - - VERB1 log("Locked '%s'", lock_file); - return true; -} - -static void dd_lock(struct dump_dir *dd) -{ - if (dd->locked) - error_msg_and_die("Locking bug on '%s'", dd->dd_dir); - - char lock_buf[strlen(dd->dd_dir) + sizeof(".lock")]; - sprintf(lock_buf, "%s.lock", dd->dd_dir); - - char pid_buf[sizeof(long)*3 + 2]; - sprintf(pid_buf, "%lu", (long)getpid()); - while ((dd->locked = get_and_set_lock(lock_buf, pid_buf)) != true) - { - sleep(1); /* was 0.5 seconds */ - } -} - -static void dd_unlock(struct dump_dir *dd) -{ - if (dd->locked) - { - dd->locked = 0; - char lock_buf[strlen(dd->dd_dir) + sizeof(".lock")]; - sprintf(lock_buf, "%s.lock", dd->dd_dir); - xunlink(lock_buf); - VERB1 log("Unlocked '%s'", lock_buf); - } -} - -static inline struct dump_dir *dd_init(void) -{ - return (struct dump_dir*)xzalloc(sizeof(struct dump_dir)); -} - -int dd_exist(struct dump_dir *dd, const char *path) -{ - char *full_path = concat_path_file(dd->dd_dir, path); - int ret = exist_file_dir(full_path); - free(full_path); - return ret; -} - -void dd_close(struct dump_dir *dd) -{ - if (!dd) - return; - - dd_unlock(dd); - if (dd->next_dir) - { - closedir(dd->next_dir); - /* free(dd->next_dir); - WRONG! */ - } - - free(dd->dd_dir); - free(dd); -} - -static char* rm_trailing_slashes(const char *dir) -{ - unsigned len = strlen(dir); - while (len != 0 && dir[len-1] == '/') - len--; - return xstrndup(dir, len); -} - -struct dump_dir *dd_opendir(const char *dir, int flags) -{ - struct dump_dir *dd = dd_init(); - - /* Used to use rm_trailing_slashes(dir) here, but with dir = "." - * or "..", or if the last component is a symlink, - * then lock file is created in the wrong place. - * IOW: this breaks locking. - */ - dd->dd_dir = realpath(dir, NULL); - if (!dd->dd_dir) - { - if (!(flags & DD_FAIL_QUIETLY)) - error_msg("'%s' does not exist", dir); - dd_close(dd); - return NULL; - } - dir = dd->dd_dir; - - dd_lock(dd); - - struct stat stat_buf; - if (stat(dir, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode)) - { - if (!(flags & DD_FAIL_QUIETLY)) - error_msg("'%s' does not exist", dir); - dd_close(dd); - return NULL; - } - - /* In case caller would want to create more files, he'll need uid:gid */ - dd->dd_uid = stat_buf.st_uid; - dd->dd_gid = stat_buf.st_gid; - - /* Without this check, e.g. abrt-action-print happily prints any current - * directory when run without arguments, because its option -d DIR - * defaults to "."! Let's require that at least some crash dump dir - * specific files exist before we declare open successful: - */ - char *name = concat_path_file(dir, FILENAME_ANALYZER); - int bad = (lstat(name, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)); - free(name); - if (bad) - { - /*if (!(flags & DD_FAIL_QUIETLY))... - no, DD_FAIL_QUIETLY only means - * "it's ok if it doesn exist", not "ok if contents is bogus"! - */ - error_msg("'%s' is not a crash dump directory", dir); - dd_close(dd); - return NULL; - } - - return dd; -} - -/* Create a fresh empty debug dump dir. - * - * Security: we should not allow users to write new files or write - * into existing ones, but they should be able to read them. - * - * @param uid - * Crashed application's User Id - * - * We currently have only three callers: - * kernel oops hook: uid=0 - * this hook runs under 0:0 - * ccpp hook: uid=uid of crashed user's binary - * this hook runs under 0:0 - * python hook: uid=uid of crashed user's script - * this hook runs under abrt:gid - * - * Currently, we set dir's gid to passwd(uid)->pw_gid parameter, and we set uid to - * abrt's user id. We do not allow write access to group. - */ -struct dump_dir *dd_create(const char *dir, uid_t uid) -{ - struct dump_dir *dd = dd_init(); - - /* Unlike dd_opendir, can't use realpath: the directory doesn't exist yet, - * realpath will always return NULL. We don't really have to: - * dd_opendir(".") makes sense, dd_create(".") does not. - */ - dir = dd->dd_dir = rm_trailing_slashes(dir); - - const char *last_component = strrchr(dir, '/'); - if (last_component) - last_component++; - else - last_component = dir; - if (dot_or_dotdot(last_component)) - { - /* dd_create("."), dd_create(".."), dd_create("dir/."), - * dd_create("dir/..") and similar are madness, refuse them. - */ - error_msg("Bad dir name '%s'", dir); - dd_close(dd); - return NULL; - } - - dd_lock(dd); - - /* Was creating it with mode 0700 and user as the owner, but this allows - * the user to replace any file in the directory, changing security-sensitive data - * (e.g. "uid", "analyzer", "executable") - */ - if (mkdir(dir, 0750) == -1) - { - perror_msg("Can't create dir '%s'", dir); - dd_close(dd); - return NULL; - } - - /* mkdir's mode (above) can be affected by umask, fix it */ - if (chmod(dir, 0750) == -1) - { - perror_msg("Can't change mode of '%s'", dir); - dd_close(dd); - return NULL; - } - - /* Get ABRT's user id */ - /*dd->dd_uid = 0; - dd_init did this already */ - struct passwd *pw = getpwnam("abrt"); - if (pw) - dd->dd_uid = pw->pw_uid; - else - error_msg("User 'abrt' does not exist, using uid 0"); - - /* Get crashed application's group id */ - /*dd->dd_gid = 0; - dd_init did this already */ - pw = getpwuid(uid); - if (pw) - dd->dd_gid = pw->pw_gid; - else - error_msg("User %lu does not exist, using gid 0", (long)uid); - - if (chown(dir, dd->dd_uid, dd->dd_gid) == -1) - { - perror_msg("Can't change '%s' ownership to %lu:%lu", dir, - (long)dd->dd_uid, (long)dd->dd_gid); - } - - char long_str[sizeof(long) * 3 + 2]; - - sprintf(long_str, "%lu", (long)uid); - dd_save_text(dd, CD_UID, long_str); - - struct utsname buf; - uname(&buf); /* never fails */ - dd_save_text(dd, FILENAME_KERNEL, buf.release); - dd_save_text(dd, FILENAME_ARCHITECTURE, buf.machine); - char *release = load_text_file("/etc/redhat-release", /*flags:*/ 0); - strchrnul(release, '\n')[0] = '\0'; - dd_save_text(dd, FILENAME_RELEASE, release); - free(release); - - time_t t = time(NULL); - sprintf(long_str, "%lu", (long)t); - dd_save_text(dd, FILENAME_TIME, long_str); - - return dd; -} - -static void delete_file_dir(const char *dir) -{ - DIR *d = opendir(dir); - if (!d) - return; - - struct dirent *dent; - while ((dent = readdir(d)) != NULL) - { - if (dot_or_dotdot(dent->d_name)) - continue; - char *full_path = concat_path_file(dir, dent->d_name); - if (unlink(full_path) == -1 && errno != ENOENT) - { - if (errno != EISDIR) - { - error_msg("Can't remove '%s'", full_path); - free(full_path); - closedir(d); - return; - } - delete_file_dir(full_path); - } - free(full_path); - } - closedir(d); - if (rmdir(dir) == -1) - { - error_msg("Can't remove dir '%s'", dir); - } -} - -void dd_delete(struct dump_dir *dd) -{ - delete_file_dir(dd->dd_dir); -} - -static char *load_text_file(const char *path, unsigned flags) -{ - FILE *fp = fopen(path, "r"); - if (!fp) - { - if (!(flags & DD_FAIL_QUIETLY)) - perror_msg("Can't open file '%s'", path); - return (flags & DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE ? NULL : xstrdup("")); - } - - struct strbuf *buf_content = strbuf_new(); - int ch; - while ((ch = fgetc(fp)) != EOF) - { - if (ch == '\0') - strbuf_append_char(buf_content, ' '); - else if (isspace(ch) || (isascii(ch) && !iscntrl(ch))) - strbuf_append_char(buf_content, ch); - } - fclose(fp); - - return strbuf_free_nobuf(buf_content); -} - -static bool save_binary_file(const char *path, const char* data, unsigned size, uid_t uid, gid_t gid) -{ - /* "Why 0640?!" See ::Create() for security analysis */ - unlink(path); - int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0640); - if (fd < 0) - { - perror_msg("Can't open file '%s'", path); - return false; - } - if (fchown(fd, uid, gid) == -1) - { - perror_msg("can't change '%s' ownership to %lu:%lu", path, (long)uid, (long)gid); - } - unsigned r = full_write(fd, data, size); - close(fd); - if (r != size) - { - error_msg("Can't save file '%s'", path); - return false; - } - - return true; -} - -char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned flags) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - char *full_path = concat_path_file(dd->dd_dir, name); - char *ret = load_text_file(full_path, flags); - free(full_path); - - return ret; -} - -char* dd_load_text(const struct dump_dir *dd, const char *name) -{ - return dd_load_text_ext(dd, name, /*flags:*/ 0); -} - -void dd_save_text(struct dump_dir *dd, const char *name, const char *data) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - char *full_path = concat_path_file(dd->dd_dir, name); - save_binary_file(full_path, data, strlen(data), dd->dd_uid, dd->dd_gid); - free(full_path); -} - -void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, unsigned size) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - char *full_path = concat_path_file(dd->dd_dir, name); - save_binary_file(full_path, data, size, dd->dd_uid, dd->dd_gid); - free(full_path); -} - -DIR *dd_init_next_file(struct dump_dir *dd) -{ - if (!dd->locked) - error_msg_and_die("dump_dir is not opened"); /* bug */ - - if (dd->next_dir) - closedir(dd->next_dir); - - dd->next_dir = opendir(dd->dd_dir); - if (!dd->next_dir) - { - error_msg("Can't open dir '%s'", dd->dd_dir); - } - - return dd->next_dir; -} - -int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name) -{ - if (dd->next_dir == NULL) - return 0; - - struct dirent *dent; - while ((dent = readdir(dd->next_dir)) != NULL) - { - if (is_regular_file(dent, dd->dd_dir)) - { - if (short_name) - *short_name = xstrdup(dent->d_name); - if (full_name) - *full_name = concat_path_file(dd->dd_dir, dent->d_name); - return 1; - } - } - - closedir(dd->next_dir); - dd->next_dir = NULL; - return 0; -} - -/* Utility function */ -void delete_debug_dump_dir(const char *dd_dir) -{ - struct dump_dir *dd = dd_opendir(dd_dir, /*flags:*/ 0); - if (dd) - { - dd_delete(dd); - dd_close(dd); - } -} diff --git a/lib/utils/encbase64.c b/lib/utils/encbase64.c deleted file mode 100644 index 6a6f1f75..00000000 --- a/lib/utils/encbase64.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2006 Rob Landley - * - * Licensed under GPLv2 or later. - */ -#include "abrtlib.h" /* xmalloc */ - -/* Conversion table for base 64 */ -static const char tbl_base64[65 /*+ 2*/] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/', - '=' /* termination character */, - // '\n', '\0' /* needed for uudecode.c */ -}; - -/* Conversion table for uuencode -const char tbl_uuencode[65] ALIGN1 = { - '`', '!', '"', '#', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '<', '=', '>', '?', - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', - '`' -}; -*/ - -/* - * Encode bytes at S of length LENGTH. - * Result will be 0-terminated, and must point to a writable - * buffer of at least 1+BASE64_LENGTH(length) bytes, - * where BASE64_LENGTH(len) = 4 * ((LENGTH + 2) / 3) - */ -static void encode_64bit(char *p, const void *src, int length, const char *tbl) -{ - const unsigned char *s = (const unsigned char *)src; - - /* Transform the 3x8 bits to 4x6 bits */ - while (length > 0) { - unsigned s1, s2; - - /* Are s[1], s[2] valid or should be assumed 0? */ - s1 = s2 = 0; - length -= 3; /* can be >=0, -1, -2 */ - if (length >= -1) { - s1 = s[1]; - if (length >= 0) - s2 = s[2]; - } - *p++ = tbl[s[0] >> 2]; - *p++ = tbl[((s[0] & 3) << 4) + (s1 >> 4)]; - *p++ = tbl[((s1 & 0xf) << 2) + (s2 >> 6)]; - *p++ = tbl[s2 & 0x3f]; - s += 3; - } - /* Zero-terminate */ - *p = '\0'; - /* If length is -2 or -1, pad last char or two */ - while (length) { - *--p = tbl[64]; - length++; - } -} - -char *encode_base64(const void *src, int length) -{ - char *dst = (char *)xmalloc(4 * ((length + 2) / 3) + 1); - encode_64bit(dst, src, length, tbl_base64); - return dst; -} diff --git a/lib/utils/hash_md5.c b/lib/utils/hash_md5.c deleted file mode 100644 index 8bfddd54..00000000 --- a/lib/utils/hash_md5.c +++ /dev/null @@ -1,444 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * md5.c - Compute MD5 checksum of strings according to the - * definition of MD5 in RFC 1321 from April 1992. - * - * Written by Ulrich Drepper , 1995. - * - * Copyright (C) 1995-1999 Free Software Foundation, Inc. - * Copyright (C) 2001 Manuel Novoa III - * Copyright (C) 2003 Glenn L. McGrath - * Copyright (C) 2003 Erik Andersen - * - * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. - */ -#include "abrtlib.h" -#include - -#if defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ -# define MD5_BIG_ENDIAN 1 -# define MD5_LITTLE_ENDIAN 0 -#elif __BYTE_ORDER == __BIG_ENDIAN -# define MD5_BIG_ENDIAN 1 -# define MD5_LITTLE_ENDIAN 0 -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define MD5_BIG_ENDIAN 0 -# define MD5_LITTLE_ENDIAN 1 -#else -# error "Can't determine endianness" -#endif - -/* SWAP_LEnn means "convert CPU<->little_endian if needed (by swapping bytes)" */ -#if MD5_BIG_ENDIAN -# define SWAP_BE32(x) (x) -# define SWAP_LE32(x) bswap_32(x) -#else -# define SWAP_BE32(x) bswap_32(x) -# define SWAP_LE32(x) (x) -#endif - - -/* 0: fastest, 3: smallest */ -#define MD5_SIZE_VS_SPEED 3 - -/* Initialize structure containing state of computation. - * (RFC 1321, 3.3: Step 3) - */ -void md5_begin(md5_ctx_t *ctx) -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - ctx->total = 0; - ctx->buflen = 0; -} - -/* These are the four functions used in the four steps of the MD5 algorithm - * and defined in the RFC 1321. The first function is a little bit optimized - * (as found in Colin Plumbs public domain implementation). - * #define FF(b, c, d) ((b & c) | (~b & d)) - */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF(d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) - -/* Hash a single block, 64 bytes long and 4-byte aligned. */ -static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) -{ - uint32_t correct_words[16]; - const uint32_t *words = (const uint32_t *)buffer; - -#if MD5_SIZE_VS_SPEED > 0 - static const uint32_t C_array[] = { - /* round 1 */ - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - /* round 2 */ - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - /* round 3 */ - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - /* round 4 */ - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 - }; - static const char P_array[] = { -# if MD5_SIZE_VS_SPEED > 1 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ -# endif - 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ - 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ - 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ - }; -# if MD5_SIZE_VS_SPEED > 1 - static const char S_array[] = { - 7, 12, 17, 22, - 5, 9, 14, 20, - 4, 11, 16, 23, - 6, 10, 15, 21 - }; -# endif /* MD5_SIZE_VS_SPEED > 1 */ -#endif - uint32_t A = ctx->A; - uint32_t B = ctx->B; - uint32_t C = ctx->C; - uint32_t D = ctx->D; - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - uint32_t *cwp = correct_words; - uint32_t A_save = A; - uint32_t B_save = B; - uint32_t C_save = C; - uint32_t D_save = D; - -#if MD5_SIZE_VS_SPEED > 1 - const uint32_t *pc; - const char *pp; - const char *ps; - int i; - uint32_t temp; - - for (i = 0; i < 16; i++) { - cwp[i] = SWAP_LE32(words[i]); - } - words += 16; - -# if MD5_SIZE_VS_SPEED > 2 - pc = C_array; - pp = P_array; - ps = S_array - 4; - - for (i = 0; i < 64; i++) { - if ((i & 0x0f) == 0) - ps += 4; - temp = A; - switch (i >> 4) { - case 0: - temp += FF(B, C, D); - break; - case 1: - temp += FG(B, C, D); - break; - case 2: - temp += FH(B, C, D); - break; - case 3: - temp += FI(B, C, D); - } - temp += cwp[(int) (*pp++)] + *pc++; - temp = rotl32(temp, ps[i & 3]); - temp += B; - A = D; - D = C; - C = B; - B = temp; - } -# else - pc = C_array; - pp = P_array; - ps = S_array; - - for (i = 0; i < 16; i++) { - temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++; - temp = rotl32(temp, ps[i & 3]); - temp += B; - A = D; - D = C; - C = B; - B = temp; - } - ps += 4; - for (i = 0; i < 16; i++) { - temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++; - temp = rotl32(temp, ps[i & 3]); - temp += B; - A = D; - D = C; - C = B; - B = temp; - } - ps += 4; - for (i = 0; i < 16; i++) { - temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++; - temp = rotl32(temp, ps[i & 3]); - temp += B; - A = D; - D = C; - C = B; - B = temp; - } - ps += 4; - for (i = 0; i < 16; i++) { - temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++; - temp = rotl32(temp, ps[i & 3]); - temp += B; - A = D; - D = C; - C = B; - B = temp; - } - -# endif /* MD5_SIZE_VS_SPEED > 2 */ -#else - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ -# define OP(a, b, c, d, s, T) \ - do { \ - a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \ - ++words; \ - a = rotl32(a, s); \ - a += b; \ - } while (0) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 - */ - -# if MD5_SIZE_VS_SPEED == 1 - const uint32_t *pc; - const char *pp; - int i; -# endif /* MD5_SIZE_VS_SPEED */ - - /* Round 1. */ -# if MD5_SIZE_VS_SPEED == 1 - pc = C_array; - for (i = 0; i < 4; i++) { - OP(A, B, C, D, 7, *pc++); - OP(D, A, B, C, 12, *pc++); - OP(C, D, A, B, 17, *pc++); - OP(B, C, D, A, 22, *pc++); - } -# else - OP(A, B, C, D, 7, 0xd76aa478); - OP(D, A, B, C, 12, 0xe8c7b756); - OP(C, D, A, B, 17, 0x242070db); - OP(B, C, D, A, 22, 0xc1bdceee); - OP(A, B, C, D, 7, 0xf57c0faf); - OP(D, A, B, C, 12, 0x4787c62a); - OP(C, D, A, B, 17, 0xa8304613); - OP(B, C, D, A, 22, 0xfd469501); - OP(A, B, C, D, 7, 0x698098d8); - OP(D, A, B, C, 12, 0x8b44f7af); - OP(C, D, A, B, 17, 0xffff5bb1); - OP(B, C, D, A, 22, 0x895cd7be); - OP(A, B, C, D, 7, 0x6b901122); - OP(D, A, B, C, 12, 0xfd987193); - OP(C, D, A, B, 17, 0xa679438e); - OP(B, C, D, A, 22, 0x49b40821); -# endif /* MD5_SIZE_VS_SPEED == 1 */ - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -# undef OP -# define OP(f, a, b, c, d, k, s, T) \ - do { \ - a += f(b, c, d) + correct_words[k] + T; \ - a = rotl32(a, s); \ - a += b; \ - } while (0) - - /* Round 2. */ -# if MD5_SIZE_VS_SPEED == 1 - pp = P_array; - for (i = 0; i < 4; i++) { - OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++); - OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++); - OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++); - OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++); - } -# else - OP(FG, A, B, C, D, 1, 5, 0xf61e2562); - OP(FG, D, A, B, C, 6, 9, 0xc040b340); - OP(FG, C, D, A, B, 11, 14, 0x265e5a51); - OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP(FG, A, B, C, D, 5, 5, 0xd62f105d); - OP(FG, D, A, B, C, 10, 9, 0x02441453); - OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP(FG, D, A, B, C, 14, 9, 0xc33707d6); - OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP(FG, B, C, D, A, 8, 20, 0x455a14ed); - OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP(FG, C, D, A, B, 7, 14, 0x676f02d9); - OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); -# endif /* MD5_SIZE_VS_SPEED == 1 */ - - /* Round 3. */ -# if MD5_SIZE_VS_SPEED == 1 - for (i = 0; i < 4; i++) { - OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++); - OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++); - OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++); - OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++); - } -# else - OP(FH, A, B, C, D, 5, 4, 0xfffa3942); - OP(FH, D, A, B, C, 8, 11, 0x8771f681); - OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP(FH, B, C, D, A, 14, 23, 0xfde5380c); - OP(FH, A, B, C, D, 1, 4, 0xa4beea44); - OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP(FH, B, C, D, A, 6, 23, 0x04881d05); - OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); -# endif /* MD5_SIZE_VS_SPEED == 1 */ - - /* Round 4. */ -# if MD5_SIZE_VS_SPEED == 1 - for (i = 0; i < 4; i++) { - OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++); - OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++); - OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++); - OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++); - } -# else - OP(FI, A, B, C, D, 0, 6, 0xf4292244); - OP(FI, D, A, B, C, 7, 10, 0x432aff97); - OP(FI, C, D, A, B, 14, 15, 0xab9423a7); - OP(FI, B, C, D, A, 5, 21, 0xfc93a039); - OP(FI, A, B, C, D, 12, 6, 0x655b59c3); - OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP(FI, C, D, A, B, 10, 15, 0xffeff47d); - OP(FI, B, C, D, A, 1, 21, 0x85845dd1); - OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP(FI, C, D, A, B, 6, 15, 0xa3014314); - OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP(FI, A, B, C, D, 4, 6, 0xf7537e82); - OP(FI, D, A, B, C, 11, 10, 0xbd3af235); - OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP(FI, B, C, D, A, 9, 21, 0xeb86d391); -# endif /* MD5_SIZE_VS_SPEED == 1 */ -#endif /* MD5_SIZE_VS_SPEED > 1 */ - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} - -/* Feed data through a temporary buffer to call md5_hash_aligned_block() - * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. - * This function's internal buffer remembers previous data until it has 64 - * bytes worth to pass on. Call md5_end() to flush this buffer. */ -void md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) -{ - char *buf = (char *)buffer; - - /* RFC 1321 specifies the possible length of the file up to 2^64 bits, - * Here we only track the number of bytes. */ - ctx->total += len; - - /* Process all input. */ - while (len) { - unsigned i = 64 - ctx->buflen; - - /* Copy data into aligned buffer. */ - if (i > len) i = len; - memcpy(ctx->buffer + ctx->buflen, buf, i); - len -= i; - ctx->buflen += i; - buf += i; - - /* When buffer fills up, process it. */ - if (ctx->buflen == 64) { - md5_hash_block(ctx->buffer, ctx); - ctx->buflen = 0; - } - } -} - -/* Process the remaining bytes in the buffer and put result from CTX - * in first 16 bytes following RESBUF. The result is always in little - * endian byte order, so that a byte-wise output yields to the wanted - * ASCII representation of the message digest. - */ -void md5_end(void *resbuf, md5_ctx_t *ctx) -{ - char *buf = ctx->buffer; - int i; - - /* Pad data to block size. */ - buf[ctx->buflen++] = 0x80; - memset(buf + ctx->buflen, 0, 128 - ctx->buflen); - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->total <<= 3; - if (ctx->buflen > 56) - buf += 64; - for (i = 0; i < 8; i++) - buf[56 + i] = ctx->total >> (i*8); - - /* Process last bytes. */ - if (buf != ctx->buffer) - md5_hash_block(ctx->buffer, ctx); - md5_hash_block(buf, ctx); - - /* The MD5 result is in little endian byte order. - * We (ab)use the fact that A-D are consecutive in memory. - */ -#if MD5_BIG_ENDIAN - ctx->A = SWAP_LE32(ctx->A); - ctx->B = SWAP_LE32(ctx->B); - ctx->C = SWAP_LE32(ctx->C); - ctx->D = SWAP_LE32(ctx->D); -#endif - memcpy(resbuf, &ctx->A, sizeof(ctx->A) * 4); -} diff --git a/lib/utils/hash_md5.h b/lib/utils/hash_md5.h deleted file mode 100644 index cc1d2c43..00000000 --- a/lib/utils/hash_md5.h +++ /dev/null @@ -1,29 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * md5.c - Compute MD5 checksum of strings according to the - * definition of MD5 in RFC 1321 from April 1992. - * - * Written by Ulrich Drepper , 1995. - * - * Copyright (C) 1995-1999 Free Software Foundation, Inc. - * Copyright (C) 2001 Manuel Novoa III - * Copyright (C) 2003 Glenn L. McGrath - * Copyright (C) 2003 Erik Andersen - * - * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. - */ - -#define MD5_RESULT_LEN 16 - -typedef struct md5_ctx_t { - uint32_t A; - uint32_t B; - uint32_t C; - uint32_t D; - uint64_t total; - uint32_t buflen; - char buffer[128]; -} md5_ctx_t; -void md5_begin(md5_ctx_t *ctx); -void md5_hash(const void *data, size_t length, md5_ctx_t *ctx); -void md5_end(void *resbuf, md5_ctx_t *ctx); diff --git a/lib/utils/hash_sha1.c b/lib/utils/hash_sha1.c deleted file mode 100644 index 954e7bc8..00000000 --- a/lib/utils/hash_sha1.c +++ /dev/null @@ -1,213 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Based on shasum from http://www.netsw.org/crypto/hash/ - * Majorly hacked up to use Dr Brian Gladman's sha1 code - * - * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK. - * Copyright (C) 2003 Glenn L. McGrath - * Copyright (C) 2003 Erik Andersen - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - * - * --------------------------------------------------------------------------- - * Issue Date: 10/11/2002 - * - * This is a byte oriented version of SHA1 that operates on arrays of bytes - * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor - * - * --------------------------------------------------------------------------- - */ -#include "abrtlib.h" - -#if defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ -# define SHA1_BIG_ENDIAN 1 -# define SHA1_LITTLE_ENDIAN 0 -#elif __BYTE_ORDER == __BIG_ENDIAN -# define SHA1_BIG_ENDIAN 1 -# define SHA1_LITTLE_ENDIAN 0 -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define SHA1_BIG_ENDIAN 0 -# define SHA1_LITTLE_ENDIAN 1 -#else -# error "Can't determine endianness" -#endif - - -#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) -/* for sha512: */ -#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) -#if SHA1_LITTLE_ENDIAN -static inline uint64_t hton64(uint64_t v) -{ - return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); -} -#else -#define hton64(v) (v) -#endif -#define ntoh64(v) hton64(v) - -/* To check alignment gcc has an appropriate operator. Other - compilers don't. */ -#if defined(__GNUC__) && __GNUC__ >= 2 -# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0) -#else -# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0) -#endif - - -/* Some arch headers have conflicting defines */ -#undef ch -#undef parity -#undef maj -#undef rnd - -static void sha1_process_block64(sha1_ctx_t *ctx) -{ - unsigned t; - uint32_t W[80], a, b, c, d, e; - const uint32_t *words = (uint32_t*) ctx->wbuffer; - - for (t = 0; t < 16; ++t) { - W[t] = ntohl(*words); - words++; - } - - for (/*t = 16*/; t < 80; ++t) { - uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; - W[t] = rotl32(T, 1); - } - - a = ctx->hash[0]; - b = ctx->hash[1]; - c = ctx->hash[2]; - d = ctx->hash[3]; - e = ctx->hash[4]; - -/* Reverse byte order in 32-bit words */ -#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define parity(x,y,z) ((x) ^ (y) ^ (z)) -#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) -/* A normal version as set out in the FIPS. This version uses */ -/* partial loop unrolling and is optimised for the Pentium 4 */ -#define rnd(f,k) \ - do { \ - uint32_t T = a; \ - a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \ - e = d; \ - d = c; \ - c = rotl32(b, 30); \ - b = T; \ - } while (0) - - for (t = 0; t < 20; ++t) - rnd(ch, 0x5a827999); - - for (/*t = 20*/; t < 40; ++t) - rnd(parity, 0x6ed9eba1); - - for (/*t = 40*/; t < 60; ++t) - rnd(maj, 0x8f1bbcdc); - - for (/*t = 60*/; t < 80; ++t) - rnd(parity, 0xca62c1d6); -#undef ch -#undef parity -#undef maj -#undef rnd - - ctx->hash[0] += a; - ctx->hash[1] += b; - ctx->hash[2] += c; - ctx->hash[3] += d; - ctx->hash[4] += e; -} - -void sha1_begin(sha1_ctx_t *ctx) -{ - ctx->hash[0] = 0x67452301; - ctx->hash[1] = 0xefcdab89; - ctx->hash[2] = 0x98badcfe; - ctx->hash[3] = 0x10325476; - ctx->hash[4] = 0xc3d2e1f0; - ctx->total64 = 0; - ctx->process_block = sha1_process_block64; -} - -static const uint32_t init256[] = { - 0x6a09e667, - 0xbb67ae85, - 0x3c6ef372, - 0xa54ff53a, - 0x510e527f, - 0x9b05688c, - 0x1f83d9ab, - 0x5be0cd19 -}; -static const uint32_t init512_lo[] = { - 0xf3bcc908, - 0x84caa73b, - 0xfe94f82b, - 0x5f1d36f1, - 0xade682d1, - 0x2b3e6c1f, - 0xfb41bd6b, - 0x137e2179 -}; - -/* Used also for sha256 */ -void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) -{ - unsigned in_buf = ctx->total64 & 63; - unsigned add = 64 - in_buf; - - ctx->total64 += len; - - while (len >= add) { /* transfer whole blocks while possible */ - memcpy(ctx->wbuffer + in_buf, buffer, add); - buffer = (const char *)buffer + add; - len -= add; - add = 64; - in_buf = 0; - ctx->process_block(ctx); - } - - memcpy(ctx->wbuffer + in_buf, buffer, len); -} - -/* Used also for sha256 */ -void sha1_end(void *resbuf, sha1_ctx_t *ctx) -{ - unsigned pad, in_buf; - - in_buf = ctx->total64 & 63; - /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ - ctx->wbuffer[in_buf++] = 0x80; - - /* This loop iterates either once or twice, no more, no less */ - while (1) { - pad = 64 - in_buf; - memset(ctx->wbuffer + in_buf, 0, pad); - in_buf = 0; - /* Do we have enough space for the length count? */ - if (pad >= 8) { - /* Store the 64-bit counter of bits in the buffer in BE format */ - uint64_t t = ctx->total64 << 3; - t = hton64(t); - /* wbuffer is suitably aligned for this */ - *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; - } - ctx->process_block(ctx); - if (pad >= 8) - break; - } - - in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8; - /* This way we do not impose alignment constraints on resbuf: */ - if (SHA1_LITTLE_ENDIAN) { - unsigned i; - for (i = 0; i < in_buf; ++i) - ctx->hash[i] = htonl(ctx->hash[i]); - } - memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); -} diff --git a/lib/utils/hash_sha1.h b/lib/utils/hash_sha1.h deleted file mode 100644 index 02978ea4..00000000 --- a/lib/utils/hash_sha1.h +++ /dev/null @@ -1,40 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Based on shasum from http://www.netsw.org/crypto/hash/ - * Majorly hacked up to use Dr Brian Gladman's sha1 code - * - * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK. - * Copyright (C) 2003 Glenn L. McGrath - * Copyright (C) 2003 Erik Andersen - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - * - * --------------------------------------------------------------------------- - * Issue Date: 10/11/2002 - * - * This is a byte oriented version of SHA1 that operates on arrays of bytes - * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor - * - * --------------------------------------------------------------------------- - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SHA1_RESULT_LEN (5 * 4) - -typedef struct sha1_ctx_t { - uint32_t hash[8]; /* 5, +3 elements for sha256 */ - uint64_t total64; - uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ - void (*process_block)(struct sha1_ctx_t*); -} sha1_ctx_t; - -void sha1_begin(sha1_ctx_t *ctx); -void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx); -void sha1_end(void *resbuf, sha1_ctx_t *ctx); - -#ifdef __cplusplus -} -#endif diff --git a/lib/utils/hooklib.c b/lib/utils/hooklib.c deleted file mode 100644 index 062e3ddb..00000000 --- a/lib/utils/hooklib.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - Copyright (C) 2009 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 "hooklib.h" -#include - -void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore, bool *setting_SaveBinaryImage) -{ - FILE *fp = fopen(CONF_DIR"/abrt.conf", "r"); - if (!fp) - return; - - while (1) - { - char *line = xmalloc_fgetline(fp); - if (!line) - { - fclose(fp); - if (additional_conf) - { - /* Next .conf file plz */ - fp = fopen(additional_conf, "r"); - if (fp) - { - additional_conf = NULL; - continue; - } - } - break; - } - - const char *p = skip_whitespace(line); -#undef DIRECTIVE -#define DIRECTIVE "MaxCrashReportsSize" - if (setting_MaxCrashReportsSize && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) - { - p = skip_whitespace(p + sizeof(DIRECTIVE)-1); - if (*p != '=') - goto free_line; - p = skip_whitespace(p + 1); - if (isdigit(*p)) - { - /* x1.25: go a bit up, so that usual in-daemon trimming - * kicks in first, and we don't "fight" with it. */ - *setting_MaxCrashReportsSize = (unsigned long)xatou(p) * 5 / 4; - } - goto free_line; - } -#undef DIRECTIVE -#define DIRECTIVE "MakeCompatCore" - if (setting_MakeCompatCore && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) - { - p = skip_whitespace(p + sizeof(DIRECTIVE)-1); - if (*p != '=') - goto free_line; - p = skip_whitespace(p + 1); - *setting_MakeCompatCore = string_to_bool(p); - goto free_line; - } -#undef DIRECTIVE -#define DIRECTIVE "SaveBinaryImage" - if (setting_SaveBinaryImage && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) - { - p = skip_whitespace(p + sizeof(DIRECTIVE)-1); - if (*p != '=') - goto free_line; - p = skip_whitespace(p + 1); - *setting_SaveBinaryImage = string_to_bool(p); - goto free_line; - } -#undef DIRECTIVE - /* add more 'if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)' here... */ - - free_line: - free(line); - } -} - -void check_free_space(unsigned setting_MaxCrashReportsSize) -{ - struct statvfs vfs; - if (statvfs(DEBUG_DUMPS_DIR, &vfs) != 0) - { - perror_msg_and_die("statvfs('%s')", DEBUG_DUMPS_DIR); - } - - /* Check that at least MaxCrashReportsSize/4 MBs are free */ - - /* fs_free_mb_x4 ~= vfs.f_bfree * vfs.f_bsize * 4, expressed in MBytes. - * Need to neither overflow nor round f_bfree down too much. */ - unsigned long fs_free_mb_x4 = ((unsigned long long)vfs.f_bfree / (1024/4)) * vfs.f_bsize / 1024; - if (fs_free_mb_x4 < setting_MaxCrashReportsSize) - { - error_msg_and_die("aborting dump: only %luMiB is available on %s", fs_free_mb_x4 / 4, DEBUG_DUMPS_DIR); - } -} - -/* rhbz#539551: "abrt going crazy when crashing process is respawned". - * Check total size of dump dir, if it overflows, - * delete oldest/biggest dumps. - */ -void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path) -{ - int count = 10; - while (--count >= 0) - { - const char *base_dirname = strrchr(exclude_path, '/') + 1; /* never NULL */ - /* We exclude our own dump from candidates for deletion (3rd param): */ - char *worst_dir = NULL; - double dirsize = get_dirsize_find_largest_dir(DEBUG_DUMPS_DIR, &worst_dir, base_dirname); - if (dirsize / (1024*1024) < setting_MaxCrashReportsSize || !worst_dir) - { - free(worst_dir); - break; - } - log("size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, setting_MaxCrashReportsSize, worst_dir); - char *d = concat_path_file(DEBUG_DUMPS_DIR, worst_dir); - free(worst_dir); - worst_dir = NULL; - delete_debug_dump_dir(d); - free(d); - } -} diff --git a/lib/utils/hooklib.h b/lib/utils/hooklib.h deleted file mode 100644 index ba76efbc..00000000 --- a/lib/utils/hooklib.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright (C) 2009 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. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore, bool *setting_SaveBinaryImage); -void check_free_space(unsigned setting_MaxCrashReportsSize); -void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path); - -#ifdef __cplusplus -} -#endif diff --git a/lib/utils/logging.c b/lib/utils/logging.c deleted file mode 100644 index 815efb5e..00000000 --- a/lib/utils/logging.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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. -*/ - -/* - * Utility routines. - * - */ -#include "abrtlib.h" - -void (*g_custom_logger)(const char*); -const char *msg_prefix = ""; -const char *msg_eol = "\n"; -int logmode = LOGMODE_STDIO; -int xfunc_error_retval = EXIT_FAILURE; -int g_verbose; - -void xfunc_die(void) -{ - exit(xfunc_error_retval); -} - -static void verror_msg_helper(const char *s, - va_list p, - const char* strerr, - int flags) -{ - char *msg; - int prefix_len, strerr_len, msgeol_len, used; - - if (!logmode) - return; - - used = vasprintf(&msg, s, p); - if (used < 0) - return; - - /* This is ugly and costs +60 bytes compared to multiple - * fprintf's, but is guaranteed to do a single write. - * This is needed for e.g. when multiple children - * can produce log messages simultaneously. */ - - prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0; - strerr_len = strerr ? strlen(strerr) : 0; - msgeol_len = strlen(msg_eol); - /* +3 is for ": " before strerr and for terminating NUL */ - msg = (char*) xrealloc(msg, prefix_len + used + strerr_len + msgeol_len + 3); - /* TODO: maybe use writev instead of memmoving? Need full_writev? */ - if (prefix_len) { - char *p; - memmove(msg + prefix_len, msg, used); - used += prefix_len; - p = stpcpy(msg, msg_prefix); - p[0] = ':'; - p[1] = ' '; - } - if (strerr) { - if (s[0]) { - msg[used++] = ':'; - msg[used++] = ' '; - } - strcpy(&msg[used], strerr); - used += strerr_len; - } - strcpy(&msg[used], msg_eol); - - if (flags & LOGMODE_STDIO) { - fflush(stdout); - full_write(STDERR_FILENO, msg, used + msgeol_len); - } - msg[used] = '\0'; /* remove msg_eol (usually "\n") */ - if (flags & LOGMODE_SYSLOG) { - syslog(LOG_ERR, "%s", msg + prefix_len); - } - if ((flags & LOGMODE_CUSTOM) && g_custom_logger) { - g_custom_logger(msg + prefix_len); - } - free(msg); -} - -void log_msg(const char *s, ...) -{ - va_list p; - - va_start(p, s); - verror_msg_helper(s, p, NULL, logmode); - va_end(p); -} - -void error_msg(const char *s, ...) -{ - va_list p; - - va_start(p, s); - verror_msg_helper(s, p, NULL, (logmode | LOGMODE_CUSTOM)); - va_end(p); -} - -void error_msg_and_die(const char *s, ...) -{ - va_list p; - - va_start(p, s); - verror_msg_helper(s, p, NULL, (logmode | LOGMODE_CUSTOM)); - va_end(p); - xfunc_die(); -} - -void perror_msg(const char *s, ...) -{ - va_list p; - - va_start(p, s); - /* Guard against ": Success" */ - verror_msg_helper(s, p, errno ? strerror(errno) : NULL, (logmode | LOGMODE_CUSTOM)); - va_end(p); -} - -void perror_msg_and_die(const char *s, ...) -{ - va_list p; - - va_start(p, s); - /* Guard against ": Success" */ - verror_msg_helper(s, p, errno ? strerror(errno) : NULL, (logmode | LOGMODE_CUSTOM)); - va_end(p); - xfunc_die(); -} - -void die_out_of_memory(void) -{ - error_msg_and_die("Out of memory, exiting"); -} diff --git a/lib/utils/logging.h b/lib/utils/logging.h deleted file mode 100644 index 8a038bc7..00000000 --- a/lib/utils/logging.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 LOGGING_H -#define LOGGING_H - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NORETURN __attribute__ ((noreturn)) - -/* VERB1 log("what you sometimes want to see, even on a production box") */ -#define VERB1 if (g_verbose >= 1) -/* VERB2 log("debug message, not going into insanely small details") */ -#define VERB2 if (g_verbose >= 2) -/* VERB3 log("lots and lots of details") */ -#define VERB3 if (g_verbose >= 3) -/* there is no level > 3 */ - -enum { - LOGMODE_NONE = 0, - LOGMODE_STDIO = (1 << 0), - LOGMODE_SYSLOG = (1 << 1), - LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, - LOGMODE_CUSTOM = (1 << 2), -}; - -extern void (*g_custom_logger)(const char*); -extern const char *msg_prefix; -extern const char *msg_eol; -extern int logmode; -extern int xfunc_error_retval; - -/* Verbosity level */ -extern int g_verbose; - -void xfunc_die(void) NORETURN; -void log_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); -/* It's a macro, not function, since it collides with log() from math.h */ -#undef log -#define log(...) log_msg(__VA_ARGS__) -/* error_msg family will use g_custom_logger. log_msg does not. */ -void error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); -void error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); -/* Reports error message with libc's errno error description attached. */ -void perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); -void perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); -void die_out_of_memory(void) NORETURN; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/utils/make_descr.cpp b/lib/utils/make_descr.cpp deleted file mode 100644 index 79065100..00000000 --- a/lib/utils/make_descr.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 "crash_types.h" - - -using namespace std; - -// caller is responsible for freeing **dsc -static void add_content(bool *was_multiline, char **dsc, const char *header, const char *content) -{ - struct strbuf *buf_description = strbuf_new(); - if (*was_multiline) - strbuf_append_char(buf_description, '\n'); - - while (content[0] == '\n') - content++; - - if (strchr(content, '\n') == NULL) - { - if (skip_whitespace(content)[0] == '\0') - { - /* empty, dont report at all */ - *dsc = strbuf_free_nobuf(buf_description); - return; - } - /* one string value, like OS release */ - strbuf_append_strf(buf_description, "%s: %s\n", header, content); - *was_multiline = 0; - } - else - { - /* multi-string value, like backtrace */ - if (!*was_multiline && (buf_description->len != 0)) /* if wasn't yet separated */ - strbuf_append_char(buf_description, '\n'); - - strbuf_append_strf(buf_description, "%s\n-----\n%s", header, content); - if (content[strlen(content) - 1] != '\n') - strbuf_append_char(buf_description, '\n'); - - *was_multiline = 1; - } - - *dsc = strbuf_free_nobuf(buf_description); -} - -/* Items we don't want to include */ -static const char *const blacklisted_items[] = { - FILENAME_ANALYZER , - FILENAME_COREDUMP , - FILENAME_DESCRIPTION, /* package description - basically useless */ - FILENAME_HOSTNAME , - FILENAME_DUPHASH , - CD_UUID , - CD_INFORMALL , - FILENAME_DUPHASH , - CD_DUMPDIR , - CD_COUNT , - CD_REPORTED , - CD_MESSAGE , - NULL -}; - -char* make_dsc_mailx(const map_crash_data_t & crash_data) -{ - struct strbuf *buf_dsc = strbuf_new(); - struct strbuf *buf_additional_files = strbuf_new(); - struct strbuf *buf_duphash_file = strbuf_new(); - struct strbuf *buf_common_files = strbuf_new(); - - map_crash_data_t::const_iterator it; - for (it = crash_data.begin(); it != crash_data.end(); it++) - { - if (it->second[CD_TYPE] == CD_TXT) - { - const char *itemname = it->first.c_str(); - if ((strcmp(itemname, FILENAME_DUPHASH) != 0) - && (strcmp(itemname, FILENAME_ARCHITECTURE) != 0) - && (strcmp(itemname, FILENAME_KERNEL) != 0) - && (strcmp(itemname, FILENAME_PACKAGE) != 0) - ) { - strbuf_append_strf(buf_additional_files, "%s\n-----\n%s\n\n", itemname, it->second[CD_CONTENT].c_str()); - } - else if (strcmp(itemname, FILENAME_DUPHASH) == 0) - strbuf_append_strf(buf_duphash_file, "%s\n-----\n%s\n\n", itemname, it->second[CD_CONTENT].c_str()); - else - strbuf_append_strf(buf_common_files, "%s\n-----\n%s\n\n", itemname, it->second[CD_CONTENT].c_str()); - } - } - - char *common_files = strbuf_free_nobuf(buf_common_files); - char *duphash_file = strbuf_free_nobuf(buf_duphash_file); - char *additional_files = strbuf_free_nobuf(buf_additional_files); - - strbuf_append_strf(buf_dsc, "Duplicate check\n=====\n%s\n\n", duphash_file); - strbuf_append_strf(buf_dsc, "Common information\n=====\n%s\n\n", common_files); - strbuf_append_strf(buf_dsc, "Additional information\n=====\n%s\n", additional_files); - - free(common_files); - free(duphash_file); - free(additional_files); - - return strbuf_free_nobuf(buf_dsc); -} - -char* make_description_bz(const map_crash_data_t& pCrashData) -{ - struct strbuf *buf_dsc = strbuf_new(); - struct strbuf *buf_long_dsc = strbuf_new(); - - map_crash_data_t::const_iterator it = pCrashData.begin(); - for (; it != pCrashData.end(); it++) - { - const char *itemname = it->first.c_str(); - const char *type = it->second[CD_TYPE].c_str(); - const char *content = it->second[CD_CONTENT].c_str(); - if (strcmp(type, CD_TXT) == 0) - { - /* Skip items we are not interested in */ - const char *const *bl = blacklisted_items; - while (*bl) - { - if (strcmp(itemname, *bl) == 0) - break; - bl++; - } - if (*bl) - continue; /* blacklisted */ - if (strcmp(content, "1.\n2.\n3.\n") == 0) - continue; /* user did not change default "How to reproduce" */ - - if (strlen(content) <= CD_TEXT_ATT_SIZE) - { - /* Add small (less than few kb) text items inline */ - bool was_multiline = 0; - char *tmp = NULL; - add_content(&was_multiline, - &tmp, - /* "reproduce: blah" looks ugly, fixing: */ - (strcmp(itemname, FILENAME_REPRODUCE) == 0) ? "How to reproduce" : itemname, - content - ); - - if (was_multiline) - { - /* Not one-liner */ - if (buf_long_dsc->len != 0) - strbuf_append_char(buf_long_dsc, '\n'); - - strbuf_append_str(buf_long_dsc, tmp); - } - else - strbuf_append_str(buf_dsc, tmp); - - free(tmp); - } else { - bool was_multiline = 0; - char *dsc = NULL; - add_content(&was_multiline, &dsc, "Attached file", itemname); - strbuf_append_str(buf_dsc, dsc); - free(dsc); - } - } - } - - /* One-liners go first, then multi-line items */ - if (buf_dsc->len != 0 && buf_long_dsc->len != 0) - strbuf_append_char(buf_dsc, '\n'); - - - char *long_dsc = strbuf_free_nobuf(buf_long_dsc); - strbuf_append_str(buf_dsc, long_dsc); - free(long_dsc); - - return strbuf_free_nobuf(buf_dsc); -} - -char* make_description_logger(const map_crash_data_t& pCrashData) -{ - struct strbuf *buf_dsc = strbuf_new(); - struct strbuf *buf_long_dsc = strbuf_new(); - - map_crash_data_t::const_iterator it = pCrashData.begin(); - for (; it != pCrashData.end(); it++) - { - const char *filename = it->first.c_str(); - const char *type = it->second[CD_TYPE].c_str(); - const char *content = it->second[CD_CONTENT].c_str(); - if ((strcmp(type, CD_TXT) == 0) - || (strcmp(type, CD_BIN) == 0) - ) { - /* Skip items we are not interested in */ - const char *const *bl = blacklisted_items; - while (*bl) - { - if (filename == *bl) - break; - bl++; - } - if (*bl) - continue; /* blacklisted */ - if (strcmp(content, "1.\n2.\n3.\n") == 0) - continue; /* user did not change default "How to reproduce" */ - - bool was_multiline = 0; - char *tmp = NULL; - add_content(&was_multiline, &tmp, filename, content); - - if (was_multiline) - { - if (buf_long_dsc->len != 0) - strbuf_append_char(buf_long_dsc,'\n'); - - strbuf_append_str(buf_long_dsc, tmp); - } - else - strbuf_append_str(buf_dsc, tmp); - } - } - - if (buf_dsc->len != 0 && buf_long_dsc->len != 0) - strbuf_append_char(buf_dsc, '\n'); - - char *long_dsc = strbuf_free_nobuf(buf_long_dsc); - strbuf_append_str(buf_dsc, long_dsc); - free(long_dsc); - - return strbuf_free_nobuf(buf_dsc); -} - -char* make_description_reproduce_comment(const map_crash_data_t& pCrashData) -{ - char *repro = NULL; - char *comment = NULL; - - map_crash_data_t::const_iterator end = pCrashData.end(); - map_crash_data_t::const_iterator it; - - it = pCrashData.find(FILENAME_REPRODUCE); - if (it != end) - { - if ((it->second[CD_CONTENT].size() > 0) - && (it->second[CD_CONTENT] != "1.\n2.\n3.\n")) - { - repro = xasprintf("\n\nHow to reproduce\n-----\n%s", it->second[CD_CONTENT].c_str()); - } - } - - it = pCrashData.find(FILENAME_COMMENT); - if (it != end) - { - if (it->second[CD_CONTENT].size() > 0) - comment = xasprintf("\n\nComment\n-----\n%s", it->second[CD_CONTENT].c_str()); - } - - if (!repro && !comment) - return NULL; - - struct strbuf *buf_dsc = strbuf_new(); - - if (repro) - strbuf_append_str(buf_dsc, repro); - - if (comment) - strbuf_append_str(buf_dsc, comment); - - free(repro); - free(comment); - - return strbuf_free_nobuf(buf_dsc); -} diff --git a/lib/utils/numtoa.cpp b/lib/utils/numtoa.cpp deleted file mode 100644 index 061da553..00000000 --- a/lib/utils/numtoa.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - Number to string conversions - - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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" - -std::string unsigned_to_string(unsigned long long x) -{ - char buf[sizeof(x)*3]; - sprintf(buf, "%llu", x); - return buf; -} -std::string signed_to_string(long long x) -{ - char buf[sizeof(x)*3]; - sprintf(buf, "%lld", x); - return buf; -} diff --git a/lib/utils/overlapping_strcpy.c b/lib/utils/overlapping_strcpy.c deleted file mode 100644 index 41c1c1a1..00000000 --- a/lib/utils/overlapping_strcpy.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 1999-2004 by Erik Andersen - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ -#include "abrtlib.h" - -/* Like strcpy but can copy overlapping strings. */ -void overlapping_strcpy(char *dst, const char *src) -{ - /* Cheap optimization for dst == src case - - * better to have it here than in many callers. - */ - if (dst != src) - { - while ((*dst = *src) != '\0') - { - dst++; - src++; - } - } -} diff --git a/lib/utils/parse_options.c b/lib/utils/parse_options.c deleted file mode 100644 index c1a2c297..00000000 --- a/lib/utils/parse_options.c +++ /dev/null @@ -1,182 +0,0 @@ - -#include -#include "abrtlib.h" -#include "parse_options.h" - -#define USAGE_OPTS_WIDTH 24 -#define USAGE_GAP 2 - -void parse_usage_and_die(const char *usage, const struct options *opt) -{ - fprintf(stderr, _("Usage: %s\n"), usage); - - if (opt->type != OPTION_GROUP) - fputc('\n', stderr); - - for (; opt->type != OPTION_END; opt++) - { - size_t pos; - int pad; - - if (opt->type == OPTION_GROUP) - { - fputc('\n', stderr); - if (*opt->help) - fprintf(stderr, "%s\n", opt->help); - continue; - } - - pos = fprintf(stderr, " "); - if (opt->short_name) - pos += fprintf(stderr, "-%c", opt->short_name); - - if (opt->short_name && opt->long_name) - pos += fprintf(stderr, ", "); - - if (opt->long_name) - pos += fprintf(stderr, "--%s", opt->long_name); - - if (opt->argh) - { - const char *fmt = " %s"; - if (opt->type == OPTION_OPTSTRING) - fmt = "[%s]"; - pos += fprintf(stderr, fmt, opt->argh); - } - - 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, "", opt->help); - } - fputc('\n', stderr); - exit(1); -} - -static int parse_opt_size(const struct options *opt) -{ - unsigned size = 0; - for (; opt->type != OPTION_END; opt++) - size++; - - return size; -} - -unsigned parse_opts(int argc, char **argv, const struct options *opt, - const char *usage) -{ - int help = 0; - int size = parse_opt_size(opt); - - struct strbuf *shortopts = strbuf_new(); - - struct option *longopts = xzalloc(sizeof(longopts[0]) * (size+2)); - struct option *curopt = longopts; - int ii; - for (ii = 0; ii < size; ++ii) - { - curopt->name = opt[ii].long_name; - /*curopt->flag = 0; - xzalloc did it */ - curopt->val = opt[ii].short_name; - - switch (opt[ii].type) - { - case OPTION_BOOL: - curopt->has_arg = no_argument; - if (opt[ii].short_name) - strbuf_append_char(shortopts, opt[ii].short_name); - break; - case OPTION_INTEGER: - case OPTION_STRING: - curopt->has_arg = required_argument; - if (opt[ii].short_name) - strbuf_append_strf(shortopts, "%c:", opt[ii].short_name); - break; - case OPTION_OPTSTRING: - curopt->has_arg = optional_argument; - if (opt[ii].short_name) - strbuf_append_strf(shortopts, "%c::", opt[ii].short_name); - break; - case OPTION_GROUP: - case OPTION_END: - break; - } - //log("curopt[%d].name:'%s' .has_arg:%d .flag:%p .val:%d", (int)(curopt-longopts), - // curopt->name, curopt->has_arg, curopt->flag, curopt->val); - /* - * getopt_long() thinks that NULL name marks the end of longopts. - * Example: - * [0] name:'verbose' val:'v' - * [1] name:NULL val:'c' - * [2] name:'force' val:'f' - * ... ... ... - * In this case, --force won't be accepted! - * Therefore we can only advance if name is not NULL. - */ - if (curopt->name) - curopt++; - } - curopt->name = "help"; - curopt->has_arg = no_argument; - curopt->flag = &help; - curopt->val = 1; - /* xzalloc did it already: - curopt++; - curopt->name = NULL; - curopt->has_arg = 0; - curopt->flag = NULL; - curopt->val = 0; - */ - - unsigned retval = 0; - while (1) - { - int c = getopt_long(argc, argv, shortopts->buf, longopts, NULL); - - if (c == -1) - break; - - if (c == '?' || help) - { - free(longopts); - strbuf_free(shortopts); - parse_usage_and_die(usage, opt); - } - - for (ii = 0; ii < size; ++ii) - { - if (opt[ii].short_name == c) - { - if (ii < sizeof(retval)*8) - retval |= (1 << ii); - - if (opt[ii].value != NULL) switch (opt[ii].type) - { - case OPTION_BOOL: - *(int*)opt[ii].value += 1; - break; - case OPTION_INTEGER: - *(int*)opt[ii].value = xatoi(optarg); - break; - case OPTION_STRING: - case OPTION_OPTSTRING: - if (optarg) - *(char**)opt[ii].value = (char*)optarg; - break; - case OPTION_GROUP: - case OPTION_END: - break; - } - } - } - } - - free(longopts); - strbuf_free(shortopts); - - return retval; -} diff --git a/lib/utils/parse_options.h b/lib/utils/parse_options.h deleted file mode 100644 index 105f081c..00000000 --- a/lib/utils/parse_options.h +++ /dev/null @@ -1,53 +0,0 @@ - -#ifndef PARSE_OPTIONS_H -#define PARSE_OPTIONS_H - - -#ifdef __cplusplus -extern "C" { -#endif - -enum parse_opt_type { - OPTION_BOOL, - OPTION_GROUP, - OPTION_STRING, - OPTION_INTEGER, - OPTION_OPTSTRING, - OPTION_END, -}; - -struct options { - enum parse_opt_type type; - int short_name; - const char *long_name; - void *value; - const char *argh; - const char *help; -}; - -/* - * s - short_name - * l - long_name - * v - value - * a - argh argument help - * h - help - */ -#define OPT_END() { OPTION_END } -#define OPT_BOOL(s, l, v, h) { OPTION_BOOL, (s), (l), (v), NULL, (h) } -#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } -#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) } -#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } -#define OPT_OPTSTRING(s, l, v, a, h) { OPTION_OPTSTRING, (s), (l), (v), (a), (h) } - -#define OPT__VERBOSE(v) OPT_BOOL('v', "verbose", (v), "be verbose") - -unsigned parse_opts(int argc, char **argv, const struct options *opt, - const char *usage); - -void parse_usage_and_die(const char *usage, const struct options *opt); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/utils/parse_release.cpp b/lib/utils/parse_release.cpp deleted file mode 100644 index f9057bfe..00000000 --- a/lib/utils/parse_release.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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" - -// caller is reposible for freeing *product* and *version* -void parse_release(const char *release, char** product, char** version) -{ - if (strstr(release, "Rawhide")) - { - *product = xstrdup("Fedora"); - *version = xstrdup("rawhide"); - VERB3 log("%s: version:'%s' product:'%s'", __func__, *version, *product); - return; - } - - struct strbuf *buf_product = strbuf_new(); - if (strstr(release, "Fedora")) - strbuf_append_str(buf_product, "Fedora"); - else if (strstr(release, "Red Hat Enterprise Linux")) - strbuf_append_str(buf_product, "Red Hat Enterprise Linux "); - - const char *r = strstr(release, "release"); - const char *space = r ? strchr(r, ' ') : NULL; - - struct strbuf *buf_version = strbuf_new(); - if (space++) - { - while (*space != '\0' && *space != ' ') - { - /* Eat string like "5.2" */ - strbuf_append_char(buf_version, *space); - if ((strcmp(buf_product->buf, "Red Hat Enterprise Linux ") == 0)) - strbuf_append_char(buf_product, *space); - - space++; - } - } - - *version = strbuf_free_nobuf(buf_version); - *product = strbuf_free_nobuf(buf_product); - - VERB3 log("%s: version:'%s' product:'%s'", __func__, *version, *product); -} diff --git a/lib/utils/read_write.c b/lib/utils/read_write.c deleted file mode 100644 index da067f78..00000000 --- a/lib/utils/read_write.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Utility routines. - * - * Licensed under GPLv2 or later, see file COPYING in this tarball for details. - */ -#include "abrtlib.h" - -/* Die with an error message if we can't read the entire buffer. */ -void xread(int fd, void *buf, size_t count) -{ - if (count) - { - ssize_t size = full_read(fd, buf, count); - if ((size_t)size != count) - error_msg_and_die("short read"); - } -} - -ssize_t safe_read(int fd, void *buf, size_t count) -{ - ssize_t n; - - do { - n = read(fd, buf, count); - } while (n < 0 && errno == EINTR); - - return n; -} - -ssize_t safe_write(int fd, const void *buf, size_t count) -{ - ssize_t n; - - do { - n = write(fd, buf, count); - } while (n < 0 && errno == EINTR); - - return n; -} - -ssize_t full_read(int fd, void *buf, size_t len) -{ - ssize_t cc; - ssize_t total; - - total = 0; - - while (len) - { - cc = safe_read(fd, buf, len); - - if (cc < 0) - { - if (total) - { - /* we already have some! */ - /* user can do another read to know the error code */ - return total; - } - return cc; /* read() returns -1 on failure. */ - } - if (cc == 0) - break; - buf = ((char *)buf) + cc; - total += cc; - len -= cc; - } - - return total; -} - -ssize_t full_write(int fd, const void *buf, size_t len) -{ - ssize_t cc; - ssize_t total; - - total = 0; - - while (len) - { - cc = safe_write(fd, buf, len); - - if (cc < 0) - { - if (total) - { - /* we already wrote some! */ - /* user can do another write to know the error code */ - return total; - } - return cc; /* write() returns -1 on failure. */ - } - - total += cc; - buf = ((const char *)buf) + cc; - len -= cc; - } - - return total; -} - -ssize_t full_write_str(int fd, const char *buf) -{ - return full_write(fd, buf, strlen(buf)); -} diff --git a/lib/utils/read_write.h b/lib/utils/read_write.h deleted file mode 100644 index 054a1a9a..00000000 --- a/lib/utils/read_write.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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 READ_WRITE_H -#define READ_WRITE_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -// NB: will return short read on error, not -1, -// if some data was read before error occurred -void xread(int fd, void *buf, size_t count); - -ssize_t safe_read(int fd, void *buf, size_t count); -ssize_t safe_write(int fd, const void *buf, size_t count); - -ssize_t full_read(int fd, void *buf, size_t count); -ssize_t full_write(int fd, const void *buf, size_t count); - -ssize_t full_write_str(int fd, const char *buf); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/utils/run_event.c b/lib/utils/run_event.c deleted file mode 100644 index 23517923..00000000 --- a/lib/utils/run_event.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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" - -int run_event(struct run_event_state *state, - const char *dump_dir_name, - const char *event -) { - FILE *conffile = fopen(CONF_DIR"/abrt_event.conf", "r"); - if (!conffile) - { - error_msg("Can't open '%s'", CONF_DIR"/abrt_event.conf"); - return 1; - } - close_on_exec_on(fileno(conffile)); - - /* Export some useful environment variables for children */ - /* Just exporting dump_dir_name isn't always ok: it can be "." - * and some children want to cd to other directory but still - * be able to find dump directory by using $DUMP_DIR... - */ - char *full_name = realpath(dump_dir_name, NULL); - setenv("DUMP_DIR", (full_name ? full_name : dump_dir_name), 1); - free(full_name); - setenv("EVENT", event, 1); - - /* Read, match, and execute lines from abrt_event.conf */ - int retval = 0; - struct dump_dir *dd = NULL; - char *line; - while ((line = xmalloc_fgetline(conffile)) != NULL) - { - /* Line has form: [VAR=VAL]... PROG [ARGS] */ - char *p = skip_whitespace(line); - if (*p == '\0' || *p == '#') - goto next_line; /* empty or comment line, skip */ - - VERB3 log("%s: line '%s'", __func__, p); - - while (1) /* word loop */ - { - char *end_word = skip_non_whitespace(p); - char *next_word = skip_whitespace(end_word); - - /* *end_word = '\0'; - BUG, truncates command */ - - /* If there is no '=' in this word... */ - char *line_val = strchr(p, '='); - if (!line_val || line_val >= end_word) - break; /* ...we found the start of a command */ - - *end_word = '\0'; - - /* Current word has VAR=VAL form. line_val => VAL */ - *line_val++ = '\0'; - - const char *real_val; - char *malloced_val = NULL; - - /* Is it EVENT? */ - if (strcmp(p, "EVENT") == 0) - real_val = event; - else - { - /* Get this name from dump dir */ - if (!dd) - { - dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - goto stop; /* error (note: dd_opendir logged error msg) */ - } - real_val = malloced_val = dd_load_text_ext(dd, p, DD_FAIL_QUIETLY); - } - - /* Does VAL match? */ - if (strcmp(real_val, line_val) != 0) - { - VERB3 log("var '%s': '%.*s'!='%s', skipping line", - p, - (int)(strchrnul(real_val, '\n') - real_val), real_val, - line_val); - free(malloced_val); - goto next_line; /* no */ - } - free(malloced_val); - - /* Go to next word */ - p = next_word; - } /* end of word loop */ - - /* Don't keep dump dir locked across program runs */ - dd_close(dd); - dd = NULL; - - /* We found matching line, execute its command(s) in shell */ - { - VERB1 log("Executing '%s'", p); - - /* /bin/sh -c 'cmd [args]' NULL */ - char *argv[4]; - char **pp = argv; - *pp++ = (char*)"/bin/sh"; - *pp++ = (char*)"-c"; - *pp++ = (char*)p; - *pp = NULL; - int pipefds[2]; - pid_t pid = fork_execv_on_steroids(EXECFLG_INPUT_NUL + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, - argv, - pipefds, - /* unsetenv_vec: */ NULL, - /* dir: */ dump_dir_name, - /* uid(unused): */ 0 - ); - free(line); - line = NULL; - - /* Consume log from stdout */ - FILE *fp = fdopen(pipefds[0], "r"); - if (!fp) - die_out_of_memory(); - char *buf; - while ((buf = xmalloc_fgetline(fp)) != NULL) - { - if (state->logging_callback) - buf = state->logging_callback(buf, state->logging_param); - free(buf); - } - fclose(fp); /* Got EOF, close. This also closes pipefds[0] */ - - /* Wait for child to actually exit, collect status */ - int status; - waitpid(pid, &status, 0); - - if (status != 0) - { - retval = WEXITSTATUS(status); - if (WIFSIGNALED(status)) - retval = WTERMSIG(status) + 128; - break; - } - } - - if (state->post_run_callback) - { - retval = state->post_run_callback(dump_dir_name, state->post_run_param); - if (retval != 0) - break; - } - - next_line: - free(line); - } /* end of line loop */ - - stop: - free(line); - dd_close(dd); - fclose(conffile); - - return retval; -} - -char *list_possible_events(struct dump_dir *dd, const char *dump_dir_name, const char *pfx) -{ - FILE *conffile = fopen(CONF_DIR"/abrt_event.conf", "r"); - if (!conffile) - { - error_msg("Can't open '%s'", CONF_DIR"/abrt_event.conf"); - return NULL; - } - - /* We check "dump_dir_name == NULL" later. - * Prevent the possibility that both dump_dir_name - * and dd are non-NULL (which does not make sense) - */ - if (dd) - dump_dir_name = NULL; - - unsigned pfx_len = strlen(pfx); - struct strbuf *result = strbuf_new(); - char *line; - while ((line = xmalloc_fgetline(conffile)) != NULL) - { - /* Line has form: [VAR=VAL]... PROG [ARGS] */ - char *p = skip_whitespace(line); - if (*p == '\0' || *p == '#') - goto next_line; /* empty or comment line, skip */ - - VERB3 log("%s: line '%s'", __func__, p); - - while (1) /* word loop */ - { - char *end_word = skip_non_whitespace(p); - char *next_word = skip_whitespace(end_word); - *end_word = '\0'; - - /* If there is no '=' in this word... */ - char *line_val = strchr(p, '='); - if (!line_val) - break; /* ...we found the start of a command */ - - /* Current word has VAR=VAL form. line_val => VAL */ - *line_val++ = '\0'; - - /* Is it EVENT? */ - if (strcmp(p, "EVENT") == 0) - { - if (strncmp(line_val, pfx, pfx_len) != 0) - goto next_line; /* prefix doesn't match */ - /* (Ab)use line to save matching "\nEVENT_VAL\n" */ - sprintf(line, "\n%s\n", line_val); - } - else - { - /* Get this name from dump dir */ - if (!dd) - { - /* Without dir name to match, we assume match for this expr */ - if (!dump_dir_name) - goto next_word; - dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - goto stop; /* error (note: dd_opendir logged error msg) */ - } - char *real_val = dd_load_text(dd, p); - /* Does VAL match? */ - if (strcmp(real_val, line_val) != 0) - { - VERB3 log("var '%s': '%s'!='%s', skipping line", p, real_val, line_val); - free(real_val); - goto next_line; /* no */ - } - free(real_val); - } - - next_word: - /* Go to next word */ - p = next_word; - } /* end of word loop */ - - if (line[0] == '\n' /* do we *have* saved matched "\nEVENT_VAL\n"? */ - /* and does result->buf NOT yet have VAL? */ - && strncmp(result->buf, line + 1, strlen(line + 1)) != 0 - && !strstr(result->buf, line) - ) { - /* Add "EVENT_VAL\n" */ - strbuf_append_str(result, line + 1); - } - - next_line: - free(line); - } /* end of line loop */ - - stop: - free(line); - if (dump_dir_name != NULL) - dd_close(dd); - fclose(conffile); - - return strbuf_free_nobuf(result); -} diff --git a/lib/utils/skip_whitespace.c b/lib/utils/skip_whitespace.c deleted file mode 100644 index 816928bf..00000000 --- a/lib/utils/skip_whitespace.c +++ /dev/null @@ -1,22 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Copyright (C) 2003 Manuel Novoa III - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ -#include "abrtlib.h" - -char* skip_whitespace(const char *s) -{ - /* NB: isspace('\0') returns 0 */ - while (isspace(*s)) ++s; - - return (char *) s; -} - -char* skip_non_whitespace(const char *s) -{ - while (*s && !isspace(*s)) ++s; - - return (char *) s; -} diff --git a/lib/utils/spawn.c b/lib/utils/spawn.c deleted file mode 100644 index 068f4ac7..00000000 --- a/lib/utils/spawn.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Utility routines. - * - * Licensed under GPLv2, see file COPYING in this tarball for details. - */ -#include "abrtlib.h" - -static char *concat_str_vector(char **strings) -{ - if (!strings[0]) - return xzalloc(1); // returns "" - - unsigned len = 0; - char **spp = strings; - while (*spp) - len += strlen(*spp++) + 1; - - char *result = xmalloc(len); - - char *r = result; - spp = strings; - while (*spp) { - r = stpcpy(r, *spp++); - *r++ = ' '; - } - *--r = '\0'; - - return result; -} - -/* Returns pid */ -pid_t fork_execv_on_steroids(int flags, - char **argv, - int *pipefds, - char **unsetenv_vec, - const char *dir, - uid_t uid) -{ - pid_t child; - /* Reminder: [0] is read end, [1] is write end */ - int pipe_to_child[2]; - int pipe_fm_child[2]; - - /* Sanitize flags */ - if (!pipefds) - flags &= ~(EXECFLG_INPUT | EXECFLG_OUTPUT); - - if (flags & EXECFLG_INPUT) - xpipe(pipe_to_child); - if (flags & EXECFLG_OUTPUT) - xpipe(pipe_fm_child); - - fflush(NULL); - child = fork(); - if (child == -1) { - perror_msg_and_die("fork"); - } - if (child == 0) { - /* Child */ - - if (dir) - xchdir(dir); - - if (flags & EXECFLG_SETGUID) { - struct passwd* pw = getpwuid(uid); - gid_t gid = pw ? pw->pw_gid : uid; - setgroups(1, &gid); - xsetregid(gid, gid); - xsetreuid(uid, uid); - } - - if (unsetenv_vec) { - while (*unsetenv_vec) - unsetenv(*unsetenv_vec++); - } - - /* Play with stdio descriptors */ - if (flags & EXECFLG_INPUT) { - xmove_fd(pipe_to_child[0], STDIN_FILENO); - close(pipe_to_child[1]); - } else if (flags & EXECFLG_INPUT_NUL) { - xmove_fd(xopen("/dev/null", O_RDWR), STDIN_FILENO); - } - if (flags & EXECFLG_OUTPUT) { - xmove_fd(pipe_fm_child[1], STDOUT_FILENO); - close(pipe_fm_child[0]); - } else if (flags & EXECFLG_OUTPUT_NUL) { - xmove_fd(xopen("/dev/null", O_RDWR), STDOUT_FILENO); - } - - /* This should be done BEFORE stderr redirect */ - VERB1 { - char *r = concat_str_vector(argv); - log("Executing: %s", r); - free(r); - } - - if (flags & EXECFLG_ERR2OUT) { - /* Want parent to see errors in the same stream */ - xdup2(STDOUT_FILENO, STDERR_FILENO); - } else if (flags & EXECFLG_ERR_NUL) { - xmove_fd(xopen("/dev/null", O_RDWR), STDERR_FILENO); - } - - if (flags & EXECFLG_SETSID) - setsid(); - - execvp(argv[0], argv); - if (!(flags & EXECFLG_QUIET)) - perror_msg("Can't execute '%s'", argv[0]); - exit(127); /* shell uses this exitcode in this case */ - } - - if (flags & EXECFLG_INPUT) { - close(pipe_to_child[0]); - pipefds[1] = pipe_to_child[1]; - } - if (flags & EXECFLG_OUTPUT) { - close(pipe_fm_child[1]); - pipefds[0] = pipe_fm_child[0]; - } - - return child; -} - -char *run_in_shell_and_save_output(int flags, - const char *cmd, - const char *dir, - size_t *size_p) -{ - flags |= EXECFLG_OUTPUT; - flags &= ~EXECFLG_INPUT; - - const char *argv[] = { "/bin/sh", "-c", cmd, NULL }; - int pipeout[2]; - pid_t child = fork_execv_on_steroids(flags, (char **)argv, pipeout, - /*unsetenv_vec:*/ NULL, dir, /*uid (unused):*/ 0); - - size_t pos = 0; - char *result = NULL; - while (1) { - result = (char*) xrealloc(result, pos + 4*1024 + 1); - size_t sz = safe_read(pipeout[0], result + pos, 4*1024); - if (sz <= 0) { - break; - } - pos += sz; - } - result[pos] = '\0'; - if (size_p) - *size_p = pos; - close(pipeout[0]); - waitpid(child, NULL, 0); - - return result; -} diff --git a/lib/utils/stdio_helpers.c b/lib/utils/stdio_helpers.c deleted file mode 100644 index 81cf5d75..00000000 --- a/lib/utils/stdio_helpers.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Utility routines. - * - * Copyright (C) 2001 Matt Krai - * Copyright (C) 2004 Erik Andersen - * Copyright (C) 2005, 2006 Rob Landley - * Copyright (C) 2010 ABRT Team - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ -#include "abrtlib.h" - -//TODO: add sanitizing upper limit (e.g 64K, 1M, or configurable). -//This is why we don't use GNU's getline: it doesn't have -//any upper sanity bound on line size. - -static char *xmalloc_fgets_internal(FILE *file, int *sizep) -{ - unsigned idx = 0; - char *linebuf = NULL; - - while (1) { - char *r; - - linebuf = xrealloc(linebuf, idx + 0x100); - r = fgets(&linebuf[idx], 0x100, file); - if (!r) { - /* need to terminate the line */ - linebuf[idx] = '\0'; - break; - } - - /* stupid. fgets knows the len, it should report it somehow */ - unsigned len = strlen(&linebuf[idx]); - - idx += len; - if (len < 0xff || linebuf[idx - 1] == '\n') - break; /* we found \n or EOF */ - } - - *sizep = idx; - - if (!idx) { - /* The very first fgets returned NULL. It's EOF (or error) */ - free(linebuf); - linebuf = NULL; - } - return linebuf; -} - -char *xmalloc_fgets(FILE *file) -{ - int sz; - char *r = xmalloc_fgets_internal(file, &sz); - if (!r) - return r; - return xrealloc(r, sz + 1); -} - -char *xmalloc_fgetline(FILE *file) -{ - int sz; - char *r = xmalloc_fgets_internal(file, &sz); - if (!r) - return r; - if (r[sz - 1] == '\n') - r[--sz] = '\0'; - return xrealloc(r, sz + 1); -} diff --git a/lib/utils/strbuf.c b/lib/utils/strbuf.c deleted file mode 100644 index 04a35998..00000000 --- a/lib/utils/strbuf.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - String buffer implementation - - Copyright (C) 2009 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" - -int prefixcmp(const char *str, const char *prefix) -{ - for (; ; str++, prefix++) - if (!*prefix) - return 0; - else if (*str != *prefix) - return (unsigned char)*prefix - (unsigned char)*str; -} - -int suffixcmp(const char *str, const char *suffix) -{ - int len_minus_suflen = strlen(str) - strlen(suffix); - if (len_minus_suflen < 0) - return len_minus_suflen; - else - return strcmp(str + len_minus_suflen, suffix); -} - -struct strbuf *strbuf_new() -{ - struct strbuf *buf = xzalloc(sizeof(*buf)); - /*buf->len = 0; - done by xzalloc */ - buf->alloc = 8; - buf->buf = xzalloc(8); - return buf; -} - -void strbuf_free(struct strbuf *strbuf) -{ - if (!strbuf) - return; - free(strbuf->buf); - free(strbuf); -} - -char *strbuf_free_nobuf(struct strbuf *strbuf) -{ - char *ret = strbuf->buf; - free(strbuf); - return ret; -} - - -void strbuf_clear(struct strbuf *strbuf) -{ - assert(strbuf->alloc > 0); - strbuf->len = 0; - strbuf->buf[0] = '\0'; -} - -/* Ensures that the buffer can be extended by N+1 characters - * without touching malloc/realloc. - * Returns pointer where appended chars can be stored by the caller; - * increments ->len by N (therefore callers don't need to do it). - */ -static char *strbuf_grow(struct strbuf *strbuf, unsigned increment) -{ - unsigned len = strbuf->len; - unsigned need = strbuf->len = len + increment; - unsigned cur_size = strbuf->alloc; - if (cur_size <= need) - { - while (cur_size <= need) - cur_size += 64 + cur_size / 8; - strbuf->alloc = cur_size; - strbuf->buf = xrealloc(strbuf->buf, cur_size); - } - char *p = strbuf->buf + len; - return p; -} - -struct strbuf *strbuf_append_char(struct strbuf *strbuf, char c) -{ - char *p = strbuf_grow(strbuf, 1); - *p++ = c; - *p = '\0'; - return strbuf; -} - -struct strbuf *strbuf_append_str(struct strbuf *strbuf, const char *str) -{ - unsigned len = strlen(str); - char *p = strbuf_grow(strbuf, len); - assert(strbuf->len < strbuf->alloc); - strcpy(p, str); - return strbuf; -} - -struct strbuf *strbuf_prepend_str(struct strbuf *strbuf, const char *str) -{ - unsigned cur_len = strbuf->len; - unsigned inc_len = strlen(str); - strbuf_grow(strbuf, inc_len); - assert(strbuf->len < strbuf->alloc); - memmove(strbuf->buf + inc_len, strbuf->buf, cur_len); - memcpy(strbuf->buf, str, inc_len); - return strbuf; -} - -struct strbuf *strbuf_append_strf(struct strbuf *strbuf, const char *format, ...) -{ - va_list p; - char *string_ptr; - - va_start(p, format); - string_ptr = xvasprintf(format, p); - va_end(p); - - strbuf_append_str(strbuf, string_ptr); - free(string_ptr); - return strbuf; -} - -struct strbuf *strbuf_prepend_strf(struct strbuf *strbuf, const char *format, ...) -{ - va_list p; - char *string_ptr; - - va_start(p, format); - string_ptr = xvasprintf(format, p); - va_end(p); - - strbuf_prepend_str(strbuf, string_ptr); - free(string_ptr); - return strbuf; -} diff --git a/lib/utils/strbuf.h b/lib/utils/strbuf.h deleted file mode 100644 index dc45a199..00000000 --- a/lib/utils/strbuf.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - strbuf.h - string buffer - - Copyright (C) 2009 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 STRBUF_H -#define STRBUF_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct strbuf -{ - /* Size of the allocated buffer. Always > 0. */ - int alloc; - /* Length of the string, without the ending \0. */ - int len; - char *buf; -}; - -/** - * Creates and initializes a new string buffer. - * @returns - * It never returns NULL. The returned pointer must be released by - * calling the function strbuf_free(). - */ -struct strbuf *strbuf_new(); - -/** - * Releases the memory held by the string buffer. - * @param strbuf - * If the strbuf is NULL, no operation is performed. - */ -void strbuf_free(struct strbuf *strbuf); - -/** - * Releases the strbuf, but not the internal buffer. The internal - * string buffer is returned. Caller is responsible to release the - * returned memory using free(). - */ -char* strbuf_free_nobuf(struct strbuf *strbuf); - -/** - * The string content is set to an empty string, erasing any previous - * content and leaving its length at 0 characters. - */ -void strbuf_clear(struct strbuf *strbuf); - -/** - * The current content of the string buffer is extended by adding a - * character c at its end. - */ -struct strbuf *strbuf_append_char(struct strbuf *strbuf, char c); - -/** - * The current content of the string buffer is extended by adding a - * string str at its end. - */ -struct strbuf *strbuf_append_str(struct strbuf *strbuf, - const char *str); - -/** - * The current content of the string buffer is extended by inserting a - * string str at its beginning. - */ -struct strbuf *strbuf_prepend_str(struct strbuf *strbuf, - const char *str); - -/** - * The current content of the string buffer is extended by adding a - * sequence of data formatted as the format argument specifies. - */ -struct strbuf *strbuf_append_strf(struct strbuf *strbuf, - const char *format, ...); - -/** - * The current content of the string buffer is extended by inserting a - * sequence of data formatted as the format argument specifies at the - * buffer beginning. - */ -struct strbuf *strbuf_prepend_strf(struct strbuf *strbuf, - const char *format, ...); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/utils/stringops.cpp b/lib/utils/stringops.cpp deleted file mode 100644 index 7bc5413f..00000000 --- a/lib/utils/stringops.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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" - -void parse_args(const char *psArgs, vector_string_t& pArgs, int quote) -{ - unsigned ii; - bool inside_quotes = false; - std::string item; - - for (ii = 0; psArgs[ii]; ii++) - { - if (quote != -1) - { - if (psArgs[ii] == quote) - { - inside_quotes = !inside_quotes; - continue; - } - /* inside quotes we support escaping with \x */ - if (inside_quotes && psArgs[ii] == '\\' && psArgs[ii+1]) - { - ii++; - item += psArgs[ii]; - continue; - } - } - if (psArgs[ii] == ',' && !inside_quotes) - { - pArgs.push_back(item); - item.clear(); - continue; - } - item += psArgs[ii]; - } - - if (item.size() != 0) - { - pArgs.push_back(item); - } -} diff --git a/lib/utils/test.cpp b/lib/utils/test.cpp deleted file mode 100644 index a548dc21..00000000 --- a/lib/utils/test.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - test.cpp - simple library test - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 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 "MiddleWare.h" -#include "DebugDump.h" -#include "CrashTypes.h" -#include -#include -#include -#include - - -int main(int argc, char** argv) -{ - - if (argc < 2) - { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return -1; - } - try - { - CMiddleWare middleWare(PLUGINS_CONF_DIR, - PLUGINS_LIB_DIR); - vector_map_string_t loaded_plugins; - middleWare.RegisterPlugin("CCpp"); - middleWare.RegisterPlugin("Mailx"); - middleWare.RegisterPlugin("Logger"); - middleWare.RegisterPlugin("SQLite3"); - middleWare.SetDatabase("SQLite3"); - middleWare.SetOpenGPGCheck(false); - middleWare.AddActionOrReporter("Logger", ""); - middleWare.AddAnalyzerActionOrReporter("CCpp", "Mailx", ""); - - loaded_plugins = middleWare.GetPluginsInfo(); - std::cout << "Loaded plugins" << std::endl; - int ii; - for ( ii = 0; ii < loaded_plugins.size(); ii++) - { - std::cout << "-------------------------------------------" << std::endl; - map_plugin_settings_t settings; - std::cout << "Enabled: " << loaded_plugins[ii]["Enabled"] << std::endl; - std::cout << "Type: " << loaded_plugins[ii]["Type"] << std::endl; - std::cout << "Name: " << loaded_plugins[ii]["Name"] << std::endl; - std::cout << "Version: " << loaded_plugins[ii]["Version"] << std::endl; - std::cout << "Description: " << loaded_plugins[ii]["Description"] << std::endl; - std::cout << "Email: " << loaded_plugins[ii]["Email"] << std::endl; - std::cout << "WWW: " << loaded_plugins[ii]["WWW"] << std::endl; - std::cout << "GTKBuilder: " << loaded_plugins[ii]["GTKBuilder"] << std::endl; - if (loaded_plugins[ii]["Enabled"] == "yes") - { - std::cout << std::endl << "Settings: " << std::endl; - settings = middleWare.GetPluginSettings(loaded_plugins[ii]["Name"]); - map_plugin_settings_t::iterator it; - for (it = settings.begin(); it != settings.end(); it++) - { - std::cout << "\t" << it->first << ": " << it->second << std::endl; - } - } - std::cout << "-------------------------------------------" << std::endl; - } - /* Try to save it into DB */ - map_crash_data_t crashInfo; - if (middleWare.SaveDebugDump(argv[1], crashInfo)) - { - std::cout << "Application Crashed! " << - crashInfo[FILENAME_PACKAGE][CD_CONTENT] << ", " << - crashInfo[FILENAME_EXECUTABLE][CD_CONTENT] << ", " << - crashInfo[CD_COUNT][CD_CONTENT] << ", " << std::endl; - - /* Get Report, so user can change data (remove private stuff) - * If we do not want user interaction, just send data immediately - */ - map_crash_data_t crashReport; - middleWare.CreateCrashReport(crashInfo[FILENAME_DUPHASH][CD_CONTENT], - crashInfo[CD_UID][CD_CONTENT], - crashReport); - /* Report crash */ - middleWare.Report(crashReport); - } - } - catch (std::string sError) - { - std::cerr << sError << std::endl; - } - - return 0; -} diff --git a/lib/utils/time.c b/lib/utils/time.c deleted file mode 100644 index 37ade2cc..00000000 --- a/lib/utils/time.c +++ /dev/null @@ -1,65 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Utility routines. - * - * Licensed under GPL version 2, see file LICENSE in this tarball for details. - */ -#include "abrtlib.h" - -#define ENABLE_MONOTONIC_SYSCALL 1 - -#if ENABLE_MONOTONIC_SYSCALL - -#include -/* Old glibc (< 2.3.4) does not provide this constant. We use syscall - * directly so this definition is safe. */ -#ifndef CLOCK_MONOTONIC -#define CLOCK_MONOTONIC 1 -#endif - -/* libc has incredibly messy way of doing this, - * typically requiring -lrt. We just skip all this mess */ -static void get_mono(struct timespec *ts) -{ - if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts)) - error_msg_and_die("clock_gettime(MONOTONIC) failed"); -} -unsigned long long monotonic_ns(void) -{ - struct timespec ts; - get_mono(&ts); - return ts.tv_sec * 1000000000ULL + ts.tv_nsec; -} -unsigned long long monotonic_us(void) -{ - struct timespec ts; - get_mono(&ts); - return ts.tv_sec * 1000000ULL + ts.tv_nsec/1000; -} -unsigned monotonic_sec(void) -{ - struct timespec ts; - get_mono(&ts); - return ts.tv_sec; -} - -#else - -unsigned long long monotonic_ns(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; -} -unsigned long long monotonic_us(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000ULL + tv.tv_usec; -} -unsigned monotonic_sec(void) -{ - return time(NULL); -} - -#endif diff --git a/lib/utils/xatonum.c b/lib/utils/xatonum.c deleted file mode 100644 index 3b22071f..00000000 --- a/lib/utils/xatonum.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Utility routines. - * - * Copyright (C) 2003 Manuel Novoa III - * - * Licensed under GPLv2, see file LICENSE in this tarball for details. - */ -#include "abrtlib.h" - -unsigned xatou(const char *numstr) -{ - unsigned long r; - int old_errno; - char *e; - - if (*numstr < '0' || *numstr > '9') - goto inval; - - old_errno = errno; - errno = 0; - r = strtoul(numstr, &e, 10); - if (errno || numstr == e || *e != '\0' || r > UINT_MAX) - goto inval; /* error / no digits / illegal trailing chars */ - errno = old_errno; /* Ok. So restore errno. */ - return r; - -inval: - error_msg_and_die("invalid number '%s'", numstr); -} - -int xatoi_u(const char *numstr) -{ - unsigned r = xatou(numstr); - if (r > (unsigned)INT_MAX) - error_msg_and_die("invalid number '%s'", numstr); - return r; -} - -int xatoi(const char *numstr) -{ - unsigned r; - - if (*numstr != '-') - return xatoi_u(numstr); - - r = xatou(numstr + 1); - if (r > (unsigned)INT_MAX + 1) - error_msg_and_die("invalid number '%s'", numstr); - return - (int)r; -} diff --git a/lib/utils/xconnect.c b/lib/utils/xconnect.c deleted file mode 100644 index 0d02b1a4..00000000 --- a/lib/utils/xconnect.c +++ /dev/null @@ -1,415 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Utility routines. - * - * Connect to host at port using address resolution from getaddrinfo - * - * Licensed under GPLv2, see file LICENSE in this tarball for details. - */ -#include "abrtlib.h" -#include /* netinet/in.h needs it */ -#include -#include -#include -#include - -#define ENABLE_FEATURE_IPV6 1 -#define ENABLE_FEATURE_PREFER_IPV4_ADDRESS 1 - -static const int const_int_1 = 1; - -void setsockopt_reuseaddr(int fd) -{ - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)); -} -int setsockopt_broadcast(int fd) -{ - return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1)); -} -int setsockopt_bindtodevice(int fd, const char *iface) -{ - int r; - struct ifreq ifr; - strncpy(ifr.ifr_name, iface, IFNAMSIZ); - /* NB: passing (iface, strlen(iface) + 1) does not work! - * (maybe it works on _some_ kernels, but not on 2.6.26) - * Actually, ifr_name is at offset 0, and in practice - * just giving char[IFNAMSIZ] instead of struct ifreq works too. - * But just in case it's not true on some obscure arch... */ - r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); - if (r) - perror_msg("can't bind to interface %s", iface); - return r; -} - -len_and_sockaddr* get_sock_lsa(int fd) -{ - len_and_sockaddr lsa; - len_and_sockaddr *lsa_ptr; - - lsa.len = LSA_SIZEOF_SA; - if (getsockname(fd, &lsa.u.sa, &lsa.len) != 0) - return NULL; - - lsa_ptr = (len_and_sockaddr *)xzalloc(LSA_LEN_SIZE + lsa.len); - if (lsa.len > LSA_SIZEOF_SA) { /* rarely (if ever) happens */ - lsa_ptr->len = lsa.len; - getsockname(fd, &lsa_ptr->u.sa, &lsa_ptr->len); - } else { - memcpy(lsa_ptr, &lsa, LSA_LEN_SIZE + lsa.len); - } - return lsa_ptr; -} - -void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) -{ - if (connect(s, s_addr, addrlen) < 0) { - close(s); - if (s_addr->sa_family == AF_INET) - perror_msg_and_die("%s (%s)", - "cannot connect to remote host", - inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr)); - perror_msg_and_die("cannot connect to remote host"); - } -} - -/* Return port number for a service. - * If "port" is a number use it as the port. - * If "port" is a name it is looked up in /etc/services, - * if it isnt found return default_port - */ -unsigned lookup_port(const char *port, const char *protocol, unsigned default_port) -{ - unsigned port_nr = default_port; - if (port) { - int old_errno; - char *end; - - /* Since this is a lib function, we're not allowed to reset errno to 0. - * Doing so could break an app that is deferring checking of errno. */ - old_errno = errno; - errno = 0; - port_nr = strtoul(port, &end, 10); - if (errno || *end || port_nr > 65535) { - struct servent *tserv = getservbyname(port, protocol); - port_nr = default_port; - if (tserv) - port_nr = ntohs(tserv->s_port); - } - errno = old_errno; - } - return (uint16_t)port_nr; -} - -int get_nport(const struct sockaddr *sa) -{ -#if ENABLE_FEATURE_IPV6 - if (sa->sa_family == AF_INET6) { - return ((struct sockaddr_in6*)sa)->sin6_port; - } -#endif - if (sa->sa_family == AF_INET) { - return ((struct sockaddr_in*)sa)->sin_port; - } - /* What? UNIX socket? IPX?? :) */ - return -1; -} - -void set_nport(len_and_sockaddr *lsa, unsigned port) -{ -#if ENABLE_FEATURE_IPV6 - if (lsa->u.sa.sa_family == AF_INET6) { - lsa->u.sin6.sin6_port = port; - return; - } -#endif - if (lsa->u.sa.sa_family == AF_INET) { - lsa->u.sin.sin_port = port; - return; - } - /* What? UNIX socket? IPX?? :) */ -} - -/* We hijack this constant to mean something else */ -/* It doesn't hurt because we will remove this bit anyway */ -#define DIE_ON_ERROR AI_CANONNAME - -/* host: "1.2.3.4[:port]", "www.google.com[:port]" - * port: if neither of above specifies port # */ -static len_and_sockaddr* str2sockaddr( - const char *host, int port, - sa_family_t af, - int ai_flags) -{ - int rc; - len_and_sockaddr *r; - struct addrinfo *result = NULL; - struct addrinfo *used_res; - const char *org_host = host; /* only for error msg */ - const char *cp; - struct addrinfo hint; - - r = NULL; - - /* Ugly parsing of host:addr */ - if (ENABLE_FEATURE_IPV6 && host[0] == '[') { - /* Even uglier parsing of [xx]:nn */ - host++; - cp = strchr(host, ']'); - if (!cp || (cp[1] != ':' && cp[1] != '\0')) { - /* Malformed: must be [xx]:nn or [xx] */ - error_msg("bad address '%s'", org_host); - if (ai_flags & DIE_ON_ERROR) - xfunc_die(); - return NULL; - } - } else { - cp = strrchr(host, ':'); - if (ENABLE_FEATURE_IPV6 && cp && strchr(host, ':') != cp) { - /* There is more than one ':' (e.g. "::1") */ - cp = NULL; /* it's not a port spec */ - } - } - if (cp) { /* points to ":" or "]:" */ - int sz = cp - host + 1; - char *hbuf = (char*)alloca(sz); - hbuf[--sz] = '\0'; - host = strncpy(hbuf, host, sz); - if (ENABLE_FEATURE_IPV6 && *cp != ':') { - cp++; /* skip ']' */ - if (*cp == '\0') /* [xx] without port */ - goto skip; - } - cp++; /* skip ':' */ - char *end; - errno = 0; - port = strtoul(cp, &end, 10); - if (errno || *end || (unsigned)port > 0xffff) { - error_msg("bad port spec '%s'", org_host); - if (ai_flags & DIE_ON_ERROR) - xfunc_die(); - return NULL; - } - skip: ; - } - - memset(&hint, 0 , sizeof(hint)); -#if !ENABLE_FEATURE_IPV6 - hint.ai_family = AF_INET; /* do not try to find IPv6 */ -#else - hint.ai_family = af; -#endif - /* Needed. Or else we will get each address thrice (or more) - * for each possible socket type (tcp,udp,raw...): */ - hint.ai_socktype = SOCK_STREAM; - hint.ai_flags = ai_flags & ~DIE_ON_ERROR; - rc = getaddrinfo(host, NULL, &hint, &result); - if (rc || !result) { - error_msg("bad address '%s'", org_host); - if (ai_flags & DIE_ON_ERROR) - xfunc_die(); - goto ret; - } - used_res = result; -#if ENABLE_FEATURE_PREFER_IPV4_ADDRESS - while (1) { - if (used_res->ai_family == AF_INET) - break; - used_res = used_res->ai_next; - if (!used_res) { - used_res = result; - break; - } - } -#endif - r = (len_and_sockaddr *)xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen); - r->len = used_res->ai_addrlen; - memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen); - set_nport(r, htons(port)); - ret: - freeaddrinfo(result); - return r; -} -#if !ENABLE_FEATURE_IPV6 -#define str2sockaddr(host, port, af, ai_flags) str2sockaddr(host, port, ai_flags) -#endif - -#if ENABLE_FEATURE_IPV6 -len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af) -{ - return str2sockaddr(host, port, af, 0); -} - -len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t af) -{ - return str2sockaddr(host, port, af, DIE_ON_ERROR); -} -#endif - -len_and_sockaddr* host2sockaddr(const char *host, int port) -{ - return str2sockaddr(host, port, AF_UNSPEC, 0); -} - -len_and_sockaddr* xhost2sockaddr(const char *host, int port) -{ - return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR); -} - -len_and_sockaddr* xdotted2sockaddr(const char *host, int port) -{ - return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR); -} - -#undef xsocket_type -int xsocket_type(len_and_sockaddr **lsap, int family, int sock_type) -{ - len_and_sockaddr *lsa; - int fd; - int len; - -#if ENABLE_FEATURE_IPV6 - if (family == AF_UNSPEC) { - fd = socket(AF_INET6, sock_type, 0); - if (fd >= 0) { - family = AF_INET6; - goto done; - } - family = AF_INET; - } -#endif - fd = xsocket(family, sock_type, 0); - len = sizeof(struct sockaddr_in); -#if ENABLE_FEATURE_IPV6 - if (family == AF_INET6) { - done: - len = sizeof(struct sockaddr_in6); - } -#endif - lsa = (len_and_sockaddr *)xzalloc(offsetof(len_and_sockaddr, u.sa) + len); - lsa->len = len; - lsa->u.sa.sa_family = family; - *lsap = lsa; - return fd; -} - -int xsocket_stream(len_and_sockaddr **lsap) -{ - return xsocket_type(lsap, AF_UNSPEC, SOCK_STREAM); -} - -static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type) -{ - int fd; - len_and_sockaddr *lsa; - - if (bindaddr && bindaddr[0]) { - lsa = xdotted2sockaddr(bindaddr, port); - /* user specified bind addr dictates family */ - fd = xsocket(lsa->u.sa.sa_family, sock_type, 0); - } else { - fd = xsocket_type(&lsa, AF_UNSPEC, sock_type); - set_nport(lsa, htons(port)); - } - setsockopt_reuseaddr(fd); - xbind(fd, &lsa->u.sa, lsa->len); - free(lsa); - return fd; -} - -int create_and_bind_stream_or_die(const char *bindaddr, int port) -{ - return create_and_bind_or_die(bindaddr, port, SOCK_STREAM); -} - -int create_and_bind_dgram_or_die(const char *bindaddr, int port) -{ - return create_and_bind_or_die(bindaddr, port, SOCK_DGRAM); -} - - -int create_and_connect_stream_or_die(const char *peer, int port) -{ - int fd; - len_and_sockaddr *lsa; - - lsa = xhost2sockaddr(peer, port); - fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0); - setsockopt_reuseaddr(fd); - xconnect(fd, &lsa->u.sa, lsa->len); - free(lsa); - return fd; -} - -int xconnect_stream(const len_and_sockaddr *lsa) -{ - int fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0); - xconnect(fd, &lsa->u.sa, lsa->len); - return fd; -} - -/* We hijack this constant to mean something else */ -/* It doesn't hurt because we will add this bit anyway */ -#define IGNORE_PORT NI_NUMERICSERV -static char* sockaddr2str(const struct sockaddr *sa, int flags) -{ - char host[128]; - char serv[16]; - int rc; - socklen_t salen; - - salen = LSA_SIZEOF_SA; -#if ENABLE_FEATURE_IPV6 - if (sa->sa_family == AF_INET) - salen = sizeof(struct sockaddr_in); - if (sa->sa_family == AF_INET6) - salen = sizeof(struct sockaddr_in6); -#endif - rc = getnameinfo(sa, salen, - host, sizeof(host), - /* can do ((flags & IGNORE_PORT) ? NULL : serv) but why bother? */ - serv, sizeof(serv), - /* do not resolve port# into service _name_ */ - flags | NI_NUMERICSERV - ); - if (rc) - return NULL; - if (flags & IGNORE_PORT) - return xstrdup(host); -#if ENABLE_FEATURE_IPV6 - if (sa->sa_family == AF_INET6) { - if (strchr(host, ':')) /* heh, it's not a resolved hostname */ - return xasprintf("[%s]:%s", host, serv); - /*return xasprintf("%s:%s", host, serv);*/ - /* - fall through instead */ - } -#endif - /* For now we don't support anything else, so it has to be INET */ - /*if (sa->sa_family == AF_INET)*/ - return xasprintf("%s:%s", host, serv); - /*return xstrdup(host);*/ -} - -char* xmalloc_sockaddr2host(const struct sockaddr *sa) -{ - return sockaddr2str(sa, 0); -} - -char* xmalloc_sockaddr2host_noport(const struct sockaddr *sa) -{ - return sockaddr2str(sa, IGNORE_PORT); -} - -char* xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa) -{ - return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT); -} -char* xmalloc_sockaddr2dotted(const struct sockaddr *sa) -{ - return sockaddr2str(sa, NI_NUMERICHOST); -} - -char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa) -{ - return sockaddr2str(sa, NI_NUMERICHOST | IGNORE_PORT); -} diff --git a/lib/utils/xfuncs.c b/lib/utils/xfuncs.c deleted file mode 100644 index d5166037..00000000 --- a/lib/utils/xfuncs.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - Copyright (C) 2010 ABRT team - Copyright (C) 2010 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. -*/ - -/* - * Utility routines. - * - */ -#include "abrtlib.h" - -/* Turn on nonblocking I/O on a fd */ -int ndelay_on(int fd) -{ - return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); -} - -int ndelay_off(int fd) -{ - return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); -} - -int close_on_exec_on(int fd) -{ - return fcntl(fd, F_SETFD, FD_CLOEXEC); -} - -#if 0 /* unused */ -void *xcalloc(size_t nmemb, size_t size) -{ - void *ptr = calloc(nmemb, size); - if (!ptr && nmemb && size) - die_out_of_memory(); - return ptr; -} -#endif - -// Die if we can't allocate size bytes of memory. -void* xmalloc(size_t size) -{ - void *ptr = malloc(size); - if (ptr == NULL && size != 0) - die_out_of_memory(); - return ptr; -} - -// Die if we can't resize previously allocated memory. (This returns a pointer -// to the new memory, which may or may not be the same as the old memory. -// It'll copy the contents to a new chunk and free the old one if necessary.) -void* xrealloc(void *ptr, size_t size) -{ - ptr = realloc(ptr, size); - if (ptr == NULL && size != 0) - die_out_of_memory(); - return ptr; -} - -// Die if we can't allocate and zero size bytes of memory. -void* xzalloc(size_t size) -{ - void *ptr = xmalloc(size); - memset(ptr, 0, size); - return ptr; -} - -// Die if we can't copy a string to freshly allocated memory. -char* xstrdup(const char *s) -{ - char *t; - if (s == NULL) - return NULL; - - t = strdup(s); - - if (t == NULL) - die_out_of_memory(); - - return t; -} - -// Die if we can't allocate n+1 bytes (space for the null terminator) and copy -// the (possibly truncated to length n) string into it. -char* xstrndup(const char *s, int n) -{ - int m; - char *t; - - /* We can just xmalloc(n+1) and strncpy into it, */ - /* but think about xstrndup("abc", 10000) wastage! */ - m = n; - t = (char*) s; - while (m) - { - if (!*t) break; - m--; - t++; - } - n -= m; - t = (char*) xmalloc(n + 1); - t[n] = '\0'; - - return (char*) memcpy(t, s, n); -} - -void xpipe(int filedes[2]) -{ - if (pipe(filedes)) - perror_msg_and_die("can't create pipe"); -} - -void xdup(int from) -{ - if (dup(from) < 0) - perror_msg_and_die("can't duplicate file descriptor"); -} - -void xdup2(int from, int to) -{ - if (dup2(from, to) != to) - perror_msg_and_die("can't duplicate file descriptor"); -} - -// "Renumber" opened fd -void xmove_fd(int from, int to) -{ - if (from == to) - return; - xdup2(from, to); - close(from); -} - -// Die with an error message if we can't write the entire buffer. -void xwrite(int fd, const void *buf, size_t count) -{ - if (count == 0) - return; - ssize_t size = full_write(fd, buf, count); - if ((size_t)size != count) - error_msg_and_die("short write"); -} - -void xwrite_str(int fd, const char *str) -{ - xwrite(fd, str, strlen(str)); -} - -// Die with an error message if we can't lseek to the right spot. -off_t xlseek(int fd, off_t offset, int whence) -{ - off_t off = lseek(fd, offset, whence); - if (off == (off_t)-1) { - if (whence == SEEK_SET) - perror_msg_and_die("lseek(%llu)", (long long)offset); - perror_msg_and_die("lseek"); - } - return off; -} - -void xchdir(const char *path) -{ - if (chdir(path)) - perror_msg_and_die("chdir(%s)", path); -} - -char* xvasprintf(const char *format, va_list p) -{ - int r; - char *string_ptr; - -#if 1 - // GNU extension - r = vasprintf(&string_ptr, format, p); -#else - // Bloat for systems that haven't got the GNU extension. - va_list p2; - va_copy(p2, p); - r = vsnprintf(NULL, 0, format, p); - string_ptr = xmalloc(r+1); - r = vsnprintf(string_ptr, r+1, format, p2); - va_end(p2); -#endif - - if (r < 0) - die_out_of_memory(); - return string_ptr; -} - -// Die with an error message if we can't malloc() enough space and do an -// sprintf() into that space. -char* xasprintf(const char *format, ...) -{ - va_list p; - char *string_ptr; - - va_start(p, format); - string_ptr = xvasprintf(format, p); - va_end(p); - - return string_ptr; -} - -void xsetenv(const char *key, const char *value) -{ - if (setenv(key, value, 1)) - die_out_of_memory(); -} - -// Die with an error message if we can't open a new socket. -int xsocket(int domain, int type, int protocol) -{ - int r = socket(domain, type, protocol); - if (r < 0) - { - const char *s = "INET"; - if (domain == AF_PACKET) s = "PACKET"; - if (domain == AF_NETLINK) s = "NETLINK"; - if (domain == AF_INET6) s = "INET6"; - perror_msg_and_die("socket(AF_%s)", s); - } - - return r; -} - -// Die with an error message if we can't bind a socket to an address. -void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) -{ - if (bind(sockfd, my_addr, addrlen)) - perror_msg_and_die("bind"); -} - -// Die with an error message if we can't listen for connections on a socket. -void xlisten(int s, int backlog) -{ - if (listen(s, backlog)) - perror_msg_and_die("listen"); -} - -// Die with an error message if sendto failed. -// Return bytes sent otherwise -ssize_t xsendto(int s, const void *buf, size_t len, - const struct sockaddr *to, - socklen_t tolen) -{ - ssize_t ret = sendto(s, buf, len, 0, to, tolen); - if (ret < 0) - { - close(s); - perror_msg_and_die("sendto"); - } - return ret; -} - -// xstat() - a stat() which dies on failure with meaningful error message -void xstat(const char *name, struct stat *stat_buf) -{ - if (stat(name, stat_buf)) - perror_msg_and_die("can't stat '%s'", name); -} - -// Die if we can't open a file and return a fd -int xopen3(const char *pathname, int flags, int mode) -{ - int ret; - ret = open(pathname, flags, mode); - if (ret < 0) - perror_msg_and_die("can't open '%s'", pathname); - return ret; -} - -// Die if we can't open an existing file and return a fd -int xopen(const char *pathname, int flags) -{ - return xopen3(pathname, flags, 0666); -} - -void xunlink(const char *pathname) -{ - if (unlink(pathname)) - perror_msg_and_die("can't remove file '%s'", pathname); -} - -#if 0 //UNUSED -// Warn if we can't open a file and return a fd. -int open3_or_warn(const char *pathname, int flags, int mode) -{ - int ret; - ret = open(pathname, flags, mode); - if (ret < 0) - perror_msg("can't open '%s'", pathname); - return ret; -} - -// Warn if we can't open a file and return a fd. -int open_or_warn(const char *pathname, int flags) -{ - return open3_or_warn(pathname, flags, 0666); -} -#endif - -/* Just testing dent->d_type == DT_REG is wrong: some filesystems - * do not report the type, they report DT_UNKNOWN for every dirent - * (and this is not a bug in filesystem, this is allowed by standards). - */ -int is_regular_file(struct dirent *dent, const char *dirname) -{ - if (dent->d_type == DT_REG) - return 1; - if (dent->d_type != DT_UNKNOWN) - return 0; - - char *fullname = xasprintf("%s/%s", dirname, dent->d_name); - struct stat statbuf; - int r = lstat(fullname, &statbuf); - free(fullname); - - return r == 0 && S_ISREG(statbuf.st_mode); -} - -/* Is it "." or ".."? */ -/* abrtlib candidate */ -bool dot_or_dotdot(const char *filename) -{ - if (filename[0] != '.') return false; - if (filename[1] == '\0') return true; - if (filename[1] != '.') return false; - if (filename[2] == '\0') return true; - return false; -} - -/* Find out if the last character of a string matches the one given. - * Don't underrun the buffer if the string length is 0. - */ -char *last_char_is(const char *s, int c) -{ - if (s && *s) - { - s += strlen(s) - 1; - if ((unsigned char)*s == c) - return (char*)s; - } - return NULL; -} - -bool string_to_bool(const char *s) -{ - if (s[0] == '1' && s[1] == '\0') - return true; - if (strcasecmp(s, "on") == 0) - return true; - if (strcasecmp(s, "yes") == 0) - return true; - if (strcasecmp(s, "true") == 0) - return true; - return false; -} - -void xseteuid(uid_t euid) -{ - if (seteuid(euid) != 0) - perror_msg_and_die("can't set %cid %lu", 'u', (long)euid); -} - -void xsetegid(gid_t egid) -{ - if (setegid(egid) != 0) - perror_msg_and_die("can't set %cid %lu", 'g', (long)egid); -} - -void xsetreuid(uid_t ruid, uid_t euid) -{ - if (setreuid(ruid, euid) != 0) - perror_msg_and_die("can't set %cid %lu", 'u', (long)ruid); -} - -void xsetregid(gid_t rgid, gid_t egid) -{ - if (setregid(rgid, egid) != 0) - perror_msg_and_die("can't set %cid %lu", 'g', (long)rgid); -} - -const char *get_home_dir(uid_t uid) -{ - struct passwd* pw = getpwuid(uid); - // TODO: handle errno - return pw ? pw->pw_dir : NULL; -} diff --git a/scripts/dbg_rpminst b/scripts/dbg_rpminst index 36caab19..b51dbbfc 100755 --- a/scripts/dbg_rpminst +++ b/scripts/dbg_rpminst @@ -8,7 +8,7 @@ exit while rpm -qa | grep abrt >/dev/null; do rpm -qa | grep abrt | while read package; do - echo "$package: rpm -e `basename "$package" .rpm`" + echo "$package: rpm -e `basename "$package" .rpm`" rpm -e "`basename "$package" .rpm`" done done @@ -17,11 +17,11 @@ while true; do r=0 for package in *.rpm; do test -f "$package" || continue - # Is it installed? + # Is it installed? rpm -q "`basename "$package" .rpm`" >/dev/null && continue - # Try to install, record failure - echo "$package: rpm -i `basename "$package" .rpm`" - rpm -i "$package" || r=1 + # Try to install, record failure + echo "$package: rpm -i `basename "$package" .rpm`" + rpm -i "$package" || r=1 done test $r = 0 && break done diff --git a/scripts/dbg_rpmuninst b/scripts/dbg_rpmuninst index 0d0d0736..4232440d 100755 --- a/scripts/dbg_rpmuninst +++ b/scripts/dbg_rpmuninst @@ -6,7 +6,7 @@ exit while rpm -qa | grep abrt >/dev/null; do rpm -qa | grep abrt | while read package; do - echo "$package: rpm -e `basename "$package" .rpm`" + echo "$package: rpm -e `basename "$package" .rpm`" rpm -e "`basename "$package" .rpm`" done done diff --git a/src/Makefile.am b/src/Makefile.am index f6117250..fb4cba28 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1 @@ -SUBDIRS = hooks btparser daemon applet gui cli plugins +SUBDIRS = include lib hooks btparser daemon applet gui cli plugins diff --git a/src/applet/Makefile.am b/src/applet/Makefile.am index 55e28733..32d38b1f 100644 --- a/src/applet/Makefile.am +++ b/src/applet/Makefile.am @@ -5,8 +5,8 @@ abrt_applet_SOURCES = \ applet_gtk.h applet_gtk.c abrt_applet_CPPFLAGS = \ -Wall -Werror \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -I/usr/include/glib-2.0 \ -I/usr/lib/glib-2.0/include \ -DBIN_DIR=\"$(bindir)\" \ @@ -22,7 +22,7 @@ abrt_applet_CPPFLAGS = \ # $(LIBNOTIFY_CFLAGS) # $(DBUS_GLIB_CFLAGS) abrt_applet_LDADD = \ - ../../lib/utils/libABRTUtils.la \ + ../lib/libABRTUtils.la \ -lglib-2.0 \ -lgthread-2.0 \ $(DBUS_LIBS) \ diff --git a/src/btparser/Makefile.am b/src/btparser/Makefile.am index b610f30c..d69a68ba 100644 --- a/src/btparser/Makefile.am +++ b/src/btparser/Makefile.am @@ -13,9 +13,9 @@ libbtparser_la_SOURCES = \ normalize_xorg.c \ thread.h thread.c \ utils.h utils.c -libbtparser_la_CFLAGS = -Wall -Werror -D_GNU_SOURCE -I../../lib/utils +libbtparser_la_CFLAGS = -Wall -Werror -D_GNU_SOURCE -I../lib libbtparser_la_LDFLAGS = -version-info 1:1:0 -libbtparser_la_LIBADD = ../../lib/utils/libABRTUtils.la +libbtparser_la_LIBADD = ../lib/libABRTUtils.la # From http://www.seul.org/docs/autotut/ # Version consists 3 numbers: CURRENT, REVISION, AGE. diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am index be8e7d8e..bbfaa9d0 100644 --- a/src/cli/Makefile.am +++ b/src/cli/Makefile.am @@ -7,8 +7,8 @@ abrt_cli_SOURCES = \ dbus.h dbus.cpp abrt_cli_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DVAR_RUN=\"$(VAR_RUN)\" \ $(ENABLE_SOCKET_OR_DBUS) \ $(DBUS_CFLAGS) $(GLIB_CFLAGS) \ @@ -16,8 +16,8 @@ abrt_cli_CPPFLAGS = \ # $(GTK_CFLAGS) abrt_cli_LDADD = \ - ../../lib/utils/libABRTUtils.la \ - ../../lib/utils/libABRTdUtils.la \ + ../lib/libABRTUtils.la \ + ../lib/libABRTdUtils.la \ $(GLIB_LIBS) man_MANS = abrt-cli.1 diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 072f7f17..a63c014f 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -18,8 +18,8 @@ abrtd_SOURCES = \ Settings.h Settings.cpp \ Daemon.h Daemon.cpp abrtd_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -36,14 +36,14 @@ abrtd_CPPFLAGS = \ abrtd_LDADD = \ $(DL_LIBS) \ $(DBUS_LIBS) \ - ../../lib/utils/libABRTUtils.la \ - ../../lib/utils/libABRTdUtils.la + ../lib/libABRTUtils.la \ + ../lib/libABRTdUtils.la abrt_server_SOURCES = \ abrt-server.c abrt_server_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -54,13 +54,13 @@ abrt_server_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_server_LDADD = \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTUtils.la abrt_handle_crashdump_SOURCES = \ abrt-handle-crashdump.c abrt_handle_crashdump_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -72,15 +72,15 @@ abrt_handle_crashdump_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_handle_crashdump_LDADD = \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTUtils.la abrt_action_save_package_data_SOURCES = \ rpm.h rpm.c \ Settings.h Settings.cpp \ abrt-action-save-package-data.cpp abrt_action_save_package_data_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -95,8 +95,8 @@ abrt_action_save_package_data_CPPFLAGS = \ # polkit_check_authorization is in libABRTdUtils abrt_action_save_package_data_LDADD = \ $(RPM_LIBS) \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/ dist_dbusabrtconf_DATA = dbus-abrt.conf diff --git a/src/hooks/Makefile.am b/src/hooks/Makefile.am index d20fad91..76fe84c9 100644 --- a/src/hooks/Makefile.am +++ b/src/hooks/Makefile.am @@ -5,21 +5,21 @@ bin_PROGRAMS = dumpoops abrt_hook_ccpp_SOURCES = \ abrt-hook-ccpp.c abrt_hook_ccpp_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -D_GNU_SOURCE abrt_hook_ccpp_LDADD = \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTUtils.la # dumpoops dumpoops_SOURCES = \ dumpoops.cpp dumpoops_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -I$(srcdir)/../plugins \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ @@ -30,7 +30,7 @@ dumpoops_CPPFLAGS = \ -D_GNU_SOURCE # build will succeed, but at runtime plugins do need ABRT*d*Utils dumpoops_LDADD = \ - ../../lib/utils/libABRTUtils.la \ + ../lib/libABRTUtils.la \ $(GLIB_FLAGS) python_PYTHON = abrt.pth abrt_exception_handler.py diff --git a/src/include/Makefile.am b/src/include/Makefile.am new file mode 100644 index 00000000..993fa62a --- /dev/null +++ b/src/include/Makefile.am @@ -0,0 +1,18 @@ +HEADER_FILES = \ + abrt_exception.h \ + abrtlib.h \ + abrt_types.h \ + action.h \ + analyzer.h \ + comm_layer_inner.h \ + crash_types.h \ + database.h \ + dbus_common.h \ + dump_dir.h \ + observer.h \ + plugin.h \ + reporter.h \ + xfuncs.h + +lib_includedir=$(includedir)/abrt/ +lib_include_HEADERS = $(HEADER_FILES) diff --git a/src/include/abrt_exception.h b/src/include/abrt_exception.h new file mode 100644 index 00000000..b826bfa8 --- /dev/null +++ b/src/include/abrt_exception.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 ABRTEXCEPTION_H_ +#define ABRTEXCEPTION_H_ + +#include "abrtlib.h" + +typedef enum { + EXCEP_UNKNOW, + EXCEP_DD_OPEN, + EXCEP_DD_LOAD, + EXCEP_DD_SAVE, + EXCEP_DD_DELETE, + EXCEP_DL, + EXCEP_PLUGIN, + EXCEP_ERROR, +} abrt_exception_t; + +/* std::exception is a class with virtual members. + * deriving from it makes our ctor/dtor much more heavy, + * and those are inlined in every throw and catch site! + */ +class CABRTException /*: public std::exception*/ +{ + private: + abrt_exception_t m_type; + char *m_what; + + /* Not defined. You can't use it */ + CABRTException& operator= (const CABRTException&); + + public: + ~CABRTException() { free(m_what); } + CABRTException(abrt_exception_t type, const char* fmt, ...); + CABRTException(const CABRTException& rhs); + + abrt_exception_t type() { return m_type; } + const char* what() const { return m_what; } +}; + +#endif diff --git a/src/include/abrt_types.h b/src/include/abrt_types.h new file mode 100644 index 00000000..38804895 --- /dev/null +++ b/src/include/abrt_types.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2009 Denys Vlasenko (dvlasenk@redhat.com) + Copyright (C) 2009 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 ABRT_TYPES_H_ +#define ABRT_TYPES_H_ + +#ifdef __cplusplus + +#include +#include +#include +#include + +typedef std::vector vector_string_t; +typedef std::set set_string_t; +typedef std::pair pair_string_string_t; +typedef std::map map_string_t; + +typedef std::vector vector_pair_string_string_t; +typedef std::vector vector_map_string_t; +typedef std::map map_map_string_t; +typedef std::map map_vector_string_t; +typedef std::map map_vector_pair_string_string_t; + +/* Report() method return type */ +typedef map_vector_string_t report_status_t; +/* map_vector_string_t's vector element meaning: */ +#define REPORT_STATUS_IDX_FLAG 0 +#define REPORT_STATUS_IDX_MSG 1 +/* Holds result of .conf file section parsing: map["name"] = "value" */ +typedef map_string_t map_plugin_settings_t; + +#endif /* __cplusplus */ + +#endif diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h new file mode 100644 index 00000000..4d565644 --- /dev/null +++ b/src/include/abrtlib.h @@ -0,0 +1,269 @@ +/* + * Utility routines. + * + * Licensed under GPLv2, see file COPYING in this tarball for details. + */ +#ifndef ABRTLIB_H_ +#define ABRTLIB_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* sockaddr_in, sockaddr_in6 etc */ +#include +#include +#include +/* Try to pull in PATH_MAX */ +#include +#include +#ifndef PATH_MAX +# define PATH_MAX 256 +#endif +#include +#include +/* C++ bits */ +#ifdef __cplusplus +# include +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Must be after #include "config.h" */ +#if ENABLE_NLS +# include +# define _(S) gettext(S) +#else +# define _(S) (S) +#endif + +/* Some libc's forget to declare these, do it ourself */ +extern char **environ; +#if defined(__GLIBC__) && __GLIBC__ < 2 +int vdprintf(int d, const char *format, va_list ap); +#endif + +#undef NORETURN +#define NORETURN __attribute__ ((noreturn)) + +#undef ERR_PTR +#define ERR_PTR ((void*)(uintptr_t)1) + +#undef ARRAY_SIZE +#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) + +#include "xfuncs.h" +#include "logging.h" +#include "read_write.h" +#include "strbuf.h" +#include "hash_sha1.h" +#include "hash_md5.h" + +#include "crash_types.h" +#include "dump_dir.h" +#include "abrt_types.h" +#include "abrt_packages.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +int prefixcmp(const char *str, const char *prefix); +int suffixcmp(const char *str, const char *suffix); +char *concat_path_file(const char *path, const char *filename); +char *append_to_malloced_string(char *mstr, const char *append); +char* skip_whitespace(const char *s); +char* skip_non_whitespace(const char *s); +/* Like strcpy but can copy overlapping strings. */ +void overlapping_strcpy(char *dst, const char *src); + +/* A-la fgets, but malloced and of unlimited size */ +char *xmalloc_fgets(FILE *file); +/* Similar, but removes trailing \n */ +char *xmalloc_fgetline(FILE *file); + +/* On error, copyfd_XX prints error messages and returns -1 */ +enum { + COPYFD_SPARSE = 1 << 0, +}; +off_t copyfd_eof(int src_fd, int dst_fd, int flags); +off_t copyfd_size(int src_fd, int dst_fd, off_t size, int flags); +void copyfd_exact_size(int src_fd, int dst_fd, off_t size); +off_t copy_file(const char *src_name, const char *dst_name, int mode); + +/* Returns malloc'ed block */ +char *encode_base64(const void *src, int length); + +unsigned xatou(const char *numstr); +int xatoi(const char *numstr); +/* Using xatoi() instead of naive atoi() is not always convenient - + * in many places people want *non-negative* values, but store them + * in signed int. Therefore we need this one: + * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc */ +int xatoi_u(const char *numstr); + +unsigned long long monotonic_ns(void); +unsigned long long monotonic_us(void); +unsigned monotonic_sec(void); + +enum { + /* on return, pipefds[1] is fd to which parent may write + * and deliver data to child's stdin: */ + EXECFLG_INPUT = 1 << 0, + /* on return, pipefds[0] is fd from which parent may read + * child's stdout: */ + EXECFLG_OUTPUT = 1 << 1, + /* open child's stdin to /dev/null: */ + EXECFLG_INPUT_NUL = 1 << 2, + /* open child's stdout to /dev/null: */ + EXECFLG_OUTPUT_NUL = 1 << 3, + /* redirect child's stderr to stdout: */ + EXECFLG_ERR2OUT = 1 << 4, + /* open child's stderr to /dev/null: */ + EXECFLG_ERR_NUL = 1 << 5, + /* suppress perror_msg("Can't execute 'foo'") if exec fails */ + EXECFLG_QUIET = 1 << 6, + EXECFLG_SETGUID = 1 << 7, + EXECFLG_SETSID = 1 << 8, +}; +/* Returns pid */ +pid_t fork_execv_on_steroids(int flags, + char **argv, + int *pipefds, + char **unsetenv_vec, + const char *dir, + uid_t uid); +/* Returns malloc'ed string. NULs are retained, and extra one is appended + * after the last byte (this NUL is not accounted for in *size_p) */ +char *run_in_shell_and_save_output(int flags, + const char *cmd, + const char *dir, + size_t *size_p); + +/* Networking helpers */ +typedef struct len_and_sockaddr { + socklen_t len; + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } u; +} len_and_sockaddr; +enum { + LSA_LEN_SIZE = offsetof(len_and_sockaddr, u), + LSA_SIZEOF_SA = sizeof(struct sockaddr) > sizeof(struct sockaddr_in6) ? + sizeof(struct sockaddr) : sizeof(struct sockaddr_in6), +}; +void setsockopt_reuseaddr(int fd); +int setsockopt_broadcast(int fd); +int setsockopt_bindtodevice(int fd, const char *iface); +len_and_sockaddr* get_sock_lsa(int fd); +void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen); +unsigned lookup_port(const char *port, const char *protocol, unsigned default_port); +int get_nport(const struct sockaddr *sa); +void set_nport(len_and_sockaddr *lsa, unsigned port); +len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af); +len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t af); +len_and_sockaddr* host2sockaddr(const char *host, int port); +len_and_sockaddr* xhost2sockaddr(const char *host, int port); +len_and_sockaddr* xdotted2sockaddr(const char *host, int port); +int xsocket_type(len_and_sockaddr **lsap, int family, int sock_type); +int xsocket_stream(len_and_sockaddr **lsap); +int create_and_bind_stream_or_die(const char *bindaddr, int port); +int create_and_bind_dgram_or_die(const char *bindaddr, int port); +int create_and_connect_stream_or_die(const char *peer, int port); +int xconnect_stream(const len_and_sockaddr *lsa); +char* xmalloc_sockaddr2host(const struct sockaddr *sa); +char* xmalloc_sockaddr2host_noport(const struct sockaddr *sa); +char* xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa); +char* xmalloc_sockaddr2dotted(const struct sockaddr *sa); +char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa); + +/* Random utility functions */ + +double get_dirsize(const char *pPath); +double get_dirsize_find_largest_dir( + const char *pPath, + char **worst_dir, /* can be NULL */ + const char *excluded /* can be NULL */ +); + +/* Returns command line of running program. + * Caller is responsible to free() the returned value. + * If the pid is not valid or command line can not be obtained, + * empty string is returned. + */ +char* get_cmdline(pid_t pid); + +/* Returns 1 if abrtd daemon is running, 0 otherwise. */ +int daemon_is_ok(); + +struct run_event_state { + int (*post_run_callback)(const char *dump_dir_name, void *param); + void *post_run_param; + char* (*logging_callback)(char *log_line, void *param); + void *logging_param; +}; +static inline struct run_event_state *new_run_event_state() + { return (struct run_event_state*)xzalloc(sizeof(struct run_event_state)); } +static inline void free_run_event_state(struct run_event_state *state) + { free(state); } +int run_event(struct run_event_state *state, const char *dump_dir_name, const char *event); +char *list_possible_events(struct dump_dir *dd, const char *dump_dir_name, const char *pfx); + +#ifdef __cplusplus +} +#endif + + +/* C++ style stuff */ +#ifdef __cplusplus +std::string unsigned_to_string(unsigned long long x); +std::string signed_to_string(long long x); +template inline +std::string to_string(T x) +{ + if ((T)~(T)0 < (T)0) /* T is a signed type */ + return signed_to_string(x); + return unsigned_to_string(x); +} + +void parse_args(const char *psArgs, vector_string_t& pArgs, int quote = -1); +void parse_release(const char *pRelease, char **product, char **version); + +// TODO: npajkovs: full rewrite ssprintf -> xasprintf +static inline std::string ssprintf(const char *format, ...) +{ + va_list p; + char *string_ptr; + + va_start(p, format); + string_ptr = xvasprintf(format, p); + va_end(p); + + std::string res = string_ptr; + free(string_ptr); + return res; +} +#endif + +#endif diff --git a/src/include/action.h b/src/include/action.h new file mode 100644 index 00000000..21183366 --- /dev/null +++ b/src/include/action.h @@ -0,0 +1,44 @@ +/* + Action.h - header file for action plugin + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 ACTION_H_ +#define ACTION_H_ + +#include "plugin.h" + +/** + * An abstract class. The class defines an action plugin interface. + */ +class CAction : public CPlugin +{ + public: + /** + * A Method which performs particular action. As the first parameter it + * takes an action directory. It could be either a directory of actual + * crash or it could be a directory contains all crashes. It depends on + * who call the plugin. The plugin can takes arguments, but the plugin + * has to parse them by itself. + * @param pActionDir An actual directory. + * @param pArgs Plugin's arguments. + */ + virtual void Run(const char *pActionDir, const char *pArgs, int force) = 0; +}; + +#endif diff --git a/src/include/analyzer.h b/src/include/analyzer.h new file mode 100644 index 00000000..1d78d576 --- /dev/null +++ b/src/include/analyzer.h @@ -0,0 +1,34 @@ +/* + Analyzer.h - header file for analyzer plugin + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 ANALYZER_H_ +#define ANALYZER_H_ + +#include +#include "plugin.h" + +/** + * An abstract class. The class defines an analyzer plugin interface. + */ +class CAnalyzer : public CPlugin +{ +}; + +#endif /*ANALYZER_H_*/ diff --git a/src/include/comm_layer_inner.h b/src/include/comm_layer_inner.h new file mode 100644 index 00000000..2cca9add --- /dev/null +++ b/src/include/comm_layer_inner.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 COMMLAYERINNER_H_ +#define COMMLAYERINNER_H_ + +#ifdef __cplusplus + +#include "observer.h" + +void init_daemon_logging(CObserver *pObs); + +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Set client's name (dbus ID). NULL unsets it. + */ +void set_client_name(const char* name); + +/* + * Ask a client to warn the user about a non-fatal, but unexpected condition. + * In GUI, it will usually be presented as a popup message. + * Usually there is no need to call it directly, just use [p]error_msg(). + */ +//now static: +//void warn_client(const char *msg); +//use [p]error_msg[_and_die] instead, it sends the message as a warning to client +//as well as to the log. + +/* + * Logs a message to a client. + * In UI, it will usually appear as a new status line message in GUI, + * or as a new message line in CLI. + */ +void update_client(const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/crash_types.h b/src/include/crash_types.h new file mode 100644 index 00000000..de9f7bf2 --- /dev/null +++ b/src/include/crash_types.h @@ -0,0 +1,133 @@ +/* + Copyright (C) 2009 Abrt team. + Copyright (C) 2009 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 CRASHTYPES_H_ +#define CRASHTYPES_H_ + +#include "abrt_types.h" + +// Keep in sync with CCDump.py: + +// Filenames in dump directory: +// filled by a hook: +#define FILENAME_ANALYZER "analyzer" +#define FILENAME_EXECUTABLE "executable" +#define FILENAME_BINARY "binary" +#define FILENAME_CMDLINE "cmdline" +#define FILENAME_REASON "reason" +#define FILENAME_COREDUMP "coredump" +#define FILENAME_BACKTRACE "backtrace" +#define FILENAME_MEMORYMAP "memorymap" +#define FILENAME_DUPHASH "global_uuid" /* name is compat, to be renamed to "duphash" */ +// Name of the function where the application crashed. +// Optional. +#define FILENAME_CRASH_FUNCTION "crash_function" +// filled by CDebugDump::Create() (which also fills CD_UID): +#define FILENAME_ARCHITECTURE "architecture" +#define FILENAME_KERNEL "kernel" +#define FILENAME_TIME "time" +#define FILENAME_RELEASE "release" /* from /etc/redhat-release */ +// filled by +#define FILENAME_PACKAGE "package" +#define FILENAME_COMPONENT "component" +#define FILENAME_DESCRIPTION "description" /* package descr (not crash descr) */ +#define FILENAME_COMMENT "comment" +#define FILENAME_REPRODUCE "reproduce" +#define FILENAME_RATING "rating" +#define FILENAME_HOSTNAME "hostname" +// Optional. Set to "1" by abrt-handle-upload for every unpacked crashdump +#define FILENAME_REMOTE "remote" +// TODO: TicketUploader also has open-coded "TICKET", "CUSTOMER" files + +// Apart from CD_UID, which is also stored as a file in dump directory, +// these items only exist in db. (CD_UID is also a file because +// dump directory is created before its DB entry, and DB has to learn +// CD_UID from _somewhere_ in order to be able to store it in DB record, +// right?) +#define CD_UID "uid" +// Now uuid also is saved as a file (but is still stored in database too): +#define CD_UUID "uuid" +#define CD_INFORMALL "InformAll" +#define CD_DUMPDIR "DumpDir" +#define CD_COUNT "Count" +#define CD_REPORTED "Reported" +#define CD_MESSAGE "Message" +// "Which events are possible (make sense) on this crash dump?" +// (a string with "\n" terminated event names) +#define CD_EVENTS "Events" + + +// Crash data is a map of 3-element vectors of strings: type, editable, content +#define CD_TYPE 0 +#define CD_EDITABLE 1 +#define CD_CONTENT 2 + +// SYS - system value, should not be displayed +// BIN - binary data +// TXT - text data, can be displayed +#define CD_SYS "s" +#define CD_BIN "b" +#define CD_TXT "t" +// Text bigger than this usually is attached, not added inline +#define CD_TEXT_ATT_SIZE (2*1024) + +#define CD_ISEDITABLE "y" +#define CD_ISNOTEDITABLE "n" + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char *const must_have_files[]; + +bool is_editable_file(const char *file_name); + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus + +// +typedef map_vector_string_t map_crash_data_t; +typedef std::vector vector_map_crash_data_t; + +void add_to_crash_data_ext(map_crash_data_t& pCrashData, + const char *pItem, + const char *pType, + const char *pEditable, + const char *pContent); +// Uses type:CD_TXT, editable:CD_ISNOTEDITABLE +void add_to_crash_data(map_crash_data_t& pCrashData, + const char *pItem, + const char *pContent); + +void load_crash_data_from_debug_dump(struct dump_dir *dd, map_crash_data_t& data); + +const char *get_crash_data_item_content_or_NULL(const map_crash_data_t& crash_data, const char *key); +// Aborts if key is not found: +const std::string& get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key); + +void log_map_crash_data(const map_crash_data_t& data, const char *name); + +#endif /* __cplusplus */ + + +#endif diff --git a/src/include/database.h b/src/include/database.h new file mode 100644 index 00000000..5eaceed7 --- /dev/null +++ b/src/include/database.h @@ -0,0 +1,134 @@ +/* + Database.h - header file for database plugin + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 DATABASE_H_ +#define DATABASE_H_ + +#include + +/** + * Table + * ===== + * UUID | UID| DebugDumpPath | Count | Reported | Time | Message + * + * primary key (UUID, UID) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A struct contains one database row. + */ +struct db_row +{ + char *db_uuid; /**< A local UUID.*/ + char *db_uid; /**< An UID of an user.*/ + char *db_inform_all; + char *db_dump_dir; /**< A debugdump directory of a crash.*/ + char *db_count; /**< Crash rate.*/ + char *db_reported; /**< Is a row reported?*/ + char *db_message; /**< if a row is reported, then there can be store message abotu that*/ + char *db_time; /**< Time of last occurred crash with same local UUID*/ +}; + +void db_row_free(struct db_row *row); + +void db_list_free(GList *list); + +struct db_row *db_rowcpy_from_list(GList* list); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +#include +#include + +#include "plugin.h" + +/** + * An abstract class. The class defines a database plugin interface. + */ +class CDatabase : public CPlugin +{ + public: + /** + * A method, which connects to a database. + */ + virtual void Connect() = 0; + /** + * A method, which disconnects from a database. + */ + virtual void DisConnect() = 0; + /** + * A method, which inserts one row to a database. + * @param pUUID A local UUID of a crash. + * @param pUID An UID of an user. + * @param pDebugDumpPath A debugdump path. + * @param pTime Time when a crash occurs. + */ + virtual void Insert_or_Update(const char *crash_id, + bool inform_all_users, + const char *pDebugDumpPath, + const char *pTime) = 0; + /** + * A method, which deletes one row in a database. + * @param pUUID A lodal UUID of a crash. + * @param pUID An UID of an user. + */ + virtual void DeleteRow(const char *crash_id) = 0; + virtual void DeleteRows_by_dir(const char *dump_dir) = 0; + /** + * A method, which sets that particular row was reported. + * @param pUUID A local UUID of a crash. + * @param pUID An UID of an user. + * @param pMessage A text explanation of reported problem + * (where it is stored etc)... + */ + virtual void SetReported(const char *crash_id, + const char *pMessage) = 0; + virtual void SetReportedPerReporter(const char *crash_id, + const char *reporter, + const char *pMessage) = 0; + /** + * A method, which gets all rows which belongs to particular user. + * If the user is root, then all rows are returned. If there are no + * rows, empty vector is returned. + * @param pUID An UID of an user. + * @return A vector of matched rows. + */ + virtual GList *GetUIDData(long caller_uid) = 0; + /** + * A method, which returns one row accordind to UUID of a crash and + * UID of an user. If there are no row, empty row is returned. + * @param pUUID A UUID of a crash. + * @param pUID An UID of an user. + * @return A matched row. + */ + virtual struct db_row *GetRow(const char *crash_id) = 0; + virtual struct db_row *GetRow_by_dir(const char *dir) = 0; +}; +#endif + +#endif diff --git a/src/include/dbus_common.h b/src/include/dbus_common.h new file mode 100644 index 00000000..63053cc9 --- /dev/null +++ b/src/include/dbus_common.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) + Copyright (C) 2009 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 DBUSCOMMON_H_ +#define DBUSCOMMON_H_ + +#include "crash_types.h" + +#define ABRTD_DBUS_NAME "com.redhat.abrt" +#define ABRTD_DBUS_PATH "/com/redhat/abrt" +#define ABRTD_DBUS_IFACE "com.redhat.abrt" + +#endif diff --git a/src/include/dump_dir.h b/src/include/dump_dir.h new file mode 100644 index 00000000..aeaa3180 --- /dev/null +++ b/src/include/dump_dir.h @@ -0,0 +1,65 @@ +/* + DebugDump.h - header file for the library caring of writing new reports + to the specific directory + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 DEBUGDUMP_H_ +#define DEBUGDUMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + DD_FAIL_QUIETLY = (1 << 0), +}; + +struct dump_dir { + char *dd_dir; + DIR *next_dir; + int locked; + uid_t dd_uid; + gid_t dd_gid; +}; + +void dd_close(struct dump_dir *dd); + +struct dump_dir *dd_opendir(const char *dir, int flags); +struct dump_dir *dd_create(const char *dir, uid_t uid); +int dd_exist(struct dump_dir *dd, const char *path); +DIR *dd_init_next_file(struct dump_dir *dd); +int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name); + +enum { + /* DD_FAIL_QUIETLY bit is valid for dd_load_text_ext too, */ + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE = (1 << 1), +}; +char* dd_load_text_ext(const struct dump_dir *dd, const char* name, unsigned flags); +char* dd_load_text(const struct dump_dir *dd, const char* name); +void dd_save_text(struct dump_dir *dd, const char *name, const char *data); +void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, unsigned size); +void dd_delete(struct dump_dir *dd); + +void delete_debug_dump_dir(const char *dd_dir); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/observer.h b/src/include/observer.h new file mode 100644 index 00000000..1c8f2355 --- /dev/null +++ b/src/include/observer.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 OBSERVER_H_ +#define OBSERVER_H_ + +#include +#include "dbus_common.h" + +class CObserver { + public: + virtual ~CObserver() {} + virtual void Status(const char *pMessage, const char* peer) = 0; + virtual void Warning(const char *pMessage, const char* peer) = 0; +}; + +#endif diff --git a/src/include/plugin.h b/src/include/plugin.h new file mode 100644 index 00000000..e0f45b6c --- /dev/null +++ b/src/include/plugin.h @@ -0,0 +1,135 @@ +/* + Plugin.h - header file for plugin. It contains mandatory macros + and common function for plugins + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 PLUGIN_H_ +#define PLUGIN_H_ + +#include "abrt_types.h" +#include "crash_types.h" + +#define PLUGINS_MAGIC_NUMBER 6 + +#define PLUGINS_CONF_EXTENSION "conf" +#define PLUGINS_LIB_EXTENSION "so" +#define PLUGINS_LIB_PREFIX "lib" + +/** + * An abstract class. The class defines a common plugin interface. If a plugin + * has some settings, then a *Settings(*) method has to be written. + */ +class CPlugin +{ + protected: + map_plugin_settings_t m_pSettings; + + public: + CPlugin(); + /** + * A destructor. + */ + virtual ~CPlugin(); + /** + * A method, which initializes a plugin. It is not mandatory method. + */ + virtual void Init(); + /** + * A method, which deinitializes a plugin. It is not mandatory method. + */ + virtual void DeInit(); + /** + * A method, which takes a settings and apply them. It is not a mandatory method. + * @param pSettings Plugin's settings + */ + virtual void SetSettings(const map_plugin_settings_t& pSettings); + /** + * A method, which return current settings. It is not mandatory method. + * @return Plugin's settings + */ +/// +// virtual const map_plugin_settings_t& GetSettings(); +}; + +/** + * An enum of plugin types. + */ +typedef enum { + ANALYZER, /**< An analyzer plugin*/ + ACTION, /**< An action plugin*/ + REPORTER, /**< A reporter plugin*/ + DATABASE, /**< A database plugin*/ + MAX_PLUGIN_TYPE = DATABASE, +} plugin_type_t; + +/** + * A struct contains all needed data about particular plugin. + */ +typedef struct SPluginInfo +{ + const plugin_type_t m_Type; /**< Plugin type.*/ + const char *const m_sName; /**< Plugin name.*/ + const char *const m_sVersion; /**< Plugin version.*/ + const char *const m_sDescription; /**< Plugin description.*/ + const char *const m_sEmail; /**< Plugin author's email.*/ + const char *const m_sWWW; /**< Plugin's home page.*/ + const char *const m_sGTKBuilder; /**< Plugin's gui description.*/ + const int m_nMagicNumber; /**< Plugin magical number.*/ +} plugin_info_t; + +#define PLUGIN_INFO(type, plugin_class, name, version, description, email, www, gtk_builder)\ + extern "C" CPlugin* plugin_new()\ + {\ + return new plugin_class();\ + }\ + extern "C" const plugin_info_t plugin_info =\ + {\ + type,\ + name,\ + version,\ + description,\ + email,\ + www,\ + gtk_builder,\ + PLUGINS_MAGIC_NUMBER,\ + }; + +/* helper functions */ +char* make_description_bz(const map_crash_data_t& pCrashData); +char* make_description_reproduce_comment(const map_crash_data_t& pCrashData); +char* make_description_logger(const map_crash_data_t& pCrashData); +char* make_dsc_mailx(const map_crash_data_t& pCrashData); + +/** + * Loads settings and stores it in second parameter. On success it + * returns true, otherwise returns false. + * + * @param path A path of config file. + * Config file consists of "key=value" lines. + * @param settings A readed plugin's settings. + * @param skipKeysWithoutValue + * If true, lines in format "key=" (without value) are skipped. + * Otherwise empty value "" is inserted into pSettings. + * @return if it success it returns true, otherwise it returns false. + */ +extern bool LoadPluginSettings(const char *pPath, + map_plugin_settings_t& pSettings, + bool skipKeysWithoutValue = true); + +#endif diff --git a/src/include/reporter.h b/src/include/reporter.h new file mode 100644 index 00000000..469e828e --- /dev/null +++ b/src/include/reporter.h @@ -0,0 +1,48 @@ +/* + Reporter.h - header file for reporter plugin + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 REPORTER_H_ +#define REPORTER_H_ + +#include +#include "plugin.h" +#include "crash_types.h" + +/** + * An abstract class. The class defines a reporter plugin interface. + */ +class CReporter : public CPlugin +{ + public: + /** + * A method, which reports a crash report to particular receiver. + * The plugin can takes arguments, but the plugin has to parse them + * by itself. + * @param pCrashData A crash report. + * @param pArgs Plugin's arguments. + * @retun A message which can be displayed after a report is created. + */ +/// +// virtual std::string Report(const map_crash_data_t& pCrashData, +// const map_plugin_settings_t& pSettings, +// const char *pArgs) = 0; +}; + +#endif /* REPORTER_H_ */ diff --git a/src/include/xfuncs.h b/src/include/xfuncs.h new file mode 100644 index 00000000..20284564 --- /dev/null +++ b/src/include/xfuncs.h @@ -0,0 +1,95 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 ABRT_XFUNCS_H +#define ABRT_XFUNCS_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int ndelay_on(int fd); +int ndelay_off(int fd); +int close_on_exec_on(int fd); + +void* xcalloc(size_t nmemb, size_t size); +void* xmalloc(size_t size); +void* xrealloc(void *ptr, size_t size); +void* xzalloc(size_t size); +char* xstrdup(const char *s); +char* xstrndup(const char *s, int n); + +void xpipe(int filedes[2]); +void xdup(int from); +void xdup2(int from, int to); +void xmove_fd(int from, int to); + +void xwrite(int fd, const void *buf, size_t count); +void xwrite_str(int fd, const char *str); + +off_t xlseek(int fd, off_t offset, int whence); + +void xchdir(const char *path); + +char* xvasprintf(const char *format, va_list p); +char* xasprintf(const char *format, ...); + +void xsetenv(const char *key, const char *value); +int xsocket(int domain, int type, int protocol); +void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); +void xlisten(int s, int backlog); +ssize_t xsendto(int s, const void *buf, size_t len, + const struct sockaddr *to, socklen_t tolen); + +void xstat(const char *name, struct stat *stat_buf); + +int xopen3(const char *pathname, int flags, int mode); +int xopen(const char *pathname, int flags); +void xunlink(const char *pathname); + +/* Just testing dent->d_type == DT_REG is wrong: some filesystems + * do not report the type, they report DT_UNKNOWN for every dirent + * (and this is not a bug in filesystem, this is allowed by standards). + * This function handles this case. Note: it returns 0 on symlinks + * even if they point to regular files. + */ +int is_regular_file(struct dirent *dent, const char *dirname); +bool dot_or_dotdot(const char *filename); +char *last_char_is(const char *s, int c); + +bool string_to_bool(const char *s); + +void xseteuid(uid_t euid); +void xsetegid(gid_t egid); +void xsetreuid(uid_t ruid, uid_t euid); +void xsetregid(gid_t rgid, gid_t egid); + +/* Returns getpwuid(uid)->pw_dir or NULL */ +const char *get_home_dir(uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/ABRTException.cpp b/src/lib/ABRTException.cpp new file mode 100644 index 00000000..0ae5d452 --- /dev/null +++ b/src/lib/ABRTException.cpp @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 "abrt_exception.h" + +CABRTException::CABRTException(abrt_exception_t type, const char* fmt, ...) +{ + m_type = type; + va_list ap; + va_start(ap, fmt); + m_what = xvasprintf(fmt, ap); + va_end(ap); +} + +CABRTException::CABRTException(const CABRTException& rhs): + m_type(rhs.m_type), + m_what(xstrdup(rhs.m_what)) +{} diff --git a/src/lib/CommLayerInner.cpp b/src/lib/CommLayerInner.cpp new file mode 100644 index 00000000..3c102d6e --- /dev/null +++ b/src/lib/CommLayerInner.cpp @@ -0,0 +1,94 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 +#include +#include "abrtlib.h" +#include "comm_layer_inner.h" + +static CObserver *s_pObs; + +typedef std::map map_uint_str_t; +static map_uint_str_t s_mapClientID; +static pthread_mutex_t s_map_mutex; +static bool s_map_mutex_inited; + +/* called via [p]error_msg() */ +static void warn_client(const char *msg) +{ + if (!s_pObs) + return; + + uint64_t key = uint64_t(pthread_self()); + + pthread_mutex_lock(&s_map_mutex); + map_uint_str_t::const_iterator ki = s_mapClientID.find(key); + const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); + pthread_mutex_unlock(&s_map_mutex); + + if (peer) + s_pObs->Warning(msg, peer); +} + +void init_daemon_logging(CObserver *pObs) +{ + s_pObs = pObs; + if (!s_map_mutex_inited) + { + s_map_mutex_inited = true; + pthread_mutex_init(&s_map_mutex, NULL); + g_custom_logger = &warn_client; + } +} + +void set_client_name(const char *name) +{ + uint64_t key = uint64_t(pthread_self()); + + pthread_mutex_lock(&s_map_mutex); + if (!name) { + s_mapClientID.erase(key); + } else { + s_mapClientID[key] = name; + } + pthread_mutex_unlock(&s_map_mutex); +} + +void update_client(const char *fmt, ...) +{ + if (!s_pObs) + return; + + uint64_t key = uint64_t(pthread_self()); + + pthread_mutex_lock(&s_map_mutex); + map_uint_str_t::const_iterator ki = s_mapClientID.find(key); + const char* peer = (ki != s_mapClientID.end() ? ki->second.c_str() : NULL); + pthread_mutex_unlock(&s_map_mutex); + + if (!peer) + return; + + va_list p; + va_start(p, fmt); + char *msg = xvasprintf(fmt, p); + va_end(p); + + s_pObs->Status(msg, peer); + free(msg); +} diff --git a/src/lib/CrashTypes.cpp b/src/lib/CrashTypes.cpp new file mode 100644 index 00000000..acacda5e --- /dev/null +++ b/src/lib/CrashTypes.cpp @@ -0,0 +1,254 @@ +/* + Copyright (C) 2010 Denys Vlasenko (dvlasenk@redhat.com) + Copyright (C) 2010 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 "crash_types.h" + +const char *const must_have_files[] = { + FILENAME_ARCHITECTURE, + FILENAME_KERNEL , + FILENAME_PACKAGE , + FILENAME_COMPONENT , + FILENAME_RELEASE , + FILENAME_EXECUTABLE , + NULL +}; + +static const char *const editable_files[] = { + FILENAME_DESCRIPTION, + FILENAME_COMMENT , + FILENAME_REPRODUCE , + FILENAME_BACKTRACE , + NULL +}; + +static bool is_editable(const char *name, const char *const *v) +{ + while (*v) { + if (strcmp(*v, name) == 0) + return true; + v++; + } + return false; +} + +bool is_editable_file(const char *file_name) +{ + return is_editable(file_name, editable_files); +} + + +void add_to_crash_data_ext(map_crash_data_t& pCrashData, + const char *pItem, + const char *pType, + const char *pEditable, + const char *pContent) +{ + map_crash_data_t::iterator it = pCrashData.find(pItem); + if (it == pCrashData.end()) { + vector_string_t& v = pCrashData[pItem]; /* create empty vector */ + v.push_back(pType); + v.push_back(pEditable); + v.push_back(pContent); + return; + } + vector_string_t& v = it->second; + while (v.size() < 3) + v.push_back(""); + v[CD_TYPE] = pType; + v[CD_EDITABLE] = pEditable; + v[CD_CONTENT] = pContent; +} + +void add_to_crash_data(map_crash_data_t& pCrashData, + const char *pItem, + const char *pContent) +{ + add_to_crash_data_ext(pCrashData, pItem, CD_TXT, CD_ISNOTEDITABLE, pContent); +} + +static char* is_text_file(const char *name, ssize_t *sz) +{ + /* We were using magic.h API to check for file being text, but it thinks + * that file containing just "0" is not text (!!) + * So, we do it ourself. + */ + + int fd = open(name, O_RDONLY); + if (fd < 0) + return NULL; /* it's not text (because it does not exist! :) */ + + /* Maybe 64k limit is small. But _some_ limit is necessary: + * fields declared "text" may end up in editing fields and such. + * We don't want to accidentally end up with 100meg text in a textbox! + * So, don't remove this. If you really need to, raise the limit. + */ + off_t size = lseek(fd, 0, SEEK_END); + if (size < 0 || size > 64*1024) + { + close(fd); + return NULL; /* it's not a SMALL text */ + } + lseek(fd, 0, SEEK_SET); + + char *buf = (char*)xmalloc(*sz); + ssize_t r = *sz = full_read(fd, buf, *sz); + close(fd); + if (r < 0) + { + free(buf); + return NULL; /* it's not text (because we can't read it) */ + } + + /* Some files in our dump directories are known to always be textual */ + const char *base = strrchr(name, '/'); + if (base) + { + base++; + if (strcmp(base, FILENAME_BACKTRACE) == 0 + || strcmp(base, FILENAME_CMDLINE) == 0 + ) { + return buf; + } + } + + /* Every once in a while, even a text file contains a few garbled + * or unexpected non-ASCII chars. We should not declare it "binary". + */ + const unsigned RATIO = 50; + unsigned total_chars = r + RATIO; + unsigned bad_chars = 1; /* 1 prevents division by 0 later */ + while (--r >= 0) + { + if (buf[r] >= 0x7f + /* among control chars, only '\t','\n' etc are allowed */ + || (buf[r] < ' ' && !isspace(buf[r])) + ) { + if (buf[r] == '\0') + { + /* We don't like NULs very much. Not text for sure! */ + free(buf); + return NULL; + } + bad_chars++; + } + } + + if ((total_chars / bad_chars) >= RATIO) + return buf; /* looks like text to me */ + + free(buf); + return NULL; /* it's binary */ +} + +void load_crash_data_from_debug_dump(struct dump_dir *dd, map_crash_data_t& data) +{ + char *short_name; + char *full_name; + + dd_init_next_file(dd); + while (dd_get_next_file(dd, &short_name, &full_name)) + { + ssize_t sz = 4*1024; + char *text = NULL; + bool editable = is_editable_file(short_name); + + if (!editable) + { + text = is_text_file(full_name, &sz); + if (!text) + { + add_to_crash_data_ext(data, + short_name, + CD_BIN, + CD_ISNOTEDITABLE, + full_name + ); + + free(short_name); + free(full_name); + continue; + } + } + + char *content; + if (sz < 4*1024) /* is_text_file did read entire file */ + content = xstrndup(text, sz); //TODO: can avoid this copying if is_text_file() adds NUL + else /* no, need to read it all */ + content = dd_load_text(dd, short_name); + free(text); + + add_to_crash_data_ext(data, + short_name, + CD_TXT, + editable ? CD_ISEDITABLE : CD_ISNOTEDITABLE, + content + ); + free(short_name); + free(full_name); + free(content); + } +} + +static const std::string* helper_get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key) +{ + map_crash_data_t::const_iterator it = crash_data.find(key); + if (it == crash_data.end()) { + return NULL; + } + if (it->second.size() <= CD_CONTENT) { + return NULL; + } + return &it->second[CD_CONTENT]; +} + +const std::string& get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key) +{ + const std::string* sp = helper_get_crash_data_item_content(crash_data, key); + if (sp == NULL) { + if (crash_data.find(key) == crash_data.end()) + error_msg_and_die("Error accessing crash data: no ['%s']", key); + error_msg_and_die("Error accessing crash data: no ['%s'][%d]", key, CD_CONTENT); + } + return *sp; +} + +const char *get_crash_data_item_content_or_NULL(const map_crash_data_t& crash_data, const char *key) +{ + const std::string* sp = helper_get_crash_data_item_content(crash_data, key); + if (!sp) { + return NULL; + } + return sp->c_str(); +} + +void log_map_crash_data(const map_crash_data_t& data, const char *name) +{ + map_crash_data_t::const_iterator it = data.begin(); + while (it != data.end()) + { + ssize_t sz = it->second.size(); + log("%s[%s]:%s/%s/'%.20s'", + name, it->first.c_str(), + sz > 0 ? it->second[0].c_str() : "", + sz > 1 ? it->second[1].c_str() : "", + sz > 2 ? it->second[2].c_str() : "" + ); + it++; + } +} diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 00000000..153af2d0 --- /dev/null +++ b/src/lib/Makefile.am @@ -0,0 +1,109 @@ +# ABRTUtils has small set of deps. This reduces deps of smaller abrt binaries +# ABRTdUtils has much more. It is used by daemon and plugins only +# ABRT_web_utils is used only by some abrt-action-foo programs, not by daemon +lib_LTLIBRARIES = \ + libABRTUtils.la \ + libABRTdUtils.la \ + libABRT_web_utils.la +HEADER_DIR = $(srcdir)/../include +AM_CPPFLAGS = -I$(HEADER_DIR) + +# Not used just yet: +# time.cpp +# xconnect.cpp + +libABRTUtils_la_SOURCES = \ + xfuncs.c \ + concat_path_file.c \ + append_to_malloced_string.c \ + overlapping_strcpy.c \ + encbase64.c \ + stdio_helpers.c \ + hash_md5.c hash_md5.h \ + hash_sha1.c hash_sha1.h \ + read_write.c read_write.h \ + logging.c logging.h \ + copyfd.c \ + daemon.c \ + skip_whitespace.c \ + xatonum.c numtoa.cpp \ + spawn.c \ + stringops.cpp \ + dirsize.c \ + dump_dir.c \ + strbuf.c strbuf.h \ + abrt_dbus.c abrt_dbus.h \ + CrashTypes.cpp \ + ABRTException.cpp \ + run_event.c \ + abrt_packages.c abrt_packages.h \ + hooklib.c hooklib.h \ + database.c \ + parse_options.c parse_options.h +libABRTUtils_la_CPPFLAGS = \ + -Wall -Werror \ + -I$(srcdir)/../include \ + -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ + -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ + -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ + -DCONF_DIR=\"$(CONF_DIR)\" \ + -DVAR_RUN=\"$(VAR_RUN)\" \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) \ + -D_GNU_SOURCE +libABRTUtils_la_LDFLAGS = \ + -version-info 0:1:0 +libABRTUtils_la_LIBADD = \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) \ + -ldl + +libABRTdUtils_la_SOURCES = \ + parse_release.cpp \ + make_descr.cpp \ + $(HEADER_DIR)/comm_layer_inner.h CommLayerInner.cpp \ + $(HEADER_DIR)/plugin.h Plugin.cpp \ + Polkit.h Polkit.cpp +libABRTdUtils_la_CPPFLAGS = \ + -Wall -Werror \ + -I$(srcdir)/../include \ + -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ + -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ + -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ + -DCONF_DIR=\"$(CONF_DIR)\" \ + -DVAR_RUN=\"$(VAR_RUN)\" \ + $(POLKIT_CFLAGS) \ + -D_GNU_SOURCE +libABRTdUtils_la_LDFLAGS = \ + -version-info 0:1:0 +libABRTdUtils_la_LIBADD = \ + $(POLKIT_LIBS) \ + -ldl + +libABRT_web_utils_la_SOURCES = \ + abrt_curl.h abrt_curl.c \ + abrt_xmlrpc.h abrt_xmlrpc.cpp +libABRT_web_utils_la_CPPFLAGS = \ + -Wall -Werror \ + -I$(srcdir)/../include \ + -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ + -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ + -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ + -DCONF_DIR=\"$(CONF_DIR)\" \ + -DVAR_RUN=\"$(VAR_RUN)\" \ + $(CURL_CFLAGS) \ + $(LIBXML_CFLAGS) \ + $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \ + -D_GNU_SOURCE +libABRT_web_utils_la_LDFLAGS = \ + -version-info 0:1:0 +libABRT_web_utils_la_LIBADD = \ + $(CURL_LIBS) \ + $(LIBXML_LIBS) \ + $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) + +$(DESTDIR)/$(DEBUG_DUMPS_DIR): + $(mkdir_p) '$@' +# no need to chmod it here +#chmod 1777 '$@' +install-data-local: $(DESTDIR)/$(DEBUG_DUMPS_DIR) diff --git a/src/lib/Plugin.cpp b/src/lib/Plugin.cpp new file mode 100644 index 00000000..bf237959 --- /dev/null +++ b/src/lib/Plugin.cpp @@ -0,0 +1,116 @@ +/* + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 "plugin.h" +#include "abrtlib.h" + +CPlugin::CPlugin() {} + +/* class CPlugin's virtuals */ +CPlugin::~CPlugin() {} +void CPlugin::Init() {} +void CPlugin::DeInit() {} +void CPlugin::SetSettings(const map_plugin_settings_t& pSettings) +{ + m_pSettings = pSettings; + VERB3 + { + log("SetSettings:"); + map_plugin_settings_t::const_iterator it = m_pSettings.begin(); + while (it != m_pSettings.end()) + { + log(" settings[%s]='%s'", it->first.c_str(), it->second.c_str()); + it++; + } + } +} + +bool LoadPluginSettings(const char *pPath, map_plugin_settings_t& pSettings, + bool skipKeysWithoutValue /*= true*/) +{ + FILE *fp = stdin; + if (strcmp(pPath, "-") != 0) + { + fp = fopen(pPath, "r"); + if (!fp) + return false; + } + + char *line; + while ((line = xmalloc_fgetline(fp)) != NULL) + { + unsigned ii; + bool is_value = false; + bool valid = false; + bool in_quote = false; + std::string key; + std::string value; + for (ii = 0; line[ii] != '\0'; ii++) + { + if (line[ii] == '"') + { + in_quote = !in_quote; + } + if (isspace(line[ii]) && !in_quote) + { + continue; + } + if (line[ii] == '#' && !in_quote && key == "") + { + break; + } + if (line[ii] == '=' && !in_quote) + { + is_value = true; + valid = true; + continue; + } + if (!is_value) + { + key += line[ii]; + } + else + { + value += line[ii]; + } + } + + /* Skip broken or empty lines. */ + if (!valid) + goto free_line; + + /* Skip lines with empty key. */ + if (key.length() == 0) + goto free_line; + + if (skipKeysWithoutValue && value.length() == 0) + goto free_line; + + /* Skip lines with unclosed quotes. */ + if (in_quote) + goto free_line; + + pSettings[key] = value; + free_line: + free(line); + } + + if (fp != stdin) + fclose(fp); + return true; +} diff --git a/src/lib/Polkit.cpp b/src/lib/Polkit.cpp new file mode 100644 index 00000000..a5e07760 --- /dev/null +++ b/src/lib/Polkit.cpp @@ -0,0 +1,102 @@ +/* + Polkit.cpp - PolicyKit integration for ABRT + + Copyright (C) 2009 Daniel Novotny (dnovotny@redhat.com) + Copyright (C) 2009 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 +#include +#include +#include + +#include "Polkit.h" +#include "abrtlib.h" + +/*number of seconds: timeout for the authorization*/ +#define POLKIT_TIMEOUT 20 + +static gboolean do_cancel(GCancellable* cancellable) +{ + log("Timer has expired; cancelling authorization check\n"); + g_cancellable_cancel(cancellable); + return FALSE; +} + + +static PolkitResult do_check(PolkitSubject *subject, const char *action_id) +{ + PolkitAuthority *authority; + PolkitAuthorizationResult *result; + GError *error = NULL; + GCancellable * cancellable; + + authority = polkit_authority_get(); + cancellable = g_cancellable_new(); + + guint cancel_timeout = g_timeout_add(POLKIT_TIMEOUT * 1000, + (GSourceFunc) do_cancel, + cancellable); + + result = polkit_authority_check_authorization_sync(authority, + subject, + action_id, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + cancellable, + &error); + g_object_unref(authority); + g_source_remove(cancel_timeout); + if (error) + { + g_error_free(error); + return PolkitUnknown; + } + + if (result) + { + if (polkit_authorization_result_get_is_challenge(result)) + { + /* Can't happen (happens only with + * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */ + g_object_unref(result); + return PolkitChallenge; + } + if (polkit_authorization_result_get_is_authorized(result)) + { + g_object_unref(result); + return PolkitYes; + } + g_object_unref(result); + return PolkitNo; + } + + return PolkitUnknown; +} + +PolkitResult polkit_check_authorization(const char *dbus_name, const char *action_id) +{ + g_type_init(); + PolkitSubject *subject = polkit_system_bus_name_new(dbus_name); + return do_check(subject, action_id); +} + +PolkitResult polkit_check_authorization(pid_t pid, const char *action_id) +{ + g_type_init(); + PolkitSubject *subject = polkit_unix_process_new(pid); + return do_check(subject, action_id); +} diff --git a/src/lib/Polkit.h b/src/lib/Polkit.h new file mode 100644 index 00000000..d9e097ac --- /dev/null +++ b/src/lib/Polkit.h @@ -0,0 +1,42 @@ +/* + Polkit.h - header file for PolicyKit integration + + Copyright (C) 2009 Daniel Novotny (dnovotny@redhat.com) + Copyright (C) 2009 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 ABRT_POLKIT_H +#define ABRT_POLKIT_H + +#include +#include + +typedef enum { +/* Authorization status is unknown */ + PolkitUnknown = 0x0, + /* Subject is authorized for the action */ + PolkitYes = 0x01, + /* Subject is not authorized for the action */ + PolkitNo = 0x02, + /* Challenge is needed for this action, only when flag is + * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE */ + PolkitChallenge = 0x03 +} PolkitResult; + +PolkitResult polkit_check_authorization(const char *dbus_name, const char *action_id); +PolkitResult polkit_check_authorization(pid_t pid, const char *action_id); + +#endif diff --git a/src/lib/abrt_curl.c b/src/lib/abrt_curl.c new file mode 100644 index 00000000..f23d3949 --- /dev/null +++ b/src/lib/abrt_curl.c @@ -0,0 +1,375 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 "abrt_curl.h" + +/* + * Utility functions + */ +CURL* xcurl_easy_init() +{ + CURL* curl = curl_easy_init(); + if (!curl) + { + error_msg_and_die("Can't create curl handle"); + } + return curl; +} + +static char* +check_curl_error(CURLcode err, const char* msg) +{ + if (err) + return xasprintf("%s: %s", msg, curl_easy_strerror(err)); + return NULL; +} + +static void +die_if_curl_error(CURLcode err) +{ + if (err) { + char *msg = check_curl_error(err, "curl"); + error_msg_and_die("%s", msg); + } +} + +static void +xcurl_easy_setopt_ptr(CURL *handle, CURLoption option, const void *parameter) +{ + CURLcode err = curl_easy_setopt(handle, option, parameter); + if (err) { + char *msg = check_curl_error(err, "curl"); + error_msg_and_die("%s", msg); + } +} +static inline void +xcurl_easy_setopt_long(CURL *handle, CURLoption option, long parameter) +{ + xcurl_easy_setopt_ptr(handle, option, (void*)parameter); +} + +/* + * post_state utility functions + */ + +abrt_post_state_t *new_abrt_post_state(int flags) +{ + abrt_post_state_t *state = (abrt_post_state_t *)xzalloc(sizeof(*state)); + state->flags = flags; + return state; +} + +void free_abrt_post_state(abrt_post_state_t *state) +{ + char **headers = state->headers; + if (headers) + { + while (*headers) + free(*headers++); + free(state->headers); + } + free(state->curl_error_msg); + free(state->body); + free(state); +} + +char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char *str) +{ + char **headers = state->headers; + if (headers) + { + unsigned len = strlen(str); + while (*headers) + { + if (strncmp(*headers, str, len) == 0) + return skip_whitespace(*headers + len); + headers++; + } + } + return NULL; +} + +/* + * abrt_post: perform HTTP POST transaction + */ + +/* "save headers" callback */ +static size_t +save_headers(void *buffer_pv, size_t count, size_t nmemb, void *ptr) +{ + abrt_post_state_t* state = (abrt_post_state_t*)ptr; + size_t size = count * nmemb; + + char *h = xstrndup((char*)buffer_pv, size); + strchrnul(h, '\r')[0] = '\0'; + strchrnul(h, '\n')[0] = '\0'; + + unsigned cnt = state->header_cnt; + + /* Check for the case when curl follows a redirect: + * header 0: 'HTTP/1.1 301 Moved Permanently' + * header 1: 'Connection: close' + * header 2: 'Location: NEW_URL' + * header 3: '' + * header 0: 'HTTP/1.1 200 OK' <-- we need to forget all hdrs and start anew + */ + if (cnt != 0 + && strncmp(h, "HTTP/", 5) == 0 + && state->headers[cnt-1][0] == '\0' /* prev header is an empty string */ + ) { + char **headers = state->headers; + if (headers) + { + while (*headers) + free(*headers++); + } + cnt = 0; + } + + VERB3 log("save_headers: header %d: '%s'", cnt, h); + state->headers = (char**)xrealloc(state->headers, (cnt+2) * sizeof(state->headers[0])); + state->headers[cnt] = h; + state->header_cnt = ++cnt; + state->headers[cnt] = NULL; + + return size; +} + +/* "read local data from a file" callback */ +static size_t fread_with_reporting(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + static time_t last_t; // hack + + FILE *fp = (FILE*)userdata; + time_t t = time(NULL); + + // Report current file position every 16 seconds + if (!(t & 0xf) && last_t != t) + { + last_t = t; + off_t cur_pos = ftello(fp); + fseeko(fp, 0, SEEK_END); + off_t sz = ftello(fp); + fseeko(fp, cur_pos, SEEK_SET); + log(_("Uploaded: %llu of %llu kbytes"), + (unsigned long long)cur_pos / 1024, + (unsigned long long)sz / 1024); + } + + return fread(ptr, size, nmemb, fp); +} + +int +abrt_post(abrt_post_state_t *state, + const char *url, + const char *content_type, + const char *data, + off_t data_size) +{ + CURLcode curl_err; + long response_code; + abrt_post_state_t localstate; + + VERB3 log("abrt_post('%s','%s')", url, data); + + if (!state) + { + memset(&localstate, 0, sizeof(localstate)); + state = &localstate; + } + + state->http_resp_code = response_code = -1; + + CURL *handle = xcurl_easy_init(); + + // Buffer[CURL_ERROR_SIZE] curl stores human readable error messages in. + // This may be more helpful than just return code from curl_easy_perform. + // curl will need it until curl_easy_cleanup. + state->errmsg[0] = '\0'; + xcurl_easy_setopt_ptr(handle, CURLOPT_ERRORBUFFER, state->errmsg); + // "Display a lot of verbose information about its operations. + // Very useful for libcurl and/or protocol debugging and understanding. + // The verbose information will be sent to stderr, or the stream set + // with CURLOPT_STDERR" + //xcurl_easy_setopt_long(handle, CURLOPT_VERBOSE, 1); + // Shut off the built-in progress meter completely + xcurl_easy_setopt_long(handle, CURLOPT_NOPROGRESS, 1); + + // TODO: do we need to check for CURLE_URL_MALFORMAT error *here*, + // not in curl_easy_perform? + xcurl_easy_setopt_ptr(handle, CURLOPT_URL, url); + + // Auth if configured + if (state->username) { + // bitmask of allowed auth methods + xcurl_easy_setopt_long(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + xcurl_easy_setopt_ptr(handle, CURLOPT_USERNAME, state->username); + xcurl_easy_setopt_ptr(handle, CURLOPT_PASSWORD, (state->password ? state->password : "")); + } + + // Do a regular HTTP post. This also makes curl use + // a "Content-Type: application/x-www-form-urlencoded" header. + // (This is by far the most commonly used POST method). + xcurl_easy_setopt_long(handle, CURLOPT_POST, 1); + // Supply POST data... + struct curl_httppost* post = NULL; + struct curl_httppost* last = NULL; + FILE* data_file = NULL; + if (data_size == ABRT_POST_DATA_FROMFILE) { + // ...from a file + data_file = fopen(data, "r"); + if (!data_file) +//FIXME: + perror_msg_and_die("can't open '%s'", data); + xcurl_easy_setopt_ptr(handle, CURLOPT_READDATA, data_file); + // Want to use custom read function + xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const void*)fread_with_reporting); + } else if (data_size == ABRT_POST_DATA_FROMFILE_AS_FORM_DATA) { + // ...from a file, in multipart/formdata format + const char *basename = strrchr(data, '/'); + if (basename) basename++; + else basename = data; +#if 0 + // Simple way, without custom reader function + CURLFORMcode curlform_err = curl_formadd(&post, &last, + CURLFORM_PTRNAME, "file", // element name + CURLFORM_FILE, data, // filename to read from + CURLFORM_CONTENTTYPE, content_type, + CURLFORM_FILENAME, basename, // filename to put in the form + CURLFORM_END); +#else + data_file = fopen(data, "r"); + if (!data_file) +//FIXME: + perror_msg_and_die("can't open '%s'", data); + // Want to use custom read function + xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const void*)fread_with_reporting); + // Need to know file size + fseeko(data_file, 0, SEEK_END); + off_t sz = ftello(data_file); + fseeko(data_file, 0, SEEK_SET); + // Create formdata + CURLFORMcode curlform_err = curl_formadd(&post, &last, + CURLFORM_PTRNAME, "file", // element name + // use CURLOPT_READFUNCTION for reading, pass data_file as its last param: + CURLFORM_STREAM, data_file, + CURLFORM_CONTENTSLENGTH, (long)sz, // a must if we use CURLFORM_STREAM option + CURLFORM_CONTENTTYPE, content_type, + CURLFORM_FILENAME, basename, // filename to put in the form + CURLFORM_END); +#endif + if (curlform_err != 0) +//FIXME: + error_msg_and_die("out of memory or read error (curl_formadd error code: %d)", (int)curlform_err); + xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post); + } else { + // .. from a blob in memory + xcurl_easy_setopt_ptr(handle, CURLOPT_POSTFIELDS, data); + // note1: if data_size == ABRT_POST_DATA_STRING == -1, curl will use strlen(data) + xcurl_easy_setopt_long(handle, CURLOPT_POSTFIELDSIZE, data_size); + // note2: CURLOPT_POSTFIELDSIZE_LARGE can't be used: xcurl_easy_setopt_long() + // truncates data_size on 32-bit arch. Need xcurl_easy_setopt_long_long()? + // Also, I'm not sure CURLOPT_POSTFIELDSIZE_LARGE special-cases -1. + } + // Override "Content-Type:" + struct curl_slist *httpheader_list = NULL; + if (data_size != ABRT_POST_DATA_FROMFILE_AS_FORM_DATA) + { + char *content_type_header = xasprintf("Content-Type: %s", content_type); + // Note: curl_slist_append() copies content_type_header + httpheader_list = curl_slist_append(httpheader_list, content_type_header); + if (!httpheader_list) + error_msg_and_die("out of memory"); + free(content_type_header); + xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPHEADER, httpheader_list); + } + +// Disabled: was observed to also handle "305 Use proxy" redirect, +// apparently with POST->GET remapping - which server didn't like at all. +// Attempted to suppress remapping on 305 using CURLOPT_POSTREDIR of -1, +// but it still did not work. +#if 0 + // Please handle 301/302 redirects for me + xcurl_easy_setopt_long(handle, CURLOPT_FOLLOWLOCATION, 1); + xcurl_easy_setopt_long(handle, CURLOPT_MAXREDIRS, 10); + // Bitmask to control how libcurl acts on redirects after POSTs. + // Bit 0 set (value CURL_REDIR_POST_301) makes libcurl + // not convert POST requests into GET requests when following + // a 301 redirection. Bit 1 (value CURL_REDIR_POST_302) makes libcurl + // maintain the request method after a 302 redirect. + // CURL_REDIR_POST_ALL is a convenience define that sets both bits. + // The non-RFC behaviour is ubiquitous in web browsers, so the library + // does the conversion by default to maintain consistency. + // However, a server may require a POST to remain a POST. + xcurl_easy_setopt_long(handle, CURLOPT_POSTREDIR, -1L /*CURL_REDIR_POST_ALL*/ ); +#endif + + // Prepare for saving information + if (state->flags & ABRT_POST_WANT_HEADERS) + { + xcurl_easy_setopt_ptr(handle, CURLOPT_HEADERFUNCTION, (void*)save_headers); + xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEHEADER, state); + } + FILE* body_stream = NULL; + if (state->flags & ABRT_POST_WANT_BODY) + { + body_stream = open_memstream(&state->body, &state->body_size); + if (!body_stream) + error_msg_and_die("out of memory"); + xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEDATA, body_stream); + } + if (!(state->flags & ABRT_POST_WANT_SSL_VERIFY)) + { + xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYPEER, 0); + xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYHOST, 0); + } + + // This is the place where everything happens. + // Here errors are not limited to "out of memory", can't just die. + curl_err = curl_easy_perform(handle); + if (curl_err) + { + VERB2 log("curl_easy_perform: error %d", (int)curl_err); + if (state->flags & ABRT_POST_WANT_ERROR_MSG) + { + state->curl_error_msg = check_curl_error(curl_err, "curl_easy_perform"); + VERB3 log("curl_easy_perform: error_msg: %s", state->curl_error_msg); + } + goto ret; + } + + // Headers/body are already saved (if requested), extract more info + curl_err = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code); + die_if_curl_error(curl_err); + state->http_resp_code = response_code; + VERB3 log("after curl_easy_perform: http code %ld body:'%s'", response_code, state->body); + + ret: + curl_easy_cleanup(handle); + if (httpheader_list) + curl_slist_free_all(httpheader_list); + if (body_stream) + fclose(body_stream); + if (data_file) + fclose(data_file); + if (post) + curl_formfree(post); + + return response_code; +} diff --git a/src/lib/abrt_curl.h b/src/lib/abrt_curl.h new file mode 100644 index 00000000..77b4605c --- /dev/null +++ b/src/lib/abrt_curl.h @@ -0,0 +1,96 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 ABRT_CURL_H_ +#define ABRT_CURL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CURL* xcurl_easy_init(); + +typedef struct abrt_post_state { + /* Supplied by caller: */ + int flags; + const char *username; + const char *password; + /* Results of POST transaction: */ + int http_resp_code; + unsigned header_cnt; + char **headers; + char *curl_error_msg; + char *body; + size_t body_size; + char errmsg[CURL_ERROR_SIZE]; +} abrt_post_state_t; + +abrt_post_state_t *new_abrt_post_state(int flags); +void free_abrt_post_state(abrt_post_state_t *state); +char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char *str); + +enum { + ABRT_POST_WANT_HEADERS = (1 << 0), + ABRT_POST_WANT_ERROR_MSG = (1 << 1), + ABRT_POST_WANT_BODY = (1 << 2), + ABRT_POST_WANT_SSL_VERIFY = (1 << 3), +}; +enum { + /* Must be -1! CURLOPT_POSTFIELDSIZE interprets -1 as "use strlen" */ + ABRT_POST_DATA_STRING = -1, + ABRT_POST_DATA_FROMFILE = -2, + ABRT_POST_DATA_FROMFILE_AS_FORM_DATA = -3, +}; +int +abrt_post(abrt_post_state_t *state, + const char *url, + const char *content_type, + const char *data, + off_t data_size); +static inline int +abrt_post_string(abrt_post_state_t *state, + const char *url, + const char *content_type, + const char *str) +{ + return abrt_post(state, url, content_type, str, ABRT_POST_DATA_STRING); +} +static inline int +abrt_post_file(abrt_post_state_t *state, + const char *url, + const char *content_type, + const char *filename) +{ + return abrt_post(state, url, content_type, filename, ABRT_POST_DATA_FROMFILE); +} +static inline int +abrt_post_file_as_form(abrt_post_state_t *state, + const char *url, + const char *content_type, + const char *filename) +{ + return abrt_post(state, url, content_type, filename, ABRT_POST_DATA_FROMFILE_AS_FORM_DATA); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/abrt_dbus.c b/src/lib/abrt_dbus.c new file mode 100644 index 00000000..6bc155e3 --- /dev/null +++ b/src/lib/abrt_dbus.c @@ -0,0 +1,430 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 +#include +#include "abrtlib.h" +#include "abrt_dbus.h" + +DBusConnection* g_dbus_conn; + + +/* + * Helpers for building DBus messages + */ + +//void store_bool(DBusMessageIter* iter, bool val) +//{ +// dbus_bool_t db = val; +// if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &db)) +// die_out_of_memory(); +//} +void store_int32(DBusMessageIter* iter, int32_t val) +{ + if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &val)) + die_out_of_memory(); +} +void store_uint32(DBusMessageIter* iter, uint32_t val) +{ + if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &val)) + die_out_of_memory(); +} +void store_int64(DBusMessageIter* iter, int64_t val) +{ + if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &val)) + die_out_of_memory(); +} +void store_uint64(DBusMessageIter* iter, uint64_t val) +{ + if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &val)) + die_out_of_memory(); +} + +/* dbus daemon will simply close our connection if we send broken utf8. + * Therefore we must never do that. + */ +static char *sanitize_utf8(const char *src) +{ + const char *initial_src = src; + char *sanitized = NULL; + unsigned sanitized_pos = 0; + + while (*src) + { + int bytes = 0; + + unsigned c = (unsigned char) *src; + if (c <= 0x7f) + { + bytes = 1; + goto good_byte; + } + + /* Unicode -> utf8: */ + /* 80-7FF -> 110yyyxx 10xxxxxx */ + /* 800-FFFF -> 1110yyyy 10yyyyxx 10xxxxxx */ + /* 10000-1FFFFF -> 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx */ + /* 200000-3FFFFFF -> 111110tt 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx */ + /* 4000000-FFFFFFFF -> 111111tt 10tttttt 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx */ + do { + c <<= 1; + bytes++; + } while ((c & 0x80) && bytes < 6); + if (bytes == 1) + { + /* A bare "continuation" byte. Say, 80 */ + goto bad_byte; + } + + c = (uint8_t)(c) >> bytes; + { + const char *pp = src; + int cnt = bytes; + while (--cnt) + { + unsigned ch = (unsigned char) *++pp; + if ((ch & 0xc0) != 0x80) /* Missing "continuation" byte. Example: e0 80 */ + { + goto bad_byte; + } + c = (c << 6) + (ch & 0x3f); + } + } + /* TODO */ + /* Need to check that c isn't produced by overlong encoding */ + /* Example: 11000000 10000000 converts to NUL */ + /* 11110000 10000000 10000100 10000000 converts to 0x100 */ + /* correct encoding: 11000100 10000000 */ + if (c <= 0x7f) /* crude check: only catches bad encodings which map to chars <= 7f */ + { + goto bad_byte; + } + + good_byte: + while (--bytes >= 0) + { + c = (unsigned char) *src++; + if (sanitized) + { + sanitized = (char*) xrealloc(sanitized, sanitized_pos + 2); + sanitized[sanitized_pos++] = c; + sanitized[sanitized_pos] = '\0'; + } + } + continue; + + bad_byte: + if (!sanitized) + { + sanitized_pos = src - initial_src; + sanitized = xstrndup(initial_src, sanitized_pos); + } + sanitized = (char*) xrealloc(sanitized, sanitized_pos + 5); + sanitized[sanitized_pos++] = '['; + c = (unsigned char) *src++; + sanitized[sanitized_pos++] = "0123456789ABCDEF"[c >> 4]; + sanitized[sanitized_pos++] = "0123456789ABCDEF"[c & 0xf]; + sanitized[sanitized_pos++] = ']'; + sanitized[sanitized_pos] = '\0'; + } + + if (sanitized) + VERB2 log("note: bad utf8, converted '%s' -> '%s'", initial_src, sanitized); + + return sanitized; /* usually NULL: the whole string is ok */ +} +void store_string(DBusMessageIter* iter, const char* val) +{ + const char *sanitized = sanitize_utf8(val); + if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, sanitized ? &sanitized : &val)) + die_out_of_memory(); + free((char*)sanitized); +} + + +/* + * Helpers for parsing DBus messages + */ + +//int load_bool(DBusMessageIter* iter, bool& val) +//{ +// int type = dbus_message_iter_get_arg_type(iter); +// if (type != DBUS_TYPE_BOOLEAN) +// error_msg_and_die("%s expected in dbus message, but not found ('%c')", "bool", type); +// dbus_bool_t db; +// dbus_message_iter_get_basic(iter, &db); +// val = db; +// return dbus_message_iter_next(iter); +//} +int load_int32(DBusMessageIter* iter, int32_t *val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_INT32) + { + error_msg("%s expected in dbus message, but not found ('%c')", "int32", type); + return -1; + } + dbus_message_iter_get_basic(iter, val); + return dbus_message_iter_next(iter); +} +int load_uint32(DBusMessageIter* iter, uint32_t *val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_UINT32) + { + error_msg("%s expected in dbus message, but not found ('%c')", "uint32", type); + return -1; + } + dbus_message_iter_get_basic(iter, val); + return dbus_message_iter_next(iter); +} +int load_int64(DBusMessageIter* iter, int64_t *val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_INT64) + { + error_msg("%s expected in dbus message, but not found ('%c')", "int64", type); + return -1; + } + dbus_message_iter_get_basic(iter, val); + return dbus_message_iter_next(iter); +} +int load_uint64(DBusMessageIter* iter, uint64_t *val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_UINT64) + { + error_msg("%s expected in dbus message, but not found ('%c')", "uint64", type); + return -1; + } + dbus_message_iter_get_basic(iter, val); + return dbus_message_iter_next(iter); +} +int load_charp(DBusMessageIter* iter, const char** val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_STRING) + { + error_msg("%s expected in dbus message, but not found ('%c')", "string", type); + return -1; + } + dbus_message_iter_get_basic(iter, val); +//log("load_charp:'%s'", *val); + return dbus_message_iter_next(iter); +} + + +/* + * Glib integration machinery + */ + +/* Callback: "glib says dbus fd is active" */ +static gboolean handle_dbus_fd(GIOChannel *gio, GIOCondition condition, gpointer data) +{ + DBusWatch *watch = (DBusWatch*)data; + + VERB3 log("%s(gio, condition:%x [bits:IN/PRI/OUT/ERR/HUP...], data)", __func__, (int)condition); + + /* Notify the D-Bus library when a previously-added watch + * is ready for reading or writing, or has an exception such as a hangup. + */ + int glib_flags = (int)condition; + int dbus_flags = 0; + if (glib_flags & G_IO_IN) dbus_flags |= DBUS_WATCH_READABLE; + if (glib_flags & G_IO_OUT) dbus_flags |= DBUS_WATCH_WRITABLE; + if (glib_flags & G_IO_ERR) dbus_flags |= DBUS_WATCH_ERROR; + if (glib_flags & G_IO_HUP) dbus_flags |= DBUS_WATCH_HANGUP; + /* + * TODO: + * If dbus_watch_handle returns FALSE, then the file descriptor + * may still be ready for reading or writing, but more memory + * is needed in order to do the reading or writing. If you ignore + * the FALSE return, your application may spin in a busy loop + * on the file descriptor until memory becomes available, + * but nothing more catastrophic should happen. + */ + dbus_watch_handle(watch, dbus_flags); + + while (dbus_connection_dispatch(g_dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) + VERB3 log("%s: more data to process, looping", __func__); + return TRUE; /* "glib, do not remove this event source!" */ +} + +typedef struct watch_app_info_t +{ + GIOChannel *channel; + guint event_source_id; + bool watch_enabled; +} watch_app_info_t; +/* Callback: "dbus_watch_get_enabled() may return a different value than it did before" */ +static void toggled_watch(DBusWatch *watch, void* data) +{ + VERB3 log("%s(watch:%p, data)", __func__, watch); + + watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); + if (dbus_watch_get_enabled(watch)) + { + if (!app_info->watch_enabled) + { + app_info->watch_enabled = true; + int dbus_flags = dbus_watch_get_flags(watch); + int glib_flags = 0; + if (dbus_flags & DBUS_WATCH_READABLE) glib_flags |= G_IO_IN; + if (dbus_flags & DBUS_WATCH_WRITABLE) glib_flags |= G_IO_OUT; + VERB3 log(" adding watch to glib main loop. dbus_flags:%x glib_flags:%x", dbus_flags, glib_flags); + app_info->event_source_id = g_io_add_watch(app_info->channel, (GIOCondition)glib_flags, handle_dbus_fd, watch); + } + /* else: it was already enabled */ + } else { + if (app_info->watch_enabled) + { + app_info->watch_enabled = false; + /* does it free the hidden GSource too? */ + VERB3 log(" removing watch from glib main loop"); + g_source_remove(app_info->event_source_id); + } + /* else: it was already disabled */ + } +} +/* Callback: "libdbus needs a new watch to be monitored by the main loop" */ +static dbus_bool_t add_watch(DBusWatch *watch, void* data) +{ + VERB3 log("%s(watch:%p, data)", __func__, watch); + + watch_app_info_t* app_info = (watch_app_info_t*)xzalloc(sizeof(*app_info)); + dbus_watch_set_data(watch, app_info, free); + + int fd = dbus_watch_get_unix_fd(watch); + VERB3 log(" dbus_watch_get_unix_fd():%d", fd); + app_info->channel = g_io_channel_unix_new(fd); + /* _unconditionally_ adding it to event loop would be an error */ + toggled_watch(watch, data); + return TRUE; +} +/* Callback: "libdbus no longer needs a watch to be monitored by the main loop" */ +static void remove_watch(DBusWatch *watch, void* data) +{ + VERB3 log("%s()", __func__); + watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); + if (app_info->watch_enabled) + { + app_info->watch_enabled = false; + g_source_remove(app_info->event_source_id); + } + g_io_channel_unref(app_info->channel); +} + +/* Callback: "libdbus needs a new timeout to be monitored by the main loop" */ +static dbus_bool_t add_timeout(DBusTimeout *timeout, void* data) +{ + VERB3 log("%s()", __func__); + return TRUE; +} +/* Callback: "libdbus no longer needs a timeout to be monitored by the main loop" */ +static void remove_timeout(DBusTimeout *timeout, void* data) +{ + VERB3 log("%s()", __func__); +} +/* Callback: "dbus_timeout_get_enabled() may return a different value than it did before" */ +static void timeout_toggled(DBusTimeout *timeout, void* data) +{ +//seems to be never called, let's make it noisy + error_msg_and_die("%s(): FIXME: some dbus machinery is missing here", __func__); +} + +/* Callback: "DBusObjectPathVTable is unregistered (or its connection is freed)" */ +static void unregister_vtable(DBusConnection *conn, void* data) +{ + VERB3 log("%s()", __func__); +} + +/* + * Initialization works as follows: + * + * we have a DBusConnection* (say, obtained with dbus_bus_get) + * we call dbus_connection_set_watch_functions + * libdbus calls back add_watch(watch:0x2341090, data), this watch is for writing + * we call toggled_watch, but it finds that watch is not to be enabled yet + * libdbus calls back add_watch(watch:0x23410e0, data), this watch is for reading + * we call toggled_watch, it adds watch's fd to glib main loop with POLLIN + * (note: these watches are different objects, but they have the same fd) + * we call dbus_connection_set_timeout_functions + * we call dbus_connection_register_object_path + * + * Note: if user will later call dbus_bus_request_name(conn, ...): + * libdbus calls back add_timeout() + * libdbus calls back remove_timeout() + * note - no callback to timeout_toggled()! + * (therefore there is no code yet in timeout_toggled (see above), it's not used) + */ +void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, + const char* object_path, + DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) +) { + if (g_dbus_conn) + error_msg_and_die("Internal bug: can't connect to more than one dbus"); + g_dbus_conn = conn; + +//do we need this? why? +//log("dbus_connection_set_dispatch_status_function"); +// dbus_connection_set_dispatch_status_function(conn, +// dispatch, /* void dispatch(DBusConnection *conn, DBusDispatchStatus new_status, void* data) */ +// NULL, /* data */ +// NULL /* free_data_function */ +// ) + VERB3 log("dbus_connection_set_watch_functions"); + if (!dbus_connection_set_watch_functions(conn, + add_watch, + remove_watch, + toggled_watch, + NULL, /* data */ + NULL /* free_data_function */ + ) + ) { + die_out_of_memory(); + } + VERB3 log("dbus_connection_set_timeout_functions"); + if (!dbus_connection_set_timeout_functions(conn, + add_timeout, + remove_timeout, + timeout_toggled, + NULL, /* data */ + NULL /* free_data_function */ + ) + ) { + die_out_of_memory(); + } + + if (object_path && message_received_func) + { + /* Table */ + const DBusObjectPathVTable vtable = { + /* .unregister_function = */ unregister_vtable, + /* .message_function = */ message_received_func, + }; + VERB3 log("dbus_connection_register_object_path"); + if (!dbus_connection_register_object_path(conn, + object_path, + &vtable, + NULL /* data */ + ) + ) { + die_out_of_memory(); + } + } +} diff --git a/src/lib/abrt_dbus.h b/src/lib/abrt_dbus.h new file mode 100644 index 00000000..cdc963ca --- /dev/null +++ b/src/lib/abrt_dbus.h @@ -0,0 +1,324 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 ABRT_DBUS_H +#define ABRT_DBUS_H + +#include +#include "abrtlib.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +extern DBusConnection* g_dbus_conn; + +/* + * Glib integration machinery + */ + +/* Hook up to DBus and to glib main loop. + * Usage cases: + * + * - server: + * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err); + * attach_dbus_conn_to_glib_main_loop(conn, "/some/path", handler_of_calls_to_some_path); + * rc = dbus_bus_request_name(conn, "server.name", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); + * + * - client which does not receive signals (only makes calls and emits signals): + * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err); + * // needed only if you need to use async dbus calls (not shown below): + * attach_dbus_conn_to_glib_main_loop(conn, NULL, NULL); + * // syncronous method call: + * msg = dbus_message_new_method_call("some.serv", "/path/on/serv", "optional.iface.on.serv", "method_name"); + * reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout, &err); + * // emitting signal: + * msg = dbus_message_new_signal("/path/sig/emitted/from", "iface.sig.emitted.from", "sig_name"); + * // (note: "iface.sig.emitted.from" is not optional for signals!) + * dbus_message_set_destination(msg, "peer"); // optional + * dbus_connection_send(conn, msg, &serial); // &serial can be NULL + * + * - client which receives and processes signals: + * conn = dbus_bus_get(DBUS_BUS_SYSTEM/SESSION, &err); + * attach_dbus_conn_to_glib_main_loop(conn, NULL, NULL); + * dbus_connection_add_filter(conn, handle_message, NULL, NULL) + * dbus_bus_add_match(system_conn, "type='signal',...", &err); + * // signal is a dbus message which looks like this: + * // sender=XXX dest=YYY(or null) path=/path/sig/emitted/from interface=iface.sig.emitted.from member=sig_name + * // and handler_for_signals(conn,msg,opaque) will be called by glib + * // main loop to process received signals (and other messages + * // if you ask for them in dbus_bus_add_match[es], but this + * // would turn you into a server if you handle them too) ;] + */ +void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, + /* NULL if you are just a client */ + const char* object_path_to_register, + /* makes sense only if you use object_path_to_register: */ + DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) +); + +/* + * Helpers for building DBus messages + */ +//void store_bool(DBusMessageIter* iter, bool val); +void store_int32(DBusMessageIter* iter, int32_t val); +void store_uint32(DBusMessageIter* iter, uint32_t val); +void store_int64(DBusMessageIter* iter, int64_t val); +void store_uint64(DBusMessageIter* iter, uint64_t val); +void store_string(DBusMessageIter* iter, const char* val); + +/* + * Helpers for parsing DBus messages + */ +enum { + ABRT_DBUS_ERROR = -1, + ABRT_DBUS_LAST_FIELD = 0, + ABRT_DBUS_MORE_FIELDS = 1, + /* note that dbus_message_iter_next() returns FALSE on last field + * and TRUE if there are more fields. + * It maps exactly on the above constants. */ +}; +/* Checks type, loads data, advances to the next arg. + * Returns TRUE if next arg exists. + */ +//int load_bool(DBusMessageIter* iter, bool& val); +int load_int32(DBusMessageIter* iter, int32_t *val); +int load_uint32(DBusMessageIter* iter, uint32_t *val); +int load_int64(DBusMessageIter* iter, int64_t *val); +int load_uint64(DBusMessageIter* iter, uint64_t *val); +int load_charp(DBusMessageIter* iter, const char **val); + +#ifdef __cplusplus +} +#endif + + +/* C++ style stuff */ +#ifdef __cplusplus + +#include +#include + +/* + * Helpers for building DBus messages + */ + +//static inline void store_val(DBusMessageIter* iter, bool val) { store_bool(iter, val); } +static inline void store_val(DBusMessageIter* iter, int32_t val) { store_int32(iter, val); } +static inline void store_val(DBusMessageIter* iter, uint32_t val) { store_uint32(iter, val); } +static inline void store_val(DBusMessageIter* iter, int64_t val) { store_int64(iter, val); } +static inline void store_val(DBusMessageIter* iter, uint64_t val) { store_uint64(iter, val); } +static inline void store_val(DBusMessageIter* iter, const char* val) { store_string(iter, val); } +static inline void store_val(DBusMessageIter* iter, const std::string& val) { store_string(iter, val.c_str()); } + +/* Templates for vector and map */ +template struct abrt_dbus_type {}; +//template <> struct abrt_dbus_type { static const char* csig() { return "b"; } }; +template <> struct abrt_dbus_type { static const char* csig() { return "i"; } static std::string sig(); }; +template <> struct abrt_dbus_type { static const char* csig() { return "u"; } static std::string sig(); }; +template <> struct abrt_dbus_type { static const char* csig() { return "x"; } static std::string sig(); }; +template <> struct abrt_dbus_type { static const char* csig() { return "t"; } static std::string sig(); }; +template <> struct abrt_dbus_type { static const char* csig() { return "s"; } static std::string sig(); }; +#define ABRT_DBUS_SIG(T) (abrt_dbus_type::csig() ? abrt_dbus_type::csig() : abrt_dbus_type::sig().c_str()) +template +struct abrt_dbus_type< std::vector > { + static const char* csig() { return NULL; } + static std::string sig() { return ssprintf("a%s", ABRT_DBUS_SIG(E)); } +}; +template +struct abrt_dbus_type< std::map > { + static const char* csig() { return NULL; } + static std::string sig() { return ssprintf("a{%s%s}", ABRT_DBUS_SIG(K), ABRT_DBUS_SIG(V)); } +}; + +template +static void store_vector(DBusMessageIter* iter, const std::vector& val) +{ + DBusMessageIter sub_iter; + if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, ABRT_DBUS_SIG(E), &sub_iter)) + die_out_of_memory(); + + typename std::vector::const_iterator vit = val.begin(); + for (; vit != val.end(); ++vit) + { + store_val(&sub_iter, *vit); + } + + if (!dbus_message_iter_close_container(iter, &sub_iter)) + die_out_of_memory(); +} +/* +template<> +static void store_vector(DBus::MessageIter &iter, const std::vector& val) +{ + if we use such vector, MUST add specialized code here (see in dbus-c++ source) +} +*/ +template +static void store_map(DBusMessageIter* iter, const std::map& val) +{ + DBusMessageIter sub_iter; + if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + ssprintf("{%s%s}", ABRT_DBUS_SIG(K), ABRT_DBUS_SIG(V)).c_str(), + &sub_iter)) + die_out_of_memory(); + + typename std::map::const_iterator mit = val.begin(); + for (; mit != val.end(); ++mit) + { + DBusMessageIter sub_sub_iter; + if (!dbus_message_iter_open_container(&sub_iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub_sub_iter)) + die_out_of_memory(); + store_val(&sub_sub_iter, mit->first); + store_val(&sub_sub_iter, mit->second); + if (!dbus_message_iter_close_container(&sub_iter, &sub_sub_iter)) + die_out_of_memory(); + } + + if (!dbus_message_iter_close_container(iter, &sub_iter)) + die_out_of_memory(); +} + +template +static inline void store_val(DBusMessageIter* iter, const std::vector& val) { store_vector(iter, val); } +template +static inline void store_val(DBusMessageIter* iter, const std::map& val) { store_map(iter, val); } + + +/* + * Helpers for parsing DBus messages + */ + +//static inline int load_val(DBusMessageIter* iter, bool &val) { return load_bool(iter, &val); } +static inline int load_val(DBusMessageIter* iter, int32_t &val) { return load_int32(iter, &val); } +static inline int load_val(DBusMessageIter* iter, uint32_t &val) { return load_uint32(iter, &val); } +static inline int load_val(DBusMessageIter* iter, int64_t &val) { return load_int64(iter, &val); } +static inline int load_val(DBusMessageIter* iter, uint64_t &val) { return load_uint64(iter, &val); } +static inline int load_val(DBusMessageIter* iter, const char*& val) { return load_charp(iter, &val); } +static inline int load_val(DBusMessageIter* iter, std::string& val) +{ + const char* str; + int r = load_charp(iter, &str); + val = str; + return r; +} + +/* Templates for vector and map */ +template +static int load_vector(DBusMessageIter* iter, std::vector& val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_ARRAY) + { + error_msg("array expected in dbus message, but not found ('%c')", type); + return -1; + } + + DBusMessageIter sub_iter; + dbus_message_iter_recurse(iter, &sub_iter); + + int r; +//int cnt = 0; + /* When the vector has 0 elements, we see DBUS_TYPE_INVALID here */ + type = dbus_message_iter_get_arg_type(&sub_iter); + if (type != DBUS_TYPE_INVALID) + { + do { + E elem; +//cnt++; + r = load_val(&sub_iter, elem); + if (r < 0) + return r; + val.push_back(elem); + } while (r == ABRT_DBUS_MORE_FIELDS); + } +//log("%s: %d elems", __func__, cnt); + + return dbus_message_iter_next(iter); +} +/* +template<> +static int load_vector(DBusMessageIter* iter, std::vector& val) +{ + if we use such vector, MUST add specialized code here (see in dbus-c++ source) +} +*/ +template +static int load_map(DBusMessageIter* iter, std::map& val) +{ + int type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_ARRAY) + { + error_msg("array expected in dbus message, but not found ('%c')", type); + return -1; + } + + DBusMessageIter sub_iter; + dbus_message_iter_recurse(iter, &sub_iter); + + bool next_exists; + int r; +//int cnt = 0; + do { + type = dbus_message_iter_get_arg_type(&sub_iter); + if (type != DBUS_TYPE_DICT_ENTRY) + { + /* When the map has 0 elements, we see DBUS_TYPE_INVALID (on the first iteration) */ + if (type == DBUS_TYPE_INVALID) + break; + error_msg("sub_iter type is not DBUS_TYPE_DICT_ENTRY (%c)!", type); + return -1; + } + + DBusMessageIter sub_sub_iter; + dbus_message_iter_recurse(&sub_iter, &sub_sub_iter); + + K key; + r = load_val(&sub_sub_iter, key); + if (r != ABRT_DBUS_MORE_FIELDS) + { + if (r == ABRT_DBUS_LAST_FIELD) + error_msg("malformed map element in dbus message"); + return -1; + } + V value; + r = load_val(&sub_sub_iter, value); + if (r != ABRT_DBUS_LAST_FIELD) + { + if (r == ABRT_DBUS_MORE_FIELDS) + error_msg("malformed map element in dbus message"); + return -1; + } + val[key] = value; +//cnt++; + next_exists = dbus_message_iter_next(&sub_iter); + } while (next_exists); +//log("%s: %d elems", __func__, cnt); + + return dbus_message_iter_next(iter); +} + +template +static inline int load_val(DBusMessageIter* iter, std::vector& val) { return load_vector(iter, val); } +template +static inline int load_val(DBusMessageIter* iter, std::map& val) { return load_map(iter, val); } + +#endif /* __cplusplus */ + +#endif diff --git a/src/lib/abrt_packages.c b/src/lib/abrt_packages.c new file mode 100644 index 00000000..bbf0e729 --- /dev/null +++ b/src/lib/abrt_packages.c @@ -0,0 +1,43 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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" + +/* cuts the name from the NVR format: foo-1.2.3-1.el6 + returns a newly allocated string +*/ +char* get_package_name_from_NVR_or_NULL(const char* packageNVR) +{ + char* package_name = NULL; + if (packageNVR != NULL) + { + VERB1 log("packageNVR %s", packageNVR); + package_name = xstrdup(packageNVR); + char *pos = strrchr(package_name, '-'); + if (pos != NULL) + { + *pos = 0; + pos = strrchr(package_name, '-'); + if (pos != NULL) + { + *pos = 0; + } + } + } + return package_name; +} diff --git a/src/lib/abrt_packages.h b/src/lib/abrt_packages.h new file mode 100644 index 00000000..6a952f5e --- /dev/null +++ b/src/lib/abrt_packages.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 ABRT_PACKAGES_H +#define ABRT_PACKAGES_H + +#ifdef __cplusplus +extern "C" { +#endif + +char* get_package_name_from_NVR_or_NULL(const char* packageNVR); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/abrt_xmlrpc.cpp b/src/lib/abrt_xmlrpc.cpp new file mode 100644 index 00000000..bf74f05b --- /dev/null +++ b/src/lib/abrt_xmlrpc.cpp @@ -0,0 +1,97 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 "abrt_xmlrpc.h" +#include "abrt_exception.h" + +void throw_xml_fault(xmlrpc_env *env) +{ + std::string errmsg = ssprintf("XML-RPC Fault(%d): %s", env->fault_code, env->fault_string); + xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred + xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env + error_msg("%s", errmsg.c_str()); // show error in daemon log + throw CABRTException(EXCEP_PLUGIN, errmsg.c_str()); +} + +void throw_if_xml_fault_occurred(xmlrpc_env *env) +{ + if (env->fault_occurred) + { + throw_xml_fault(env); + } +} + +void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool ssl_verify) +{ + m_pClient = NULL; + m_pServer_info = NULL; + + xmlrpc_env env; + xmlrpc_env_init(&env); + + /* This should be done at program startup, once. + * We do it in abrtd's main */ + /* xmlrpc_client_setup_global_const(&env); */ + + struct xmlrpc_curl_xportparms curlParms; + memset(&curlParms, 0, sizeof(curlParms)); + /* curlParms.network_interface = NULL; - done by memset */ + curlParms.no_ssl_verifypeer = !ssl_verify; + curlParms.no_ssl_verifyhost = !ssl_verify; +#ifdef VERSION + curlParms.user_agent = PACKAGE_NAME"/"VERSION; +#else + curlParms.user_agent = "abrt"; +#endif + + struct xmlrpc_clientparms clientParms; + memset(&clientParms, 0, sizeof(clientParms)); + clientParms.transport = "curl"; + clientParms.transportparmsP = &curlParms; + clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent); + + xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, + PACKAGE_NAME, VERSION, + &clientParms, XMLRPC_CPSIZE(transportparm_size), + &m_pClient); + if (env.fault_occurred) + throw_xml_fault(&env); + + m_pServer_info = xmlrpc_server_info_new(&env, url); + if (env.fault_occurred) + { + xmlrpc_client_destroy(m_pClient); + m_pClient = NULL; + throw_xml_fault(&env); + } +} + +void abrt_xmlrpc_conn::destroy_xmlrpc_client() +{ + if (m_pServer_info) + { + xmlrpc_server_info_free(m_pServer_info); + m_pServer_info = NULL; + } + if (m_pClient) + { + xmlrpc_client_destroy(m_pClient); + m_pClient = NULL; + } +} diff --git a/src/lib/abrt_xmlrpc.h b/src/lib/abrt_xmlrpc.h new file mode 100644 index 00000000..ad1a87d3 --- /dev/null +++ b/src/lib/abrt_xmlrpc.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 ABRT_XMLRPC_H_ +#define ABRT_XMLRPC_H_ 1 + +#include +#include +#include + +/* + * Simple class holding XMLRPC connection data. + * Used mainly to ensure we always destroy xmlrpc client and server_info + * on return or throw. + */ + +struct abrt_xmlrpc_conn { + xmlrpc_client* m_pClient; + xmlrpc_server_info* m_pServer_info; + + abrt_xmlrpc_conn(const char* url, bool ssl_verify) { new_xmlrpc_client(url, ssl_verify); } + /* this never throws exceptions - calls C functions only */ + ~abrt_xmlrpc_conn() { destroy_xmlrpc_client(); } + + void new_xmlrpc_client(const char* url, bool ssl_verify); + void destroy_xmlrpc_client(); +}; + +/* Utility functions */ +void throw_xml_fault(xmlrpc_env *env); +void throw_if_xml_fault_occurred(xmlrpc_env *env); + +#endif diff --git a/src/lib/append_to_malloced_string.c b/src/lib/append_to_malloced_string.c new file mode 100644 index 00000000..430cef0b --- /dev/null +++ b/src/lib/append_to_malloced_string.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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" + +char *append_to_malloced_string(char *mstr, const char *append) +{ + unsigned mlen = strlen(mstr); + mstr = (char*) xrealloc(mstr, mlen + strlen(append) + 1); + strcpy(mstr + mlen, append); + return mstr; +} diff --git a/src/lib/concat_path_file.c b/src/lib/concat_path_file.c new file mode 100644 index 00000000..4c946628 --- /dev/null +++ b/src/lib/concat_path_file.c @@ -0,0 +1,25 @@ +/* + * Utility routines. + * + * Copyright (C) 2001 Erik Andersen + * + * Licensed under GPLv2 or later. + */ + +/* Concatenate path and filename to new allocated buffer. + * Add '/' only as needed (no duplicate // are produced). + * If path is NULL, it is assumed to be "/". + * filename should not be NULL. + */ + +#include "abrtlib.h" + +char *concat_path_file(const char *path, const char *filename) +{ + if (!path) + path = ""; + const char *end = path + strlen(path); + while (*filename == '/') + filename++; + return xasprintf("%s%s%s", path, (end != path && end[-1] != '/' ? "/" : ""), filename); +} diff --git a/src/lib/copyfd.c b/src/lib/copyfd.c new file mode 100644 index 00000000..bfe0fa49 --- /dev/null +++ b/src/lib/copyfd.c @@ -0,0 +1,172 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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. +*/ + +/* + * Utility routines. + * + */ +#include "abrtlib.h" + +#define CONFIG_FEATURE_COPYBUF_KB 4 + +static const char msg_write_error[] = "write error"; +static const char msg_read_error[] = "read error"; + +static off_t full_fd_action(int src_fd, int dst_fd, off_t size, int flags) +{ + int status = -1; + off_t total = 0; + int last_was_seek = 0; +#if CONFIG_FEATURE_COPYBUF_KB <= 4 + char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; + enum { buffer_size = sizeof(buffer) }; +#else + char *buffer; + int buffer_size; + + /* We want page-aligned buffer, just in case kernel is clever + * and can do page-aligned io more efficiently */ + buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, + /* ignored: */ -1, 0); + buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; + if (buffer == MAP_FAILED) { + buffer = alloca(4 * 1024); + buffer_size = 4 * 1024; + } +#endif + + if (src_fd < 0) + goto out; + + if (!size) { + size = buffer_size; + status = 1; /* copy until eof */ + } + + while (1) { + ssize_t rd; + + rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); + + if (!rd) { /* eof - all done */ + if (last_was_seek) { + if (lseek(dst_fd, -1, SEEK_CUR) < 0 + || safe_write(dst_fd, "", 1) != 1 + ) { + perror_msg("%s", msg_write_error); + break; + } + } + status = 0; + break; + } + if (rd < 0) { + perror_msg("%s", msg_read_error); + break; + } + /* dst_fd == -1 is a fake, else... */ + if (dst_fd >= 0) { + if (flags & COPYFD_SPARSE) { + ssize_t cnt = rd; + while (--cnt >= 0) + if (buffer[cnt] != 0) + goto need2write; + if (lseek(dst_fd, rd, SEEK_CUR) < 0) { + flags &= ~COPYFD_SPARSE; + goto need2write; + } + last_was_seek = 1; + } else { + need2write: + { + ssize_t wr = full_write(dst_fd, buffer, rd); + if (wr < rd) { + perror_msg("%s", msg_write_error); + break; + } + last_was_seek = 0; + } + } + } + total += rd; + if (status < 0) { /* if we aren't copying till EOF... */ + size -= rd; + if (!size) { + /* 'size' bytes copied - all done */ + status = 0; + break; + } + } + } + out: + +#if CONFIG_FEATURE_COPYBUF_KB > 4 + if (buffer_size != 4 * 1024) + munmap(buffer, buffer_size); +#endif + return status ? -1 : total; +} + +off_t copyfd_size(int fd1, int fd2, off_t size, int flags) +{ + if (size) { + return full_fd_action(fd1, fd2, size, flags); + } + return 0; +} + +void copyfd_exact_size(int fd1, int fd2, off_t size) +{ + off_t sz = copyfd_size(fd1, fd2, size, /*flags:*/ 0); + if (sz == size) + return; + if (sz != -1) + error_msg_and_die("short read"); + /* if sz == -1, copyfd_XX already complained */ + xfunc_die(); +} + +off_t copyfd_eof(int fd1, int fd2, int flags) +{ + return full_fd_action(fd1, fd2, 0, flags); +} + +off_t copy_file(const char *src_name, const char *dst_name, int mode) +{ + off_t r; + int src = open(src_name, O_RDONLY); + if (src < 0) + { + perror_msg("Can't open '%s'", src_name); + return -1; + } + int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, mode); + if (dst < 0) + { + close(src); + perror_msg("Can't open '%s'", dst_name); + return -1; + } + r = copyfd_eof(src, dst, /*flags:*/ 0); + close(src); + close(dst); + return r; +} diff --git a/src/lib/daemon.c b/src/lib/daemon.c new file mode 100644 index 00000000..944aef0c --- /dev/null +++ b/src/lib/daemon.c @@ -0,0 +1,139 @@ +/* + Copyright (C) 2009 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" + +#define VAR_RUN_PID_FILE VAR_RUN"/abrtd.pid" + +static char *append_escaped(char *start, const char *s) +{ + char hex_char_buf[] = "\\x00"; + + *start++ = ' '; + char *dst = start; + const unsigned char *p = (unsigned char *)s; + + while (1) + { + const unsigned char *old_p = p; + while (*p > ' ' && *p <= 0x7e && *p != '\"' && *p != '\'' && *p != '\\') + p++; + if (dst == start) + { + if (p != (unsigned char *)s && *p == '\0') + { + /* entire word does not need escaping and quoting */ + strcpy(dst, s); + dst += strlen(s); + return dst; + } + *dst++ = '\''; + } + + strncpy(dst, (char *)old_p, (p - old_p)); + dst += (p - old_p); + + if (*p == '\0') + { + *dst++ = '\''; + *dst = '\0'; + return dst; + } + const char *a; + switch (*p) + { + case '\r': a = "\\r"; break; + case '\n': a = "\\n"; break; + case '\t': a = "\\t"; break; + case '\'': a = "\\\'"; break; + case '\"': a = "\\\""; break; + case '\\': a = "\\\\"; break; + case ' ': a = " "; break; + default: + hex_char_buf[2] = "0123456789abcdef"[*p >> 4]; + hex_char_buf[3] = "0123456789abcdef"[*p & 0xf]; + a = hex_char_buf; + } + strcpy(dst, a); + dst += strlen(a); + p++; + } +} + +// taken from kernel +#define COMMAND_LINE_SIZE 2048 +char* get_cmdline(pid_t pid) +{ + char path[sizeof("/proc/%lu/cmdline") + sizeof(long)*3]; + char cmdline[COMMAND_LINE_SIZE]; + char escaped_cmdline[COMMAND_LINE_SIZE*4 + 4]; + + escaped_cmdline[1] = '\0'; + sprintf(path, "/proc/%lu/cmdline", (long)pid); + int fd = open(path, O_RDONLY); + if (fd >= 0) + { + int len = read(fd, cmdline, sizeof(cmdline) - 1); + close(fd); + + if (len > 0) + { + cmdline[len] = '\0'; + char *src = cmdline; + char *dst = escaped_cmdline; + while ((src - cmdline) < len) + { + dst = append_escaped(dst, src); + src += strlen(src) + 1; + } + } + } + + return xstrdup(escaped_cmdline + 1); /* +1 skips extraneous leading space */ +} + +int daemon_is_ok() +{ + int fd = open(VAR_RUN_PID_FILE, O_RDONLY); + if (fd < 0) + { + return 0; + } + + char pid[sizeof(pid_t)*3 + 2]; + int len = read(fd, pid, sizeof(pid)-1); + close(fd); + if (len <= 0) + return 0; + + pid[len] = '\0'; + *strchrnul(pid, '\n') = '\0'; + /* paranoia: we don't want to check /proc//stat or /proc///stat */ + if (pid[0] == '\0' || pid[0] == '/') + return 0; + + /* TODO: maybe readlink and check that it is "xxx/abrt"? */ + char path[sizeof("/proc/%s/stat") + sizeof(pid)]; + sprintf(path, "/proc/%s/stat", pid); + struct stat sb; + if (stat(path, &sb) == -1) + { + return 0; + } + + return 1; +} diff --git a/src/lib/database.c b/src/lib/database.c new file mode 100644 index 00000000..2b742ebf --- /dev/null +++ b/src/lib/database.c @@ -0,0 +1,73 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 "database.h" + +struct db_row *db_rowcpy_from_list(GList* list) +{ + GList *first = g_list_first(list); + struct db_row *row = (struct db_row*)xzalloc(sizeof(struct db_row)); + struct db_row *src_row = (struct db_row*)first->data; + /* All fields are initialized below, copying is not needed + * memcpy(row, (struct db_row*)first->data, sizeof(struct db_row)); + */ + + row->db_uuid = xstrdup(src_row->db_uuid); + row->db_uid = xstrdup(src_row->db_uid); + row->db_inform_all = xstrdup(src_row->db_inform_all); + row->db_dump_dir = xstrdup(src_row->db_dump_dir); + row->db_count = xstrdup(src_row->db_count); + row->db_reported = xstrdup(src_row->db_reported); + row->db_message = xstrdup(src_row->db_message); + row->db_time = xstrdup(src_row->db_time); + + return row; +} + +void db_row_free(struct db_row *row) +{ + if (!row) + return; + + free(row->db_uuid); + free(row->db_uid); + free(row->db_inform_all); + free(row->db_dump_dir); + free(row->db_count); + free(row->db_reported); + free(row->db_message); + free(row->db_time); + + free(row); +} + +void db_list_free(GList *list) +{ + if (!list) + return; + + for (GList *li = list; li != NULL; li = g_list_next(li)) + { + struct db_row *row = (struct db_row*)li->data; + db_row_free(row); + } + g_list_free(list); +} + diff --git a/src/lib/dirsize.c b/src/lib/dirsize.c new file mode 100644 index 00000000..be927ad5 --- /dev/null +++ b/src/lib/dirsize.c @@ -0,0 +1,110 @@ +/* + Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) + Copyright (C) 2009 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" + +double get_dirsize(const char *pPath) +{ + DIR *dp = opendir(pPath); + if (dp == NULL) + return 0; + + struct dirent *ep; + struct stat statbuf; + double size = 0; + while ((ep = readdir(dp)) != NULL) + { + if (dot_or_dotdot(ep->d_name)) + continue; + char *dname = concat_path_file(pPath, ep->d_name); + if (lstat(dname, &statbuf) != 0) + { + free(dname); + continue; + } + if (S_ISDIR(statbuf.st_mode)) + { + size += get_dirsize(dname); + } + else if (S_ISREG(statbuf.st_mode)) + { + size += statbuf.st_size; + } + free(dname); + } + closedir(dp); + return size; +} + +double get_dirsize_find_largest_dir( + const char *pPath, + char **worst_dir, + const char *excluded) +{ + if (worst_dir) + *worst_dir = NULL; + + DIR *dp = opendir(pPath); + if (dp == NULL) + return 0; + + struct dirent *ep; + struct stat statbuf; + double size = 0; + double maxsz = 0; + while ((ep = readdir(dp)) != NULL) + { + if (dot_or_dotdot(ep->d_name)) + continue; + char *dname = concat_path_file(pPath, ep->d_name); + if (lstat(dname, &statbuf) != 0) + { + free(dname); + continue; + } + if (S_ISDIR(statbuf.st_mode)) + { + double sz = get_dirsize(dname); + size += sz; + + if (worst_dir && (!excluded || strcmp(excluded, ep->d_name) != 0)) + { + /* Calculate "weighted" size and age + * w = sz_kbytes * age_mins */ + sz /= 1024; + long age = (time(NULL) - statbuf.st_mtime) / 60; + if (age > 0) + sz *= age; + + if (sz > maxsz) + { + maxsz = sz; + free(*worst_dir); + *worst_dir = xstrdup(ep->d_name); + } + } + } + else if (S_ISREG(statbuf.st_mode)) + { + size += statbuf.st_size; + } + free(dname); + } + closedir(dp); + return size; +} diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c new file mode 100644 index 00000000..0328bb26 --- /dev/null +++ b/src/lib/dump_dir.c @@ -0,0 +1,504 @@ +/* + DebugDump.cpp + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 +#include "abrtlib.h" +#include "strbuf.h" + +// TODO: +// +// Perhaps dd_opendir should do some sanity checking like +// "if there is no "uid" file in the directory, it's not a crash dump", +// and fail. + +static char *load_text_file(const char *path, unsigned flags); + +static bool isdigit_str(const char *str) +{ + do + { + if (*str < '0' || *str > '9') return false; + str++; + } while (*str); + return true; +} + +static bool exist_file_dir(const char *path) +{ + struct stat buf; + if (stat(path, &buf) == 0) + { + if (S_ISDIR(buf.st_mode) || S_ISREG(buf.st_mode)) + { + return true; + } + } + return false; +} + +static bool get_and_set_lock(const char* lock_file, const char* pid) +{ + while (symlink(pid, lock_file) != 0) + { + if (errno != EEXIST) + perror_msg_and_die("Can't create lock file '%s'", lock_file); + + char pid_buf[sizeof(pid_t)*3 + 4]; + ssize_t r = readlink(lock_file, pid_buf, sizeof(pid_buf) - 1); + if (r < 0) + { + if (errno == ENOENT) + { + /* Looks like lock_file was deleted */ + usleep(10 * 1000); /* avoid CPU eating loop */ + continue; + } + perror_msg_and_die("Can't read lock file '%s'", lock_file); + } + pid_buf[r] = '\0'; + + if (strcmp(pid_buf, pid) == 0) + { + log("Lock file '%s' is already locked by us", lock_file); + return false; + } + if (isdigit_str(pid_buf)) + { + char pid_str[sizeof("/proc/") + strlen(pid_buf)]; + sprintf(pid_str, "/proc/%s", pid_buf); + if (access(pid_str, F_OK) == 0) + { + log("Lock file '%s' is locked by process %s", lock_file, pid_buf); + return false; + } + log("Lock file '%s' was locked by process %s, but it crashed?", lock_file, pid_buf); + } + /* The file may be deleted by now by other process. Ignore ENOENT */ + if (unlink(lock_file) != 0 && errno != ENOENT) + { + perror_msg_and_die("Can't remove stale lock file '%s'", lock_file); + } + } + + VERB1 log("Locked '%s'", lock_file); + return true; +} + +static void dd_lock(struct dump_dir *dd) +{ + if (dd->locked) + error_msg_and_die("Locking bug on '%s'", dd->dd_dir); + + char lock_buf[strlen(dd->dd_dir) + sizeof(".lock")]; + sprintf(lock_buf, "%s.lock", dd->dd_dir); + + char pid_buf[sizeof(long)*3 + 2]; + sprintf(pid_buf, "%lu", (long)getpid()); + while ((dd->locked = get_and_set_lock(lock_buf, pid_buf)) != true) + { + sleep(1); /* was 0.5 seconds */ + } +} + +static void dd_unlock(struct dump_dir *dd) +{ + if (dd->locked) + { + dd->locked = 0; + char lock_buf[strlen(dd->dd_dir) + sizeof(".lock")]; + sprintf(lock_buf, "%s.lock", dd->dd_dir); + xunlink(lock_buf); + VERB1 log("Unlocked '%s'", lock_buf); + } +} + +static inline struct dump_dir *dd_init(void) +{ + return (struct dump_dir*)xzalloc(sizeof(struct dump_dir)); +} + +int dd_exist(struct dump_dir *dd, const char *path) +{ + char *full_path = concat_path_file(dd->dd_dir, path); + int ret = exist_file_dir(full_path); + free(full_path); + return ret; +} + +void dd_close(struct dump_dir *dd) +{ + if (!dd) + return; + + dd_unlock(dd); + if (dd->next_dir) + { + closedir(dd->next_dir); + /* free(dd->next_dir); - WRONG! */ + } + + free(dd->dd_dir); + free(dd); +} + +static char* rm_trailing_slashes(const char *dir) +{ + unsigned len = strlen(dir); + while (len != 0 && dir[len-1] == '/') + len--; + return xstrndup(dir, len); +} + +struct dump_dir *dd_opendir(const char *dir, int flags) +{ + struct dump_dir *dd = dd_init(); + + /* Used to use rm_trailing_slashes(dir) here, but with dir = "." + * or "..", or if the last component is a symlink, + * then lock file is created in the wrong place. + * IOW: this breaks locking. + */ + dd->dd_dir = realpath(dir, NULL); + if (!dd->dd_dir) + { + if (!(flags & DD_FAIL_QUIETLY)) + error_msg("'%s' does not exist", dir); + dd_close(dd); + return NULL; + } + dir = dd->dd_dir; + + dd_lock(dd); + + struct stat stat_buf; + if (stat(dir, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode)) + { + if (!(flags & DD_FAIL_QUIETLY)) + error_msg("'%s' does not exist", dir); + dd_close(dd); + return NULL; + } + + /* In case caller would want to create more files, he'll need uid:gid */ + dd->dd_uid = stat_buf.st_uid; + dd->dd_gid = stat_buf.st_gid; + + /* Without this check, e.g. abrt-action-print happily prints any current + * directory when run without arguments, because its option -d DIR + * defaults to "."! Let's require that at least some crash dump dir + * specific files exist before we declare open successful: + */ + char *name = concat_path_file(dir, FILENAME_ANALYZER); + int bad = (lstat(name, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)); + free(name); + if (bad) + { + /*if (!(flags & DD_FAIL_QUIETLY))... - no, DD_FAIL_QUIETLY only means + * "it's ok if it doesn exist", not "ok if contents is bogus"! + */ + error_msg("'%s' is not a crash dump directory", dir); + dd_close(dd); + return NULL; + } + + return dd; +} + +/* Create a fresh empty debug dump dir. + * + * Security: we should not allow users to write new files or write + * into existing ones, but they should be able to read them. + * + * @param uid + * Crashed application's User Id + * + * We currently have only three callers: + * kernel oops hook: uid=0 + * this hook runs under 0:0 + * ccpp hook: uid=uid of crashed user's binary + * this hook runs under 0:0 + * python hook: uid=uid of crashed user's script + * this hook runs under abrt:gid + * + * Currently, we set dir's gid to passwd(uid)->pw_gid parameter, and we set uid to + * abrt's user id. We do not allow write access to group. + */ +struct dump_dir *dd_create(const char *dir, uid_t uid) +{ + struct dump_dir *dd = dd_init(); + + /* Unlike dd_opendir, can't use realpath: the directory doesn't exist yet, + * realpath will always return NULL. We don't really have to: + * dd_opendir(".") makes sense, dd_create(".") does not. + */ + dir = dd->dd_dir = rm_trailing_slashes(dir); + + const char *last_component = strrchr(dir, '/'); + if (last_component) + last_component++; + else + last_component = dir; + if (dot_or_dotdot(last_component)) + { + /* dd_create("."), dd_create(".."), dd_create("dir/."), + * dd_create("dir/..") and similar are madness, refuse them. + */ + error_msg("Bad dir name '%s'", dir); + dd_close(dd); + return NULL; + } + + dd_lock(dd); + + /* Was creating it with mode 0700 and user as the owner, but this allows + * the user to replace any file in the directory, changing security-sensitive data + * (e.g. "uid", "analyzer", "executable") + */ + if (mkdir(dir, 0750) == -1) + { + perror_msg("Can't create dir '%s'", dir); + dd_close(dd); + return NULL; + } + + /* mkdir's mode (above) can be affected by umask, fix it */ + if (chmod(dir, 0750) == -1) + { + perror_msg("Can't change mode of '%s'", dir); + dd_close(dd); + return NULL; + } + + /* Get ABRT's user id */ + /*dd->dd_uid = 0; - dd_init did this already */ + struct passwd *pw = getpwnam("abrt"); + if (pw) + dd->dd_uid = pw->pw_uid; + else + error_msg("User 'abrt' does not exist, using uid 0"); + + /* Get crashed application's group id */ + /*dd->dd_gid = 0; - dd_init did this already */ + pw = getpwuid(uid); + if (pw) + dd->dd_gid = pw->pw_gid; + else + error_msg("User %lu does not exist, using gid 0", (long)uid); + + if (chown(dir, dd->dd_uid, dd->dd_gid) == -1) + { + perror_msg("Can't change '%s' ownership to %lu:%lu", dir, + (long)dd->dd_uid, (long)dd->dd_gid); + } + + char long_str[sizeof(long) * 3 + 2]; + + sprintf(long_str, "%lu", (long)uid); + dd_save_text(dd, CD_UID, long_str); + + struct utsname buf; + uname(&buf); /* never fails */ + dd_save_text(dd, FILENAME_KERNEL, buf.release); + dd_save_text(dd, FILENAME_ARCHITECTURE, buf.machine); + char *release = load_text_file("/etc/redhat-release", /*flags:*/ 0); + strchrnul(release, '\n')[0] = '\0'; + dd_save_text(dd, FILENAME_RELEASE, release); + free(release); + + time_t t = time(NULL); + sprintf(long_str, "%lu", (long)t); + dd_save_text(dd, FILENAME_TIME, long_str); + + return dd; +} + +static void delete_file_dir(const char *dir) +{ + DIR *d = opendir(dir); + if (!d) + return; + + struct dirent *dent; + while ((dent = readdir(d)) != NULL) + { + if (dot_or_dotdot(dent->d_name)) + continue; + char *full_path = concat_path_file(dir, dent->d_name); + if (unlink(full_path) == -1 && errno != ENOENT) + { + if (errno != EISDIR) + { + error_msg("Can't remove '%s'", full_path); + free(full_path); + closedir(d); + return; + } + delete_file_dir(full_path); + } + free(full_path); + } + closedir(d); + if (rmdir(dir) == -1) + { + error_msg("Can't remove dir '%s'", dir); + } +} + +void dd_delete(struct dump_dir *dd) +{ + delete_file_dir(dd->dd_dir); +} + +static char *load_text_file(const char *path, unsigned flags) +{ + FILE *fp = fopen(path, "r"); + if (!fp) + { + if (!(flags & DD_FAIL_QUIETLY)) + perror_msg("Can't open file '%s'", path); + return (flags & DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE ? NULL : xstrdup("")); + } + + struct strbuf *buf_content = strbuf_new(); + int ch; + while ((ch = fgetc(fp)) != EOF) + { + if (ch == '\0') + strbuf_append_char(buf_content, ' '); + else if (isspace(ch) || (isascii(ch) && !iscntrl(ch))) + strbuf_append_char(buf_content, ch); + } + fclose(fp); + + return strbuf_free_nobuf(buf_content); +} + +static bool save_binary_file(const char *path, const char* data, unsigned size, uid_t uid, gid_t gid) +{ + /* "Why 0640?!" See ::Create() for security analysis */ + unlink(path); + int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0640); + if (fd < 0) + { + perror_msg("Can't open file '%s'", path); + return false; + } + if (fchown(fd, uid, gid) == -1) + { + perror_msg("can't change '%s' ownership to %lu:%lu", path, (long)uid, (long)gid); + } + unsigned r = full_write(fd, data, size); + close(fd); + if (r != size) + { + error_msg("Can't save file '%s'", path); + return false; + } + + return true; +} + +char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned flags) +{ + if (!dd->locked) + error_msg_and_die("dump_dir is not opened"); /* bug */ + + char *full_path = concat_path_file(dd->dd_dir, name); + char *ret = load_text_file(full_path, flags); + free(full_path); + + return ret; +} + +char* dd_load_text(const struct dump_dir *dd, const char *name) +{ + return dd_load_text_ext(dd, name, /*flags:*/ 0); +} + +void dd_save_text(struct dump_dir *dd, const char *name, const char *data) +{ + if (!dd->locked) + error_msg_and_die("dump_dir is not opened"); /* bug */ + + char *full_path = concat_path_file(dd->dd_dir, name); + save_binary_file(full_path, data, strlen(data), dd->dd_uid, dd->dd_gid); + free(full_path); +} + +void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, unsigned size) +{ + if (!dd->locked) + error_msg_and_die("dump_dir is not opened"); /* bug */ + + char *full_path = concat_path_file(dd->dd_dir, name); + save_binary_file(full_path, data, size, dd->dd_uid, dd->dd_gid); + free(full_path); +} + +DIR *dd_init_next_file(struct dump_dir *dd) +{ + if (!dd->locked) + error_msg_and_die("dump_dir is not opened"); /* bug */ + + if (dd->next_dir) + closedir(dd->next_dir); + + dd->next_dir = opendir(dd->dd_dir); + if (!dd->next_dir) + { + error_msg("Can't open dir '%s'", dd->dd_dir); + } + + return dd->next_dir; +} + +int dd_get_next_file(struct dump_dir *dd, char **short_name, char **full_name) +{ + if (dd->next_dir == NULL) + return 0; + + struct dirent *dent; + while ((dent = readdir(dd->next_dir)) != NULL) + { + if (is_regular_file(dent, dd->dd_dir)) + { + if (short_name) + *short_name = xstrdup(dent->d_name); + if (full_name) + *full_name = concat_path_file(dd->dd_dir, dent->d_name); + return 1; + } + } + + closedir(dd->next_dir); + dd->next_dir = NULL; + return 0; +} + +/* Utility function */ +void delete_debug_dump_dir(const char *dd_dir) +{ + struct dump_dir *dd = dd_opendir(dd_dir, /*flags:*/ 0); + if (dd) + { + dd_delete(dd); + dd_close(dd); + } +} diff --git a/src/lib/encbase64.c b/src/lib/encbase64.c new file mode 100644 index 00000000..6a6f1f75 --- /dev/null +++ b/src/lib/encbase64.c @@ -0,0 +1,78 @@ +/* + * Copyright 2006 Rob Landley + * + * Licensed under GPLv2 or later. + */ +#include "abrtlib.h" /* xmalloc */ + +/* Conversion table for base 64 */ +static const char tbl_base64[65 /*+ 2*/] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/', + '=' /* termination character */, + // '\n', '\0' /* needed for uudecode.c */ +}; + +/* Conversion table for uuencode +const char tbl_uuencode[65] ALIGN1 = { + '`', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`' +}; +*/ + +/* + * Encode bytes at S of length LENGTH. + * Result will be 0-terminated, and must point to a writable + * buffer of at least 1+BASE64_LENGTH(length) bytes, + * where BASE64_LENGTH(len) = 4 * ((LENGTH + 2) / 3) + */ +static void encode_64bit(char *p, const void *src, int length, const char *tbl) +{ + const unsigned char *s = (const unsigned char *)src; + + /* Transform the 3x8 bits to 4x6 bits */ + while (length > 0) { + unsigned s1, s2; + + /* Are s[1], s[2] valid or should be assumed 0? */ + s1 = s2 = 0; + length -= 3; /* can be >=0, -1, -2 */ + if (length >= -1) { + s1 = s[1]; + if (length >= 0) + s2 = s[2]; + } + *p++ = tbl[s[0] >> 2]; + *p++ = tbl[((s[0] & 3) << 4) + (s1 >> 4)]; + *p++ = tbl[((s1 & 0xf) << 2) + (s2 >> 6)]; + *p++ = tbl[s2 & 0x3f]; + s += 3; + } + /* Zero-terminate */ + *p = '\0'; + /* If length is -2 or -1, pad last char or two */ + while (length) { + *--p = tbl[64]; + length++; + } +} + +char *encode_base64(const void *src, int length) +{ + char *dst = (char *)xmalloc(4 * ((length + 2) / 3) + 1); + encode_64bit(dst, src, length, tbl_base64); + return dst; +} diff --git a/src/lib/hash_md5.c b/src/lib/hash_md5.c new file mode 100644 index 00000000..8bfddd54 --- /dev/null +++ b/src/lib/hash_md5.c @@ -0,0 +1,444 @@ +/* vi: set sw=4 ts=4: */ +/* + * md5.c - Compute MD5 checksum of strings according to the + * definition of MD5 in RFC 1321 from April 1992. + * + * Written by Ulrich Drepper , 1995. + * + * Copyright (C) 1995-1999 Free Software Foundation, Inc. + * Copyright (C) 2001 Manuel Novoa III + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. + */ +#include "abrtlib.h" +#include + +#if defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ +# define MD5_BIG_ENDIAN 1 +# define MD5_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __BIG_ENDIAN +# define MD5_BIG_ENDIAN 1 +# define MD5_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define MD5_BIG_ENDIAN 0 +# define MD5_LITTLE_ENDIAN 1 +#else +# error "Can't determine endianness" +#endif + +/* SWAP_LEnn means "convert CPU<->little_endian if needed (by swapping bytes)" */ +#if MD5_BIG_ENDIAN +# define SWAP_BE32(x) (x) +# define SWAP_LE32(x) bswap_32(x) +#else +# define SWAP_BE32(x) bswap_32(x) +# define SWAP_LE32(x) (x) +#endif + + +/* 0: fastest, 3: smallest */ +#define MD5_SIZE_VS_SPEED 3 + +/* Initialize structure containing state of computation. + * (RFC 1321, 3.3: Step 3) + */ +void md5_begin(md5_ctx_t *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + ctx->total = 0; + ctx->buflen = 0; +} + +/* These are the four functions used in the four steps of the MD5 algorithm + * and defined in the RFC 1321. The first function is a little bit optimized + * (as found in Colin Plumbs public domain implementation). + * #define FF(b, c, d) ((b & c) | (~b & d)) + */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF(d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) + +/* Hash a single block, 64 bytes long and 4-byte aligned. */ +static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) +{ + uint32_t correct_words[16]; + const uint32_t *words = (const uint32_t *)buffer; + +#if MD5_SIZE_VS_SPEED > 0 + static const uint32_t C_array[] = { + /* round 1 */ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + /* round 2 */ + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + /* round 3 */ + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + /* round 4 */ + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + static const char P_array[] = { +# if MD5_SIZE_VS_SPEED > 1 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ +# endif + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ + }; +# if MD5_SIZE_VS_SPEED > 1 + static const char S_array[] = { + 7, 12, 17, 22, + 5, 9, 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21 + }; +# endif /* MD5_SIZE_VS_SPEED > 1 */ +#endif + uint32_t A = ctx->A; + uint32_t B = ctx->B; + uint32_t C = ctx->C; + uint32_t D = ctx->D; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + uint32_t *cwp = correct_words; + uint32_t A_save = A; + uint32_t B_save = B; + uint32_t C_save = C; + uint32_t D_save = D; + +#if MD5_SIZE_VS_SPEED > 1 + const uint32_t *pc; + const char *pp; + const char *ps; + int i; + uint32_t temp; + + for (i = 0; i < 16; i++) { + cwp[i] = SWAP_LE32(words[i]); + } + words += 16; + +# if MD5_SIZE_VS_SPEED > 2 + pc = C_array; + pp = P_array; + ps = S_array - 4; + + for (i = 0; i < 64; i++) { + if ((i & 0x0f) == 0) + ps += 4; + temp = A; + switch (i >> 4) { + case 0: + temp += FF(B, C, D); + break; + case 1: + temp += FG(B, C, D); + break; + case 2: + temp += FH(B, C, D); + break; + case 3: + temp += FI(B, C, D); + } + temp += cwp[(int) (*pp++)] + *pc++; + temp = rotl32(temp, ps[i & 3]); + temp += B; + A = D; + D = C; + C = B; + B = temp; + } +# else + pc = C_array; + pp = P_array; + ps = S_array; + + for (i = 0; i < 16; i++) { + temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = rotl32(temp, ps[i & 3]); + temp += B; + A = D; + D = C; + C = B; + B = temp; + } + ps += 4; + for (i = 0; i < 16; i++) { + temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = rotl32(temp, ps[i & 3]); + temp += B; + A = D; + D = C; + C = B; + B = temp; + } + ps += 4; + for (i = 0; i < 16; i++) { + temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = rotl32(temp, ps[i & 3]); + temp += B; + A = D; + D = C; + C = B; + B = temp; + } + ps += 4; + for (i = 0; i < 16; i++) { + temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++; + temp = rotl32(temp, ps[i & 3]); + temp += B; + A = D; + D = C; + C = B; + B = temp; + } + +# endif /* MD5_SIZE_VS_SPEED > 2 */ +#else + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ +# define OP(a, b, c, d, s, T) \ + do { \ + a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \ + ++words; \ + a = rotl32(a, s); \ + a += b; \ + } while (0) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 + */ + +# if MD5_SIZE_VS_SPEED == 1 + const uint32_t *pc; + const char *pp; + int i; +# endif /* MD5_SIZE_VS_SPEED */ + + /* Round 1. */ +# if MD5_SIZE_VS_SPEED == 1 + pc = C_array; + for (i = 0; i < 4; i++) { + OP(A, B, C, D, 7, *pc++); + OP(D, A, B, C, 12, *pc++); + OP(C, D, A, B, 17, *pc++); + OP(B, C, D, A, 22, *pc++); + } +# else + OP(A, B, C, D, 7, 0xd76aa478); + OP(D, A, B, C, 12, 0xe8c7b756); + OP(C, D, A, B, 17, 0x242070db); + OP(B, C, D, A, 22, 0xc1bdceee); + OP(A, B, C, D, 7, 0xf57c0faf); + OP(D, A, B, C, 12, 0x4787c62a); + OP(C, D, A, B, 17, 0xa8304613); + OP(B, C, D, A, 22, 0xfd469501); + OP(A, B, C, D, 7, 0x698098d8); + OP(D, A, B, C, 12, 0x8b44f7af); + OP(C, D, A, B, 17, 0xffff5bb1); + OP(B, C, D, A, 22, 0x895cd7be); + OP(A, B, C, D, 7, 0x6b901122); + OP(D, A, B, C, 12, 0xfd987193); + OP(C, D, A, B, 17, 0xa679438e); + OP(B, C, D, A, 22, 0x49b40821); +# endif /* MD5_SIZE_VS_SPEED == 1 */ + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +# undef OP +# define OP(f, a, b, c, d, k, s, T) \ + do { \ + a += f(b, c, d) + correct_words[k] + T; \ + a = rotl32(a, s); \ + a += b; \ + } while (0) + + /* Round 2. */ +# if MD5_SIZE_VS_SPEED == 1 + pp = P_array; + for (i = 0; i < 4; i++) { + OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++); + OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++); + OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++); + OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++); + } +# else + OP(FG, A, B, C, D, 1, 5, 0xf61e2562); + OP(FG, D, A, B, C, 6, 9, 0xc040b340); + OP(FG, C, D, A, B, 11, 14, 0x265e5a51); + OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP(FG, A, B, C, D, 5, 5, 0xd62f105d); + OP(FG, D, A, B, C, 10, 9, 0x02441453); + OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP(FG, D, A, B, C, 14, 9, 0xc33707d6); + OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP(FG, B, C, D, A, 8, 20, 0x455a14ed); + OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP(FG, C, D, A, B, 7, 14, 0x676f02d9); + OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); +# endif /* MD5_SIZE_VS_SPEED == 1 */ + + /* Round 3. */ +# if MD5_SIZE_VS_SPEED == 1 + for (i = 0; i < 4; i++) { + OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++); + OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++); + OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++); + OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++); + } +# else + OP(FH, A, B, C, D, 5, 4, 0xfffa3942); + OP(FH, D, A, B, C, 8, 11, 0x8771f681); + OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP(FH, B, C, D, A, 14, 23, 0xfde5380c); + OP(FH, A, B, C, D, 1, 4, 0xa4beea44); + OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP(FH, B, C, D, A, 6, 23, 0x04881d05); + OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); +# endif /* MD5_SIZE_VS_SPEED == 1 */ + + /* Round 4. */ +# if MD5_SIZE_VS_SPEED == 1 + for (i = 0; i < 4; i++) { + OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++); + OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++); + OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++); + OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++); + } +# else + OP(FI, A, B, C, D, 0, 6, 0xf4292244); + OP(FI, D, A, B, C, 7, 10, 0x432aff97); + OP(FI, C, D, A, B, 14, 15, 0xab9423a7); + OP(FI, B, C, D, A, 5, 21, 0xfc93a039); + OP(FI, A, B, C, D, 12, 6, 0x655b59c3); + OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP(FI, C, D, A, B, 10, 15, 0xffeff47d); + OP(FI, B, C, D, A, 1, 21, 0x85845dd1); + OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP(FI, C, D, A, B, 6, 15, 0xa3014314); + OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP(FI, A, B, C, D, 4, 6, 0xf7537e82); + OP(FI, D, A, B, C, 11, 10, 0xbd3af235); + OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP(FI, B, C, D, A, 9, 21, 0xeb86d391); +# endif /* MD5_SIZE_VS_SPEED == 1 */ +#endif /* MD5_SIZE_VS_SPEED > 1 */ + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} + +/* Feed data through a temporary buffer to call md5_hash_aligned_block() + * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. + * This function's internal buffer remembers previous data until it has 64 + * bytes worth to pass on. Call md5_end() to flush this buffer. */ +void md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) +{ + char *buf = (char *)buffer; + + /* RFC 1321 specifies the possible length of the file up to 2^64 bits, + * Here we only track the number of bytes. */ + ctx->total += len; + + /* Process all input. */ + while (len) { + unsigned i = 64 - ctx->buflen; + + /* Copy data into aligned buffer. */ + if (i > len) i = len; + memcpy(ctx->buffer + ctx->buflen, buf, i); + len -= i; + ctx->buflen += i; + buf += i; + + /* When buffer fills up, process it. */ + if (ctx->buflen == 64) { + md5_hash_block(ctx->buffer, ctx); + ctx->buflen = 0; + } + } +} + +/* Process the remaining bytes in the buffer and put result from CTX + * in first 16 bytes following RESBUF. The result is always in little + * endian byte order, so that a byte-wise output yields to the wanted + * ASCII representation of the message digest. + */ +void md5_end(void *resbuf, md5_ctx_t *ctx) +{ + char *buf = ctx->buffer; + int i; + + /* Pad data to block size. */ + buf[ctx->buflen++] = 0x80; + memset(buf + ctx->buflen, 0, 128 - ctx->buflen); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + ctx->total <<= 3; + if (ctx->buflen > 56) + buf += 64; + for (i = 0; i < 8; i++) + buf[56 + i] = ctx->total >> (i*8); + + /* Process last bytes. */ + if (buf != ctx->buffer) + md5_hash_block(ctx->buffer, ctx); + md5_hash_block(buf, ctx); + + /* The MD5 result is in little endian byte order. + * We (ab)use the fact that A-D are consecutive in memory. + */ +#if MD5_BIG_ENDIAN + ctx->A = SWAP_LE32(ctx->A); + ctx->B = SWAP_LE32(ctx->B); + ctx->C = SWAP_LE32(ctx->C); + ctx->D = SWAP_LE32(ctx->D); +#endif + memcpy(resbuf, &ctx->A, sizeof(ctx->A) * 4); +} diff --git a/src/lib/hash_md5.h b/src/lib/hash_md5.h new file mode 100644 index 00000000..cc1d2c43 --- /dev/null +++ b/src/lib/hash_md5.h @@ -0,0 +1,29 @@ +/* vi: set sw=4 ts=4: */ +/* + * md5.c - Compute MD5 checksum of strings according to the + * definition of MD5 in RFC 1321 from April 1992. + * + * Written by Ulrich Drepper , 1995. + * + * Copyright (C) 1995-1999 Free Software Foundation, Inc. + * Copyright (C) 2001 Manuel Novoa III + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. + */ + +#define MD5_RESULT_LEN 16 + +typedef struct md5_ctx_t { + uint32_t A; + uint32_t B; + uint32_t C; + uint32_t D; + uint64_t total; + uint32_t buflen; + char buffer[128]; +} md5_ctx_t; +void md5_begin(md5_ctx_t *ctx); +void md5_hash(const void *data, size_t length, md5_ctx_t *ctx); +void md5_end(void *resbuf, md5_ctx_t *ctx); diff --git a/src/lib/hash_sha1.c b/src/lib/hash_sha1.c new file mode 100644 index 00000000..954e7bc8 --- /dev/null +++ b/src/lib/hash_sha1.c @@ -0,0 +1,213 @@ +/* vi: set sw=4 ts=4: */ +/* + * Based on shasum from http://www.netsw.org/crypto/hash/ + * Majorly hacked up to use Dr Brian Gladman's sha1 code + * + * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK. + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * + * --------------------------------------------------------------------------- + * Issue Date: 10/11/2002 + * + * This is a byte oriented version of SHA1 that operates on arrays of bytes + * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor + * + * --------------------------------------------------------------------------- + */ +#include "abrtlib.h" + +#if defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ +# define SHA1_BIG_ENDIAN 1 +# define SHA1_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __BIG_ENDIAN +# define SHA1_BIG_ENDIAN 1 +# define SHA1_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define SHA1_BIG_ENDIAN 0 +# define SHA1_LITTLE_ENDIAN 1 +#else +# error "Can't determine endianness" +#endif + + +#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) +/* for sha512: */ +#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) +#if SHA1_LITTLE_ENDIAN +static inline uint64_t hton64(uint64_t v) +{ + return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); +} +#else +#define hton64(v) (v) +#endif +#define ntoh64(v) hton64(v) + +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +#if defined(__GNUC__) && __GNUC__ >= 2 +# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0) +#else +# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0) +#endif + + +/* Some arch headers have conflicting defines */ +#undef ch +#undef parity +#undef maj +#undef rnd + +static void sha1_process_block64(sha1_ctx_t *ctx) +{ + unsigned t; + uint32_t W[80], a, b, c, d, e; + const uint32_t *words = (uint32_t*) ctx->wbuffer; + + for (t = 0; t < 16; ++t) { + W[t] = ntohl(*words); + words++; + } + + for (/*t = 16*/; t < 80; ++t) { + uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; + W[t] = rotl32(T, 1); + } + + a = ctx->hash[0]; + b = ctx->hash[1]; + c = ctx->hash[2]; + d = ctx->hash[3]; + e = ctx->hash[4]; + +/* Reverse byte order in 32-bit words */ +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +/* A normal version as set out in the FIPS. This version uses */ +/* partial loop unrolling and is optimised for the Pentium 4 */ +#define rnd(f,k) \ + do { \ + uint32_t T = a; \ + a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \ + e = d; \ + d = c; \ + c = rotl32(b, 30); \ + b = T; \ + } while (0) + + for (t = 0; t < 20; ++t) + rnd(ch, 0x5a827999); + + for (/*t = 20*/; t < 40; ++t) + rnd(parity, 0x6ed9eba1); + + for (/*t = 40*/; t < 60; ++t) + rnd(maj, 0x8f1bbcdc); + + for (/*t = 60*/; t < 80; ++t) + rnd(parity, 0xca62c1d6); +#undef ch +#undef parity +#undef maj +#undef rnd + + ctx->hash[0] += a; + ctx->hash[1] += b; + ctx->hash[2] += c; + ctx->hash[3] += d; + ctx->hash[4] += e; +} + +void sha1_begin(sha1_ctx_t *ctx) +{ + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; + ctx->total64 = 0; + ctx->process_block = sha1_process_block64; +} + +static const uint32_t init256[] = { + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 +}; +static const uint32_t init512_lo[] = { + 0xf3bcc908, + 0x84caa73b, + 0xfe94f82b, + 0x5f1d36f1, + 0xade682d1, + 0x2b3e6c1f, + 0xfb41bd6b, + 0x137e2179 +}; + +/* Used also for sha256 */ +void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) +{ + unsigned in_buf = ctx->total64 & 63; + unsigned add = 64 - in_buf; + + ctx->total64 += len; + + while (len >= add) { /* transfer whole blocks while possible */ + memcpy(ctx->wbuffer + in_buf, buffer, add); + buffer = (const char *)buffer + add; + len -= add; + add = 64; + in_buf = 0; + ctx->process_block(ctx); + } + + memcpy(ctx->wbuffer + in_buf, buffer, len); +} + +/* Used also for sha256 */ +void sha1_end(void *resbuf, sha1_ctx_t *ctx) +{ + unsigned pad, in_buf; + + in_buf = ctx->total64 & 63; + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ + ctx->wbuffer[in_buf++] = 0x80; + + /* This loop iterates either once or twice, no more, no less */ + while (1) { + pad = 64 - in_buf; + memset(ctx->wbuffer + in_buf, 0, pad); + in_buf = 0; + /* Do we have enough space for the length count? */ + if (pad >= 8) { + /* Store the 64-bit counter of bits in the buffer in BE format */ + uint64_t t = ctx->total64 << 3; + t = hton64(t); + /* wbuffer is suitably aligned for this */ + *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; + } + ctx->process_block(ctx); + if (pad >= 8) + break; + } + + in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8; + /* This way we do not impose alignment constraints on resbuf: */ + if (SHA1_LITTLE_ENDIAN) { + unsigned i; + for (i = 0; i < in_buf; ++i) + ctx->hash[i] = htonl(ctx->hash[i]); + } + memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); +} diff --git a/src/lib/hash_sha1.h b/src/lib/hash_sha1.h new file mode 100644 index 00000000..02978ea4 --- /dev/null +++ b/src/lib/hash_sha1.h @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* + * Based on shasum from http://www.netsw.org/crypto/hash/ + * Majorly hacked up to use Dr Brian Gladman's sha1 code + * + * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK. + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * + * --------------------------------------------------------------------------- + * Issue Date: 10/11/2002 + * + * This is a byte oriented version of SHA1 that operates on arrays of bytes + * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor + * + * --------------------------------------------------------------------------- + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA1_RESULT_LEN (5 * 4) + +typedef struct sha1_ctx_t { + uint32_t hash[8]; /* 5, +3 elements for sha256 */ + uint64_t total64; + uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ + void (*process_block)(struct sha1_ctx_t*); +} sha1_ctx_t; + +void sha1_begin(sha1_ctx_t *ctx); +void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx); +void sha1_end(void *resbuf, sha1_ctx_t *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/src/lib/hooklib.c b/src/lib/hooklib.c new file mode 100644 index 00000000..062e3ddb --- /dev/null +++ b/src/lib/hooklib.c @@ -0,0 +1,138 @@ +/* + Copyright (C) 2009 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 "hooklib.h" +#include + +void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore, bool *setting_SaveBinaryImage) +{ + FILE *fp = fopen(CONF_DIR"/abrt.conf", "r"); + if (!fp) + return; + + while (1) + { + char *line = xmalloc_fgetline(fp); + if (!line) + { + fclose(fp); + if (additional_conf) + { + /* Next .conf file plz */ + fp = fopen(additional_conf, "r"); + if (fp) + { + additional_conf = NULL; + continue; + } + } + break; + } + + const char *p = skip_whitespace(line); +#undef DIRECTIVE +#define DIRECTIVE "MaxCrashReportsSize" + if (setting_MaxCrashReportsSize && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) + { + p = skip_whitespace(p + sizeof(DIRECTIVE)-1); + if (*p != '=') + goto free_line; + p = skip_whitespace(p + 1); + if (isdigit(*p)) + { + /* x1.25: go a bit up, so that usual in-daemon trimming + * kicks in first, and we don't "fight" with it. */ + *setting_MaxCrashReportsSize = (unsigned long)xatou(p) * 5 / 4; + } + goto free_line; + } +#undef DIRECTIVE +#define DIRECTIVE "MakeCompatCore" + if (setting_MakeCompatCore && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) + { + p = skip_whitespace(p + sizeof(DIRECTIVE)-1); + if (*p != '=') + goto free_line; + p = skip_whitespace(p + 1); + *setting_MakeCompatCore = string_to_bool(p); + goto free_line; + } +#undef DIRECTIVE +#define DIRECTIVE "SaveBinaryImage" + if (setting_SaveBinaryImage && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) + { + p = skip_whitespace(p + sizeof(DIRECTIVE)-1); + if (*p != '=') + goto free_line; + p = skip_whitespace(p + 1); + *setting_SaveBinaryImage = string_to_bool(p); + goto free_line; + } +#undef DIRECTIVE + /* add more 'if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)' here... */ + + free_line: + free(line); + } +} + +void check_free_space(unsigned setting_MaxCrashReportsSize) +{ + struct statvfs vfs; + if (statvfs(DEBUG_DUMPS_DIR, &vfs) != 0) + { + perror_msg_and_die("statvfs('%s')", DEBUG_DUMPS_DIR); + } + + /* Check that at least MaxCrashReportsSize/4 MBs are free */ + + /* fs_free_mb_x4 ~= vfs.f_bfree * vfs.f_bsize * 4, expressed in MBytes. + * Need to neither overflow nor round f_bfree down too much. */ + unsigned long fs_free_mb_x4 = ((unsigned long long)vfs.f_bfree / (1024/4)) * vfs.f_bsize / 1024; + if (fs_free_mb_x4 < setting_MaxCrashReportsSize) + { + error_msg_and_die("aborting dump: only %luMiB is available on %s", fs_free_mb_x4 / 4, DEBUG_DUMPS_DIR); + } +} + +/* rhbz#539551: "abrt going crazy when crashing process is respawned". + * Check total size of dump dir, if it overflows, + * delete oldest/biggest dumps. + */ +void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path) +{ + int count = 10; + while (--count >= 0) + { + const char *base_dirname = strrchr(exclude_path, '/') + 1; /* never NULL */ + /* We exclude our own dump from candidates for deletion (3rd param): */ + char *worst_dir = NULL; + double dirsize = get_dirsize_find_largest_dir(DEBUG_DUMPS_DIR, &worst_dir, base_dirname); + if (dirsize / (1024*1024) < setting_MaxCrashReportsSize || !worst_dir) + { + free(worst_dir); + break; + } + log("size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, setting_MaxCrashReportsSize, worst_dir); + char *d = concat_path_file(DEBUG_DUMPS_DIR, worst_dir); + free(worst_dir); + worst_dir = NULL; + delete_debug_dump_dir(d); + free(d); + } +} diff --git a/src/lib/hooklib.h b/src/lib/hooklib.h new file mode 100644 index 00000000..ba76efbc --- /dev/null +++ b/src/lib/hooklib.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2009 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. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore, bool *setting_SaveBinaryImage); +void check_free_space(unsigned setting_MaxCrashReportsSize); +void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path); + +#ifdef __cplusplus +} +#endif diff --git a/src/lib/logging.c b/src/lib/logging.c new file mode 100644 index 00000000..815efb5e --- /dev/null +++ b/src/lib/logging.c @@ -0,0 +1,148 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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. +*/ + +/* + * Utility routines. + * + */ +#include "abrtlib.h" + +void (*g_custom_logger)(const char*); +const char *msg_prefix = ""; +const char *msg_eol = "\n"; +int logmode = LOGMODE_STDIO; +int xfunc_error_retval = EXIT_FAILURE; +int g_verbose; + +void xfunc_die(void) +{ + exit(xfunc_error_retval); +} + +static void verror_msg_helper(const char *s, + va_list p, + const char* strerr, + int flags) +{ + char *msg; + int prefix_len, strerr_len, msgeol_len, used; + + if (!logmode) + return; + + used = vasprintf(&msg, s, p); + if (used < 0) + return; + + /* This is ugly and costs +60 bytes compared to multiple + * fprintf's, but is guaranteed to do a single write. + * This is needed for e.g. when multiple children + * can produce log messages simultaneously. */ + + prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0; + strerr_len = strerr ? strlen(strerr) : 0; + msgeol_len = strlen(msg_eol); + /* +3 is for ": " before strerr and for terminating NUL */ + msg = (char*) xrealloc(msg, prefix_len + used + strerr_len + msgeol_len + 3); + /* TODO: maybe use writev instead of memmoving? Need full_writev? */ + if (prefix_len) { + char *p; + memmove(msg + prefix_len, msg, used); + used += prefix_len; + p = stpcpy(msg, msg_prefix); + p[0] = ':'; + p[1] = ' '; + } + if (strerr) { + if (s[0]) { + msg[used++] = ':'; + msg[used++] = ' '; + } + strcpy(&msg[used], strerr); + used += strerr_len; + } + strcpy(&msg[used], msg_eol); + + if (flags & LOGMODE_STDIO) { + fflush(stdout); + full_write(STDERR_FILENO, msg, used + msgeol_len); + } + msg[used] = '\0'; /* remove msg_eol (usually "\n") */ + if (flags & LOGMODE_SYSLOG) { + syslog(LOG_ERR, "%s", msg + prefix_len); + } + if ((flags & LOGMODE_CUSTOM) && g_custom_logger) { + g_custom_logger(msg + prefix_len); + } + free(msg); +} + +void log_msg(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg_helper(s, p, NULL, logmode); + va_end(p); +} + +void error_msg(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg_helper(s, p, NULL, (logmode | LOGMODE_CUSTOM)); + va_end(p); +} + +void error_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg_helper(s, p, NULL, (logmode | LOGMODE_CUSTOM)); + va_end(p); + xfunc_die(); +} + +void perror_msg(const char *s, ...) +{ + va_list p; + + va_start(p, s); + /* Guard against ": Success" */ + verror_msg_helper(s, p, errno ? strerror(errno) : NULL, (logmode | LOGMODE_CUSTOM)); + va_end(p); +} + +void perror_msg_and_die(const char *s, ...) +{ + va_list p; + + va_start(p, s); + /* Guard against ": Success" */ + verror_msg_helper(s, p, errno ? strerror(errno) : NULL, (logmode | LOGMODE_CUSTOM)); + va_end(p); + xfunc_die(); +} + +void die_out_of_memory(void) +{ + error_msg_and_die("Out of memory, exiting"); +} diff --git a/src/lib/logging.h b/src/lib/logging.h new file mode 100644 index 00000000..8a038bc7 --- /dev/null +++ b/src/lib/logging.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 LOGGING_H +#define LOGGING_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NORETURN __attribute__ ((noreturn)) + +/* VERB1 log("what you sometimes want to see, even on a production box") */ +#define VERB1 if (g_verbose >= 1) +/* VERB2 log("debug message, not going into insanely small details") */ +#define VERB2 if (g_verbose >= 2) +/* VERB3 log("lots and lots of details") */ +#define VERB3 if (g_verbose >= 3) +/* there is no level > 3 */ + +enum { + LOGMODE_NONE = 0, + LOGMODE_STDIO = (1 << 0), + LOGMODE_SYSLOG = (1 << 1), + LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, + LOGMODE_CUSTOM = (1 << 2), +}; + +extern void (*g_custom_logger)(const char*); +extern const char *msg_prefix; +extern const char *msg_eol; +extern int logmode; +extern int xfunc_error_retval; + +/* Verbosity level */ +extern int g_verbose; + +void xfunc_die(void) NORETURN; +void log_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); +/* It's a macro, not function, since it collides with log() from math.h */ +#undef log +#define log(...) log_msg(__VA_ARGS__) +/* error_msg family will use g_custom_logger. log_msg does not. */ +void error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); +void error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +/* Reports error message with libc's errno error description attached. */ +void perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); +void perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +void die_out_of_memory(void) NORETURN; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/make_descr.cpp b/src/lib/make_descr.cpp new file mode 100644 index 00000000..79065100 --- /dev/null +++ b/src/lib/make_descr.cpp @@ -0,0 +1,287 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 "crash_types.h" + + +using namespace std; + +// caller is responsible for freeing **dsc +static void add_content(bool *was_multiline, char **dsc, const char *header, const char *content) +{ + struct strbuf *buf_description = strbuf_new(); + if (*was_multiline) + strbuf_append_char(buf_description, '\n'); + + while (content[0] == '\n') + content++; + + if (strchr(content, '\n') == NULL) + { + if (skip_whitespace(content)[0] == '\0') + { + /* empty, dont report at all */ + *dsc = strbuf_free_nobuf(buf_description); + return; + } + /* one string value, like OS release */ + strbuf_append_strf(buf_description, "%s: %s\n", header, content); + *was_multiline = 0; + } + else + { + /* multi-string value, like backtrace */ + if (!*was_multiline && (buf_description->len != 0)) /* if wasn't yet separated */ + strbuf_append_char(buf_description, '\n'); + + strbuf_append_strf(buf_description, "%s\n-----\n%s", header, content); + if (content[strlen(content) - 1] != '\n') + strbuf_append_char(buf_description, '\n'); + + *was_multiline = 1; + } + + *dsc = strbuf_free_nobuf(buf_description); +} + +/* Items we don't want to include */ +static const char *const blacklisted_items[] = { + FILENAME_ANALYZER , + FILENAME_COREDUMP , + FILENAME_DESCRIPTION, /* package description - basically useless */ + FILENAME_HOSTNAME , + FILENAME_DUPHASH , + CD_UUID , + CD_INFORMALL , + FILENAME_DUPHASH , + CD_DUMPDIR , + CD_COUNT , + CD_REPORTED , + CD_MESSAGE , + NULL +}; + +char* make_dsc_mailx(const map_crash_data_t & crash_data) +{ + struct strbuf *buf_dsc = strbuf_new(); + struct strbuf *buf_additional_files = strbuf_new(); + struct strbuf *buf_duphash_file = strbuf_new(); + struct strbuf *buf_common_files = strbuf_new(); + + map_crash_data_t::const_iterator it; + for (it = crash_data.begin(); it != crash_data.end(); it++) + { + if (it->second[CD_TYPE] == CD_TXT) + { + const char *itemname = it->first.c_str(); + if ((strcmp(itemname, FILENAME_DUPHASH) != 0) + && (strcmp(itemname, FILENAME_ARCHITECTURE) != 0) + && (strcmp(itemname, FILENAME_KERNEL) != 0) + && (strcmp(itemname, FILENAME_PACKAGE) != 0) + ) { + strbuf_append_strf(buf_additional_files, "%s\n-----\n%s\n\n", itemname, it->second[CD_CONTENT].c_str()); + } + else if (strcmp(itemname, FILENAME_DUPHASH) == 0) + strbuf_append_strf(buf_duphash_file, "%s\n-----\n%s\n\n", itemname, it->second[CD_CONTENT].c_str()); + else + strbuf_append_strf(buf_common_files, "%s\n-----\n%s\n\n", itemname, it->second[CD_CONTENT].c_str()); + } + } + + char *common_files = strbuf_free_nobuf(buf_common_files); + char *duphash_file = strbuf_free_nobuf(buf_duphash_file); + char *additional_files = strbuf_free_nobuf(buf_additional_files); + + strbuf_append_strf(buf_dsc, "Duplicate check\n=====\n%s\n\n", duphash_file); + strbuf_append_strf(buf_dsc, "Common information\n=====\n%s\n\n", common_files); + strbuf_append_strf(buf_dsc, "Additional information\n=====\n%s\n", additional_files); + + free(common_files); + free(duphash_file); + free(additional_files); + + return strbuf_free_nobuf(buf_dsc); +} + +char* make_description_bz(const map_crash_data_t& pCrashData) +{ + struct strbuf *buf_dsc = strbuf_new(); + struct strbuf *buf_long_dsc = strbuf_new(); + + map_crash_data_t::const_iterator it = pCrashData.begin(); + for (; it != pCrashData.end(); it++) + { + const char *itemname = it->first.c_str(); + const char *type = it->second[CD_TYPE].c_str(); + const char *content = it->second[CD_CONTENT].c_str(); + if (strcmp(type, CD_TXT) == 0) + { + /* Skip items we are not interested in */ + const char *const *bl = blacklisted_items; + while (*bl) + { + if (strcmp(itemname, *bl) == 0) + break; + bl++; + } + if (*bl) + continue; /* blacklisted */ + if (strcmp(content, "1.\n2.\n3.\n") == 0) + continue; /* user did not change default "How to reproduce" */ + + if (strlen(content) <= CD_TEXT_ATT_SIZE) + { + /* Add small (less than few kb) text items inline */ + bool was_multiline = 0; + char *tmp = NULL; + add_content(&was_multiline, + &tmp, + /* "reproduce: blah" looks ugly, fixing: */ + (strcmp(itemname, FILENAME_REPRODUCE) == 0) ? "How to reproduce" : itemname, + content + ); + + if (was_multiline) + { + /* Not one-liner */ + if (buf_long_dsc->len != 0) + strbuf_append_char(buf_long_dsc, '\n'); + + strbuf_append_str(buf_long_dsc, tmp); + } + else + strbuf_append_str(buf_dsc, tmp); + + free(tmp); + } else { + bool was_multiline = 0; + char *dsc = NULL; + add_content(&was_multiline, &dsc, "Attached file", itemname); + strbuf_append_str(buf_dsc, dsc); + free(dsc); + } + } + } + + /* One-liners go first, then multi-line items */ + if (buf_dsc->len != 0 && buf_long_dsc->len != 0) + strbuf_append_char(buf_dsc, '\n'); + + + char *long_dsc = strbuf_free_nobuf(buf_long_dsc); + strbuf_append_str(buf_dsc, long_dsc); + free(long_dsc); + + return strbuf_free_nobuf(buf_dsc); +} + +char* make_description_logger(const map_crash_data_t& pCrashData) +{ + struct strbuf *buf_dsc = strbuf_new(); + struct strbuf *buf_long_dsc = strbuf_new(); + + map_crash_data_t::const_iterator it = pCrashData.begin(); + for (; it != pCrashData.end(); it++) + { + const char *filename = it->first.c_str(); + const char *type = it->second[CD_TYPE].c_str(); + const char *content = it->second[CD_CONTENT].c_str(); + if ((strcmp(type, CD_TXT) == 0) + || (strcmp(type, CD_BIN) == 0) + ) { + /* Skip items we are not interested in */ + const char *const *bl = blacklisted_items; + while (*bl) + { + if (filename == *bl) + break; + bl++; + } + if (*bl) + continue; /* blacklisted */ + if (strcmp(content, "1.\n2.\n3.\n") == 0) + continue; /* user did not change default "How to reproduce" */ + + bool was_multiline = 0; + char *tmp = NULL; + add_content(&was_multiline, &tmp, filename, content); + + if (was_multiline) + { + if (buf_long_dsc->len != 0) + strbuf_append_char(buf_long_dsc,'\n'); + + strbuf_append_str(buf_long_dsc, tmp); + } + else + strbuf_append_str(buf_dsc, tmp); + } + } + + if (buf_dsc->len != 0 && buf_long_dsc->len != 0) + strbuf_append_char(buf_dsc, '\n'); + + char *long_dsc = strbuf_free_nobuf(buf_long_dsc); + strbuf_append_str(buf_dsc, long_dsc); + free(long_dsc); + + return strbuf_free_nobuf(buf_dsc); +} + +char* make_description_reproduce_comment(const map_crash_data_t& pCrashData) +{ + char *repro = NULL; + char *comment = NULL; + + map_crash_data_t::const_iterator end = pCrashData.end(); + map_crash_data_t::const_iterator it; + + it = pCrashData.find(FILENAME_REPRODUCE); + if (it != end) + { + if ((it->second[CD_CONTENT].size() > 0) + && (it->second[CD_CONTENT] != "1.\n2.\n3.\n")) + { + repro = xasprintf("\n\nHow to reproduce\n-----\n%s", it->second[CD_CONTENT].c_str()); + } + } + + it = pCrashData.find(FILENAME_COMMENT); + if (it != end) + { + if (it->second[CD_CONTENT].size() > 0) + comment = xasprintf("\n\nComment\n-----\n%s", it->second[CD_CONTENT].c_str()); + } + + if (!repro && !comment) + return NULL; + + struct strbuf *buf_dsc = strbuf_new(); + + if (repro) + strbuf_append_str(buf_dsc, repro); + + if (comment) + strbuf_append_str(buf_dsc, comment); + + free(repro); + free(comment); + + return strbuf_free_nobuf(buf_dsc); +} diff --git a/src/lib/numtoa.cpp b/src/lib/numtoa.cpp new file mode 100644 index 00000000..061da553 --- /dev/null +++ b/src/lib/numtoa.cpp @@ -0,0 +1,34 @@ +/* + Number to string conversions + + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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" + +std::string unsigned_to_string(unsigned long long x) +{ + char buf[sizeof(x)*3]; + sprintf(buf, "%llu", x); + return buf; +} +std::string signed_to_string(long long x) +{ + char buf[sizeof(x)*3]; + sprintf(buf, "%lld", x); + return buf; +} diff --git a/src/lib/overlapping_strcpy.c b/src/lib/overlapping_strcpy.c new file mode 100644 index 00000000..41c1c1a1 --- /dev/null +++ b/src/lib/overlapping_strcpy.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 1999-2004 by Erik Andersen + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" + +/* Like strcpy but can copy overlapping strings. */ +void overlapping_strcpy(char *dst, const char *src) +{ + /* Cheap optimization for dst == src case - + * better to have it here than in many callers. + */ + if (dst != src) + { + while ((*dst = *src) != '\0') + { + dst++; + src++; + } + } +} diff --git a/src/lib/parse_options.c b/src/lib/parse_options.c new file mode 100644 index 00000000..c1a2c297 --- /dev/null +++ b/src/lib/parse_options.c @@ -0,0 +1,182 @@ + +#include +#include "abrtlib.h" +#include "parse_options.h" + +#define USAGE_OPTS_WIDTH 24 +#define USAGE_GAP 2 + +void parse_usage_and_die(const char *usage, const struct options *opt) +{ + fprintf(stderr, _("Usage: %s\n"), usage); + + if (opt->type != OPTION_GROUP) + fputc('\n', stderr); + + for (; opt->type != OPTION_END; opt++) + { + size_t pos; + int pad; + + if (opt->type == OPTION_GROUP) + { + fputc('\n', stderr); + if (*opt->help) + fprintf(stderr, "%s\n", opt->help); + continue; + } + + pos = fprintf(stderr, " "); + if (opt->short_name) + pos += fprintf(stderr, "-%c", opt->short_name); + + if (opt->short_name && opt->long_name) + pos += fprintf(stderr, ", "); + + if (opt->long_name) + pos += fprintf(stderr, "--%s", opt->long_name); + + if (opt->argh) + { + const char *fmt = " %s"; + if (opt->type == OPTION_OPTSTRING) + fmt = "[%s]"; + pos += fprintf(stderr, fmt, opt->argh); + } + + 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, "", opt->help); + } + fputc('\n', stderr); + exit(1); +} + +static int parse_opt_size(const struct options *opt) +{ + unsigned size = 0; + for (; opt->type != OPTION_END; opt++) + size++; + + return size; +} + +unsigned parse_opts(int argc, char **argv, const struct options *opt, + const char *usage) +{ + int help = 0; + int size = parse_opt_size(opt); + + struct strbuf *shortopts = strbuf_new(); + + struct option *longopts = xzalloc(sizeof(longopts[0]) * (size+2)); + struct option *curopt = longopts; + int ii; + for (ii = 0; ii < size; ++ii) + { + curopt->name = opt[ii].long_name; + /*curopt->flag = 0; - xzalloc did it */ + curopt->val = opt[ii].short_name; + + switch (opt[ii].type) + { + case OPTION_BOOL: + curopt->has_arg = no_argument; + if (opt[ii].short_name) + strbuf_append_char(shortopts, opt[ii].short_name); + break; + case OPTION_INTEGER: + case OPTION_STRING: + curopt->has_arg = required_argument; + if (opt[ii].short_name) + strbuf_append_strf(shortopts, "%c:", opt[ii].short_name); + break; + case OPTION_OPTSTRING: + curopt->has_arg = optional_argument; + if (opt[ii].short_name) + strbuf_append_strf(shortopts, "%c::", opt[ii].short_name); + break; + case OPTION_GROUP: + case OPTION_END: + break; + } + //log("curopt[%d].name:'%s' .has_arg:%d .flag:%p .val:%d", (int)(curopt-longopts), + // curopt->name, curopt->has_arg, curopt->flag, curopt->val); + /* + * getopt_long() thinks that NULL name marks the end of longopts. + * Example: + * [0] name:'verbose' val:'v' + * [1] name:NULL val:'c' + * [2] name:'force' val:'f' + * ... ... ... + * In this case, --force won't be accepted! + * Therefore we can only advance if name is not NULL. + */ + if (curopt->name) + curopt++; + } + curopt->name = "help"; + curopt->has_arg = no_argument; + curopt->flag = &help; + curopt->val = 1; + /* xzalloc did it already: + curopt++; + curopt->name = NULL; + curopt->has_arg = 0; + curopt->flag = NULL; + curopt->val = 0; + */ + + unsigned retval = 0; + while (1) + { + int c = getopt_long(argc, argv, shortopts->buf, longopts, NULL); + + if (c == -1) + break; + + if (c == '?' || help) + { + free(longopts); + strbuf_free(shortopts); + parse_usage_and_die(usage, opt); + } + + for (ii = 0; ii < size; ++ii) + { + if (opt[ii].short_name == c) + { + if (ii < sizeof(retval)*8) + retval |= (1 << ii); + + if (opt[ii].value != NULL) switch (opt[ii].type) + { + case OPTION_BOOL: + *(int*)opt[ii].value += 1; + break; + case OPTION_INTEGER: + *(int*)opt[ii].value = xatoi(optarg); + break; + case OPTION_STRING: + case OPTION_OPTSTRING: + if (optarg) + *(char**)opt[ii].value = (char*)optarg; + break; + case OPTION_GROUP: + case OPTION_END: + break; + } + } + } + } + + free(longopts); + strbuf_free(shortopts); + + return retval; +} diff --git a/src/lib/parse_options.h b/src/lib/parse_options.h new file mode 100644 index 00000000..105f081c --- /dev/null +++ b/src/lib/parse_options.h @@ -0,0 +1,53 @@ + +#ifndef PARSE_OPTIONS_H +#define PARSE_OPTIONS_H + + +#ifdef __cplusplus +extern "C" { +#endif + +enum parse_opt_type { + OPTION_BOOL, + OPTION_GROUP, + OPTION_STRING, + OPTION_INTEGER, + OPTION_OPTSTRING, + OPTION_END, +}; + +struct options { + enum parse_opt_type type; + int short_name; + const char *long_name; + void *value; + const char *argh; + const char *help; +}; + +/* + * s - short_name + * l - long_name + * v - value + * a - argh argument help + * h - help + */ +#define OPT_END() { OPTION_END } +#define OPT_BOOL(s, l, v, h) { OPTION_BOOL, (s), (l), (v), NULL, (h) } +#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } +#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) } +#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } +#define OPT_OPTSTRING(s, l, v, a, h) { OPTION_OPTSTRING, (s), (l), (v), (a), (h) } + +#define OPT__VERBOSE(v) OPT_BOOL('v', "verbose", (v), "be verbose") + +unsigned parse_opts(int argc, char **argv, const struct options *opt, + const char *usage); + +void parse_usage_and_die(const char *usage, const struct options *opt); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/parse_release.cpp b/src/lib/parse_release.cpp new file mode 100644 index 00000000..f9057bfe --- /dev/null +++ b/src/lib/parse_release.cpp @@ -0,0 +1,59 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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" + +// caller is reposible for freeing *product* and *version* +void parse_release(const char *release, char** product, char** version) +{ + if (strstr(release, "Rawhide")) + { + *product = xstrdup("Fedora"); + *version = xstrdup("rawhide"); + VERB3 log("%s: version:'%s' product:'%s'", __func__, *version, *product); + return; + } + + struct strbuf *buf_product = strbuf_new(); + if (strstr(release, "Fedora")) + strbuf_append_str(buf_product, "Fedora"); + else if (strstr(release, "Red Hat Enterprise Linux")) + strbuf_append_str(buf_product, "Red Hat Enterprise Linux "); + + const char *r = strstr(release, "release"); + const char *space = r ? strchr(r, ' ') : NULL; + + struct strbuf *buf_version = strbuf_new(); + if (space++) + { + while (*space != '\0' && *space != ' ') + { + /* Eat string like "5.2" */ + strbuf_append_char(buf_version, *space); + if ((strcmp(buf_product->buf, "Red Hat Enterprise Linux ") == 0)) + strbuf_append_char(buf_product, *space); + + space++; + } + } + + *version = strbuf_free_nobuf(buf_version); + *product = strbuf_free_nobuf(buf_product); + + VERB3 log("%s: version:'%s' product:'%s'", __func__, *version, *product); +} diff --git a/src/lib/read_write.c b/src/lib/read_write.c new file mode 100644 index 00000000..da067f78 --- /dev/null +++ b/src/lib/read_write.c @@ -0,0 +1,105 @@ +/* + * Utility routines. + * + * Licensed under GPLv2 or later, see file COPYING in this tarball for details. + */ +#include "abrtlib.h" + +/* Die with an error message if we can't read the entire buffer. */ +void xread(int fd, void *buf, size_t count) +{ + if (count) + { + ssize_t size = full_read(fd, buf, count); + if ((size_t)size != count) + error_msg_and_die("short read"); + } +} + +ssize_t safe_read(int fd, void *buf, size_t count) +{ + ssize_t n; + + do { + n = read(fd, buf, count); + } while (n < 0 && errno == EINTR); + + return n; +} + +ssize_t safe_write(int fd, const void *buf, size_t count) +{ + ssize_t n; + + do { + n = write(fd, buf, count); + } while (n < 0 && errno == EINTR); + + return n; +} + +ssize_t full_read(int fd, void *buf, size_t len) +{ + ssize_t cc; + ssize_t total; + + total = 0; + + while (len) + { + cc = safe_read(fd, buf, len); + + if (cc < 0) + { + if (total) + { + /* we already have some! */ + /* user can do another read to know the error code */ + return total; + } + return cc; /* read() returns -1 on failure. */ + } + if (cc == 0) + break; + buf = ((char *)buf) + cc; + total += cc; + len -= cc; + } + + return total; +} + +ssize_t full_write(int fd, const void *buf, size_t len) +{ + ssize_t cc; + ssize_t total; + + total = 0; + + while (len) + { + cc = safe_write(fd, buf, len); + + if (cc < 0) + { + if (total) + { + /* we already wrote some! */ + /* user can do another write to know the error code */ + return total; + } + return cc; /* write() returns -1 on failure. */ + } + + total += cc; + buf = ((const char *)buf) + cc; + len -= cc; + } + + return total; +} + +ssize_t full_write_str(int fd, const char *buf) +{ + return full_write(fd, buf, strlen(buf)); +} diff --git a/src/lib/read_write.h b/src/lib/read_write.h new file mode 100644 index 00000000..054a1a9a --- /dev/null +++ b/src/lib/read_write.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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 READ_WRITE_H +#define READ_WRITE_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// NB: will return short read on error, not -1, +// if some data was read before error occurred +void xread(int fd, void *buf, size_t count); + +ssize_t safe_read(int fd, void *buf, size_t count); +ssize_t safe_write(int fd, const void *buf, size_t count); + +ssize_t full_read(int fd, void *buf, size_t count); +ssize_t full_write(int fd, const void *buf, size_t count); + +ssize_t full_write_str(int fd, const char *buf); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/run_event.c b/src/lib/run_event.c new file mode 100644 index 00000000..23517923 --- /dev/null +++ b/src/lib/run_event.c @@ -0,0 +1,276 @@ +/* + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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" + +int run_event(struct run_event_state *state, + const char *dump_dir_name, + const char *event +) { + FILE *conffile = fopen(CONF_DIR"/abrt_event.conf", "r"); + if (!conffile) + { + error_msg("Can't open '%s'", CONF_DIR"/abrt_event.conf"); + return 1; + } + close_on_exec_on(fileno(conffile)); + + /* Export some useful environment variables for children */ + /* Just exporting dump_dir_name isn't always ok: it can be "." + * and some children want to cd to other directory but still + * be able to find dump directory by using $DUMP_DIR... + */ + char *full_name = realpath(dump_dir_name, NULL); + setenv("DUMP_DIR", (full_name ? full_name : dump_dir_name), 1); + free(full_name); + setenv("EVENT", event, 1); + + /* Read, match, and execute lines from abrt_event.conf */ + int retval = 0; + struct dump_dir *dd = NULL; + char *line; + while ((line = xmalloc_fgetline(conffile)) != NULL) + { + /* Line has form: [VAR=VAL]... PROG [ARGS] */ + char *p = skip_whitespace(line); + if (*p == '\0' || *p == '#') + goto next_line; /* empty or comment line, skip */ + + VERB3 log("%s: line '%s'", __func__, p); + + while (1) /* word loop */ + { + char *end_word = skip_non_whitespace(p); + char *next_word = skip_whitespace(end_word); + + /* *end_word = '\0'; - BUG, truncates command */ + + /* If there is no '=' in this word... */ + char *line_val = strchr(p, '='); + if (!line_val || line_val >= end_word) + break; /* ...we found the start of a command */ + + *end_word = '\0'; + + /* Current word has VAR=VAL form. line_val => VAL */ + *line_val++ = '\0'; + + const char *real_val; + char *malloced_val = NULL; + + /* Is it EVENT? */ + if (strcmp(p, "EVENT") == 0) + real_val = event; + else + { + /* Get this name from dump dir */ + if (!dd) + { + dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + goto stop; /* error (note: dd_opendir logged error msg) */ + } + real_val = malloced_val = dd_load_text_ext(dd, p, DD_FAIL_QUIETLY); + } + + /* Does VAL match? */ + if (strcmp(real_val, line_val) != 0) + { + VERB3 log("var '%s': '%.*s'!='%s', skipping line", + p, + (int)(strchrnul(real_val, '\n') - real_val), real_val, + line_val); + free(malloced_val); + goto next_line; /* no */ + } + free(malloced_val); + + /* Go to next word */ + p = next_word; + } /* end of word loop */ + + /* Don't keep dump dir locked across program runs */ + dd_close(dd); + dd = NULL; + + /* We found matching line, execute its command(s) in shell */ + { + VERB1 log("Executing '%s'", p); + + /* /bin/sh -c 'cmd [args]' NULL */ + char *argv[4]; + char **pp = argv; + *pp++ = (char*)"/bin/sh"; + *pp++ = (char*)"-c"; + *pp++ = (char*)p; + *pp = NULL; + int pipefds[2]; + pid_t pid = fork_execv_on_steroids(EXECFLG_INPUT_NUL + EXECFLG_OUTPUT + EXECFLG_ERR2OUT, + argv, + pipefds, + /* unsetenv_vec: */ NULL, + /* dir: */ dump_dir_name, + /* uid(unused): */ 0 + ); + free(line); + line = NULL; + + /* Consume log from stdout */ + FILE *fp = fdopen(pipefds[0], "r"); + if (!fp) + die_out_of_memory(); + char *buf; + while ((buf = xmalloc_fgetline(fp)) != NULL) + { + if (state->logging_callback) + buf = state->logging_callback(buf, state->logging_param); + free(buf); + } + fclose(fp); /* Got EOF, close. This also closes pipefds[0] */ + + /* Wait for child to actually exit, collect status */ + int status; + waitpid(pid, &status, 0); + + if (status != 0) + { + retval = WEXITSTATUS(status); + if (WIFSIGNALED(status)) + retval = WTERMSIG(status) + 128; + break; + } + } + + if (state->post_run_callback) + { + retval = state->post_run_callback(dump_dir_name, state->post_run_param); + if (retval != 0) + break; + } + + next_line: + free(line); + } /* end of line loop */ + + stop: + free(line); + dd_close(dd); + fclose(conffile); + + return retval; +} + +char *list_possible_events(struct dump_dir *dd, const char *dump_dir_name, const char *pfx) +{ + FILE *conffile = fopen(CONF_DIR"/abrt_event.conf", "r"); + if (!conffile) + { + error_msg("Can't open '%s'", CONF_DIR"/abrt_event.conf"); + return NULL; + } + + /* We check "dump_dir_name == NULL" later. + * Prevent the possibility that both dump_dir_name + * and dd are non-NULL (which does not make sense) + */ + if (dd) + dump_dir_name = NULL; + + unsigned pfx_len = strlen(pfx); + struct strbuf *result = strbuf_new(); + char *line; + while ((line = xmalloc_fgetline(conffile)) != NULL) + { + /* Line has form: [VAR=VAL]... PROG [ARGS] */ + char *p = skip_whitespace(line); + if (*p == '\0' || *p == '#') + goto next_line; /* empty or comment line, skip */ + + VERB3 log("%s: line '%s'", __func__, p); + + while (1) /* word loop */ + { + char *end_word = skip_non_whitespace(p); + char *next_word = skip_whitespace(end_word); + *end_word = '\0'; + + /* If there is no '=' in this word... */ + char *line_val = strchr(p, '='); + if (!line_val) + break; /* ...we found the start of a command */ + + /* Current word has VAR=VAL form. line_val => VAL */ + *line_val++ = '\0'; + + /* Is it EVENT? */ + if (strcmp(p, "EVENT") == 0) + { + if (strncmp(line_val, pfx, pfx_len) != 0) + goto next_line; /* prefix doesn't match */ + /* (Ab)use line to save matching "\nEVENT_VAL\n" */ + sprintf(line, "\n%s\n", line_val); + } + else + { + /* Get this name from dump dir */ + if (!dd) + { + /* Without dir name to match, we assume match for this expr */ + if (!dump_dir_name) + goto next_word; + dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + goto stop; /* error (note: dd_opendir logged error msg) */ + } + char *real_val = dd_load_text(dd, p); + /* Does VAL match? */ + if (strcmp(real_val, line_val) != 0) + { + VERB3 log("var '%s': '%s'!='%s', skipping line", p, real_val, line_val); + free(real_val); + goto next_line; /* no */ + } + free(real_val); + } + + next_word: + /* Go to next word */ + p = next_word; + } /* end of word loop */ + + if (line[0] == '\n' /* do we *have* saved matched "\nEVENT_VAL\n"? */ + /* and does result->buf NOT yet have VAL? */ + && strncmp(result->buf, line + 1, strlen(line + 1)) != 0 + && !strstr(result->buf, line) + ) { + /* Add "EVENT_VAL\n" */ + strbuf_append_str(result, line + 1); + } + + next_line: + free(line); + } /* end of line loop */ + + stop: + free(line); + if (dump_dir_name != NULL) + dd_close(dd); + fclose(conffile); + + return strbuf_free_nobuf(result); +} diff --git a/src/lib/skip_whitespace.c b/src/lib/skip_whitespace.c new file mode 100644 index 00000000..816928bf --- /dev/null +++ b/src/lib/skip_whitespace.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2003 Manuel Novoa III + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" + +char* skip_whitespace(const char *s) +{ + /* NB: isspace('\0') returns 0 */ + while (isspace(*s)) ++s; + + return (char *) s; +} + +char* skip_non_whitespace(const char *s) +{ + while (*s && !isspace(*s)) ++s; + + return (char *) s; +} diff --git a/src/lib/spawn.c b/src/lib/spawn.c new file mode 100644 index 00000000..068f4ac7 --- /dev/null +++ b/src/lib/spawn.c @@ -0,0 +1,156 @@ +/* + * Utility routines. + * + * Licensed under GPLv2, see file COPYING in this tarball for details. + */ +#include "abrtlib.h" + +static char *concat_str_vector(char **strings) +{ + if (!strings[0]) + return xzalloc(1); // returns "" + + unsigned len = 0; + char **spp = strings; + while (*spp) + len += strlen(*spp++) + 1; + + char *result = xmalloc(len); + + char *r = result; + spp = strings; + while (*spp) { + r = stpcpy(r, *spp++); + *r++ = ' '; + } + *--r = '\0'; + + return result; +} + +/* Returns pid */ +pid_t fork_execv_on_steroids(int flags, + char **argv, + int *pipefds, + char **unsetenv_vec, + const char *dir, + uid_t uid) +{ + pid_t child; + /* Reminder: [0] is read end, [1] is write end */ + int pipe_to_child[2]; + int pipe_fm_child[2]; + + /* Sanitize flags */ + if (!pipefds) + flags &= ~(EXECFLG_INPUT | EXECFLG_OUTPUT); + + if (flags & EXECFLG_INPUT) + xpipe(pipe_to_child); + if (flags & EXECFLG_OUTPUT) + xpipe(pipe_fm_child); + + fflush(NULL); + child = fork(); + if (child == -1) { + perror_msg_and_die("fork"); + } + if (child == 0) { + /* Child */ + + if (dir) + xchdir(dir); + + if (flags & EXECFLG_SETGUID) { + struct passwd* pw = getpwuid(uid); + gid_t gid = pw ? pw->pw_gid : uid; + setgroups(1, &gid); + xsetregid(gid, gid); + xsetreuid(uid, uid); + } + + if (unsetenv_vec) { + while (*unsetenv_vec) + unsetenv(*unsetenv_vec++); + } + + /* Play with stdio descriptors */ + if (flags & EXECFLG_INPUT) { + xmove_fd(pipe_to_child[0], STDIN_FILENO); + close(pipe_to_child[1]); + } else if (flags & EXECFLG_INPUT_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDIN_FILENO); + } + if (flags & EXECFLG_OUTPUT) { + xmove_fd(pipe_fm_child[1], STDOUT_FILENO); + close(pipe_fm_child[0]); + } else if (flags & EXECFLG_OUTPUT_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDOUT_FILENO); + } + + /* This should be done BEFORE stderr redirect */ + VERB1 { + char *r = concat_str_vector(argv); + log("Executing: %s", r); + free(r); + } + + if (flags & EXECFLG_ERR2OUT) { + /* Want parent to see errors in the same stream */ + xdup2(STDOUT_FILENO, STDERR_FILENO); + } else if (flags & EXECFLG_ERR_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDERR_FILENO); + } + + if (flags & EXECFLG_SETSID) + setsid(); + + execvp(argv[0], argv); + if (!(flags & EXECFLG_QUIET)) + perror_msg("Can't execute '%s'", argv[0]); + exit(127); /* shell uses this exitcode in this case */ + } + + if (flags & EXECFLG_INPUT) { + close(pipe_to_child[0]); + pipefds[1] = pipe_to_child[1]; + } + if (flags & EXECFLG_OUTPUT) { + close(pipe_fm_child[1]); + pipefds[0] = pipe_fm_child[0]; + } + + return child; +} + +char *run_in_shell_and_save_output(int flags, + const char *cmd, + const char *dir, + size_t *size_p) +{ + flags |= EXECFLG_OUTPUT; + flags &= ~EXECFLG_INPUT; + + const char *argv[] = { "/bin/sh", "-c", cmd, NULL }; + int pipeout[2]; + pid_t child = fork_execv_on_steroids(flags, (char **)argv, pipeout, + /*unsetenv_vec:*/ NULL, dir, /*uid (unused):*/ 0); + + size_t pos = 0; + char *result = NULL; + while (1) { + result = (char*) xrealloc(result, pos + 4*1024 + 1); + size_t sz = safe_read(pipeout[0], result + pos, 4*1024); + if (sz <= 0) { + break; + } + pos += sz; + } + result[pos] = '\0'; + if (size_p) + *size_p = pos; + close(pipeout[0]); + waitpid(child, NULL, 0); + + return result; +} diff --git a/src/lib/stdio_helpers.c b/src/lib/stdio_helpers.c new file mode 100644 index 00000000..81cf5d75 --- /dev/null +++ b/src/lib/stdio_helpers.c @@ -0,0 +1,69 @@ +/* + * Utility routines. + * + * Copyright (C) 2001 Matt Krai + * Copyright (C) 2004 Erik Andersen + * Copyright (C) 2005, 2006 Rob Landley + * Copyright (C) 2010 ABRT Team + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +#include "abrtlib.h" + +//TODO: add sanitizing upper limit (e.g 64K, 1M, or configurable). +//This is why we don't use GNU's getline: it doesn't have +//any upper sanity bound on line size. + +static char *xmalloc_fgets_internal(FILE *file, int *sizep) +{ + unsigned idx = 0; + char *linebuf = NULL; + + while (1) { + char *r; + + linebuf = xrealloc(linebuf, idx + 0x100); + r = fgets(&linebuf[idx], 0x100, file); + if (!r) { + /* need to terminate the line */ + linebuf[idx] = '\0'; + break; + } + + /* stupid. fgets knows the len, it should report it somehow */ + unsigned len = strlen(&linebuf[idx]); + + idx += len; + if (len < 0xff || linebuf[idx - 1] == '\n') + break; /* we found \n or EOF */ + } + + *sizep = idx; + + if (!idx) { + /* The very first fgets returned NULL. It's EOF (or error) */ + free(linebuf); + linebuf = NULL; + } + return linebuf; +} + +char *xmalloc_fgets(FILE *file) +{ + int sz; + char *r = xmalloc_fgets_internal(file, &sz); + if (!r) + return r; + return xrealloc(r, sz + 1); +} + +char *xmalloc_fgetline(FILE *file) +{ + int sz; + char *r = xmalloc_fgets_internal(file, &sz); + if (!r) + return r; + if (r[sz - 1] == '\n') + r[--sz] = '\0'; + return xrealloc(r, sz + 1); +} diff --git a/src/lib/strbuf.c b/src/lib/strbuf.c new file mode 100644 index 00000000..04a35998 --- /dev/null +++ b/src/lib/strbuf.c @@ -0,0 +1,147 @@ +/* + String buffer implementation + + Copyright (C) 2009 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" + +int prefixcmp(const char *str, const char *prefix) +{ + for (; ; str++, prefix++) + if (!*prefix) + return 0; + else if (*str != *prefix) + return (unsigned char)*prefix - (unsigned char)*str; +} + +int suffixcmp(const char *str, const char *suffix) +{ + int len_minus_suflen = strlen(str) - strlen(suffix); + if (len_minus_suflen < 0) + return len_minus_suflen; + else + return strcmp(str + len_minus_suflen, suffix); +} + +struct strbuf *strbuf_new() +{ + struct strbuf *buf = xzalloc(sizeof(*buf)); + /*buf->len = 0; - done by xzalloc */ + buf->alloc = 8; + buf->buf = xzalloc(8); + return buf; +} + +void strbuf_free(struct strbuf *strbuf) +{ + if (!strbuf) + return; + free(strbuf->buf); + free(strbuf); +} + +char *strbuf_free_nobuf(struct strbuf *strbuf) +{ + char *ret = strbuf->buf; + free(strbuf); + return ret; +} + + +void strbuf_clear(struct strbuf *strbuf) +{ + assert(strbuf->alloc > 0); + strbuf->len = 0; + strbuf->buf[0] = '\0'; +} + +/* Ensures that the buffer can be extended by N+1 characters + * without touching malloc/realloc. + * Returns pointer where appended chars can be stored by the caller; + * increments ->len by N (therefore callers don't need to do it). + */ +static char *strbuf_grow(struct strbuf *strbuf, unsigned increment) +{ + unsigned len = strbuf->len; + unsigned need = strbuf->len = len + increment; + unsigned cur_size = strbuf->alloc; + if (cur_size <= need) + { + while (cur_size <= need) + cur_size += 64 + cur_size / 8; + strbuf->alloc = cur_size; + strbuf->buf = xrealloc(strbuf->buf, cur_size); + } + char *p = strbuf->buf + len; + return p; +} + +struct strbuf *strbuf_append_char(struct strbuf *strbuf, char c) +{ + char *p = strbuf_grow(strbuf, 1); + *p++ = c; + *p = '\0'; + return strbuf; +} + +struct strbuf *strbuf_append_str(struct strbuf *strbuf, const char *str) +{ + unsigned len = strlen(str); + char *p = strbuf_grow(strbuf, len); + assert(strbuf->len < strbuf->alloc); + strcpy(p, str); + return strbuf; +} + +struct strbuf *strbuf_prepend_str(struct strbuf *strbuf, const char *str) +{ + unsigned cur_len = strbuf->len; + unsigned inc_len = strlen(str); + strbuf_grow(strbuf, inc_len); + assert(strbuf->len < strbuf->alloc); + memmove(strbuf->buf + inc_len, strbuf->buf, cur_len); + memcpy(strbuf->buf, str, inc_len); + return strbuf; +} + +struct strbuf *strbuf_append_strf(struct strbuf *strbuf, const char *format, ...) +{ + va_list p; + char *string_ptr; + + va_start(p, format); + string_ptr = xvasprintf(format, p); + va_end(p); + + strbuf_append_str(strbuf, string_ptr); + free(string_ptr); + return strbuf; +} + +struct strbuf *strbuf_prepend_strf(struct strbuf *strbuf, const char *format, ...) +{ + va_list p; + char *string_ptr; + + va_start(p, format); + string_ptr = xvasprintf(format, p); + va_end(p); + + strbuf_prepend_str(strbuf, string_ptr); + free(string_ptr); + return strbuf; +} diff --git a/src/lib/strbuf.h b/src/lib/strbuf.h new file mode 100644 index 00000000..dc45a199 --- /dev/null +++ b/src/lib/strbuf.h @@ -0,0 +1,103 @@ +/* + strbuf.h - string buffer + + Copyright (C) 2009 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 STRBUF_H +#define STRBUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct strbuf +{ + /* Size of the allocated buffer. Always > 0. */ + int alloc; + /* Length of the string, without the ending \0. */ + int len; + char *buf; +}; + +/** + * Creates and initializes a new string buffer. + * @returns + * It never returns NULL. The returned pointer must be released by + * calling the function strbuf_free(). + */ +struct strbuf *strbuf_new(); + +/** + * Releases the memory held by the string buffer. + * @param strbuf + * If the strbuf is NULL, no operation is performed. + */ +void strbuf_free(struct strbuf *strbuf); + +/** + * Releases the strbuf, but not the internal buffer. The internal + * string buffer is returned. Caller is responsible to release the + * returned memory using free(). + */ +char* strbuf_free_nobuf(struct strbuf *strbuf); + +/** + * The string content is set to an empty string, erasing any previous + * content and leaving its length at 0 characters. + */ +void strbuf_clear(struct strbuf *strbuf); + +/** + * The current content of the string buffer is extended by adding a + * character c at its end. + */ +struct strbuf *strbuf_append_char(struct strbuf *strbuf, char c); + +/** + * The current content of the string buffer is extended by adding a + * string str at its end. + */ +struct strbuf *strbuf_append_str(struct strbuf *strbuf, + const char *str); + +/** + * The current content of the string buffer is extended by inserting a + * string str at its beginning. + */ +struct strbuf *strbuf_prepend_str(struct strbuf *strbuf, + const char *str); + +/** + * The current content of the string buffer is extended by adding a + * sequence of data formatted as the format argument specifies. + */ +struct strbuf *strbuf_append_strf(struct strbuf *strbuf, + const char *format, ...); + +/** + * The current content of the string buffer is extended by inserting a + * sequence of data formatted as the format argument specifies at the + * buffer beginning. + */ +struct strbuf *strbuf_prepend_strf(struct strbuf *strbuf, + const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/stringops.cpp b/src/lib/stringops.cpp new file mode 100644 index 00000000..7bc5413f --- /dev/null +++ b/src/lib/stringops.cpp @@ -0,0 +1,57 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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" + +void parse_args(const char *psArgs, vector_string_t& pArgs, int quote) +{ + unsigned ii; + bool inside_quotes = false; + std::string item; + + for (ii = 0; psArgs[ii]; ii++) + { + if (quote != -1) + { + if (psArgs[ii] == quote) + { + inside_quotes = !inside_quotes; + continue; + } + /* inside quotes we support escaping with \x */ + if (inside_quotes && psArgs[ii] == '\\' && psArgs[ii+1]) + { + ii++; + item += psArgs[ii]; + continue; + } + } + if (psArgs[ii] == ',' && !inside_quotes) + { + pArgs.push_back(item); + item.clear(); + continue; + } + item += psArgs[ii]; + } + + if (item.size() != 0) + { + pArgs.push_back(item); + } +} diff --git a/src/lib/test.cpp b/src/lib/test.cpp new file mode 100644 index 00000000..a548dc21 --- /dev/null +++ b/src/lib/test.cpp @@ -0,0 +1,105 @@ +/* + test.cpp - simple library test + + Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) + Copyright (C) 2009 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 "MiddleWare.h" +#include "DebugDump.h" +#include "CrashTypes.h" +#include +#include +#include +#include + + +int main(int argc, char** argv) +{ + + if (argc < 2) + { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return -1; + } + try + { + CMiddleWare middleWare(PLUGINS_CONF_DIR, + PLUGINS_LIB_DIR); + vector_map_string_t loaded_plugins; + middleWare.RegisterPlugin("CCpp"); + middleWare.RegisterPlugin("Mailx"); + middleWare.RegisterPlugin("Logger"); + middleWare.RegisterPlugin("SQLite3"); + middleWare.SetDatabase("SQLite3"); + middleWare.SetOpenGPGCheck(false); + middleWare.AddActionOrReporter("Logger", ""); + middleWare.AddAnalyzerActionOrReporter("CCpp", "Mailx", ""); + + loaded_plugins = middleWare.GetPluginsInfo(); + std::cout << "Loaded plugins" << std::endl; + int ii; + for ( ii = 0; ii < loaded_plugins.size(); ii++) + { + std::cout << "-------------------------------------------" << std::endl; + map_plugin_settings_t settings; + std::cout << "Enabled: " << loaded_plugins[ii]["Enabled"] << std::endl; + std::cout << "Type: " << loaded_plugins[ii]["Type"] << std::endl; + std::cout << "Name: " << loaded_plugins[ii]["Name"] << std::endl; + std::cout << "Version: " << loaded_plugins[ii]["Version"] << std::endl; + std::cout << "Description: " << loaded_plugins[ii]["Description"] << std::endl; + std::cout << "Email: " << loaded_plugins[ii]["Email"] << std::endl; + std::cout << "WWW: " << loaded_plugins[ii]["WWW"] << std::endl; + std::cout << "GTKBuilder: " << loaded_plugins[ii]["GTKBuilder"] << std::endl; + if (loaded_plugins[ii]["Enabled"] == "yes") + { + std::cout << std::endl << "Settings: " << std::endl; + settings = middleWare.GetPluginSettings(loaded_plugins[ii]["Name"]); + map_plugin_settings_t::iterator it; + for (it = settings.begin(); it != settings.end(); it++) + { + std::cout << "\t" << it->first << ": " << it->second << std::endl; + } + } + std::cout << "-------------------------------------------" << std::endl; + } + /* Try to save it into DB */ + map_crash_data_t crashInfo; + if (middleWare.SaveDebugDump(argv[1], crashInfo)) + { + std::cout << "Application Crashed! " << + crashInfo[FILENAME_PACKAGE][CD_CONTENT] << ", " << + crashInfo[FILENAME_EXECUTABLE][CD_CONTENT] << ", " << + crashInfo[CD_COUNT][CD_CONTENT] << ", " << std::endl; + + /* Get Report, so user can change data (remove private stuff) + * If we do not want user interaction, just send data immediately + */ + map_crash_data_t crashReport; + middleWare.CreateCrashReport(crashInfo[FILENAME_DUPHASH][CD_CONTENT], + crashInfo[CD_UID][CD_CONTENT], + crashReport); + /* Report crash */ + middleWare.Report(crashReport); + } + } + catch (std::string sError) + { + std::cerr << sError << std::endl; + } + + return 0; +} diff --git a/src/lib/time.c b/src/lib/time.c new file mode 100644 index 00000000..37ade2cc --- /dev/null +++ b/src/lib/time.c @@ -0,0 +1,65 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Licensed under GPL version 2, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" + +#define ENABLE_MONOTONIC_SYSCALL 1 + +#if ENABLE_MONOTONIC_SYSCALL + +#include +/* Old glibc (< 2.3.4) does not provide this constant. We use syscall + * directly so this definition is safe. */ +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC 1 +#endif + +/* libc has incredibly messy way of doing this, + * typically requiring -lrt. We just skip all this mess */ +static void get_mono(struct timespec *ts) +{ + if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts)) + error_msg_and_die("clock_gettime(MONOTONIC) failed"); +} +unsigned long long monotonic_ns(void) +{ + struct timespec ts; + get_mono(&ts); + return ts.tv_sec * 1000000000ULL + ts.tv_nsec; +} +unsigned long long monotonic_us(void) +{ + struct timespec ts; + get_mono(&ts); + return ts.tv_sec * 1000000ULL + ts.tv_nsec/1000; +} +unsigned monotonic_sec(void) +{ + struct timespec ts; + get_mono(&ts); + return ts.tv_sec; +} + +#else + +unsigned long long monotonic_ns(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; +} +unsigned long long monotonic_us(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000ULL + tv.tv_usec; +} +unsigned monotonic_sec(void) +{ + return time(NULL); +} + +#endif diff --git a/src/lib/xatonum.c b/src/lib/xatonum.c new file mode 100644 index 00000000..3b22071f --- /dev/null +++ b/src/lib/xatonum.c @@ -0,0 +1,50 @@ +/* + * Utility routines. + * + * Copyright (C) 2003 Manuel Novoa III + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" + +unsigned xatou(const char *numstr) +{ + unsigned long r; + int old_errno; + char *e; + + if (*numstr < '0' || *numstr > '9') + goto inval; + + old_errno = errno; + errno = 0; + r = strtoul(numstr, &e, 10); + if (errno || numstr == e || *e != '\0' || r > UINT_MAX) + goto inval; /* error / no digits / illegal trailing chars */ + errno = old_errno; /* Ok. So restore errno. */ + return r; + +inval: + error_msg_and_die("invalid number '%s'", numstr); +} + +int xatoi_u(const char *numstr) +{ + unsigned r = xatou(numstr); + if (r > (unsigned)INT_MAX) + error_msg_and_die("invalid number '%s'", numstr); + return r; +} + +int xatoi(const char *numstr) +{ + unsigned r; + + if (*numstr != '-') + return xatoi_u(numstr); + + r = xatou(numstr + 1); + if (r > (unsigned)INT_MAX + 1) + error_msg_and_die("invalid number '%s'", numstr); + return - (int)r; +} diff --git a/src/lib/xconnect.c b/src/lib/xconnect.c new file mode 100644 index 00000000..0d02b1a4 --- /dev/null +++ b/src/lib/xconnect.c @@ -0,0 +1,415 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Connect to host at port using address resolution from getaddrinfo + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ +#include "abrtlib.h" +#include /* netinet/in.h needs it */ +#include +#include +#include +#include + +#define ENABLE_FEATURE_IPV6 1 +#define ENABLE_FEATURE_PREFER_IPV4_ADDRESS 1 + +static const int const_int_1 = 1; + +void setsockopt_reuseaddr(int fd) +{ + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)); +} +int setsockopt_broadcast(int fd) +{ + return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1)); +} +int setsockopt_bindtodevice(int fd, const char *iface) +{ + int r; + struct ifreq ifr; + strncpy(ifr.ifr_name, iface, IFNAMSIZ); + /* NB: passing (iface, strlen(iface) + 1) does not work! + * (maybe it works on _some_ kernels, but not on 2.6.26) + * Actually, ifr_name is at offset 0, and in practice + * just giving char[IFNAMSIZ] instead of struct ifreq works too. + * But just in case it's not true on some obscure arch... */ + r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); + if (r) + perror_msg("can't bind to interface %s", iface); + return r; +} + +len_and_sockaddr* get_sock_lsa(int fd) +{ + len_and_sockaddr lsa; + len_and_sockaddr *lsa_ptr; + + lsa.len = LSA_SIZEOF_SA; + if (getsockname(fd, &lsa.u.sa, &lsa.len) != 0) + return NULL; + + lsa_ptr = (len_and_sockaddr *)xzalloc(LSA_LEN_SIZE + lsa.len); + if (lsa.len > LSA_SIZEOF_SA) { /* rarely (if ever) happens */ + lsa_ptr->len = lsa.len; + getsockname(fd, &lsa_ptr->u.sa, &lsa_ptr->len); + } else { + memcpy(lsa_ptr, &lsa, LSA_LEN_SIZE + lsa.len); + } + return lsa_ptr; +} + +void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) +{ + if (connect(s, s_addr, addrlen) < 0) { + close(s); + if (s_addr->sa_family == AF_INET) + perror_msg_and_die("%s (%s)", + "cannot connect to remote host", + inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr)); + perror_msg_and_die("cannot connect to remote host"); + } +} + +/* Return port number for a service. + * If "port" is a number use it as the port. + * If "port" is a name it is looked up in /etc/services, + * if it isnt found return default_port + */ +unsigned lookup_port(const char *port, const char *protocol, unsigned default_port) +{ + unsigned port_nr = default_port; + if (port) { + int old_errno; + char *end; + + /* Since this is a lib function, we're not allowed to reset errno to 0. + * Doing so could break an app that is deferring checking of errno. */ + old_errno = errno; + errno = 0; + port_nr = strtoul(port, &end, 10); + if (errno || *end || port_nr > 65535) { + struct servent *tserv = getservbyname(port, protocol); + port_nr = default_port; + if (tserv) + port_nr = ntohs(tserv->s_port); + } + errno = old_errno; + } + return (uint16_t)port_nr; +} + +int get_nport(const struct sockaddr *sa) +{ +#if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET6) { + return ((struct sockaddr_in6*)sa)->sin6_port; + } +#endif + if (sa->sa_family == AF_INET) { + return ((struct sockaddr_in*)sa)->sin_port; + } + /* What? UNIX socket? IPX?? :) */ + return -1; +} + +void set_nport(len_and_sockaddr *lsa, unsigned port) +{ +#if ENABLE_FEATURE_IPV6 + if (lsa->u.sa.sa_family == AF_INET6) { + lsa->u.sin6.sin6_port = port; + return; + } +#endif + if (lsa->u.sa.sa_family == AF_INET) { + lsa->u.sin.sin_port = port; + return; + } + /* What? UNIX socket? IPX?? :) */ +} + +/* We hijack this constant to mean something else */ +/* It doesn't hurt because we will remove this bit anyway */ +#define DIE_ON_ERROR AI_CANONNAME + +/* host: "1.2.3.4[:port]", "www.google.com[:port]" + * port: if neither of above specifies port # */ +static len_and_sockaddr* str2sockaddr( + const char *host, int port, + sa_family_t af, + int ai_flags) +{ + int rc; + len_and_sockaddr *r; + struct addrinfo *result = NULL; + struct addrinfo *used_res; + const char *org_host = host; /* only for error msg */ + const char *cp; + struct addrinfo hint; + + r = NULL; + + /* Ugly parsing of host:addr */ + if (ENABLE_FEATURE_IPV6 && host[0] == '[') { + /* Even uglier parsing of [xx]:nn */ + host++; + cp = strchr(host, ']'); + if (!cp || (cp[1] != ':' && cp[1] != '\0')) { + /* Malformed: must be [xx]:nn or [xx] */ + error_msg("bad address '%s'", org_host); + if (ai_flags & DIE_ON_ERROR) + xfunc_die(); + return NULL; + } + } else { + cp = strrchr(host, ':'); + if (ENABLE_FEATURE_IPV6 && cp && strchr(host, ':') != cp) { + /* There is more than one ':' (e.g. "::1") */ + cp = NULL; /* it's not a port spec */ + } + } + if (cp) { /* points to ":" or "]:" */ + int sz = cp - host + 1; + char *hbuf = (char*)alloca(sz); + hbuf[--sz] = '\0'; + host = strncpy(hbuf, host, sz); + if (ENABLE_FEATURE_IPV6 && *cp != ':') { + cp++; /* skip ']' */ + if (*cp == '\0') /* [xx] without port */ + goto skip; + } + cp++; /* skip ':' */ + char *end; + errno = 0; + port = strtoul(cp, &end, 10); + if (errno || *end || (unsigned)port > 0xffff) { + error_msg("bad port spec '%s'", org_host); + if (ai_flags & DIE_ON_ERROR) + xfunc_die(); + return NULL; + } + skip: ; + } + + memset(&hint, 0 , sizeof(hint)); +#if !ENABLE_FEATURE_IPV6 + hint.ai_family = AF_INET; /* do not try to find IPv6 */ +#else + hint.ai_family = af; +#endif + /* Needed. Or else we will get each address thrice (or more) + * for each possible socket type (tcp,udp,raw...): */ + hint.ai_socktype = SOCK_STREAM; + hint.ai_flags = ai_flags & ~DIE_ON_ERROR; + rc = getaddrinfo(host, NULL, &hint, &result); + if (rc || !result) { + error_msg("bad address '%s'", org_host); + if (ai_flags & DIE_ON_ERROR) + xfunc_die(); + goto ret; + } + used_res = result; +#if ENABLE_FEATURE_PREFER_IPV4_ADDRESS + while (1) { + if (used_res->ai_family == AF_INET) + break; + used_res = used_res->ai_next; + if (!used_res) { + used_res = result; + break; + } + } +#endif + r = (len_and_sockaddr *)xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen); + r->len = used_res->ai_addrlen; + memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen); + set_nport(r, htons(port)); + ret: + freeaddrinfo(result); + return r; +} +#if !ENABLE_FEATURE_IPV6 +#define str2sockaddr(host, port, af, ai_flags) str2sockaddr(host, port, ai_flags) +#endif + +#if ENABLE_FEATURE_IPV6 +len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af) +{ + return str2sockaddr(host, port, af, 0); +} + +len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t af) +{ + return str2sockaddr(host, port, af, DIE_ON_ERROR); +} +#endif + +len_and_sockaddr* host2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, 0); +} + +len_and_sockaddr* xhost2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR); +} + +len_and_sockaddr* xdotted2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR); +} + +#undef xsocket_type +int xsocket_type(len_and_sockaddr **lsap, int family, int sock_type) +{ + len_and_sockaddr *lsa; + int fd; + int len; + +#if ENABLE_FEATURE_IPV6 + if (family == AF_UNSPEC) { + fd = socket(AF_INET6, sock_type, 0); + if (fd >= 0) { + family = AF_INET6; + goto done; + } + family = AF_INET; + } +#endif + fd = xsocket(family, sock_type, 0); + len = sizeof(struct sockaddr_in); +#if ENABLE_FEATURE_IPV6 + if (family == AF_INET6) { + done: + len = sizeof(struct sockaddr_in6); + } +#endif + lsa = (len_and_sockaddr *)xzalloc(offsetof(len_and_sockaddr, u.sa) + len); + lsa->len = len; + lsa->u.sa.sa_family = family; + *lsap = lsa; + return fd; +} + +int xsocket_stream(len_and_sockaddr **lsap) +{ + return xsocket_type(lsap, AF_UNSPEC, SOCK_STREAM); +} + +static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type) +{ + int fd; + len_and_sockaddr *lsa; + + if (bindaddr && bindaddr[0]) { + lsa = xdotted2sockaddr(bindaddr, port); + /* user specified bind addr dictates family */ + fd = xsocket(lsa->u.sa.sa_family, sock_type, 0); + } else { + fd = xsocket_type(&lsa, AF_UNSPEC, sock_type); + set_nport(lsa, htons(port)); + } + setsockopt_reuseaddr(fd); + xbind(fd, &lsa->u.sa, lsa->len); + free(lsa); + return fd; +} + +int create_and_bind_stream_or_die(const char *bindaddr, int port) +{ + return create_and_bind_or_die(bindaddr, port, SOCK_STREAM); +} + +int create_and_bind_dgram_or_die(const char *bindaddr, int port) +{ + return create_and_bind_or_die(bindaddr, port, SOCK_DGRAM); +} + + +int create_and_connect_stream_or_die(const char *peer, int port) +{ + int fd; + len_and_sockaddr *lsa; + + lsa = xhost2sockaddr(peer, port); + fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0); + setsockopt_reuseaddr(fd); + xconnect(fd, &lsa->u.sa, lsa->len); + free(lsa); + return fd; +} + +int xconnect_stream(const len_and_sockaddr *lsa) +{ + int fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0); + xconnect(fd, &lsa->u.sa, lsa->len); + return fd; +} + +/* We hijack this constant to mean something else */ +/* It doesn't hurt because we will add this bit anyway */ +#define IGNORE_PORT NI_NUMERICSERV +static char* sockaddr2str(const struct sockaddr *sa, int flags) +{ + char host[128]; + char serv[16]; + int rc; + socklen_t salen; + + salen = LSA_SIZEOF_SA; +#if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET) + salen = sizeof(struct sockaddr_in); + if (sa->sa_family == AF_INET6) + salen = sizeof(struct sockaddr_in6); +#endif + rc = getnameinfo(sa, salen, + host, sizeof(host), + /* can do ((flags & IGNORE_PORT) ? NULL : serv) but why bother? */ + serv, sizeof(serv), + /* do not resolve port# into service _name_ */ + flags | NI_NUMERICSERV + ); + if (rc) + return NULL; + if (flags & IGNORE_PORT) + return xstrdup(host); +#if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET6) { + if (strchr(host, ':')) /* heh, it's not a resolved hostname */ + return xasprintf("[%s]:%s", host, serv); + /*return xasprintf("%s:%s", host, serv);*/ + /* - fall through instead */ + } +#endif + /* For now we don't support anything else, so it has to be INET */ + /*if (sa->sa_family == AF_INET)*/ + return xasprintf("%s:%s", host, serv); + /*return xstrdup(host);*/ +} + +char* xmalloc_sockaddr2host(const struct sockaddr *sa) +{ + return sockaddr2str(sa, 0); +} + +char* xmalloc_sockaddr2host_noport(const struct sockaddr *sa) +{ + return sockaddr2str(sa, IGNORE_PORT); +} + +char* xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa) +{ + return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT); +} +char* xmalloc_sockaddr2dotted(const struct sockaddr *sa) +{ + return sockaddr2str(sa, NI_NUMERICHOST); +} + +char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa) +{ + return sockaddr2str(sa, NI_NUMERICHOST | IGNORE_PORT); +} diff --git a/src/lib/xfuncs.c b/src/lib/xfuncs.c new file mode 100644 index 00000000..d5166037 --- /dev/null +++ b/src/lib/xfuncs.c @@ -0,0 +1,400 @@ +/* + Copyright (C) 2010 ABRT team + Copyright (C) 2010 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. +*/ + +/* + * Utility routines. + * + */ +#include "abrtlib.h" + +/* Turn on nonblocking I/O on a fd */ +int ndelay_on(int fd) +{ + return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +} + +int ndelay_off(int fd) +{ + return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); +} + +int close_on_exec_on(int fd) +{ + return fcntl(fd, F_SETFD, FD_CLOEXEC); +} + +#if 0 /* unused */ +void *xcalloc(size_t nmemb, size_t size) +{ + void *ptr = calloc(nmemb, size); + if (!ptr && nmemb && size) + die_out_of_memory(); + return ptr; +} +#endif + +// Die if we can't allocate size bytes of memory. +void* xmalloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr == NULL && size != 0) + die_out_of_memory(); + return ptr; +} + +// Die if we can't resize previously allocated memory. (This returns a pointer +// to the new memory, which may or may not be the same as the old memory. +// It'll copy the contents to a new chunk and free the old one if necessary.) +void* xrealloc(void *ptr, size_t size) +{ + ptr = realloc(ptr, size); + if (ptr == NULL && size != 0) + die_out_of_memory(); + return ptr; +} + +// Die if we can't allocate and zero size bytes of memory. +void* xzalloc(size_t size) +{ + void *ptr = xmalloc(size); + memset(ptr, 0, size); + return ptr; +} + +// Die if we can't copy a string to freshly allocated memory. +char* xstrdup(const char *s) +{ + char *t; + if (s == NULL) + return NULL; + + t = strdup(s); + + if (t == NULL) + die_out_of_memory(); + + return t; +} + +// Die if we can't allocate n+1 bytes (space for the null terminator) and copy +// the (possibly truncated to length n) string into it. +char* xstrndup(const char *s, int n) +{ + int m; + char *t; + + /* We can just xmalloc(n+1) and strncpy into it, */ + /* but think about xstrndup("abc", 10000) wastage! */ + m = n; + t = (char*) s; + while (m) + { + if (!*t) break; + m--; + t++; + } + n -= m; + t = (char*) xmalloc(n + 1); + t[n] = '\0'; + + return (char*) memcpy(t, s, n); +} + +void xpipe(int filedes[2]) +{ + if (pipe(filedes)) + perror_msg_and_die("can't create pipe"); +} + +void xdup(int from) +{ + if (dup(from) < 0) + perror_msg_and_die("can't duplicate file descriptor"); +} + +void xdup2(int from, int to) +{ + if (dup2(from, to) != to) + perror_msg_and_die("can't duplicate file descriptor"); +} + +// "Renumber" opened fd +void xmove_fd(int from, int to) +{ + if (from == to) + return; + xdup2(from, to); + close(from); +} + +// Die with an error message if we can't write the entire buffer. +void xwrite(int fd, const void *buf, size_t count) +{ + if (count == 0) + return; + ssize_t size = full_write(fd, buf, count); + if ((size_t)size != count) + error_msg_and_die("short write"); +} + +void xwrite_str(int fd, const char *str) +{ + xwrite(fd, str, strlen(str)); +} + +// Die with an error message if we can't lseek to the right spot. +off_t xlseek(int fd, off_t offset, int whence) +{ + off_t off = lseek(fd, offset, whence); + if (off == (off_t)-1) { + if (whence == SEEK_SET) + perror_msg_and_die("lseek(%llu)", (long long)offset); + perror_msg_and_die("lseek"); + } + return off; +} + +void xchdir(const char *path) +{ + if (chdir(path)) + perror_msg_and_die("chdir(%s)", path); +} + +char* xvasprintf(const char *format, va_list p) +{ + int r; + char *string_ptr; + +#if 1 + // GNU extension + r = vasprintf(&string_ptr, format, p); +#else + // Bloat for systems that haven't got the GNU extension. + va_list p2; + va_copy(p2, p); + r = vsnprintf(NULL, 0, format, p); + string_ptr = xmalloc(r+1); + r = vsnprintf(string_ptr, r+1, format, p2); + va_end(p2); +#endif + + if (r < 0) + die_out_of_memory(); + return string_ptr; +} + +// Die with an error message if we can't malloc() enough space and do an +// sprintf() into that space. +char* xasprintf(const char *format, ...) +{ + va_list p; + char *string_ptr; + + va_start(p, format); + string_ptr = xvasprintf(format, p); + va_end(p); + + return string_ptr; +} + +void xsetenv(const char *key, const char *value) +{ + if (setenv(key, value, 1)) + die_out_of_memory(); +} + +// Die with an error message if we can't open a new socket. +int xsocket(int domain, int type, int protocol) +{ + int r = socket(domain, type, protocol); + if (r < 0) + { + const char *s = "INET"; + if (domain == AF_PACKET) s = "PACKET"; + if (domain == AF_NETLINK) s = "NETLINK"; + if (domain == AF_INET6) s = "INET6"; + perror_msg_and_die("socket(AF_%s)", s); + } + + return r; +} + +// Die with an error message if we can't bind a socket to an address. +void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) +{ + if (bind(sockfd, my_addr, addrlen)) + perror_msg_and_die("bind"); +} + +// Die with an error message if we can't listen for connections on a socket. +void xlisten(int s, int backlog) +{ + if (listen(s, backlog)) + perror_msg_and_die("listen"); +} + +// Die with an error message if sendto failed. +// Return bytes sent otherwise +ssize_t xsendto(int s, const void *buf, size_t len, + const struct sockaddr *to, + socklen_t tolen) +{ + ssize_t ret = sendto(s, buf, len, 0, to, tolen); + if (ret < 0) + { + close(s); + perror_msg_and_die("sendto"); + } + return ret; +} + +// xstat() - a stat() which dies on failure with meaningful error message +void xstat(const char *name, struct stat *stat_buf) +{ + if (stat(name, stat_buf)) + perror_msg_and_die("can't stat '%s'", name); +} + +// Die if we can't open a file and return a fd +int xopen3(const char *pathname, int flags, int mode) +{ + int ret; + ret = open(pathname, flags, mode); + if (ret < 0) + perror_msg_and_die("can't open '%s'", pathname); + return ret; +} + +// Die if we can't open an existing file and return a fd +int xopen(const char *pathname, int flags) +{ + return xopen3(pathname, flags, 0666); +} + +void xunlink(const char *pathname) +{ + if (unlink(pathname)) + perror_msg_and_die("can't remove file '%s'", pathname); +} + +#if 0 //UNUSED +// Warn if we can't open a file and return a fd. +int open3_or_warn(const char *pathname, int flags, int mode) +{ + int ret; + ret = open(pathname, flags, mode); + if (ret < 0) + perror_msg("can't open '%s'", pathname); + return ret; +} + +// Warn if we can't open a file and return a fd. +int open_or_warn(const char *pathname, int flags) +{ + return open3_or_warn(pathname, flags, 0666); +} +#endif + +/* Just testing dent->d_type == DT_REG is wrong: some filesystems + * do not report the type, they report DT_UNKNOWN for every dirent + * (and this is not a bug in filesystem, this is allowed by standards). + */ +int is_regular_file(struct dirent *dent, const char *dirname) +{ + if (dent->d_type == DT_REG) + return 1; + if (dent->d_type != DT_UNKNOWN) + return 0; + + char *fullname = xasprintf("%s/%s", dirname, dent->d_name); + struct stat statbuf; + int r = lstat(fullname, &statbuf); + free(fullname); + + return r == 0 && S_ISREG(statbuf.st_mode); +} + +/* Is it "." or ".."? */ +/* abrtlib candidate */ +bool dot_or_dotdot(const char *filename) +{ + if (filename[0] != '.') return false; + if (filename[1] == '\0') return true; + if (filename[1] != '.') return false; + if (filename[2] == '\0') return true; + return false; +} + +/* Find out if the last character of a string matches the one given. + * Don't underrun the buffer if the string length is 0. + */ +char *last_char_is(const char *s, int c) +{ + if (s && *s) + { + s += strlen(s) - 1; + if ((unsigned char)*s == c) + return (char*)s; + } + return NULL; +} + +bool string_to_bool(const char *s) +{ + if (s[0] == '1' && s[1] == '\0') + return true; + if (strcasecmp(s, "on") == 0) + return true; + if (strcasecmp(s, "yes") == 0) + return true; + if (strcasecmp(s, "true") == 0) + return true; + return false; +} + +void xseteuid(uid_t euid) +{ + if (seteuid(euid) != 0) + perror_msg_and_die("can't set %cid %lu", 'u', (long)euid); +} + +void xsetegid(gid_t egid) +{ + if (setegid(egid) != 0) + perror_msg_and_die("can't set %cid %lu", 'g', (long)egid); +} + +void xsetreuid(uid_t ruid, uid_t euid) +{ + if (setreuid(ruid, euid) != 0) + perror_msg_and_die("can't set %cid %lu", 'u', (long)ruid); +} + +void xsetregid(gid_t rgid, gid_t egid) +{ + if (setregid(rgid, egid) != 0) + perror_msg_and_die("can't set %cid %lu", 'g', (long)rgid); +} + +const char *get_home_dir(uid_t uid) +{ + struct passwd* pw = getpwuid(uid); + // TODO: handle errno + return pw ? pw->pw_dir : NULL; +} diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index f213804e..8a8a6f30 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -1,5 +1,5 @@ -INC_PATH=$(srcdir)/../../inc -UTILS_PATH=$(srcdir)/../../lib/utils +INC_PATH=$(srcdir)/../include +UTILS_PATH=$(srcdir)/../lib AM_CPPFLAGS = -I$(INC_PATH) -I$(UTILS_PATH) pluginslibdir=$(PLUGINS_LIB_DIR) libexec_SCRIPTS = \ @@ -54,7 +54,8 @@ install-data-hook: $(DESTDIR)/$(DEBUG_INFO_DIR) libCCpp_la_SOURCES = CCpp.cpp CCpp.h libCCpp_la_LDFLAGS = -avoid-version libCCpp_la_CPPFLAGS = -Wall -Werror \ - -I$(INC_PATH) -I$(UTILS_PATH) \ + -I$(INC_PATH) \ + -I$(UTILS_PATH) \ -DCCPP_HOOK_PATH=\"${libexecdir}/abrt-hook-ccpp\" \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ -DLOCALSTATEDIR='"$(localstatedir)"' @@ -86,8 +87,8 @@ libexec_PROGRAMS = \ abrt_action_analyze_c_SOURCES = \ abrt-action-analyze-c.c abrt_action_analyze_c_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -99,13 +100,13 @@ abrt_action_analyze_c_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_action_analyze_c_LDADD = \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTUtils.la abrt_action_analyze_python_SOURCES = \ abrt-action-analyze-python.c abrt_action_analyze_python_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -117,13 +118,13 @@ abrt_action_analyze_python_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_action_analyze_python_LDADD = \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTUtils.la abrt_action_analyze_oops_SOURCES = \ abrt-action-analyze-oops.c abrt_action_analyze_oops_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -135,13 +136,13 @@ abrt_action_analyze_oops_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_action_analyze_oops_LDADD = \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTUtils.la abrt_action_generate_backtrace_SOURCES = \ abrt-action-generate-backtrace.c abrt_action_generate_backtrace_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -153,14 +154,14 @@ abrt_action_generate_backtrace_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_action_generate_backtrace_LDADD = \ - ../../lib/utils/libABRTUtils.la \ + ../lib/libABRTUtils.la \ ../btparser/libbtparser.la abrt_action_bugzilla_SOURCES = \ abrt-action-bugzilla.cpp abrt_action_bugzilla_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -174,16 +175,16 @@ abrt_action_bugzilla_CPPFLAGS = \ -Wall -Werror abrt_action_bugzilla_LDADD = \ $(GLIB_LIBS) \ - ../../lib/utils/libABRT_web_utils.la \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRT_web_utils.la \ + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la abrt_action_rhtsupport_SOURCES = \ abrt_rh_support.h abrt_rh_support.c \ abrt-action-rhtsupport.cpp abrt_action_rhtsupport_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -200,15 +201,15 @@ abrt_action_rhtsupport_LDFLAGS = -ltar abrt_action_rhtsupport_LDADD = \ $(GLIB_LIBS) \ $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) \ - ../../lib/utils/libABRT_web_utils.la \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRT_web_utils.la \ + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la abrt_action_upload_SOURCES = \ abrt-action-upload.cpp abrt_action_upload_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -226,14 +227,14 @@ abrt_action_upload_LDFLAGS = -ltar abrt_action_upload_LDADD = \ $(GLIB_LIBS) \ $(CURL_LIBS) \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la abrt_action_kerneloops_SOURCES = \ abrt-action-kerneloops.cpp abrt_action_kerneloops_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -247,15 +248,15 @@ abrt_action_kerneloops_CPPFLAGS = \ -Wall -Werror # libABRTdUtils is used only because of LoadPluginSettings: abrt_action_kerneloops_LDADD = \ - ../../lib/utils/libABRT_web_utils.la \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRT_web_utils.la \ + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la abrt_action_mailx_SOURCES = \ abrt-action-mailx.cpp abrt_action_mailx_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -268,14 +269,14 @@ abrt_action_mailx_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Werror abrt_action_mailx_LDADD = \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la abrt_action_print_SOURCES = \ abrt-action-print.cpp abrt_action_print_CPPFLAGS = \ - -I$(srcdir)/../../inc \ - -I$(srcdir)/../../lib/utils \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ -DBIN_DIR=\"$(bindir)\" \ -DVAR_RUN=\"$(VAR_RUN)\" \ -DCONF_DIR=\"$(CONF_DIR)\" \ @@ -289,7 +290,7 @@ abrt_action_print_CPPFLAGS = \ -Wall -Werror # libABRTdUtils is used only because of make_description_logger: abrt_action_print_LDADD = \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la + ../lib/libABRTdUtils.la \ + ../lib/libABRTUtils.la DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ diff --git a/tests/atlocal.in b/tests/atlocal.in index 62cba99d..f3649ccb 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -6,7 +6,7 @@ CC='@CC@' LIBTOOL="$abs_top_builddir/libtool" # We want no optimization. -CFLAGS="@O0CFLAGS@ -I$abs_top_builddir/src/btparser -I$abs_top_builddir/lib/utils -D_GNU_SOURCE" +CFLAGS="@O0CFLAGS@ -I$abs_top_builddir/src/btparser -I$abs_top_builddir/src/lib -D_GNU_SOURCE" # Are special link options needed? LDFLAGS="@LDFLAGS@ $abs_top_builddir/src/btparser/libbtparser.la" -- cgit