Files
ModemManager/src/mm-context.c
T
Aleksander Morgado 1c4da332ee build: new option to build plugins within the daemon binary
Instead of creating libmm-plugin* and libmm-shared* libraries that are
dlopen()-ed on runtime, allow incorporating all plugins into the
daemon binary itself.

This makes the startup of the daemon much faster and also avoids
issues with builds that require linker namespace isolation.

Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/674
2023-01-03 13:56:25 +00:00

475 lines
11 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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:
*
* Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org>
*/
#include <config.h>
#include <stdlib.h>
#include <ModemManager.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-context.h"
/*****************************************************************************/
/* Application context */
#if defined WITH_UDEV || defined WITH_QRTR
# define NO_AUTO_SCAN_OPTION_FLAG 0
# define NO_AUTO_SCAN_DEFAULT FALSE
#else
/* Keep the option when udev and QRTR disabled, just so that the unit test
* setup can unconditionally use --no-auto-scan */
# define NO_AUTO_SCAN_OPTION_FLAG G_OPTION_FLAG_HIDDEN
# define NO_AUTO_SCAN_DEFAULT TRUE
#endif
static gboolean help_flag;
static gboolean version_flag;
static gboolean debug;
static MMFilterRule filter_policy = MM_FILTER_POLICY_STRICT;
static gboolean no_auto_scan = NO_AUTO_SCAN_DEFAULT;
static const gchar *initial_kernel_events;
static gboolean
filter_policy_option_arg (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
if (!g_ascii_strcasecmp (value, "allowlist-only")
#ifndef MM_DISABLE_DEPRECATED
|| !g_ascii_strcasecmp (value, "whitelist-only")
#endif
) {
filter_policy = MM_FILTER_POLICY_ALLOWLIST_ONLY;
return TRUE;
}
if (!g_ascii_strcasecmp (value, "strict")) {
filter_policy = MM_FILTER_POLICY_STRICT;
return TRUE;
}
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Invalid filter policy value given: %s",
value);
return FALSE;
}
static const GOptionEntry entries[] = {
{
"filter-policy", 0, 0, G_OPTION_ARG_CALLBACK, filter_policy_option_arg,
"Filter policy: one of ALLOWLIST-ONLY, STRICT",
"[POLICY]"
},
{
"no-auto-scan", 0, NO_AUTO_SCAN_OPTION_FLAG, G_OPTION_ARG_NONE, &no_auto_scan,
"Don't auto-scan looking for devices",
NULL
},
{
"initial-kernel-events", 0, 0, G_OPTION_ARG_FILENAME, &initial_kernel_events,
"Path to initial kernel events file",
"[PATH]"
},
{
"debug", 0, 0, G_OPTION_ARG_NONE, &debug,
"Run with extended debugging capabilities",
NULL
},
{
"version", 'V', 0, G_OPTION_ARG_NONE, &version_flag,
"Print version",
NULL
},
{
"help", 'h', 0, G_OPTION_ARG_NONE, &help_flag,
"Show help",
NULL
},
{ NULL }
};
gboolean
mm_context_get_debug (void)
{
return debug;
}
const gchar *
mm_context_get_initial_kernel_events (void)
{
return initial_kernel_events;
}
gboolean
mm_context_get_no_auto_scan (void)
{
return no_auto_scan;
}
MMFilterRule
mm_context_get_filter_policy (void)
{
return filter_policy;
}
/*****************************************************************************/
/* Log context */
static const gchar *log_level;
static const gchar *log_file;
static gboolean log_journal;
static gboolean log_show_ts;
static gboolean log_rel_ts;
static gboolean log_personal_info;
static const GOptionEntry log_entries[] = {
{
"log-level", 0, 0, G_OPTION_ARG_STRING, &log_level,
"Log level: one of ERR, WARN, MSG, INFO, DEBUG",
"[LEVEL]"
},
{
"log-file", 0, 0, G_OPTION_ARG_FILENAME, &log_file,
"Path to log file",
"[PATH]"
},
#if defined WITH_SYSTEMD_JOURNAL
{
"log-journal", 0, 0, G_OPTION_ARG_NONE, &log_journal,
"Log to systemd journal",
NULL
},
#endif
{
"log-timestamps", 0, 0, G_OPTION_ARG_NONE, &log_show_ts,
"Show timestamps in log output",
NULL
},
{
"log-relative-timestamps", 0, 0, G_OPTION_ARG_NONE, &log_rel_ts,
"Use relative timestamps (from MM start)",
NULL
},
{
"log-personal-info", 0, 0, G_OPTION_ARG_NONE, &log_personal_info,
"Show personal info in logs",
NULL
},
{ NULL }
};
static GOptionGroup *
log_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("log",
"Logging options:",
"Show logging options",
NULL,
NULL);
g_option_group_add_entries (group, log_entries);
return group;
}
const gchar *
mm_context_get_log_level (void)
{
return log_level;
}
const gchar *
mm_context_get_log_file (void)
{
return log_file;
}
gboolean
mm_context_get_log_journal (void)
{
return log_journal;
}
gboolean
mm_context_get_log_timestamps (void)
{
return log_show_ts;
}
gboolean
mm_context_get_log_relative_timestamps (void)
{
return log_rel_ts;
}
gboolean
mm_context_get_log_personal_info (void)
{
return log_personal_info;
}
/*****************************************************************************/
/* Test context */
static gboolean test_session;
#if defined WITH_TESTS
static gboolean test_enable;
#endif
#if !defined WITH_BUILTIN_PLUGINS
static gchar *test_plugin_dir;
#endif
#if defined WITH_UDEV
static gboolean test_no_udev;
#endif
#if defined WITH_SUSPEND_RESUME
static gboolean test_no_suspend_resume;
static gboolean test_quick_suspend_resume;
#endif
#if defined WITH_QRTR
static gboolean test_no_qrtr;
#endif
static gboolean test_multiplex_requested;
#if defined WITH_MBIM
static gboolean test_mbimex_profile_management;
#endif
static const GOptionEntry test_entries[] = {
{
"test-session", 0, 0, G_OPTION_ARG_NONE, &test_session,
"Run in session DBus",
NULL
},
#if defined WITH_TESTS
{
"test-enable", 0, 0, G_OPTION_ARG_NONE, &test_enable,
"Enable the Test interface in the daemon",
NULL
},
#endif
#if !defined WITH_BUILTIN_PLUGINS
{
"test-plugin-dir", 0, 0, G_OPTION_ARG_FILENAME, &test_plugin_dir,
"Path to look for plugins",
"[PATH]"
},
#endif
#if defined WITH_UDEV
{
"test-no-udev", 0, 0, G_OPTION_ARG_NONE, &test_no_udev,
"Run without udev support even if available",
NULL
},
#endif
#if defined WITH_SUSPEND_RESUME
{
"test-no-suspend-resume", 0, 0, G_OPTION_ARG_NONE, &test_no_suspend_resume,
"Disable suspend/resume support at runtime even if available",
NULL
},
{
"test-quick-suspend-resume", 0, 0, G_OPTION_ARG_NONE, &test_quick_suspend_resume,
"Enable quick suspend/resume support for modems which stay on during host suspension",
NULL
},
#endif
#if defined WITH_QRTR
{
"test-no-qrtr", 0, 0, G_OPTION_ARG_NONE, &test_no_qrtr,
"Run without qrtr support even if available",
NULL
},
#endif
{
"test-multiplex-requested", 0, 0, G_OPTION_ARG_NONE, &test_multiplex_requested,
"Default to request multiplex support if no explicitly given",
NULL
},
#if defined WITH_MBIM
{
"test-mbimex-profile-management", 0, 0, G_OPTION_ARG_NONE, &test_mbimex_profile_management,
"Default to use profile management MBIM extensions",
NULL
},
#endif
{ NULL }
};
static GOptionGroup *
test_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("test",
"Test options:",
"Show Test options",
NULL,
NULL);
g_option_group_add_entries (group, test_entries);
return group;
}
gboolean
mm_context_get_test_session (void)
{
return test_session;
}
#if defined WITH_TESTS
gboolean
mm_context_get_test_enable (void)
{
return test_enable;
}
#endif
#if !defined WITH_BUILTIN_PLUGINS
const gchar *
mm_context_get_test_plugin_dir (void)
{
return test_plugin_dir ? test_plugin_dir : PLUGINDIR;
}
#endif
#if defined WITH_UDEV
gboolean
mm_context_get_test_no_udev (void)
{
return test_no_udev;
}
#endif
#if defined WITH_SUSPEND_RESUME
gboolean
mm_context_get_test_no_suspend_resume (void)
{
return test_no_suspend_resume;
}
gboolean
mm_context_get_test_quick_suspend_resume (void)
{
return test_quick_suspend_resume;
}
#endif
#if defined WITH_QRTR
gboolean
mm_context_get_test_no_qrtr (void)
{
return test_no_qrtr;
}
#endif
gboolean
mm_context_get_test_multiplex_requested (void)
{
return test_multiplex_requested;
}
#if defined WITH_MBIM
gboolean
mm_context_get_test_mbimex_profile_management (void)
{
return test_mbimex_profile_management;
}
#endif
/*****************************************************************************/
static void
print_version (void)
{
g_print ("ModemManager " MM_DIST_VERSION "\n"
"Copyright (C) 2008-2022 The ModemManager authors\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n"
"\n");
}
static void
print_help (GOptionContext *context)
{
gchar *str;
/* Always print --help-all */
str = g_option_context_get_help (context, FALSE, NULL);
g_print ("%s", str);
g_free (str);
}
void
mm_context_init (gint argc,
gchar **argv)
{
GError *error = NULL;
GOptionContext *ctx;
ctx = g_option_context_new (NULL);
g_option_context_set_summary (ctx, "DBus system service to control mobile broadband modems.");
g_option_context_add_main_entries (ctx, entries, NULL);
g_option_context_add_group (ctx, log_get_option_group ());
g_option_context_add_group (ctx, test_get_option_group ());
g_option_context_set_help_enabled (ctx, FALSE);
if (!g_option_context_parse (ctx, &argc, &argv, &error)) {
g_printerr ("error: %s\n", error->message);
g_error_free (error);
exit (1);
}
if (version_flag) {
print_version ();
g_option_context_free (ctx);
exit (EXIT_SUCCESS);
}
if (help_flag) {
print_help (ctx);
g_option_context_free (ctx);
exit (EXIT_SUCCESS);
}
g_option_context_free (ctx);
/* Additional setup to be done on debug mode */
if (debug) {
log_level = "DEBUG";
if (!log_show_ts && !log_rel_ts)
log_show_ts = TRUE;
}
/* Initial kernel events processing may only be used if autoscan is disabled */
#if defined WITH_UDEV || defined WITH_QRTR
if (!no_auto_scan && initial_kernel_events) {
g_printerr ("error: --initial-kernel-events must be used only if --no-auto-scan is also used\n");
exit (1);
}
# if defined WITH_UDEV
/* Force skipping autoscan if running test without udev */
if (test_no_udev)
no_auto_scan = TRUE;
# endif
# if defined WITH_QRTR
/* Force skipping autoscan if running test without qrtr */
if (test_no_qrtr)
no_auto_scan = TRUE;
# endif
#endif
}