Example #1
0
/* Callback called by glib main loop when a client connects to ABRT's socket. */
static gboolean server_socket_cb(GIOChannel *source, GIOCondition condition, gpointer ptr_unused)
{
    kill_idle_timeout();
    load_abrt_conf();

    int socket = accept(g_io_channel_unix_get_fd(source), NULL, NULL);
    if (socket == -1)
    {
        perror_msg("accept");
        goto server_socket_finitio;
    }

    log_notice("New client connected");
    fflush(NULL); /* paranoia */

    int pipefd[2];
    xpipe(pipefd);

    pid_t pid = fork();
    if (pid < 0)
    {
        perror_msg("fork");
        close(socket);
        close(pipefd[0]);
        close(pipefd[1]);
        goto server_socket_finitio;
    }
    if (pid == 0) /* child */
    {
        xdup2(socket, STDIN_FILENO);
        xdup2(socket, STDOUT_FILENO);
        close(socket);

        close(pipefd[0]);
        xmove_fd(pipefd[1], STDERR_FILENO);

        char *argv[3];  /* abrt-server [-s] NULL */
        char **pp = argv;
        *pp++ = (char*)"abrt-server";
        if (logmode & LOGMODE_JOURNAL)
            *pp++ = (char*)"-s";
        *pp = NULL;

        execvp(argv[0], argv);
        perror_msg_and_die("Can't execute '%s'", argv[0]);
    }

    /* parent */
    close(socket);
    close(pipefd[1]);
    add_abrt_server_proc(pid, pipefd[0]);

server_socket_finitio:
    start_idle_timeout();
    return TRUE;
}
Example #2
0
File: list.c Project: abrt/abrt
int cmd_list(int argc, const char **argv)
{
    const char *program_usage_string = _(
        "& list [options]"
        );

    int opt_not_reported = 0;
    int opt_detailed = 0;
    int opt_since = 0;
    int opt_until = 0;
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL('n', "not-reported"     , &opt_not_reported,      _("List only not-reported problems")),
        /* deprecate -d option with --pretty=full*/
        OPT_BOOL('d', "detailed" , &opt_detailed,  _("Show detailed report")),
        OPT_INTEGER('s', "since" , &opt_since,  _("List only the problems more recent than specified timestamp")),
        OPT_INTEGER('u', "until" , &opt_until,  _("List only the problems older than specified timestamp")),
        OPT_END()
    };

    parse_opts(argc, (char **)argv, program_options, program_usage_string);

    vector_of_problem_data_t *ci = fetch_crash_infos();
    if (ci == NULL)
        return 1;

    g_ptr_array_sort_with_data(ci, &cmp_problem_data, (char *) FILENAME_LAST_OCCURRENCE);

#if SUGGEST_AUTOREPORTING != 0
    const bool output =
#endif
    print_crash_list(ci, opt_detailed, opt_not_reported, opt_since, opt_until, CD_TEXT_ATT_SIZE_BZ);

    free_vector_of_problem_data(ci);

#if SUGGEST_AUTOREPORTING != 0
    load_abrt_conf();
    if (!g_settings_autoreporting)
    {
        if (output)
            putc('\n', stderr);

        fprintf(stderr, _("The Autoreporting feature is disabled. Please consider enabling it by issuing\n"
                          "'abrt-auto-reporting enabled' as a user with root privileges\n"));
    }
#endif

    return 0;
}
Example #3
0
char* problem_data_save(problem_data_t *pd)
{
    load_abrt_conf();

    struct dump_dir *dd = create_dump_dir_from_problem_data_ext(pd, g_settings_dump_location, /*fs owner*/0);

    char *problem_id = NULL;
    if (dd)
    {
        problem_id = xstrdup(dd->dd_dirname);
        dd_close(dd);
    }

    log_info("problem id: '%s'", problem_id);
    return problem_id;
}
Example #4
0
static void handle_inotify_cb(struct abrt_inotify_watch *watch, struct inotify_event *event, gpointer ptr_unused)
{
    kill_idle_timeout();

    if (event->mask & IN_DELETE_SELF || event->mask & IN_MOVE_SELF)
    {
        log_warning("Recreating deleted dump location '%s'", g_settings_dump_location);

        load_abrt_conf();

        sanitize_dump_dir_rights();
        abrt_inotify_watch_reset(watch, g_settings_dump_location, IN_DUMP_LOCATION_FLAGS);
    }

    start_idle_timeout();
}
Example #5
0
int cmd_report(int argc, const char **argv)
{
    const char *program_usage_string = _(
        "& report [options] DIR..."
    );

    enum {
        OPT_v = 1 << 0,
        OPT_d = 1 << 1,
        OPT_u = 1 << 2,
    };

    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL('d', "delete", NULL, _("Remove PROBLEM_DIR after reporting")),
        OPT_BOOL('u', "unsafe", NULL, _("Ignore security checks to be able to "
                                        "report all problems")),
        OPT_END()
    };

    unsigned opts = parse_opts(argc, (char **)argv, program_options, program_usage_string);
    argv += optind;

    if (!argv[0])
        show_usage_and_die(program_usage_string, program_options);

    export_abrt_envvars(/*prog_prefix:*/ 0);

    load_abrt_conf();
    free_abrt_conf_data();

    int report_flags = 0;
    if (opts & OPT_d)
        report_flags |= CMD_REPORT_REMOVE;
    if (opts & OPT_u)
        report_flags |= CMD_REPORT_UNSAFE;

    return _cmd_report(argv, report_flags);
}
Example #6
0
int main(int argc, char **argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
        "& [options]"
    );
    enum {
        OPT_v = 1 << 0,
        OPT_u = 1 << 1,
        OPT_s = 1 << 2,
        OPT_p = 1 << 3,
    };
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_INTEGER('u', NULL, &client_uid, _("Use NUM as client uid")),
        OPT_BOOL(   's', NULL, NULL       , _("Log to syslog")),
        OPT_BOOL(   'p', NULL, NULL       , _("Add program names to log")),
        OPT_END()
    };
    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(opts & OPT_p);

    msg_prefix = xasprintf("%s[%u]", g_progname, getpid());
    if (opts & OPT_s)
    {
        logmode = LOGMODE_JOURNAL;
    }

    /* Set up timeout handling */
    /* Part 1 - need this to make SIGALRM interrupt syscalls
     * (as opposed to restarting them): I want read syscall to be interrupted
     */
    struct sigaction sa;
    /* sa.sa_flags.SA_RESTART bit is clear: make signal interrupt syscalls */
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = dummy_handler; /* pity, SIG_DFL won't do */
    sigaction(SIGALRM, &sa, NULL);
    /* Part 2 - set the timeout per se */
    alarm(TIMEOUT);

    if (client_uid == (uid_t)-1L)
    {
        /* Get uid of the connected client */
        struct ucred cr;
        socklen_t crlen = sizeof(cr);
        if (0 != getsockopt(STDIN_FILENO, SOL_SOCKET, SO_PEERCRED, &cr, &crlen))
            perror_msg_and_die("getsockopt(SO_PEERCRED)");
        if (crlen != sizeof(cr))
            error_msg_and_die("%s: bad crlen %d", "getsockopt(SO_PEERCRED)", (int)crlen);
        client_uid = cr.uid;
    }

    load_abrt_conf();

    int r = perform_http_xact();
    if (r == 0)
        r = 200;

    free_abrt_conf_data();

    printf("HTTP/1.1 %u \r\n\r\n", r);

    return (r >= 400); /* Error if 400+ */
}
Example #7
0
int main(int argc, char **argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    const char *program_usage_string = _(
        "& [-v -i -n INCREMENT] -e|--event EVENT DIR..."
        );

    char *event_name = NULL;
    int interactive = 0; /* must be _int_, OPT_BOOL expects that! */
    int nice_incr = 0;

    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_STRING('e', "event" , &event_name, "EVENT",  _("Run EVENT on DIR")),
        OPT_BOOL('i', "interactive" , &interactive, _("Communicate directly to the user")),
        OPT_INTEGER('n',     "nice" , &nice_incr,   _("Increment the nice value by INCREMENT")),
        OPT_END()
    };

    parse_opts(argc, argv, program_options, program_usage_string);
    argv += optind;
    if (!*argv || !event_name)
        show_usage_and_die(program_usage_string, program_options);

    load_abrt_conf();

    const char *const opt_env_nice = getenv("ABRT_EVENT_NICE");
    if (opt_env_nice != NULL && opt_env_nice[0] != '\0')
    {
        log_debug("Using ABRT_EVENT_NICE=%s to increment the nice value", opt_env_nice);
        nice_incr = xatoi(opt_env_nice);
    }

    if (nice_incr != 0)
    {
        log_debug("Incrementing the nice value by %d", nice_incr);
        const int ret = nice(nice_incr);
        if (ret == -1)
            perror_msg_and_die("Failed to increment the nice value");
    }

    bool post_create = (strcmp(event_name, "post-create") == 0);
    char *dump_dir_name = NULL;
    while (*argv)
    {
        dump_dir_name = xstrdup(*argv++);
        int i = strlen(dump_dir_name);
        while (--i >= 0)
            if (dump_dir_name[i] != '/')
                break;
        dump_dir_name[++i] = '\0';

        struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ DD_OPEN_READONLY);
        if (!dd)
            return 1;

        uid = dd_load_text_ext(dd, FILENAME_UID, DD_FAIL_QUIETLY_ENOENT);
        dd_close(dd);

        struct run_event_state *run_state = new_run_event_state();
        if (!interactive)
            make_run_event_state_forwarding(run_state);
        run_state->logging_callback = do_log;
        if (post_create)
            run_state->post_run_callback = is_crash_a_dup;

        int r = run_event_on_dir_name(run_state, dump_dir_name, event_name);

        const bool no_action_for_event = (r == 0 && run_state->children_count == 0);

        free_run_event_state(run_state);
        /* Needed only if is_crash_a_dup() was called, but harmless
         * even if it wasn't:
         */
        dup_uuid_fini();
        dup_corebt_fini();

        if (no_action_for_event)
            error_msg_and_die("No actions are found for event '%s'", event_name);

//TODO: consider this case:
// new dump is created, post-create detects that it is a dup,
// but then load_crash_info(dup_name) *FAILS*.
// In this case, we later delete damaged dup_name (right?)
// but new dump never gets its FILENAME_COUNT set!

        /* Is crash a dup? (In this case, is_crash_a_dup() should have
         * aborted "post-create" event processing as soon as it saw uuid
         * and determined that there is another crash with same uuid.
         * In this case it sets crash_dump_dup_name)
         */
        if (crash_dump_dup_name)
            error_msg_and_die("DUP_OF_DIR: %s", crash_dump_dup_name);

        /* Was there error on one of processing steps in run_event? */
        if (r != 0)
            return r; /* yes */

        free(dump_dir_name);
        dump_dir_name = NULL;
    }

    /* exit 0 means, that there is no duplicate of dump-dir */
    return 0;
}
Example #8
0
int main(int argc, char **argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
        "& [-vsoxm] [-d DIR]/[-D] [FILE]\n"
        "\n"
        "Extract Xorg crash from FILE (or standard input)"
    );
    /* Keep OPT_z enums and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
        OPT_BOOL(  'o', NULL, NULL, _("Print found crash data on standard output")),
        OPT_STRING('d', NULL, &debug_dumps_dir, "DIR", _("Create problem directory in DIR for every crash found")),
        OPT_BOOL(  'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
        OPT_BOOL(  'x', NULL, NULL, _("Make the problem directory world readable")),
        OPT_BOOL(  'm', NULL, NULL, _("Print search string(s) to stdout and exit")),
        OPT_END()
    };
    unsigned opts = g_opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(0);

    msg_prefix = g_progname;
    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
    {
        logmode = LOGMODE_JOURNAL;
    }

    if (opts & OPT_m)
    {
        puts("Backtrace");
        return 0;
    }

    if (opts & OPT_D)
    {
        if (opts & OPT_d)
            show_usage_and_die(program_usage_string, program_options);
        load_abrt_conf();
        debug_dumps_dir = g_settings_dump_location;
        g_settings_dump_location = NULL;
        free_abrt_conf_data();
    }

    argv += optind;
    if (argv[0])
        xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);

    char *line;
    while ((line = xmalloc_fgetline(stdin)) != NULL)
    {
        char *p = skip_pfx(line);
        if (strcmp(p, "Backtrace:") == 0)
        {
            free(line);
            g_bt_count++;
            process_xorg_bt();
            continue;
        }
        free(line);
    }

    /* If we are run by a log watcher, this delays log rescan
     * (because log watcher waits to us to terminate)
     * and possibly prevents dreaded "abrt storm".
     */
    if (opts & (OPT_d|OPT_D))
    {
        if (g_bt_count > MAX_DUMPED_DD_COUNT)
            sleep(g_bt_count - MAX_DUMPED_DD_COUNT);
    }

    return 0;
}
Example #9
0
int main(int argc, char **argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
        "& [-vusoxm] [-d DIR]/[-D] [FILE]\n"
        "\n"
        "Extract oops from FILE (or standard input)"
    );
    enum {
        OPT_v = 1 << 0,
        OPT_s = 1 << 1,
        OPT_o = 1 << 2,
        OPT_d = 1 << 3,
        OPT_D = 1 << 4,
        OPT_u = 1 << 5,
        OPT_x = 1 << 6,
        OPT_t = 1 << 7,
        OPT_m = 1 << 8,
    };
    char *problem_dir = NULL;
    char *dump_location = NULL;
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
        OPT_BOOL(  'o', NULL, NULL, _("Print found oopses on standard output")),
        /* oopses don't contain any sensitive info, and even
         * the old koops app was showing the oopses to all users
         */
        OPT_STRING('d', NULL, &dump_location, "DIR", _("Create new problem directory in DIR for every oops found")),
        OPT_BOOL(  'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
        OPT_STRING('u', NULL, &problem_dir, "PROBLEM", _("Save the extracted information in PROBLEM")),
        OPT_BOOL(  'x', NULL, NULL, _("Make the problem directory world readable")),
        OPT_BOOL(  't', NULL, NULL, _("Throttle problem directory creation to 1 per second")),
        OPT_BOOL(  'm', NULL, NULL, _("Print search string(s) to stdout and exit")),
        OPT_END()
    };
    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(0);

    msg_prefix = g_progname;
    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
    {
        logmode = LOGMODE_JOURNAL;
    }

    if (opts & OPT_m)
    {
        char *oops_string_filter_regex = abrt_oops_string_filter_regex();
        if (oops_string_filter_regex)
        {
            regex_t filter_re;
            if (regcomp(&filter_re, oops_string_filter_regex, REG_NOSUB) != 0)
                perror_msg_and_die(_("Failed to compile regex"));

            const regex_t *filter[] = { &filter_re, NULL };

            koops_print_suspicious_strings_filtered(filter);

            regfree(&filter_re);
            free(oops_string_filter_regex);
        }
        else
            koops_print_suspicious_strings();

        return 1;
    }

    if (opts & OPT_D)
    {
        if (opts & OPT_d)
            show_usage_and_die(program_usage_string, program_options);
        load_abrt_conf();
        dump_location = g_settings_dump_location;
        g_settings_dump_location = NULL;
        free_abrt_conf_data();
    }

    int oops_utils_flags = 0;
    if ((opts & OPT_x))
        oops_utils_flags |= ABRT_OOPS_WORLD_READABLE;

    if ((opts & OPT_t))
        oops_utils_flags |= ABRT_OOPS_THROTTLE_CREATION;

    if ((opts & OPT_o))
        oops_utils_flags |= ABRT_OOPS_PRINT_STDOUT;

    argv += optind;
    if (argv[0])
        xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);

    GList *oops_list = NULL;
    scan_syslog_file(&oops_list, STDIN_FILENO);

    unsigned errors = 0;
    if (opts & OPT_u)
    {
        log_warning("Updating problem directory");
        switch (g_list_length(oops_list))
        {
            case 0:
                {
                    error_msg(_("Can't update the problem: no oops found"));
                    errors = 1;
                    break;
                }
            default:
                {
                    log_notice(_("More oopses found: process only the first one"));
                }
                /* falls trought */
            case 1:
                {
                    struct dump_dir *dd = dd_opendir(problem_dir, /*open for writing*/0);
                    if (dd)
                    {
                        abrt_oops_save_data_in_dump_dir(dd, (char *)oops_list->data, /*no proc modules*/NULL);
                        dd_close(dd);
                    }
                }
        }
    }
    else
        errors = abrt_oops_process_list(oops_list, dump_location,
                                        ABRT_DUMP_OOPS_ANALYZER, oops_utils_flags);

    list_free_with_free(oops_list);
    //oops_list = NULL;

    return errors;
}
Example #10
0
int main(int argc, char** argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    int parent_pid = getpid();

    const char *program_usage_string = _(
        "& [options]"
    );
    enum {
        OPT_v = 1 << 0,
        OPT_d = 1 << 1,
        OPT_s = 1 << 2,
// TODO: get rid of -t NUM, it is no longer useful since dbus is moved to a separate tool
        OPT_t = 1 << 3,
        OPT_p = 1 << 4,
    };
    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL(   'd', NULL, NULL      , _("Do not daemonize")),
        OPT_BOOL(   's', NULL, NULL      , _("Log to syslog even with -d")),
        OPT_INTEGER('t', NULL, &s_timeout, _("Exit after NUM seconds of inactivity")),
        OPT_BOOL(   'p', NULL, NULL      , _("Add program names to log")),
        OPT_END()
    };
    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(opts & OPT_p);

#if 0 /* We no longer use dbus */
    /* When dbus daemon starts us, it doesn't set PATH
     * (I saw it set only DBUS_STARTER_ADDRESS and DBUS_STARTER_BUS_TYPE).
     * In this case, set something sane:
     */
    const char *env_path = getenv("PATH");
    if (!env_path || !env_path[0])
        putenv((char*)"PATH=/usr/sbin:/usr/bin:/sbin:/bin");
#endif

    unsetenv("ABRT_SYSLOG");
    msg_prefix = g_progname; /* for log_warning(), error_msg() and such */

    if (getuid() != 0)
        error_msg_and_die("Must be run as root");

    if (opts & OPT_s)
        start_logging();

    xpipe(s_signal_pipe);
    close_on_exec_on(s_signal_pipe[0]);
    close_on_exec_on(s_signal_pipe[1]);
    ndelay_on(s_signal_pipe[0]); /* I/O should not block - */
    ndelay_on(s_signal_pipe[1]); /* especially writes! they happen in signal handler! */
    signal(SIGTERM, handle_signal);
    signal(SIGINT,  handle_signal);
    signal(SIGCHLD, handle_signal);

    GIOChannel* channel_signal = NULL;
    guint channel_id_signal_event = 0;
    bool pidfile_created = false;
    struct abrt_inotify_watch *aiw = NULL;
    int ret = 1;

    /* Initialization */
    log_notice("Loading settings");
    if (load_abrt_conf() != 0)
        goto init_error;

    /* Moved before daemonization because parent waits for signal from daemon
     * only for short period and time consumed by
     * mark_unprocessed_dump_dirs_not_reportable() is slightly unpredictable.
     */
    sanitize_dump_dir_rights();
    mark_unprocessed_dump_dirs_not_reportable(g_settings_dump_location);

    /* Daemonize unless -d */
    if (!(opts & OPT_d))
    {
        /* forking to background */
        fflush(NULL); /* paranoia */
        pid_t pid = fork();
        if (pid < 0)
        {
            perror_msg_and_die("fork");
        }
        if (pid > 0)
        {
            /* Parent */
            /* Wait for child to notify us via SIGTERM that it feels ok */
            int i = 20; /* 2 sec */
            while (s_sig_caught == 0 && --i)
            {
                usleep(100 * 1000);
            }
            if (s_sig_caught == SIGTERM)
            {
                exit(0);
            }
            if (s_sig_caught)
            {
                error_msg_and_die("Failed to start: got sig %d", s_sig_caught);
            }
            error_msg_and_die("Failed to start: timeout waiting for child");
        }
        /* Child (daemon) continues */
        if (setsid() < 0)
            perror_msg_and_die("setsid");
        if (g_verbose == 0 && logmode != LOGMODE_JOURNAL)
            start_logging();
    }

    log_notice("Creating glib main loop");
    s_main_loop = g_main_loop_new(NULL, FALSE);

    /* Watching 'g_settings_dump_location' for delete self
     * because hooks expects that the dump location exists if abrtd is running
     */
    aiw = abrt_inotify_watch_init(g_settings_dump_location,
            IN_DUMP_LOCATION_FLAGS, handle_inotify_cb, /*user data*/NULL);

    /* Add an event source which waits for INT/TERM signal */
    log_notice("Adding signal pipe watch to glib main loop");
    channel_signal = abrt_gio_channel_unix_new(s_signal_pipe[0]);
    channel_id_signal_event = add_watch_or_die(channel_signal,
                        G_IO_IN | G_IO_PRI | G_IO_HUP,
                        handle_signal_cb);

    guint name_id = 0;

    /* Mark the territory */
    log_notice("Creating pid file");
    if (create_pidfile() != 0)
        goto init_error;
    pidfile_created = true;

    /* Open socket to receive new problem data (from python etc). */
    dumpsocket_init();

    /* Inform parent that we initialized ok */
    if (!(opts & OPT_d))
    {
        log_notice("Signalling parent");
        kill(parent_pid, SIGTERM);
        if (logmode != LOGMODE_JOURNAL)
            start_logging();
    }

    /* Only now we want signal pipe to work */
    s_signal_pipe_write = s_signal_pipe[1];

    /* Own a name on D-Bus */
    name_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
                             ABRTD_DBUS_NAME,
                             G_BUS_NAME_OWNER_FLAGS_NONE,
                             on_bus_acquired,
                             on_name_acquired,
                             on_name_lost,
                             NULL, NULL);

    start_idle_timeout();

    /* Enter the event loop */
    log_debug("Init complete, entering main loop");
    g_main_loop_run(s_main_loop);

    ret = 0;
    /* Jump to exit */
    goto cleanup;


 init_error:
    /* Initialization error */
    error_msg("Error while initializing daemon");
    /* Inform parent that initialization failed */
    if (!(opts & OPT_d))
        kill(parent_pid, SIGINT);


 cleanup:
    if (name_id > 0)
        g_bus_unown_name (name_id);

    /* Error or INT/TERM. Clean up, in reverse order.
     * Take care to not undo things we did not do.
     */
    dumpsocket_shutdown();
    if (pidfile_created)
        unlink(VAR_RUN_PIDFILE);

    if (channel_id_signal_event > 0)
        g_source_remove(channel_id_signal_event);
    if (channel_signal)
        g_io_channel_unref(channel_signal);

    abrt_inotify_watch_destroy(aiw);

    if (s_main_loop)
        g_main_loop_unref(s_main_loop);

    free_abrt_conf_data();

    if (s_sig_caught && s_sig_caught != SIGCHLD)
    {
        /* We use TERM to stop abrtd, so not printing out error message. */
        if (s_sig_caught != SIGTERM)
        {
            error_msg("Got signal %d, exiting", s_sig_caught);
            signal(s_sig_caught, SIG_DFL);
            raise(s_sig_caught);
        }
    }

    /* Exiting */
    log_notice("Exiting");
    return ret;
}
Example #11
0
/* Queueing the process will also lead to cleaning up the dump location.
 */
static void queue_post_craete_process(struct abrt_server_proc *proc)
{
    load_abrt_conf();
    struct abrt_server_proc *running = s_dir_queue == NULL ? NULL
                                                           : (struct abrt_server_proc *)s_dir_queue->data;
    if (g_settings_nMaxCrashReportsSize == 0)
        goto consider_processing;

    const char *full_path_ignored = running != NULL ? running->dirname
                                                    : proc->dirname;
    const char *ignored = strrchr(full_path_ignored, '/');
    if (NULL == ignored)
        /* Paranoia, this should not happen. */
        ignored = full_path_ignored;
    else
        /* Move behind '/' */
        ++ignored;

    char *worst_dir = NULL;
    const double max_size = 1024 * 1024 * g_settings_nMaxCrashReportsSize;
    while (get_dirsize_find_largest_dir(g_settings_dump_location, &worst_dir, ignored) >= max_size
           && worst_dir)
    {
        const char *kind = "old";

        GList *proc_of_deleted_item = NULL;
        if (proc != NULL && strcmp(worst_dir, proc->dirname) == 0)
        {
            kind = "new";
            stop_abrt_server(proc);
            proc = NULL;
        }
        else if ((proc_of_deleted_item = g_list_find_custom(s_dir_queue, worst_dir, (GCompareFunc)abrt_server_compare_dirname)))
        {
            kind = "unprocessed";
            struct abrt_server_proc *removed_proc = (struct abrt_server_proc *)proc_of_deleted_item->data;
            s_dir_queue = g_list_delete_link(s_dir_queue, proc_of_deleted_item);
            stop_abrt_server(removed_proc);
        }

        log_warning("Size of '%s' >= %u MB (MaxCrashReportsSize), deleting %s directory '%s'",
                g_settings_dump_location, g_settings_nMaxCrashReportsSize,
                kind, worst_dir);

        char *deleted = concat_path_file(g_settings_dump_location, worst_dir);
        free(worst_dir);
        worst_dir = NULL;

        struct dump_dir *dd = dd_opendir(deleted, DD_FAIL_QUIETLY_ENOENT);
        if (dd != NULL)
            dd_delete(dd);

        free(deleted);
    }

consider_processing:
    /* If the process survived cleaning up the dump location, append it to the
     * post-create queue.
     */
    if (proc != NULL)
        s_dir_queue = g_list_append(s_dir_queue, proc);

    /* If there were no running post-crate process before we added the
     * currently handled process to the post-create queue, start processing of
     * the currently handled process.
     */
    if (running == NULL)
        notify_next_post_create_process(NULL/*finished*/);
}
Example #12
0
int main(int argc, char *argv[])
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */

    const char *program_usage_string_template = _(
        "& [-vsoxtf] [-e]/[-c CURSOR] [-d DIR]/[-D]\n"
        "\n"
        "Extract Xorg crash from systemd-journal\n"
        "\n"
        "-c and -e options conflicts because both specifies the first read message.\n"
        "\n"
        "-e is useful only for -f because the following of journal starts by reading \n"
        "the entire journal if the last seen possition is not available.\n"
        "\n"
        "The last seen position is saved in %s\n"
        "\n"
        "Journal filter is required parameter and must be specified either by parameter\n"
        "-j or in %s conf file.\n"
    );

    char program_usage_string[strlen(program_usage_string_template)
                            + strlen(ABRT_JOURNAL_XORG_WATCH_STATE_FILE)
                            + strlen(XORG_CONF_PATH)];
    sprintf(program_usage_string, program_usage_string_template,
            ABRT_JOURNAL_XORG_WATCH_STATE_FILE, XORG_CONF_PATH);

    enum {
        OPT_v = 1 << 0,
        OPT_s = 1 << 1,
        OPT_o = 1 << 2,
        OPT_d = 1 << 3,
        OPT_D = 1 << 4,
        OPT_x = 1 << 5,
        OPT_t = 1 << 6,
        OPT_c = 1 << 7,
        OPT_e = 1 << 8,
        OPT_f = 1 << 9,
        OPT_a = 1 << 10,
        OPT_J = 1 << 11,
        OPT_j = 1 << 12,
    };

    char *cursor = NULL;
    char *dump_location = NULL;
    char *journal_dir = NULL;
    GList *journal_filters = NULL;

    /* Keep enum above and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
        OPT_BOOL(  'o', NULL, NULL, _("Print found crashes on standard output")),
        OPT_STRING('d', NULL, &dump_location, "DIR", _("Create new problem directory in DIR for every crash found")),
        OPT_BOOL(  'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
        OPT_BOOL(  'x', NULL, NULL, _("Make the problem directory world readable")),
        OPT_BOOL(  't', NULL, NULL, _("Throttle problem directory creation to 1 per second")),
        OPT_STRING('c', NULL, &cursor, "CURSOR", _("Start reading systemd-journal from the CURSOR position")),
        OPT_BOOL(  'e', NULL, NULL, _("Start reading systemd-journal from the end")),
        OPT_BOOL(  'f', NULL, NULL, _("Follow systemd-journal from the last seen position (if available)")),
        OPT_BOOL(  'a', NULL, NULL, _("Read journal files from all machines")),
        OPT_STRING('J', NULL, &journal_dir,  "PATH", _("Read all journal files from directory at PATH")),
        OPT_LIST(  'j', NULL, &journal_filters,  "FILTER", _("Journal filter e.g. '_COMM=gdm-x-session' (may be given many times)")),
        OPT_END()
    };
    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(0);

    msg_prefix = g_progname;
    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
    {
        logmode = LOGMODE_JOURNAL;
    }

    if ((opts & OPT_c) && (opts & OPT_e))
        error_msg_and_die(_("You need to specify either -c CURSOR or -e"));

    if (opts & OPT_D)
    {
        if (opts & OPT_d)
            show_usage_and_die(program_usage_string, program_options);
        load_abrt_conf();
        dump_location = g_settings_dump_location;
        g_settings_dump_location = NULL;
        free_abrt_conf_data();
    }

    int xorg_utils_flags = 0;
    if ((opts & OPT_x))
        xorg_utils_flags |= ABRT_XORG_WORLD_READABLE;

    if ((opts & OPT_t))
        xorg_utils_flags |= ABRT_XORG_THROTTLE_CREATION;

    if ((opts & OPT_o))
        xorg_utils_flags |= ABRT_XORG_PRINT_STDOUT;

    /* get journal filters */
    const char *const env_journal_filter = getenv("ABRT_DUMP_JOURNAL_XORG_DEBUG_FILTER");
    bool free_filter_list_data = false;
    GList *xorg_journal_filter = NULL;
    if (env_journal_filter != NULL)
    {
        xorg_journal_filter = g_list_append(xorg_journal_filter, (gpointer)env_journal_filter);
        log_debug("Using journal filter from environment variable");
    }
    else if (journal_filters != NULL)
    {
        xorg_journal_filter = journal_filters;
        log_debug("Using journal filter passed by parameter -j");
    }
    else
    {
        map_string_t *settings = new_map_string();
        log_notice("Loading settings from '%s'", XORG_CONF);
        load_abrt_plugin_conf_file(XORG_CONF, settings);
        log_debug("Loaded '%s'", XORG_CONF);
        const char *conf_journal_filters = get_map_string_item_or_NULL(settings, "JournalFilters");
        xorg_journal_filter = parse_list(conf_journal_filters);
        /* list data will be free by g_list_free_full */
        free_filter_list_data = true;
        free_map_string(settings);
        if (xorg_journal_filter)
            log_debug("Using journal filter from conf file %s", XORG_CONF);
    }

    if (xorg_journal_filter == NULL)
        error_msg_and_die(_("Journal filter must be specified either by parameter -j or stored in /etc/abrt/plugins/xorg.conf file"));

    abrt_journal_t *journal = NULL;
    if ((opts & OPT_J))
    {
        log_debug("Using journal files from directory '%s'", journal_dir);

        if (abrt_journal_open_directory(&journal, journal_dir))
            error_msg_and_die(_("Cannot initialize systemd-journal in directory '%s'"), journal_dir);
    }
    else
    {
        if (((opts & OPT_a) ? abrt_journal_new_merged : abrt_journal_new)(&journal))
            error_msg_and_die(_("Cannot open systemd-journal"));
    }

    if (abrt_journal_set_journal_filter(journal, xorg_journal_filter) < 0)
        error_msg_and_die(_("Cannot filter systemd-journal to Xorg data only"));

    /* free filter list */
    if (free_filter_list_data)
        g_list_free_full(xorg_journal_filter, free);
    else
        g_list_free(xorg_journal_filter);

    if ((opts & OPT_e) && abrt_journal_seek_tail(journal) < 0)
        error_msg_and_die(_("Cannot seek to the end of journal"));

    if ((opts & OPT_f))
    {
        if (!cursor)
            abrt_journal_restore_position(journal, ABRT_JOURNAL_XORG_WATCH_STATE_FILE);
        else if(abrt_journal_set_cursor(journal, cursor))
            error_msg_and_die(_("Failed to start watch from cursor '%s'"), cursor);

        watch_journald(journal, dump_location, xorg_utils_flags);

        abrt_journal_save_current_position(journal, ABRT_JOURNAL_XORG_WATCH_STATE_FILE);
    }
    else
    {
        if (cursor && abrt_journal_set_cursor(journal, cursor))
            error_msg_and_die(_("Failed to set systemd-journal cursor '%s'"), cursor);

        /* Compatibility hack, a watch's callback gets the journal already moved
         * to a next message.*/
        abrt_journal_next(journal);

        GList *crashes = abrt_journal_extract_xorg_crashes(journal);
        abrt_xorg_process_list_of_crashes(crashes, dump_location, xorg_utils_flags);
        g_list_free_full(crashes, (GDestroyNotify)xorg_crash_info_free);
    }

    abrt_journal_free(journal);

    return EXIT_SUCCESS;
}