1d012387afef0ba02185ebe27bc6bb15551912e92Havoc Pennington/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington/* dbus-transport-unix.c UNIX socket subclasses of DBusTransport
3041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
4dbdea921b5967ed25b24a9e5af5d6a3db54c5ec7Havoc Pennington * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
5041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
643605a6f4e78a8c28afb4b1e924dff0301e0e95cHavoc Pennington * Licensed under the Academic Free License version 2.1
7041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
8041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * This program is free software; you can redistribute it and/or modify
9041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * it under the terms of the GNU General Public License as published by
10041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * the Free Software Foundation; either version 2 of the License, or
11041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * (at your option) any later version.
12041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
13041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * This program is distributed in the hope that it will be useful,
14041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * but WITHOUT ANY WARRANTY; without even the implied warranty of
15041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * GNU General Public License for more details.
17041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
18041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * You should have received a copy of the GNU General Public License
19041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * along with this program; if not, write to the Free Software
205baf2f856a9c6625993234855b07680da1c8916fTobias Mueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
22041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington */
23041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington
24dbecdeabb20e0ce11121819c63373f0afba57c58Marcus Brinkmann#include <config.h>
254299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
264299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#include <stdio.h>
274299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
28041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington#include "dbus-internals.h"
29041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington#include "dbus-connection-internal.h"
30041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington#include "dbus-transport-unix.h"
31fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington#include "dbus-transport-socket.h"
32041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington#include "dbus-transport-protected.h"
33041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington#include "dbus-watch.h"
348027efc97b4bec85f674570f878919cb72456745Havoc Pennington#include "dbus-sysdeps-unix.h"
354299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#include "dbus-test.h"
36041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington
37041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington/**
38041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * @defgroup DBusTransportUnix DBusTransport implementations for UNIX
39041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * @ingroup  DBusInternals
40041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * @brief Implementation details of DBusTransport on UNIX
41041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
42041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * @{
43041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington */
44041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington
45041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington/**
46041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * Creates a new transport for the given Unix domain socket
4729c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington * path. This creates a client-side of a transport.
48041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington *
49a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington * @todo once we add a way to escape paths in a dbus
50a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington * address, this function needs to do escaping.
51a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington *
52041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * @param path the path to the domain socket.
53a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington * @param abstract #TRUE to use abstract socket namespace
544b13bb6d7f9a8e240cc41466dc70d9beb912a35eAnders Carlsson * @param error address where an error can be returned.
55041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington * @returns a new transport, or #NULL on failure.
56041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington */
57041b0767b284034aee09e9a0de2a3844b8cc546aHavoc PenningtonDBusTransport*
58041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington_dbus_transport_new_for_domain_socket (const char     *path,
59a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington                                       dbus_bool_t     abstract,
60ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington                                       DBusError      *error)
61041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington{
62041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington  int fd;
63041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington  DBusTransport *transport;
6429c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington  DBusString address;
6529c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington
66ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
6729c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington
68fa05de9230d62e7c427b5313796fc6ccd4d0ff60Havoc Pennington  if (!_dbus_string_init (&address))
6929c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington    {
7029c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
7129c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington      return NULL;
7229c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington    }
736d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington
746d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington  fd = -1;
75a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington
76a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington  if ((abstract &&
77a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington       !_dbus_string_append (&address, "unix:abstract=")) ||
78a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington      (!abstract &&
79a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington       !_dbus_string_append (&address, "unix:path=")) ||
8029c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington      !_dbus_string_append (&address, path))
8129c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington    {
8229c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
836d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington      goto failed_0;
8429c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington    }
85ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington
86a70b042f0dcebb10689975c65a2c45b52b7a4437Havoc Pennington  fd = _dbus_connect_unix_socket (path, abstract, error);
87041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington  if (fd < 0)
88ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington    {
89ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington      _DBUS_ASSERT_ERROR_IS_SET (error);
906d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington      goto failed_0;
91ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington    }
92ff5283ab92c668453fd2f28c1715a1e0e9b949f5Havoc Pennington
93ff5283ab92c668453fd2f28c1715a1e0e9b949f5Havoc Pennington  _dbus_verbose ("Successfully connected to unix socket %s\n",
94ff5283ab92c668453fd2f28c1715a1e0e9b949f5Havoc Pennington                 path);
9529c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington
968027efc97b4bec85f674570f878919cb72456745Havoc Pennington  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
97041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington  if (transport == NULL)
98041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington    {
99ce4fd314c6be9bfee16a172d5ca34e5097d309fcHavoc Pennington      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1006d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington      goto failed_1;
101041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington    }
1026d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington
10329c71168cd17b11eed65023c97aff401d5305b01Havoc Pennington  _dbus_string_free (&address);
10401af5ff4101e540a6456bca01d56272e701bea78Havoc Pennington
105041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington  return transport;
1066d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington
1076d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington failed_1:
10808079a5bdedd6ec91cda413983e4bd3b6ee0252dHavoc Pennington  _dbus_close_socket (fd, NULL);
1096d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington failed_0:
1106d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington  _dbus_string_free (&address);
1116d54407dbb089dd0b0d8d79189b029c4d82bae81Havoc Pennington  return NULL;
112041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington}
113041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington
11415ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington/**
1154299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * Creates a new transport for the given binary and arguments. This
1164299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * creates a client-side of a transport. The process will be forked
1174299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * off and executed with stdin/stdout connected to a local AF_UNIX
1184299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * socket.
1194299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat *
1204299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * @param path the path to the domain socket.
1214299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * @param argv Parameters list
1224299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * @param error address where an error can be returned.
1234299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat * @returns a new transport, or #NULL on failure.
1244299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat */
1254299eb3c0907100fe95d2986984b48d40cc52841Daniel Eratstatic DBusTransport*
1264299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat_dbus_transport_new_for_exec (const char     *path,
1274299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                              char *const     argv[],
1284299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                              DBusError      *error)
1294299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat{
1304299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  int fd;
1314299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  DBusTransport *transport;
1324299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  DBusString address;
1334299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  unsigned i;
1344299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  char *escaped;
1354299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1364299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1374299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1384299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (!_dbus_string_init (&address))
1394299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
1404299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1414299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      return NULL;
1424299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
1434299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1444299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  fd = -1;
1454299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1464299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  escaped = dbus_address_escape_value (path);
1474299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (!escaped)
1484299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
1494299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1504299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      goto failed;
1514299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
1524299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1534299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (!_dbus_string_append (&address, "unixexec:path=") ||
1544299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      !_dbus_string_append (&address, escaped))
1554299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
1564299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1574299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_free (escaped);
1584299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      goto failed;
1594299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
1604299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1614299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  dbus_free (escaped);
1624299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1634299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (argv)
1644299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
1654299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      for (i = 0; argv[i]; i++)
1664299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
1674299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          dbus_bool_t success;
1684299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1694299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          escaped = dbus_address_escape_value (argv[i]);
1704299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          if (!escaped)
1714299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            {
1724299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1734299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              goto failed;
1744299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            }
1754299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1764299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          success = _dbus_string_append_printf (&address, ",argv%u=%s", i, escaped);
1774299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          dbus_free (escaped);
1784299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1794299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          if (!success)
1804299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            {
1814299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1824299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              goto failed;
1834299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            }
1844299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
1854299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
1864299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1874299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  fd = _dbus_connect_exec (path, argv, error);
1884299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (fd < 0)
1894299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
1904299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      _DBUS_ASSERT_ERROR_IS_SET (error);
1914299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      goto failed;
1924299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
1934299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1944299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_verbose ("Successfully connected to process %s\n",
1954299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                 path);
1964299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
1974299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
1984299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (transport == NULL)
1994299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
2004299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2014299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      goto failed;
2024299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
2034299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2044299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_string_free (&address);
2054299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2064299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  return transport;
2074299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2084299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat failed:
2094299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  if (fd >= 0)
2104299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    _dbus_close_socket (fd, NULL);
2114299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2124299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_string_free (&address);
2134299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  return NULL;
2144299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat}
2154299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2164299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat/**
21715ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington * Opens platform specific transport types.
21815ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington *
21915ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington * @param entry the address entry to try opening
22015ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington * @param transport_p return location for the opened transport
22115ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington * @param error error to be set
22215ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington * @returns result of the attempt
22315ef0ef6fbba7827453b7973e62b6c1853576601Havoc Pennington */
224fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc PenningtonDBusTransportOpenResult
225fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington_dbus_transport_open_platform_specific (DBusAddressEntry  *entry,
226fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                        DBusTransport    **transport_p,
227fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                        DBusError         *error)
228fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington{
229fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington  const char *method;
230fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
231fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington  method = dbus_address_entry_get_method (entry);
232fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington  _dbus_assert (method != NULL);
233fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
234fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington  if (strcmp (method, "unix") == 0)
235fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington    {
236fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      const char *path = dbus_address_entry_get_value (entry, "path");
237fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
238fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      const char *abstract = dbus_address_entry_get_value (entry, "abstract");
239fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
240fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      if (tmpdir != NULL)
241fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        {
242fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          _dbus_set_bad_address (error, NULL, NULL,
243fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                 "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on");
244fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
245fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        }
246fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
247fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      if (path == NULL && abstract == NULL)
248fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        {
249fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          _dbus_set_bad_address (error, "unix",
250fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                 "path or abstract",
251fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                 NULL);
252fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
253fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        }
254fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
255fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      if (path != NULL && abstract != NULL)
256fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        {
257fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          _dbus_set_bad_address (error, NULL, NULL,
258fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                 "can't specify both \"path\" and \"abstract\" options in an address");
259fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
260fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        }
261fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
262fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      if (path)
263fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE,
264fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                                           error);
265fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      else
266fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE,
267fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington                                                           error);
268fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      if (*transport_p == NULL)
269fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        {
270fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          _DBUS_ASSERT_ERROR_IS_SET (error);
271fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
272fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        }
273fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      else
274fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington        {
275fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
276fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington          return DBUS_TRANSPORT_OPEN_OK;
2774299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
2784299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
2794299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  else if (strcmp (method, "unixexec") == 0)
2804299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
2814299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      const char *path;
2824299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      unsigned i;
2834299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      char **argv;
2844299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2854299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      path = dbus_address_entry_get_value (entry, "path");
2864299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (path == NULL)
2874299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
2884299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _dbus_set_bad_address (error, NULL, NULL,
2894299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                                 "No process path specified");
2904299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
2914299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
2924299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2934299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      /* First count argv arguments */
2944299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      for (i = 1; ; i++)
2954299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
2964299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          char t[4+20+1]; /* "argv" plus space for a formatted base 10 64bit integer, plus NUL */
2974299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
2984299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          snprintf (t, sizeof(t), "argv%u", i);
2994299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3004299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          if (!dbus_address_entry_get_value (entry, t))
3014299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            break;
3024299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3034299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3044299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      /* Allocate string array */
3054299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      argv = dbus_new0 (char*, i+1);
3064299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (!argv)
3074299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3084299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
3094299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
3104299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3114299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3124299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      /* Fill in string array */
3134299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      for (i = 0; ; i++)
3144299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3154299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          char t[4+20+1];
3164299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          const char *p;
3174299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3184299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          snprintf (t, sizeof(t), "argv%u", i);
3194299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3204299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          p = dbus_address_entry_get_value (entry, t);
3214299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          if (!p)
3224299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            {
3234299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              if (i == 0)
3244299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                /* If argv0 isn't specified, fill in the path instead */
3254299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                p = path;
3264299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              else
3274299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                break;
3284299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            }
3294299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3304299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          argv[i] = _dbus_strdup (p);
3314299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          if (!argv[i])
3324299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            {
3334299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              dbus_free_string_array (argv);
3344299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
3354299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat              return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
3364299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat            }
3374299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3384299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3394299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      *transport_p = _dbus_transport_new_for_exec (path, argv, error);
3404299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_free_string_array (argv);
3414299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3424299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (*transport_p == NULL)
3434299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3444299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _DBUS_ASSERT_ERROR_IS_SET (error);
3454299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
3464299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3474299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      else
3484299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3494299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3504299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_OK;
3514299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
352fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington    }
3534299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#ifdef DBUS_ENABLE_LAUNCHD
3544299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  else if (strcmp (method, "launchd") == 0)
3554299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    {
3564299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      DBusError tmp_error = DBUS_ERROR_INIT;
3574299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
3584299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      const char *launchd_socket;
3594299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      DBusString socket_path;
3604299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      dbus_bool_t valid_socket;
3614299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3624299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (!_dbus_string_init (&socket_path))
3634299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3644299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _DBUS_SET_OOM (error);
3654299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return FALSE;
3664299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3674299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3684299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (launchd_env_var == NULL)
3694299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3704299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _dbus_set_bad_address (error, "launchd", "env", NULL);
3714299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
3724299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3734299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3744299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      valid_socket = _dbus_lookup_launchd_socket (&socket_path, launchd_env_var, error);
3754299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3764299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (dbus_error_is_set(error))
3774299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3784299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _dbus_string_free(&socket_path);
3794299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
3804299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3814299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3824299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (!valid_socket)
3834299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3844299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          dbus_set_error(&tmp_error, DBUS_ERROR_BAD_ADDRESS,
3854299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat                         "launchd's env var %s does not exist", launchd_env_var);
3864299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          dbus_error_free(error);
3874299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          dbus_move_error(&tmp_error, error);
3884299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
3894299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3904299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3914299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      launchd_socket = _dbus_string_get_const_data(&socket_path);
3924299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      *transport_p = _dbus_transport_new_for_domain_socket (launchd_socket, FALSE, error);
3934299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
3944299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      if (*transport_p == NULL)
3954299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
3964299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _DBUS_ASSERT_ERROR_IS_SET (error);
3974299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
3984299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
3994299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat      else
4004299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        {
4014299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4024299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat          return DBUS_TRANSPORT_OPEN_OK;
4034299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat        }
4044299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat    }
4054299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#endif
406fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington  else
407fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington    {
408fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
409fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington      return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
410fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington    }
411fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington}
412fe4715b656237b89767b5dc0cba4c107541b6e0dHavoc Pennington
413041b0767b284034aee09e9a0de2a3844b8cc546aHavoc Pennington/** @} */
4144299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4154299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#ifdef DBUS_BUILD_TESTS
4164299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4174299eb3c0907100fe95d2986984b48d40cc52841Daniel Eratdbus_bool_t
4184299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat_dbus_transport_unix_test (void)
4194299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat{
4204299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  DBusConnection *c;
4214299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  DBusError error;
4224299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  dbus_bool_t ret;
4234299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  const char *address;
4244299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4254299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  dbus_error_init (&error);
4264299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4274299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  c = dbus_connection_open ("unixexec:argv0=false,argv1=foobar,path=/bin/false", &error);
4284299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_assert (c != NULL);
4294299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_assert (!dbus_error_is_set (&error));
4304299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4314299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  address = _dbus_connection_get_address (c);
4324299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  _dbus_assert (address != NULL);
4334299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4344299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  /* Let's see if the address got parsed, reordered and formatted correctly */
4354299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  ret = strcmp (address, "unixexec:path=/bin/false,argv0=false,argv1=foobar") == 0;
4364299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4374299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  dbus_connection_unref (c);
4384299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4394299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat  return ret;
4404299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat}
4414299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat
4424299eb3c0907100fe95d2986984b48d40cc52841Daniel Erat#endif
443