Files
flatpak/dbus-proxy/dbus-proxy.c
Alexander Larsson fa29b40fad dbus-proxy: Add sloppy-names mode
In this mode all clients get NameOwnerChanged events for all
unique names. This means you can track lifetimes of these, even if
you can't talk to them. This is useful on the a11y bus, because
we want to track when there are any listeners to a particular event,
and this is done my listing unique id:s and tracking them.
2017-09-01 15:34:40 +02:00

246 lines
5.8 KiB
C

/*
* Copyright © 2015 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#include "config.h"
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "libglnx/libglnx.h"
#include "flatpak-proxy.h"
static GList *proxies;
static int sync_fd = -1;
static int
parse_generic_args (int n_args, const char *args[])
{
if (g_str_has_prefix (args[0], "--fd="))
{
const char *fd_s = args[0] + strlen ("--fd=");
char *endptr;
int fd;
fd = strtol (fd_s, &endptr, 10);
if (fd < 0 || endptr == fd_s || *endptr != 0)
{
g_printerr ("Invalid fd %s\n", fd_s);
return -1;
}
sync_fd = fd;
return 1;
}
else
{
g_printerr ("Unknown argument %s\n", args[0]);
return -1;
}
}
static int
start_proxy (int n_args, const char *args[])
{
g_autoptr(FlatpakProxy) proxy = NULL;
g_autoptr(GError) error = NULL;
const char *bus_address, *socket_path;
int n;
n = 0;
if (n_args < n + 1 || args[n][0] == '-')
{
g_printerr ("No bus address given\n");
return -1;
}
bus_address = args[n++];
if (n_args < n + 1 || args[n][0] == '-')
{
g_printerr ("No socket path given\n");
return -1;
}
socket_path = args[n++];
proxy = flatpak_proxy_new (bus_address, socket_path);
while (n < n_args)
{
if (args[n][0] != '-')
break;
if (g_str_has_prefix (args[n], "--see=") ||
g_str_has_prefix (args[n], "--talk=") ||
g_str_has_prefix (args[n], "--filter=") ||
g_str_has_prefix (args[n], "--own="))
{
FlatpakPolicy policy = FLATPAK_POLICY_SEE;
g_autofree char *name = NULL;
gboolean wildcard = FALSE;
if (args[n][2] == 't')
policy = FLATPAK_POLICY_TALK;
else if (args[n][2] == 'f')
policy = FLATPAK_POLICY_FILTERED;
else if (args[n][2] == 'o')
policy = FLATPAK_POLICY_OWN;
name = g_strdup (strchr (args[n], '=') + 1);
if (policy == FLATPAK_POLICY_FILTERED)
{
char *rule = strchr (name, '=');
if (rule != NULL)
{
*rule++ = 0;
flatpak_proxy_add_filter (proxy, name, rule);
}
}
else
{
if (g_str_has_suffix (name, ".*"))
{
name[strlen (name) - 2] = 0;
wildcard = TRUE;
}
}
if (name[0] == ':' || !g_dbus_is_name (name))
{
g_printerr ("'%s' is not a valid dbus name\n", name);
return -1;
}
if (wildcard)
flatpak_proxy_add_wildcarded_policy (proxy, name, policy);
else
flatpak_proxy_add_policy (proxy, name, policy);
}
else if (g_str_equal (args[n], "--log"))
{
flatpak_proxy_set_log_messages (proxy, TRUE);
}
else if (g_str_equal (args[n], "--filter"))
{
flatpak_proxy_set_filter (proxy, TRUE);
}
else if (g_str_equal (args[n], "--sloppy-names"))
{
/* This means we're reporing the name changes for all unique names,
which is needed for the a11y bus */
flatpak_proxy_set_sloppy_names (proxy, TRUE);
}
else
{
int res = parse_generic_args (n_args - n, &args[n]);
if (res == -1)
return -1;
n += res - 1; /* res - 1, because we ++ below */
}
n++;
}
if (!flatpak_proxy_start (proxy, &error))
{
g_printerr ("Failed to start proxy for %s: %s\n", bus_address, error->message);
return -1;
}
proxies = g_list_prepend (proxies, g_object_ref (proxy));
return n;
}
static gboolean
sync_closed_cb (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
GList *l;
for (l = proxies; l != NULL; l = l->next)
flatpak_proxy_stop (FLATPAK_PROXY (l->data));
exit (0);
return TRUE;
}
int
main (int argc, const char *argv[])
{
GMainLoop *service_loop;
int n_args, res;
const char **args;
n_args = argc - 1;
args = &argv[1];
while (n_args > 0)
{
if (args[0][0] == '-')
{
res = parse_generic_args (n_args, &args[0]);
if (res == -1)
return 1;
}
else
{
res = start_proxy (n_args, args);
if (res == -1)
return 1;
}
g_assert (res > 0);
n_args -= res;
args += res;
}
if (proxies == NULL)
{
g_printerr ("No proxies specified\n");
return 1;
}
if (sync_fd >= 0)
{
ssize_t written;
GIOChannel *sync_channel;
written = write (sync_fd, "x", 1);
if (written != 1)
g_warning ("Can't write to sync socket");
sync_channel = g_io_channel_unix_new (sync_fd);
g_io_add_watch (sync_channel, G_IO_ERR | G_IO_HUP,
sync_closed_cb, NULL);
}
service_loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (service_loop);
g_main_loop_unref (service_loop);
return 0;
}