Move all the fwupdagent code to fwupdmgr

We want to provide a lot more in JSON format in the future, and this
will reduce a lot of code duplication.

As various people are using this in the wild, the existing fwupdagent
binary just shims requests to fwupdmgr as required. We'll stop doing
this for 2.0.0 or something.
This commit is contained in:
Richard Hughes 2021-07-15 14:29:04 +01:00
parent 942802063e
commit f0bc835769
7 changed files with 167 additions and 464 deletions

View File

@ -57,6 +57,7 @@ _fwupdmgr_opts=(
'--disable-ssl-strict'
'--ipfs'
'--ignore-power'
'--json'
)
_show_filters()

View File

@ -3,13 +3,6 @@ if bashcomp.found()
define_variable: bashcomp.version().version_compare('>= 2.10') ? ['datadir', datadir] : ['prefix', prefix],
)
if get_option('agent')
install_data(['fwupdagent'],
install_dir : completions_dir,
)
endif # get_option('agent')
# replace @libexecdir@
fwupdtool_path = join_paths(libexecdir, 'fwupd')
con2 = configuration_data()
@ -21,13 +14,16 @@ configure_file(
install: true,
install_dir: completions_dir)
if build_daemon and get_option('agent')
if build_daemon
install_data(['fwupdagent'],
install_dir : completions_dir,
)
configure_file(
input : 'fwupdmgr.in',
output : 'fwupdmgr',
configuration : con2,
install: true,
install_dir: completions_dir)
endif # build_daemon and get_option('agent')
endif # build_daemon
endif # bashcomp.found()

View File

@ -1,5 +1,4 @@
option('build', type : 'combo', choices : ['all', 'standalone', 'library'], value : 'all', description : 'build type')
option('agent', type : 'boolean', value : true, description : 'enable the fwupd agent')
option('consolekit', type : 'boolean', value : true, description : 'enable ConsoleKit support')
option('firmware-packager', type : 'boolean', value : true, description : 'enable firmware-packager installation')
option('docs', type : 'combo', choices : ['none', 'gtkdoc', 'docgen'], value : 'docgen', description : 'developer documentation type')

View File

@ -1,414 +0,0 @@
/*
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#define G_LOG_DOMAIN "FuAgent"
#include "config.h"
#include <fwupd.h>
#include <glib/gi18n.h>
#ifdef HAVE_GIO_UNIX
#include <glib-unix.h>
#endif
#include <locale.h>
#include <stdlib.h>
#include <unistd.h>
#include "fu-common.h"
#include "fu-util-common.h"
#include "fwupd-device-private.h"
#include "fwupd-enums-private.h"
#include "fwupd-security-attr-private.h"
struct FuUtilPrivate {
GCancellable *cancellable;
GOptionContext *context;
FwupdClient *client;
FwupdInstallFlags flags;
};
static gboolean
fu_util_add_devices_json (FuUtilPrivate *priv, JsonBuilder *builder, GError **error)
{
g_autoptr(GPtrArray) devs = NULL;
/* get results from daemon */
devs = fwupd_client_get_devices (priv->client, priv->cancellable, error);
if (devs == NULL)
return FALSE;
json_builder_set_member_name (builder, "Devices");
json_builder_begin_array (builder);
for (guint i = 0; i < devs->len; i++) {
FwupdDevice *dev = g_ptr_array_index (devs, i);
g_autoptr(GPtrArray) rels = NULL;
g_autoptr(GError) error_local = NULL;
/* add all releases that could be applied */
rels = fwupd_client_get_releases (priv->client,
fwupd_device_get_id (dev),
priv->cancellable,
&error_local);
if (rels == NULL) {
g_debug ("not adding releases to device: %s",
error_local->message);
} else {
for (guint j = 0; j < rels->len; j++) {
FwupdRelease *rel = g_ptr_array_index (rels, j);
fwupd_device_add_release (dev, rel);
}
}
/* add to builder */
json_builder_begin_object (builder);
fwupd_device_to_json (dev, builder);
json_builder_end_object (builder);
}
json_builder_end_array (builder);
return TRUE;
}
static gboolean
fu_util_add_updates_json (FuUtilPrivate *priv, JsonBuilder *builder, GError **error)
{
g_autoptr(GPtrArray) devices = NULL;
/* get devices from daemon */
devices = fwupd_client_get_devices (priv->client, NULL, error);
if (devices == NULL)
return FALSE;
json_builder_set_member_name (builder, "Devices");
json_builder_begin_array (builder);
for (guint i = 0; i < devices->len; i++) {
FwupdDevice *dev = g_ptr_array_index (devices, i);
g_autoptr(GPtrArray) rels = NULL;
g_autoptr(GError) error_local = NULL;
/* not going to have results, so save a D-Bus round-trip */
if (!fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_SUPPORTED))
continue;
/* get the releases for this device and filter for validity */
rels = fwupd_client_get_upgrades (priv->client,
fwupd_device_get_id (dev),
NULL, &error_local);
if (rels == NULL) {
g_debug ("no upgrades: %s", error_local->message);
continue;
}
for (guint j = 0; j < rels->len; j++) {
FwupdRelease *rel = g_ptr_array_index (rels, j);
fwupd_device_add_release (dev, rel);
}
/* add to builder */
json_builder_begin_object (builder);
fwupd_device_to_json (dev, builder);
json_builder_end_object (builder);
}
json_builder_end_array (builder);
return TRUE;
}
static gboolean
fu_util_add_security_attributes_json (FuUtilPrivate *priv, JsonBuilder *builder, GError **error)
{
g_autoptr(GPtrArray) attrs = NULL;
/* not ready yet */
if ((priv->flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"The HSI specification is not yet complete. "
"To ignore this warning, use --force");
return FALSE;
}
/* get attrs from daemon */
attrs = fwupd_client_get_host_security_attrs (priv->client, NULL, error);
if (attrs == NULL)
return FALSE;
json_builder_set_member_name (builder, "HostSecurityAttributes");
json_builder_begin_array (builder);
for (guint i = 0; i < attrs->len; i++) {
FwupdSecurityAttr *attr = g_ptr_array_index (attrs, i);
json_builder_begin_object (builder);
fwupd_security_attr_to_json (attr, builder);
json_builder_end_object (builder);
}
json_builder_end_array (builder);
return TRUE;
}
static gboolean
fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
{
g_autofree gchar *data = NULL;
g_autoptr(JsonBuilder) builder = NULL;
g_autoptr(JsonGenerator) json_generator = NULL;
g_autoptr(JsonNode) json_root = NULL;
/* check args */
if (g_strv_length (values) != 0) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_ARGS,
"Invalid arguments");
return FALSE;
}
/* create header */
builder = json_builder_new ();
json_builder_begin_object (builder);
if (!fu_util_add_devices_json (priv, builder, error))
return FALSE;
json_builder_end_object (builder);
/* export as a string */
json_root = json_builder_get_root (builder);
json_generator = json_generator_new ();
json_generator_set_pretty (json_generator, TRUE);
json_generator_set_root (json_generator, json_root);
data = json_generator_to_data (json_generator, NULL);
if (data == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"Failed to convert to JSON string");
return FALSE;
}
/* just print */
g_print ("%s\n", data);
return TRUE;
}
static gboolean
fu_util_get_updates (FuUtilPrivate *priv, gchar **values, GError **error)
{
g_autofree gchar *data = NULL;
g_autoptr(JsonBuilder) builder = NULL;
g_autoptr(JsonGenerator) json_generator = NULL;
g_autoptr(JsonNode) json_root = NULL;
/* check args */
if (g_strv_length (values) != 0) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_ARGS,
"Invalid arguments");
return FALSE;
}
/* create header */
builder = json_builder_new ();
json_builder_begin_object (builder);
if (!fu_util_add_updates_json (priv, builder, error))
return FALSE;
json_builder_end_object (builder);
/* export as a string */
json_root = json_builder_get_root (builder);
json_generator = json_generator_new ();
json_generator_set_pretty (json_generator, TRUE);
json_generator_set_root (json_generator, json_root);
data = json_generator_to_data (json_generator, NULL);
if (data == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"Failed to convert to JSON string");
return FALSE;
}
/* just print */
g_print ("%s\n", data);
return TRUE;
}
static gboolean
fu_util_security (FuUtilPrivate *priv, gchar **values, GError **error)
{
g_autofree gchar *data = NULL;
g_autoptr(JsonBuilder) builder = NULL;
g_autoptr(JsonGenerator) json_generator = NULL;
g_autoptr(JsonNode) json_root = NULL;
/* check args */
if (g_strv_length (values) != 0) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_ARGS,
"Invalid arguments");
return FALSE;
}
/* create header */
builder = json_builder_new ();
json_builder_begin_object (builder);
if (!fu_util_add_security_attributes_json (priv, builder, error))
return FALSE;
json_builder_end_object (builder);
/* export as a string */
json_root = json_builder_get_root (builder);
json_generator = json_generator_new ();
json_generator_set_pretty (json_generator, TRUE);
json_generator_set_root (json_generator, json_root);
data = json_generator_to_data (json_generator, NULL);
if (data == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"Failed to convert to JSON string");
return FALSE;
}
/* just print */
g_print ("%s\n", data);
return TRUE;
}
static void
fu_util_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level,
const gchar *message, gpointer user_data)
{
}
#ifdef HAVE_GIO_UNIX
static gboolean
fu_util_sigint_cb (gpointer user_data)
{
FuUtilPrivate *priv = (FuUtilPrivate *) user_data;
g_debug ("Handling SIGINT");
g_cancellable_cancel (priv->cancellable);
return FALSE;
}
#endif
static void
fu_util_private_free (FuUtilPrivate *priv)
{
if (priv->client != NULL)
g_object_unref (priv->client);
g_object_unref (priv->cancellable);
g_option_context_free (priv->context);
g_free (priv);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuUtilPrivate, fu_util_private_free)
#pragma clang diagnostic pop
int
main (int argc, char *argv[])
{
gboolean ret;
gboolean force = FALSE;
gboolean verbose = FALSE;
g_autoptr(FuUtilPrivate) priv = g_new0 (FuUtilPrivate, 1);
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) cmd_array = fu_util_cmd_array_new ();
g_autofree gchar *cmd_descriptions = NULL;
const GOptionEntry options[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
/* TRANSLATORS: command line option */
_("Show extra debugging information"), NULL },
{ "force", '\0', 0, G_OPTION_ARG_NONE, &force,
/* TRANSLATORS: command line option */
_("Override warnings and force the action"), NULL },
{ NULL}
};
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, FWUPD_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
/* ensure D-Bus errors are registered */
fwupd_error_quark ();
/* create helper object */
priv->client = fwupd_client_new ();
/* add commands */
fu_util_cmd_array_add (cmd_array,
"get-devices", NULL,
/* TRANSLATORS: command description */
_("Get all devices and possible releases"),
fu_util_get_devices);
fu_util_cmd_array_add (cmd_array,
"get-updates,get-upgrades", NULL,
/* TRANSLATORS: command description */
_("Gets the list of updates for connected hardware"),
fu_util_get_updates);
fu_util_cmd_array_add (cmd_array,
"security", NULL,
/* TRANSLATORS: command description */
_("Gets the host security attributes"),
fu_util_security);
/* sort by command name */
fu_util_cmd_array_sort (cmd_array);
/* do stuff on ctrl+c */
priv->cancellable = g_cancellable_new ();
#ifdef HAVE_GIO_UNIX
g_unix_signal_add_full (G_PRIORITY_DEFAULT,
SIGINT, fu_util_sigint_cb,
priv, NULL);
#endif
/* get a list of the commands */
priv->context = g_option_context_new (NULL);
cmd_descriptions = fu_util_cmd_array_to_string (cmd_array);
g_option_context_set_summary (priv->context, cmd_descriptions);
g_option_context_set_description (priv->context,
/* TRANSLATORS: CLI description */
_("This tool can be used from other tools and from shell scripts."));
/* TRANSLATORS: program name */
g_set_application_name (_("Firmware Agent"));
g_option_context_add_main_entries (priv->context, options, NULL);
ret = g_option_context_parse (priv->context, &argc, &argv, &error);
if (!ret) {
/* TRANSLATORS: the user didn't read the man page */
g_print ("%s: %s\n", _("Failed to parse arguments"),
error->message);
return EXIT_FAILURE;
}
/* set verbose? */
if (verbose) {
g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
} else {
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
fu_util_ignore_cb, NULL);
}
/* set flags */
if (force)
priv->flags |= FWUPD_INSTALL_FLAG_FORCE;
/* run the specified command */
ret = fu_util_cmd_array_run (cmd_array, priv, argv[1], (gchar**) &argv[2], &error);
if (!ret) {
if (g_error_matches (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_ARGS)) {
g_autofree gchar *tmp = NULL;
tmp = g_option_context_get_help (priv->context, TRUE, NULL);
g_print ("%s\n\n%s", error->message, tmp);
return EXIT_FAILURE;
}
g_print ("%s\n", error->message);
return EXIT_FAILURE;
}
/* success */
return EXIT_SUCCESS;
}

View File

@ -30,6 +30,7 @@
#include "fu-security-attrs.h"
#include "fu-util-common.h"
#include "fwupd-common-private.h"
#include "fwupd-device-private.h"
#ifdef HAVE_SYSTEMD
#include "fu-systemd.h"
@ -63,6 +64,7 @@ struct FuUtilPrivate {
gboolean sign;
gboolean show_all;
gboolean disable_ssl_strict;
gboolean as_json;
/* only valid in update and downgrade */
FuUtilOperation current_operation;
FwupdDevice *current_device;
@ -460,6 +462,32 @@ fu_util_modify_remote_warning (FuUtilPrivate *priv, FwupdRemote *remote, GError
return TRUE;
}
static gboolean
fu_util_print_builder (JsonBuilder *builder, GError **error)
{
g_autofree gchar *data = NULL;
g_autoptr(JsonGenerator) json_generator = NULL;
g_autoptr(JsonNode) json_root = NULL;
/* export as a string */
json_root = json_builder_get_root (builder);
json_generator = json_generator_new ();
json_generator_set_pretty (json_generator, TRUE);
json_generator_set_root (json_generator, json_root);
data = json_generator_to_data (json_generator, NULL);
if (data == NULL) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"Failed to convert to JSON string");
return FALSE;
}
/* just print */
g_print ("%s\n", data);
return TRUE;
}
static void
fu_util_build_device_tree (FuUtilPrivate *priv, GNode *root, GPtrArray *devs, FwupdDevice *dev)
{
@ -486,6 +514,43 @@ fu_util_get_tree_title (FuUtilPrivate *priv)
return g_strdup (fwupd_client_get_host_product (priv->client));
}
static gboolean
fu_util_get_devices_as_json (FuUtilPrivate *priv, GPtrArray *devs, GError **error)
{
g_autoptr(JsonBuilder) builder = json_builder_new ();
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "Devices");
json_builder_begin_array (builder);
for (guint i = 0; i < devs->len; i++) {
FwupdDevice *dev = g_ptr_array_index (devs, i);
g_autoptr(GPtrArray) rels = NULL;
g_autoptr(GError) error_local = NULL;
/* add all releases that could be applied */
rels = fwupd_client_get_releases (priv->client,
fwupd_device_get_id (dev),
priv->cancellable,
&error_local);
if (rels == NULL) {
g_debug ("not adding releases to device: %s",
error_local->message);
} else {
for (guint j = 0; j < rels->len; j++) {
FwupdRelease *rel = g_ptr_array_index (rels, j);
fwupd_device_add_release (dev, rel);
}
}
/* add to builder */
json_builder_begin_object (builder);
fwupd_device_to_json (dev, builder);
json_builder_end_object (builder);
}
json_builder_end_array (builder);
json_builder_end_object (builder);
return fu_util_print_builder (builder, error);
}
static gboolean
fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
{
@ -497,10 +562,14 @@ fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
devs = fwupd_client_get_devices (priv->client, NULL, error);
if (devs == NULL)
return FALSE;
if (devs->len > 0)
fu_util_build_device_tree (priv, root, devs, NULL);
/* not for human consumption */
if (priv->as_json)
return fu_util_get_devices_as_json (priv, devs, error);
/* print */
if (devs->len > 0)
fu_util_build_device_tree (priv, root, devs, NULL);
if (g_node_n_children (root) == 0) {
/* TRANSLATORS: nothing attached that can be upgraded */
g_print ("%s\n", _("No hardware detected with firmware update capability"));
@ -1345,6 +1414,46 @@ fu_util_perhaps_refresh_remotes (FuUtilPrivate *priv, GError **error)
return fu_util_download_metadata (priv, error);
}
static gboolean
fu_util_get_updates_as_json (FuUtilPrivate *priv, GPtrArray *devices, GError **error)
{
g_autoptr(JsonBuilder) builder = json_builder_new ();
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "Devices");
json_builder_begin_array (builder);
for (guint i = 0; i < devices->len; i++) {
FwupdDevice *dev = g_ptr_array_index (devices, i);
g_autoptr(GPtrArray) rels = NULL;
g_autoptr(GError) error_local = NULL;
/* not going to have results, so save a D-Bus round-trip */
if (!fwupd_device_has_flag (dev, FWUPD_DEVICE_FLAG_SUPPORTED))
continue;
/* get the releases for this device and filter for validity */
rels = fwupd_client_get_upgrades (priv->client,
fwupd_device_get_id (dev),
NULL, &error_local);
if (rels == NULL) {
g_debug ("no upgrades: %s", error_local->message);
continue;
}
for (guint j = 0; j < rels->len; j++) {
FwupdRelease *rel = g_ptr_array_index (rels, j);
fwupd_device_add_release (dev, rel);
}
/* add to builder */
json_builder_begin_object (builder);
fwupd_device_to_json (dev, builder);
json_builder_end_object (builder);
}
json_builder_end_array (builder);
json_builder_end_object (builder);
return fu_util_print_builder (builder, error);
}
static gboolean
fu_util_get_updates (FuUtilPrivate *priv, gchar **values, GError **error)
{
@ -1378,6 +1487,11 @@ fu_util_get_updates (FuUtilPrivate *priv, gchar **values, GError **error)
return FALSE;
}
g_ptr_array_sort (devices, fu_util_sort_devices_by_flags_cb);
/* not for human consumption */
if (priv->as_json)
return fu_util_get_updates_as_json (priv, devices, error);
for (guint i = 0; i < devices->len; i++) {
FwupdDevice *dev = g_ptr_array_index (devices, i);
g_autoptr(GPtrArray) rels = NULL;
@ -2449,6 +2563,24 @@ fu_util_upload_security (FuUtilPrivate *priv, GPtrArray *attrs, GError **error)
return TRUE;
}
static gboolean
fu_util_security_as_json (FuUtilPrivate *priv, GPtrArray *attrs, GError **error)
{
g_autoptr(JsonBuilder) builder = json_builder_new ();
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "HostSecurityAttributes");
json_builder_begin_array (builder);
for (guint i = 0; i < attrs->len; i++) {
FwupdSecurityAttr *attr = g_ptr_array_index (attrs, i);
json_builder_begin_object (builder);
fwupd_security_attr_to_json (attr, builder);
json_builder_end_object (builder);
}
json_builder_end_array (builder);
json_builder_end_object (builder);
return fu_util_print_builder (builder, error);
}
static gboolean
fu_util_security (FuUtilPrivate *priv, gchar **values, GError **error)
{
@ -2466,17 +2598,21 @@ fu_util_security (FuUtilPrivate *priv, gchar **values, GError **error)
return FALSE;
}
/* TRANSLATORS: this is a string like 'HSI:2-U' */
g_print ("%s \033[1m%s\033[0m\n", _("Host Security ID:"),
fwupd_client_get_host_security_id (priv->client));
/* print the "why" */
/* the "why" */
attrs = fwupd_client_get_host_security_attrs (priv->client,
priv->cancellable,
error);
if (attrs == NULL)
return FALSE;
/* not for human consumption */
if (priv->as_json)
return fu_util_security_as_json (priv, attrs, error);
/* TRANSLATORS: this is a string like 'HSI:2-U' */
g_print ("%s \033[1m%s\033[0m\n", _("Host Security ID:"),
fwupd_client_get_host_security_id (priv->client));
/* show or hide different elements */
if (priv->show_all) {
flags |= FU_SECURITY_ATTR_TO_STRING_FLAG_SHOW_OBSOLETES;
@ -2869,6 +3005,9 @@ main (int argc, char *argv[])
{ "ignore-power", '\0', 0, G_OPTION_ARG_NONE, &ignore_power,
/* TRANSLATORS: command line option */
_("Ignore requirement of external power source"), NULL },
{ "json", '\0', 0, G_OPTION_ARG_NONE, &priv->as_json,
/* TRANSLATORS: command line option */
_("Output in JSON format"), NULL },
{ NULL}
};
@ -2881,6 +3020,13 @@ main (int argc, char *argv[])
/* ensure D-Bus errors are registered */
fwupd_error_quark ();
/* this is an old command which is possibly a symlink */
if (g_str_has_suffix (argv[0], "fwupdagent")) {
g_printerr ("INFO: The fwupdagent command is deprecated, "
"use `fwupdmgr --json` instead\n");
priv->as_json = TRUE;
}
/* create helper object */
priv->main_ctx = g_main_context_new ();
priv->progressbar = fu_progressbar_new ();

View File

@ -5,11 +5,9 @@ fwupdagent \- firmware updating agent
.SH SYNOPSIS
fwupdagent [CMD]
.SH DESCRIPTION
fwupdagent is a command line fwupd client intended to be used by scripts.
fwupdagent used to be a command line fwupd client intended to be used by scripts.
You should now use the 100% compatible \fBfwupdmgr --json\fR command instead.
The output is JSON and guaranteed to be stable.
.SH OPTIONS
The fwupdagent command takes various options depending on the action.
Run \fBfwupdagent --help\fR for the full list.
.SH EXIT STATUS
Commands that successfully execute will return "0".
.SH SEE ALSO

View File

@ -94,34 +94,13 @@ fwupdmgr = executable(
install : true,
install_dir : bindir
)
endif
if get_option('agent')
fwupdagent = executable(
'fwupdagent',
sources : [
'fu-agent.c',
'fu-security-attr.c',
'fu-util-common.c',
systemd_src,
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
dependencies : [
libfwupd_deps,
libxmlb,
client_dep,
],
link_with : [
fwupd,
fwupdplugin,
],
install : true,
install_dir : bindir
)
# for compatibility
meson.add_install_script(
'sh', '-c',
'ln -fs fwupdmgr @0@@1@'.format(
'${DESTDIR}',
join_paths(get_option('prefix'), get_option('bindir'), 'fwupdagent')))
endif
if get_option('systemd')
@ -202,8 +181,6 @@ if get_option('man')
install: true,
install_dir: join_paths(mandir, 'man1'),
)
endif
if get_option('agent')
configure_file(
input : 'fwupdagent.1',
output : 'fwupdagent.1',