Add dump_systemstate-service 91/253491/10
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Mon, 15 Feb 2021 12:16:53 +0000 (13:16 +0100)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Tue, 9 Mar 2021 22:02:37 +0000 (23:02 +0100)
The service registers with the name org.tizen.systemstate and provides
the output of defined commands via dumpsys interface. The registration
of commands is done by adding dumpsyscmd parameter to the extra program
configuration file. For example, the following configuration in
/etc/dump_systemstate.conf.d/programs/crash-worker-programs.conf:

  ...

  [buxton system]
  order=141
  cmdflag=b
  title=System configuration
  path=/usr/bin/buxton2ctl
  args=dump system
  dumpsyscmd=buxton_system
  allowdumpsysargs=yes
  ...

allows to get the output of the command:

  /usr/bin/buxton2ctl dump system

by calling:

  dumpsys org.tizen.systemstate buxton_system

The allowdumpsysargs parameter is responsible for the possibility to
provide custom parameters via dumpsys (disallowed by default).

Change-Id: Iff9569d4975ab97addfcf32ea6c22d7237275b35

CMakeLists.txt
packaging/crash-worker.spec
src/dump_systemstate-service/CMakeLists.txt [new file with mode: 0644]
src/dump_systemstate-service/dump_systemstate-service.c [new file with mode: 0644]
src/dump_systemstate-service/dump_systemstate.service [new file with mode: 0644]
src/dump_systemstate-service/org.tizen.dumpsys.providers.org.tizen.systemstate.service [new file with mode: 0644]
src/dump_systemstate/extras.c
src/dump_systemstate/extras.h
src/dump_systemstate/programs/crash-worker-programs.conf
src/dump_systemstate/programs/programs.conf.example

index 8b9605f..3893dad 100644 (file)
@@ -25,5 +25,9 @@ IF("${CRASH_SERVICE}" STREQUAL "ON")
        ADD_SUBDIRECTORY(src/bugreport-service)
 ENDIF()
 
+IF("${DUMP_SYSTEMSTATE_SERVICE}" STREQUAL "ON")
+       ADD_SUBDIRECTORY(src/dump_systemstate-service)
+ENDIF()
+
 ADD_SUBDIRECTORY(tests)
 
index 30905dd..98064ef 100644 (file)
@@ -4,11 +4,13 @@
 %define _with_tests on
 %define _with_livedumper on
 %define _with_bugreportservice on
+%define _with_dumpsystemstateservice on
 
 %bcond_with doc
 %bcond_with tests
 %bcond_with livedumper
 %bcond_with bugreportservice
+%bcond_with dumpsystemstateservice
 
 %if %{?_with_bugreportservice} == on
 %define _with_livedumper on
@@ -37,6 +39,9 @@ BuildRequires:  pkgconfig(libunwind-generic)
 BuildRequires:  libcap-devel
 BuildRequires:  pkgconfig(json-c)
 BuildRequires:  pkgconfig(openssl1.1)
+%if %{with dumpsystemstateservice}
+BuildRequires:  pkgconfig(dumpsys-system)
+%endif
 
 %if %{with doc}
 BuildRequires:  doxygen
@@ -64,6 +69,7 @@ Requires:       %{_bindir}/buxton2ctl
 %if %{with bugreportservice}
 Requires:       %{name}-livedumper = %{version}-%{release}
 %endif
+
 %description -n crash-manager-core
 
 %package -n     libcrash-manager-devel
@@ -84,6 +90,13 @@ Summary:        package provides headers needed to develop programs using bugrep
 %description -n libbugreport-devel
 %endif
 
+%if %{with dumpsystemstateservice}
+%package -n     dumpsystemstate-service
+Summary:        service provides dumpsys provider to system state information
+Requires:       %{name}-dumpsystemstate-config = %{version}-%{release}
+%description -n dumpsystemstate-service
+%endif
+
 %if %{with doc}
 %package        doc
 Summary:        Documentation package for crash-worker
@@ -170,6 +183,7 @@ export CFLAGS+=" -Werror"
           -DCRASH_SYSTEM_TESTS_PATH=%{_libexecdir}/crash-worker/system-tests \
           -DLIVEDUMPER=%{on_off livedumper} \
           -DCRASH_SERVICE=%{on_off bugreportservice} \
+          -DDUMP_SYSTEMSTATE_SERVICE=%{on_off dumpsystemstateservice} \
           -DUPGRADE_SCRIPT_PATH=%{upgrade_script_path} \
           -DLOGGER=dlog \
           -DDLOG_LOG_LEVEL=DLOG_INFO \
@@ -260,6 +274,15 @@ fi
 %{_libdir}/pkgconfig/bugreport.pc
 %endif
 
+%if %{with dumpsystemstateservice}
+%files -n dumpsystemstate-service
+%license LICENSE
+%manifest crash-worker.manifest
+%attr(0750,crash_worker,crash_worker) %{_bindir}/dump_systemstate-service
+%attr(-,root,root) %{_unitdir}/dump_systemstate.service
+%attr(-,root,root) %{_datadir}/dbus-1/system-services/org.tizen.dumpsys.providers.org.tizen.systemstate.service
+%endif
+
 %if %{with doc}
 %files doc
 %{_datadir}/doc/crash-worker
diff --git a/src/dump_systemstate-service/CMakeLists.txt b/src/dump_systemstate-service/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e8bedac
--- /dev/null
@@ -0,0 +1,49 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(dump_systemstate-service C)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/)
+
+SET(DUMP_SYSTEMSTATE_SERVICE_SRC
+       dump_systemstate-service.c
+       ${CMAKE_SOURCE_DIR}/src/shared/util.c
+       ${CMAKE_SOURCE_DIR}/src/shared/spawn.c
+       ${CMAKE_SOURCE_DIR}/src/dump_systemstate/extras.c
+       )
+
+
+INCLUDE(GNUInstallDirs)
+
+INCLUDE(FindPkgConfig)
+
+pkg_check_modules(dump_systemstate-service_pkgs REQUIRED
+       dlog
+       gio-2.0
+       gio-unix-2.0
+       iniparser
+       dumpsys-system
+       )
+
+FOREACH(flag ${dump_systemstate-service_pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE -Wno-unused-function -Wno-unused-const-variable")
+
+INCLUDE(${CMAKE_SOURCE_DIR}/cmake/ProcessM4.cmake)
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${DUMP_SYSTEMSTATE_SERVICE_SRC})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dump_systemstate-service_pkgs_LDFLAGS} -pie)
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.tizen.dumpsys.providers.org.tizen.systemstate.service
+       DESTINATION /usr/share/dbus-1/system-services
+       PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dump_systemstate.service
+       DESTINATION /usr/lib/systemd/system
+       PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin
+       PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
+       GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/src/dump_systemstate-service/dump_systemstate-service.c b/src/dump_systemstate-service/dump_systemstate-service.c
new file mode 100644 (file)
index 0000000..6635429
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * dump_systemstate
+ *
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <dumpsys-system.h>
+#include <gio/gio.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "dump_systemstate/dump_systemstate.h"
+#include "dump_systemstate/extras.h"
+#include "shared/log.h"
+#include "shared/spawn.h"
+#include "shared/util.h"
+
+#define DUMP_SYSTEMSTATE_BUS_NAME            "org.tizen.systemstate"
+#define DUMP_SYSTEMSTATE_OBJECT_PATH         "/Org/Tizen/Systemstate"
+#define DUMP_SYSTEMSTATE_INTERFACE_NAME      DUMP_SYSTEMSTATE_BUS_NAME
+#define TIMEOUT_INTERVAL_SEC 30
+
+static GMainLoop *loop = NULL;
+static GMutex timeout_mutex;
+static guint timeout_id;
+static GHashTable *commands = NULL;
+struct extra_items_vector commands_list = { .size = 0, .data = NULL };
+
+static int timeout_cb(gpointer data)
+{
+       assert(data);
+       _I("Time out!");
+       g_main_loop_quit((GMainLoop *)data);
+
+       return 0;
+}
+
+static void add_timeout(void)
+{
+       g_mutex_lock(&timeout_mutex);
+
+       if (timeout_id)
+               g_source_remove(timeout_id);
+       timeout_id = g_timeout_add_seconds(TIMEOUT_INTERVAL_SEC, timeout_cb, loop);
+
+       g_mutex_unlock(&timeout_mutex);
+       _D("Add loop timeout (%d)", TIMEOUT_INTERVAL_SEC);
+}
+
+static void remove_timeout(void)
+{
+       g_mutex_lock(&timeout_mutex);
+
+       if (timeout_id) {
+               g_source_remove(timeout_id);
+               timeout_id = 0;
+       }
+
+       g_mutex_unlock(&timeout_mutex);
+       _D("Remove loop timeout");
+}
+
+static char* join(int argc, char **argv, int offset)
+{
+       assert(argv);
+
+       if (offset <= argc)
+               return strdup("");
+
+       ssize_t length = 0;
+       for (int i = offset; i < argc; i++)
+               length += strlen(argv[i]) + 1;
+
+       char *result = malloc(length + 1);
+       if (result == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+       char *pointer = result;
+
+       for (int i = offset; i < argc; i++) {
+               int printed = snprintf(pointer, strlen(argv[i]) + 2, "%s ", argv[i]);
+               if (printed < 0) {
+                       free(result);
+                       _E("Cannot concatenate strings: %m");
+                       return NULL;
+               }
+
+               pointer += printed;
+       }
+       result[length-1] = '\0';
+       return result;
+}
+
+char** split(const char *str, size_t *size)
+{
+       assert(str);
+
+       char **result = NULL;
+       char *str_tmp = strdup(str);
+       if (str_tmp == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       char *chunk = strtok(str_tmp, " ");
+       *size = 0;
+
+       while (chunk != NULL) {
+               char **result_tmp = realloc(result, (*size + 1) * sizeof(char *));
+               char *chunk_copy = strdup(chunk);
+
+               if (result_tmp == NULL || chunk_copy == NULL) {
+                       _E("Out of memory");
+                       if (result_tmp != NULL)
+                               free(result_tmp);
+                       if (chunk_copy != NULL)
+                               free(chunk_copy);
+                       free(result);
+                       result = NULL;
+                       goto out;
+               }
+
+               result = result_tmp;
+               result[(*size)++] = chunk_copy;
+               chunk = strtok(NULL, " ");
+       }
+
+       char **result_tmp = realloc(result, (*size + 1) * sizeof(char *));
+       if (result_tmp == NULL) {
+               _E("Out of memory");
+               free(result);
+               result = NULL;
+               goto out;
+       }
+
+       result = result_tmp;
+       result[*size] = NULL;
+
+out:
+       free(str_tmp);
+       return result;
+}
+
+static void free_array(char **array)
+{
+       if (array != NULL) {
+               for (size_t i = 0; array[i] != NULL; i++)
+                       free(array[i]);
+               free(array);
+       }
+}
+
+static char** build_argv_array(const char *path, int argc, char **argv)
+{
+       char **av = malloc((argc + 2) * sizeof(char *));
+       if (av == NULL) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       av[0] = strdup(path);
+       if (av[0] == NULL) {
+               _E("Out of memory");
+               free(av);
+               return NULL;
+       }
+
+       for (int i = 0; i < argc; i++) {
+               av[i + 1] = strdup(argv[i]);
+               if (av[i + 1] == NULL) {
+                       _E("Out of memory");
+                       free_array(av);
+                       return NULL;
+               }
+       }
+
+       av[argc + 1] = NULL;
+
+       return av;
+}
+
+static char** prepare_dumpsys_args(const char *path, int dumpsys_argc, char **dumpsys_argv)
+{
+       return build_argv_array(path, dumpsys_argc - 1, dumpsys_argv+1);
+}
+
+static char** prepare_config_args(const char *path, char *args)
+{
+       size_t argc = 0;
+       char **argv = split(args, &argc);
+       return build_argv_array(path, argc, argv);
+}
+
+static char** prepare_args(struct extra_dump_item *item, const int dumpsys_argc, char **dumpsys_argv)
+{
+       bool allow_dumpsys_args = false;
+       if (item->fields[INI_FIELD_ALLOWDUMPSYSARGS] != NULL)
+               allow_dumpsys_args = strncasecmp(item->fields[INI_FIELD_ALLOWDUMPSYSARGS], "yes", 4) == 0;
+
+       if (allow_dumpsys_args && dumpsys_argc > 1)
+               return prepare_dumpsys_args(item->fields[INI_FIELD_PATH], dumpsys_argc, dumpsys_argv);
+       else
+               return prepare_config_args(item->fields[INI_FIELD_PATH], item->fields[INI_FIELD_ARGS]);
+}
+
+static char** prepare_env(const char *config_env)
+{
+       char **ev = NULL;
+
+       if (config_env != NULL) {
+               size_t size = 0;
+               ev = split(config_env, &size);
+       }
+
+       return ev;
+}
+
+static int dump_item(int fd, struct extra_dump_item *item, const int dumpsys_argc, char **dumpsys_argv)
+{
+       assert(item);
+
+       int result = TIZEN_ERROR_NONE;
+
+       char **av = prepare_args(item, dumpsys_argc, dumpsys_argv);
+
+       if (av == NULL)
+               goto out;
+
+       char **ev = prepare_env(item->fields[INI_FIELD_ENV]);
+       int err;
+       spawn_param_s param_stdout = { .fn = spawn_setstdout, .u.int_val = fd };
+       spawn_param_s param_stderr = { .fn = spawn_setstderr, .u.int_val = fd, .next = &param_stdout };
+
+       if (!spawn_wait(av, ev, &param_stderr, DEFAULT_COMMAND_TIMEOUT_MS, &err))
+               result = TIZEN_ERROR_INVALID_OPERATION;
+
+       free_array(ev);
+out:
+       free_array(av);
+
+       return result;
+}
+
+static bool dumpsys_enabled(struct extra_dump_item *item)
+{
+       assert(item);
+
+       return item->fields[INI_FIELD_DUMPSYSCMD] != NULL && *(item->fields[INI_FIELD_DUMPSYSCMD]) != '\0';
+}
+
+static void print_header(int fd, struct extra_dump_item *item)
+{
+       assert(item);
+       dprintf(fd,
+               "\n==== %s (%s %s)\n",
+               item->fields[INI_FIELD_TITLE] ?: "",
+               item->fields[INI_FIELD_PATH] ?: "",
+               item->fields[INI_FIELD_ARGS] ?: "");
+}
+
+static int dump_all_items(int fd)
+{
+       int result = TIZEN_ERROR_NONE;
+
+       for (size_t i = 0; i < commands_list.size; i++) {
+               if (dumpsys_enabled(&commands_list.data[i])) {
+                       print_header(fd, &commands_list.data[i]);
+                       result |= dump_item(fd, &commands_list.data[i], 0, NULL);
+               }
+       }
+
+       return result;
+}
+
+static int dumpsys_cb(const int fd, const int argc, char **argv)
+{
+       assert(fd >= 0);
+       assert(argv);
+
+       if (commands == NULL) {
+               _E("Commands not initialized");
+               return TIZEN_ERROR_INVALID_OPERATION;
+       }
+
+       int result = TIZEN_ERROR_NONE;
+       if (argc == 0) {
+               result = dump_all_items(fd);
+       } else {
+               struct extra_dump_item *item = g_hash_table_lookup(commands, argv[0]);
+               if (item == NULL) {
+                       _E("Command not found: %s", argv[0]);
+                       return TIZEN_ERROR_INVALID_PARAMETER;
+               }
+               result = dump_item(fd, item, argc, argv);
+       }
+
+       return result;
+}
+
+static void free_item(struct extra_dump_item *item)
+{
+       assert(item);
+
+       for (size_t i = 0; i < ARRAY_SIZE(item->fields); i++)
+               free(item->fields[i]);
+}
+
+static int fill_commands()
+{
+       int result = read_ini_files(STDOUT_FILENO, DUMP_SYSTEMSTATE_CONFIG_DIR_PROGRAMS_PATH, &commands_list);
+
+       if (result != EXIT_OK)
+               return result;
+
+       commands = g_hash_table_new(g_str_hash, g_str_equal);
+       if (commands == NULL) {
+               _E("Out of memory");
+               return EXIT_ERR;
+       }
+
+       struct extra_dump_item *item = commands_list.data;
+
+       for (size_t i = 0; i < commands_list.size; i++, item++) {
+               char *dumpcmd = item->fields[INI_FIELD_DUMPSYSCMD];
+
+               if (dumpcmd != NULL && strlen(dumpcmd) > 0) {
+                       if (g_hash_table_lookup(commands, dumpcmd) != NULL) {
+                               _I("Duplicated command: %s", dumpcmd);
+                               free_item(item);
+                       } else {
+                               _D("New dumpsys command: %s", dumpcmd);
+                               g_hash_table_insert(commands, dumpcmd, item);
+                       }
+               }
+       }
+
+       return result;
+}
+
+int main()
+{
+       void *handler = NULL;
+       int exit_code = EXIT_SUCCESS;
+
+       if (fill_commands() != EXIT_OK) {
+               exit_code = EXIT_FAILURE;
+               goto out;
+       }
+
+       loop = g_main_loop_new(NULL, false);
+
+       if (dumpsys_system_register_dump_cb(dumpsys_cb, DUMP_SYSTEMSTATE_BUS_NAME, &handler) != TIZEN_ERROR_NONE) {
+               _E("Callback registration error");
+               exit_code = EXIT_FAILURE;
+               goto out;
+       }
+
+       g_mutex_init(&timeout_mutex);
+       add_timeout();
+       g_main_loop_run(loop);
+
+       g_mutex_clear(&timeout_mutex);
+
+out:
+       if (loop != NULL)
+               g_main_loop_unref(loop);
+
+       if (handler != NULL)
+               dumpsys_system_unregister_dump_cb(handler);
+
+       if (commands != NULL)
+               g_hash_table_destroy(commands);
+
+       for (size_t i = 0; i < commands_list.size; i++)
+               free_item(&commands_list.data[i]);
+
+       return exit_code;
+}
diff --git a/src/dump_systemstate-service/dump_systemstate.service b/src/dump_systemstate-service/dump_systemstate.service
new file mode 100644 (file)
index 0000000..8b1c101
--- /dev/null
@@ -0,0 +1,15 @@
+[Unit]
+Description=dump_systemstate service
+
+[Service]
+Type=dbus
+User=crash_worker
+Group=crash_worker
+Capabilities=cap_dac_read_search,cap_sys_ptrace,cap_syslog=i
+SecureBits=keep-caps
+BusName=org.tizen.systemstate
+ExecStart=/usr/bin/dump_systemstate-service
+SupplementaryGroups=log systemd-journal system_share
+SmackProcessLabel=System
+Nice=-5
+KillMode=mixed
diff --git a/src/dump_systemstate-service/org.tizen.dumpsys.providers.org.tizen.systemstate.service b/src/dump_systemstate-service/org.tizen.dumpsys.providers.org.tizen.systemstate.service
new file mode 100644 (file)
index 0000000..4cac3f1
--- /dev/null
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.tizen.dumpsys.providers.org.tizen.systemstate
+Exec=/bin/false
+SystemdService=dump_systemstate.service
index 88e42d8..42d3345 100644 (file)
@@ -51,9 +51,12 @@ static const char *const INI_KEYS[COUNT_INI_FIELDS] = {
        [INI_FIELD_ARGS]  = "args",
        [INI_FIELD_ENV]   = "env",
        [INI_FIELD_FLAG]  = "cmdflag",
+       [INI_FIELD_DUMPSYSCMD] = "dumpsyscmd",
+       [INI_FIELD_ALLOWDUMPSYSARGS] = "allowdumpsysargs",
+       [INI_FIELD_ALLOWCOMMANDLINE] = "allowcommandline",
        // non-string field: "order"
 };
-static const size_t MAX_INI_KEY_LEN = 7;
+static const size_t MAX_INI_KEY_LEN = 16;
 
 void cleanup_extra_dump_item(struct extra_dump_item *edi)
 {
@@ -86,6 +89,10 @@ int handle_extra_program(int out_fd, struct extra_dump_item *item, int argc, cha
        assert(out_fd >= 0);
        assert(item);
 
+       if (item->fields[INI_FIELD_ALLOWCOMMANDLINE] != NULL &&
+           strncasecmp(item->fields[INI_FIELD_ALLOWCOMMANDLINE], "no", 3) == 0)
+               return 0;
+
        const char *const title = item->fields[INI_FIELD_TITLE];
        const char *const path  = item->fields[INI_FIELD_PATH];
        const char *const args  = item->fields[INI_FIELD_ARGS] ?: "";
@@ -269,7 +276,7 @@ int read_ini_files(int out_fd, char *dir_path, struct extra_items_vector *eiv)
                ret |= handle_extra_ini(out_fd, eiv, ini_path);
        }
 
-       if (ret) {
+       if (ret == 0) {
                inline int cmp(const void *a, const void *b) {
                        return ((struct extra_dump_item *)a)->order - ((struct extra_dump_item *)b)->order;
                }
index 3544cab..ee0d421 100644 (file)
@@ -32,6 +32,9 @@ enum ini_fields {
        INI_FIELD_ARGS,
        INI_FIELD_ENV,
        INI_FIELD_FLAG,
+       INI_FIELD_DUMPSYSCMD,
+       INI_FIELD_ALLOWDUMPSYSARGS,
+       INI_FIELD_ALLOWCOMMANDLINE,
        COUNT_INI_FIELDS,
 };
 
index c8980ac..a96e2af 100644 (file)
@@ -22,6 +22,8 @@ order=130
 title=System memory statistics
 path=/usr/bin/memps
 args=-v
+dumpsyscmd=memory
+allowdumpsysargs=yes
 
 [buxton memory]
 order=140
@@ -57,6 +59,8 @@ title=Kernel messages
 path=/bin/dmesg
 args=-T
 env=TZ=UTC
+dumpsyscmd=klog
+allowdumpsysargs=yes
 
 [dlog]
 order=210
@@ -64,6 +68,8 @@ cmdflag=d
 title=Log messages
 path=/usr/bin/dlogutil
 args=-d -v threadtime -u 16384
+dumpsyscmd=dlog
+allowdumpsysargs=yes
 
 [journal]
 order=220
@@ -71,3 +77,14 @@ cmdflag=j
 title=Journal messages
 path=/usr/bin/journalctl
 args=-b -n 1024
+dumpsyscmd=journal
+allowdumpsysargs=yes
+
+[disk]
+order=1000
+title=Disk
+path=/bin/df
+args=-h
+dumpsyscmd=disk
+allowdumpsysargs=yes
+allowcommandline=no
index b44b9ce..b28d326 100644 (file)
@@ -10,3 +10,5 @@ env=POSIXLY_CORRECT=1
 title=dump dlog contents
 path=/usr/bin/dlogutil
 args=-d
+dumpsyscmd=dlogutil
+allowdumpsysargs=yes