mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-20 09:10:07 +01:00
2003-04-06 Havoc Pennington <hp@pobox.com>
* bus/bus.c (bus_context_new): fix wrong handling of server_data_slot_unref() in the error case. * dbus/dbus-internals.h (_dbus_assert): change so it passes "(condition) != 0" to _dbus_real_assert so that "_dbus_assert (pointer)" doesn't cause a warning * bus/main.c (main): accept --print-address option to print out the message bus address * dbus/dbus-sysdeps.c (_dbus_generate_random_ascii): export this * dbus/dbus-transport.c (_dbus_transport_open): special error for "tmpdir" option to unix: address on client side * dbus/dbus-server.c (dbus_server_listen): handle "tmpdir" option to unix: address * configure.in (TEST_SOCKET_DIR): locate a temporary directory we can use to create sockets in the test suite. * bus/main.c (signal_handler): on SIGTERM, exit the daemon cleanly. To be used for testing. * dbus/dbus-spawn.c (babysit): use _dbus_set_signal_handler() * dbus/dbus-sysdeps.c (_dbus_set_signal_handler): new * dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new): handle trying to call this when there's no servers active
This commit is contained in:
parent
2618e1a973
commit
e45e438227
14 changed files with 441 additions and 137 deletions
33
ChangeLog
33
ChangeLog
|
|
@ -1,3 +1,36 @@
|
||||||
|
2003-04-06 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
|
* bus/bus.c (bus_context_new): fix wrong handling of
|
||||||
|
server_data_slot_unref() in the error case.
|
||||||
|
|
||||||
|
* dbus/dbus-internals.h (_dbus_assert): change so it passes
|
||||||
|
"(condition) != 0" to _dbus_real_assert so that
|
||||||
|
"_dbus_assert (pointer)" doesn't cause a warning
|
||||||
|
|
||||||
|
* bus/main.c (main): accept --print-address option to print out
|
||||||
|
the message bus address
|
||||||
|
|
||||||
|
* dbus/dbus-sysdeps.c (_dbus_generate_random_ascii): export this
|
||||||
|
|
||||||
|
* dbus/dbus-transport.c (_dbus_transport_open): special error for
|
||||||
|
"tmpdir" option to unix: address on client side
|
||||||
|
|
||||||
|
* dbus/dbus-server.c (dbus_server_listen): handle "tmpdir" option
|
||||||
|
to unix: address
|
||||||
|
|
||||||
|
* configure.in (TEST_SOCKET_DIR): locate a temporary directory
|
||||||
|
we can use to create sockets in the test suite.
|
||||||
|
|
||||||
|
* bus/main.c (signal_handler): on SIGTERM, exit the daemon
|
||||||
|
cleanly. To be used for testing.
|
||||||
|
|
||||||
|
* dbus/dbus-spawn.c (babysit): use _dbus_set_signal_handler()
|
||||||
|
|
||||||
|
* dbus/dbus-sysdeps.c (_dbus_set_signal_handler): new
|
||||||
|
|
||||||
|
* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
|
||||||
|
handle trying to call this when there's no servers active
|
||||||
|
|
||||||
2003-04-05 Havoc Pennington <hp@pobox.com>
|
2003-04-05 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
* NEWS: update
|
* NEWS: update
|
||||||
|
|
|
||||||
18
bus/bus.c
18
bus/bus.c
|
|
@ -107,7 +107,10 @@ server_get_context (DBusServer *server)
|
||||||
|
|
||||||
bd = BUS_SERVER_DATA (server);
|
bd = BUS_SERVER_DATA (server);
|
||||||
if (bd == NULL)
|
if (bd == NULL)
|
||||||
return NULL;
|
{
|
||||||
|
server_data_slot_unref ();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
context = bd->context;
|
context = bd->context;
|
||||||
|
|
||||||
|
|
@ -339,6 +342,12 @@ bus_context_new (const DBusString *config_file,
|
||||||
|
|
||||||
context->refcount = 1;
|
context->refcount = 1;
|
||||||
|
|
||||||
|
/* we need another ref of the server data slot for the context
|
||||||
|
* to own
|
||||||
|
*/
|
||||||
|
if (!server_data_slot_ref ())
|
||||||
|
_dbus_assert_not_reached ("second ref of server data slot failed");
|
||||||
|
|
||||||
#ifdef DBUS_BUILD_TESTS
|
#ifdef DBUS_BUILD_TESTS
|
||||||
context->activation_timeout = 6000; /* 6 seconds */
|
context->activation_timeout = 6000; /* 6 seconds */
|
||||||
#else
|
#else
|
||||||
|
|
@ -542,6 +551,7 @@ bus_context_new (const DBusString *config_file,
|
||||||
bus_config_parser_unref (parser);
|
bus_config_parser_unref (parser);
|
||||||
_dbus_string_free (&full_address);
|
_dbus_string_free (&full_address);
|
||||||
dbus_free_string_array (auth_mechanisms);
|
dbus_free_string_array (auth_mechanisms);
|
||||||
|
server_data_slot_unref ();
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
|
|
||||||
|
|
@ -678,6 +688,12 @@ bus_context_get_type (BusContext *context)
|
||||||
return context->type;
|
return context->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
bus_context_get_address (BusContext *context)
|
||||||
|
{
|
||||||
|
return context->address;
|
||||||
|
}
|
||||||
|
|
||||||
BusRegistry*
|
BusRegistry*
|
||||||
bus_context_get_registry (BusContext *context)
|
bus_context_get_registry (BusContext *context)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ void bus_context_shutdown (BusContext *context)
|
||||||
void bus_context_ref (BusContext *context);
|
void bus_context_ref (BusContext *context);
|
||||||
void bus_context_unref (BusContext *context);
|
void bus_context_unref (BusContext *context);
|
||||||
const char* bus_context_get_type (BusContext *context);
|
const char* bus_context_get_type (BusContext *context);
|
||||||
|
const char* bus_context_get_address (BusContext *context);
|
||||||
BusRegistry* bus_context_get_registry (BusContext *context);
|
BusRegistry* bus_context_get_registry (BusContext *context);
|
||||||
BusConnections* bus_context_get_connections (BusContext *context);
|
BusConnections* bus_context_get_connections (BusContext *context);
|
||||||
BusActivation* bus_context_get_activation (BusContext *context);
|
BusActivation* bus_context_get_activation (BusContext *context);
|
||||||
|
|
|
||||||
132
bus/main.c
132
bus/main.c
|
|
@ -26,11 +26,29 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static BusContext *context;
|
||||||
|
static dbus_bool_t got_sighup = FALSE;
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler (int sig)
|
||||||
|
{
|
||||||
|
switch (sig)
|
||||||
|
{
|
||||||
|
case SIGHUP:
|
||||||
|
got_sighup = TRUE;
|
||||||
|
case SIGTERM:
|
||||||
|
bus_loop_quit (bus_context_get_loop (context));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage (void)
|
usage (void)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "dbus-daemon-1 [--session] [--system] [--config-file=FILE] [--version]\n");
|
fprintf (stderr, "dbus-daemon-1 [--version] [--session] [--system] [--config-file=FILE] [--print-address[=descriptor]]\n");
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,18 +75,37 @@ check_two_config_files (const DBusString *config_file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_two_addr_descriptors (const DBusString *addr_fd,
|
||||||
|
const char *extra_arg)
|
||||||
|
{
|
||||||
|
if (_dbus_string_get_length (addr_fd) > 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "--%s specified but printing address to %s already requested\n",
|
||||||
|
extra_arg, _dbus_string_get_const_data (addr_fd));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
BusContext *context;
|
|
||||||
DBusError error;
|
DBusError error;
|
||||||
DBusString config_file;
|
DBusString config_file;
|
||||||
|
DBusString addr_fd;
|
||||||
const char *prev_arg;
|
const char *prev_arg;
|
||||||
|
int print_addr_fd;
|
||||||
int i;
|
int i;
|
||||||
|
dbus_bool_t print_address;
|
||||||
|
|
||||||
if (!_dbus_string_init (&config_file))
|
if (!_dbus_string_init (&config_file))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (!_dbus_string_init (&addr_fd))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
print_address = FALSE;
|
||||||
|
|
||||||
prev_arg = NULL;
|
prev_arg = NULL;
|
||||||
i = 1;
|
i = 1;
|
||||||
while (i < argc)
|
while (i < argc)
|
||||||
|
|
@ -117,6 +154,32 @@ main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
else if (strcmp (arg, "--config-file") == 0)
|
else if (strcmp (arg, "--config-file") == 0)
|
||||||
; /* wait for next arg */
|
; /* wait for next arg */
|
||||||
|
else if (strstr (arg, "--print-address=") == arg)
|
||||||
|
{
|
||||||
|
const char *desc;
|
||||||
|
|
||||||
|
check_two_addr_descriptors (&addr_fd, "print-address");
|
||||||
|
|
||||||
|
desc = strchr (arg, '=');
|
||||||
|
++desc;
|
||||||
|
|
||||||
|
if (!_dbus_string_append (&addr_fd, desc))
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
print_address = TRUE;
|
||||||
|
}
|
||||||
|
else if (prev_arg &&
|
||||||
|
strcmp (prev_arg, "--print-address") == 0)
|
||||||
|
{
|
||||||
|
check_two_addr_descriptors (&addr_fd, "print-address");
|
||||||
|
|
||||||
|
if (!_dbus_string_append (&addr_fd, arg))
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
print_address = TRUE;
|
||||||
|
}
|
||||||
|
else if (strcmp (arg, "--print-address") == 0)
|
||||||
|
print_address = TRUE; /* and we'll get the next arg if appropriate */
|
||||||
else
|
else
|
||||||
usage ();
|
usage ();
|
||||||
|
|
||||||
|
|
@ -131,6 +194,27 @@ main (int argc, char **argv)
|
||||||
usage ();
|
usage ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_addr_fd = -1;
|
||||||
|
if (print_address)
|
||||||
|
{
|
||||||
|
print_addr_fd = 1; /* stdout */
|
||||||
|
if (_dbus_string_get_length (&addr_fd) > 0)
|
||||||
|
{
|
||||||
|
long val;
|
||||||
|
int end;
|
||||||
|
if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) ||
|
||||||
|
end != _dbus_string_get_length (&addr_fd) ||
|
||||||
|
val < 0 || val > _DBUS_INT_MAX)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
|
||||||
|
_dbus_string_get_const_data (&addr_fd));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
print_addr_fd = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dbus_error_init (&error);
|
dbus_error_init (&error);
|
||||||
context = bus_context_new (&config_file, &error);
|
context = bus_context_new (&config_file, &error);
|
||||||
_dbus_string_free (&config_file);
|
_dbus_string_free (&config_file);
|
||||||
|
|
@ -139,14 +223,56 @@ main (int argc, char **argv)
|
||||||
_dbus_warn ("Failed to start message bus: %s\n",
|
_dbus_warn ("Failed to start message bus: %s\n",
|
||||||
error.message);
|
error.message);
|
||||||
dbus_error_free (&error);
|
dbus_error_free (&error);
|
||||||
return 1;
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note that we don't know whether the print_addr_fd is
|
||||||
|
* one of the sockets we're using to listen on, or some
|
||||||
|
* other random thing. But I think the answer is "don't do
|
||||||
|
* that then"
|
||||||
|
*/
|
||||||
|
if (print_addr_fd >= 0)
|
||||||
|
{
|
||||||
|
DBusString addr;
|
||||||
|
const char *a = bus_context_get_address (context);
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
_dbus_assert (a != NULL);
|
||||||
|
if (!_dbus_string_init (&addr) ||
|
||||||
|
!_dbus_string_append (&addr, a) ||
|
||||||
|
!_dbus_string_append (&addr, "\n"))
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
bytes = _dbus_string_get_length (&addr);
|
||||||
|
if (_dbus_write (print_addr_fd, &addr, 0, bytes) != bytes)
|
||||||
|
{
|
||||||
|
_dbus_warn ("Failed to print message bus address: %s\n",
|
||||||
|
_dbus_strerror (errno));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (print_addr_fd > 2)
|
||||||
|
_dbus_close (print_addr_fd, NULL);
|
||||||
|
|
||||||
|
_dbus_string_free (&addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME we have to handle this properly below _dbus_set_signal_handler (SIGHUP, signal_handler); */
|
||||||
|
_dbus_set_signal_handler (SIGTERM, signal_handler);
|
||||||
|
|
||||||
_dbus_verbose ("We are on D-Bus...\n");
|
_dbus_verbose ("We are on D-Bus...\n");
|
||||||
bus_loop_run (bus_context_get_loop (context));
|
bus_loop_run (bus_context_get_loop (context));
|
||||||
|
|
||||||
bus_context_shutdown (context);
|
bus_context_shutdown (context);
|
||||||
bus_context_unref (context);
|
bus_context_unref (context);
|
||||||
|
|
||||||
|
/* If we exited on TERM we just exit, if we exited on
|
||||||
|
* HUP we restart the daemon.
|
||||||
|
*/
|
||||||
|
if (got_sighup)
|
||||||
|
{
|
||||||
|
/* FIXME execv (argv) basically */
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,7 @@
|
||||||
<!-- Our well-known bus type, don't change this -->
|
<!-- Our well-known bus type, don't change this -->
|
||||||
<type>session</type>
|
<type>session</type>
|
||||||
|
|
||||||
<!-- FIXME - this is fairly complicated to fix.
|
<listen>unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@</listen>
|
||||||
Propose the following:
|
|
||||||
- add "unix:tmpdir=/tmp" which means unix domain transport
|
|
||||||
creates a socket with a random secure name
|
|
||||||
- add dbus_server_get_address() that gets the actual
|
|
||||||
server address
|
|
||||||
- add command line option or env variable to the daemon
|
|
||||||
causing it to print its list of addresses to a given
|
|
||||||
file descriptor
|
|
||||||
- session manager or whatever launches the session bus
|
|
||||||
reads the address from there and sets the env variable
|
|
||||||
-->
|
|
||||||
<listen>unix:path=/tmp/foobar</listen>
|
|
||||||
|
|
||||||
<policy context="default">
|
<policy context="default">
|
||||||
<!-- Allow everything -->
|
<!-- Allow everything -->
|
||||||
|
|
|
||||||
66
configure.in
66
configure.in
|
|
@ -31,8 +31,10 @@ AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode]
|
||||||
AC_ARG_ENABLE(asserts, [ --enable-asserts include assertion checks],enable_asserts=$enableval,enable_asserts=yes)
|
AC_ARG_ENABLE(asserts, [ --enable-asserts include assertion checks],enable_asserts=$enableval,enable_asserts=yes)
|
||||||
AC_ARG_ENABLE(gcov, [ --enable-gcov compile with coverage profiling instrumentation (gcc only)],enable_gcov=$enableval,enable_gcov=no)
|
AC_ARG_ENABLE(gcov, [ --enable-gcov compile with coverage profiling instrumentation (gcc only)],enable_gcov=$enableval,enable_gcov=no)
|
||||||
|
|
||||||
AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use])
|
AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use])
|
||||||
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
|
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
|
||||||
|
AC_ARG_WITH(session-socket-dir, [ --with-session-socket-dir=[dirname] Where to put sockets for the per-login-session message bus])
|
||||||
|
AC_ARG_WITH(test-socket-dir, [ --with-test-socket-dir=[dirname] Where to put sockets for make check])
|
||||||
|
|
||||||
dnl DBUS_BUILD_TESTS controls unit tests built in to .c files
|
dnl DBUS_BUILD_TESTS controls unit tests built in to .c files
|
||||||
dnl and also some stuff in the test/ subdir
|
dnl and also some stuff in the test/ subdir
|
||||||
|
|
@ -123,6 +125,9 @@ else
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# compress spaces in cflags
|
||||||
|
CFLAGS=`echo "$CFLAGS" | sed -e 's/ +/ /g'`
|
||||||
|
|
||||||
if test x$enable_gcov = xyes; then
|
if test x$enable_gcov = xyes; then
|
||||||
## so that config.h changes when you toggle gcov support
|
## so that config.h changes when you toggle gcov support
|
||||||
AC_DEFINE_UNQUOTED(DBUS_GCOV_ENABLED, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing])
|
AC_DEFINE_UNQUOTED(DBUS_GCOV_ENABLED, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing])
|
||||||
|
|
@ -160,6 +165,7 @@ AC_DEFINE_UNQUOTED(DBUS_INT64_TYPE, $dbusint64, [64-bit integer type])
|
||||||
## byte order
|
## byte order
|
||||||
AC_C_BIGENDIAN
|
AC_C_BIGENDIAN
|
||||||
|
|
||||||
|
#### Various functions
|
||||||
AC_CHECK_LIB(socket,socket)
|
AC_CHECK_LIB(socket,socket)
|
||||||
AC_CHECK_LIB(nsl,gethostbyname)
|
AC_CHECK_LIB(nsl,gethostbyname)
|
||||||
|
|
||||||
|
|
@ -443,6 +449,32 @@ TEST_PATH(EXIT_BINARY, test-exit)
|
||||||
TEST_PATH(SEGFAULT_BINARY, test-segfault)
|
TEST_PATH(SEGFAULT_BINARY, test-segfault)
|
||||||
TEST_PATH(SLEEP_FOREVER_BINARY, test-sleep-forever)
|
TEST_PATH(SLEEP_FOREVER_BINARY, test-sleep-forever)
|
||||||
|
|
||||||
|
#### Find socket directories
|
||||||
|
if ! test -z "$TMPDIR" ; then
|
||||||
|
DEFAULT_SOCKET_DIR=$TMPDIR
|
||||||
|
elif ! test -z "$TEMP" ; then
|
||||||
|
DEFAULT_SOCKET_DIR=$TEMP
|
||||||
|
elif ! test -z "$TMP" ; then
|
||||||
|
DEFAULT_SOCKET_DIR=$TMP
|
||||||
|
else
|
||||||
|
DEFAULT_SOCKET_DIR=/tmp
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! test -z "$with_test_socket_dir" ; then
|
||||||
|
TEST_SOCKET_DIR="$with_test_socket_dir"
|
||||||
|
else
|
||||||
|
TEST_SOCKET_DIR=$DEFAULT_SOCKET_DIR
|
||||||
|
fi
|
||||||
|
AC_SUBST(TEST_SOCKET_DIR)
|
||||||
|
|
||||||
|
if ! test -z "$with_session_socket_dir" ; then
|
||||||
|
DBUS_SESSION_SOCKET_DIR="$with_session_socket_dir"
|
||||||
|
else
|
||||||
|
DBUS_SESSION_SOCKET_DIR=$DEFAULT_SOCKET_DIR
|
||||||
|
fi
|
||||||
|
AC_SUBST(DBUS_SESSION_SOCKET_DIR)
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
Doxyfile
|
Doxyfile
|
||||||
bus/system.conf
|
bus/system.conf
|
||||||
|
|
@ -466,21 +498,23 @@ echo "
|
||||||
D-BUS $VERSION
|
D-BUS $VERSION
|
||||||
==============
|
==============
|
||||||
|
|
||||||
prefix: ${prefix}
|
prefix: ${prefix}
|
||||||
source code location: ${srcdir}
|
source code location: ${srcdir}
|
||||||
compiler: ${CC}
|
compiler: ${CC}
|
||||||
cflags: ${CFLAGS}
|
cflags: ${CFLAGS}
|
||||||
|
|
||||||
Maintainer mode: ${USE_MAINTAINER_MODE}
|
Maintainer mode: ${USE_MAINTAINER_MODE}
|
||||||
gcc coverage profiling: ${enable_gcov}
|
gcc coverage profiling: ${enable_gcov}
|
||||||
Building unit tests: ${enable_tests}
|
Building unit tests: ${enable_tests}
|
||||||
Building verbose mode: ${enable_verbose_mode}
|
Building verbose mode: ${enable_verbose_mode}
|
||||||
Building assertions: ${enable_asserts}
|
Building assertions: ${enable_asserts}
|
||||||
Building Qt bindings: ${have_qt}
|
Building Qt bindings: ${have_qt}
|
||||||
Building GLib bindings: ${have_glib}
|
Building GLib bindings: ${have_glib}
|
||||||
Using XML parser: ${with_xml}
|
Using XML parser: ${with_xml}
|
||||||
System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET}
|
Init scripts style: ${with_init_scripts}
|
||||||
Init scripts style: ${with_init_scripts}
|
System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET}
|
||||||
|
Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR}
|
||||||
|
'make check' socket dir: ${TEST_SOCKET_DIR}
|
||||||
"
|
"
|
||||||
|
|
||||||
if test x$enable_tests = xyes; then
|
if test x$enable_tests = xyes; then
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ message_from_error (const char *error)
|
||||||
else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0)
|
else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0)
|
||||||
return "Could not authenticate to server";
|
return "Could not authenticate to server";
|
||||||
else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0)
|
else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0)
|
||||||
return "No server";
|
return "No server available at address";
|
||||||
else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0)
|
else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0)
|
||||||
return "Connection timed out";
|
return "Connection timed out";
|
||||||
else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0)
|
else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||||
/* dbus-internals.h random utility stuff (internal to D-BUS implementation)
|
/* dbus-internals.h random utility stuff (internal to D-BUS implementation)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002 Red Hat, Inc.
|
* Copyright (C) 2002, 2003 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Academic Free License version 1.2
|
* Licensed under the Academic Free License version 1.2
|
||||||
*
|
*
|
||||||
|
|
@ -81,7 +81,7 @@ void _dbus_real_assert (dbus_bool_t condition,
|
||||||
const char *file,
|
const char *file,
|
||||||
int line);
|
int line);
|
||||||
#define _dbus_assert(condition) \
|
#define _dbus_assert(condition) \
|
||||||
_dbus_real_assert ((condition), #condition, __FILE__, __LINE__)
|
_dbus_real_assert ((condition) != 0, #condition, __FILE__, __LINE__)
|
||||||
#endif /* !DBUS_DISABLE_ASSERT */
|
#endif /* !DBUS_DISABLE_ASSERT */
|
||||||
|
|
||||||
#ifdef DBUS_DISABLE_ASSERT
|
#ifdef DBUS_DISABLE_ASSERT
|
||||||
|
|
|
||||||
|
|
@ -221,12 +221,18 @@ _dbus_transport_debug_pipe_new (const char *server_name,
|
||||||
|
|
||||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||||
|
|
||||||
|
if (server_pipe_hash == NULL)
|
||||||
|
{
|
||||||
|
dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
server = _dbus_hash_table_lookup_string (server_pipe_hash,
|
server = _dbus_hash_table_lookup_string (server_pipe_hash,
|
||||||
server_name);
|
server_name);
|
||||||
if (server == NULL ||
|
if (server == NULL ||
|
||||||
((DBusServerDebugPipe*)server)->disconnected)
|
((DBusServerDebugPipe*)server)->disconnected)
|
||||||
{
|
{
|
||||||
dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, NULL);
|
dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,18 +305,68 @@ dbus_server_listen (const char *address,
|
||||||
if (strcmp (method, "unix") == 0)
|
if (strcmp (method, "unix") == 0)
|
||||||
{
|
{
|
||||||
const char *path = dbus_address_entry_get_value (entries[i], "path");
|
const char *path = dbus_address_entry_get_value (entries[i], "path");
|
||||||
|
const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
|
||||||
|
|
||||||
if (path == NULL)
|
if (path == NULL && tmpdir == NULL)
|
||||||
{
|
{
|
||||||
address_problem_type = "unix";
|
address_problem_type = "unix";
|
||||||
address_problem_field = "path";
|
address_problem_field = "path or tmpdir";
|
||||||
goto bad_address;
|
goto bad_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
server = _dbus_server_new_for_domain_socket (path, error);
|
if (path && tmpdir)
|
||||||
|
{
|
||||||
|
address_problem_other = "cannot specify both \"path\" and \"tmpdir\" at the same time";
|
||||||
|
goto bad_address;
|
||||||
|
}
|
||||||
|
|
||||||
if (server)
|
if (tmpdir != NULL)
|
||||||
break;
|
{
|
||||||
|
DBusString full_path;
|
||||||
|
DBusString filename;
|
||||||
|
|
||||||
|
if (!_dbus_string_init (&full_path))
|
||||||
|
{
|
||||||
|
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_dbus_string_init (&filename))
|
||||||
|
{
|
||||||
|
_dbus_string_free (&full_path);
|
||||||
|
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_dbus_string_append (&filename,
|
||||||
|
"dbus-") ||
|
||||||
|
!_dbus_generate_random_ascii (&filename, 10) ||
|
||||||
|
!_dbus_string_append (&full_path, tmpdir) ||
|
||||||
|
!_dbus_concat_dir_and_file (&full_path, &filename))
|
||||||
|
{
|
||||||
|
_dbus_string_free (&full_path);
|
||||||
|
_dbus_string_free (&filename);
|
||||||
|
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME - we will unconditionally unlink() the path.
|
||||||
|
* unlink() does not follow symlinks, but would like
|
||||||
|
* independent confirmation this is safe enough. See
|
||||||
|
* also _dbus_listen_unix_socket() and comments therein.
|
||||||
|
*/
|
||||||
|
|
||||||
|
server =
|
||||||
|
_dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
|
||||||
|
error);
|
||||||
|
|
||||||
|
_dbus_string_free (&full_path);
|
||||||
|
_dbus_string_free (&filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server = _dbus_server_new_for_domain_socket (path, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp (method, "tcp") == 0)
|
else if (strcmp (method, "tcp") == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -361,9 +411,6 @@ dbus_server_listen (const char *address,
|
||||||
}
|
}
|
||||||
|
|
||||||
server = _dbus_server_debug_new (name, error);
|
server = _dbus_server_debug_new (name, error);
|
||||||
|
|
||||||
if (server)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (strcmp (method, "debug-pipe") == 0)
|
else if (strcmp (method, "debug-pipe") == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -377,9 +424,6 @@ dbus_server_listen (const char *address,
|
||||||
}
|
}
|
||||||
|
|
||||||
server = _dbus_server_debug_pipe_new (name, error);
|
server = _dbus_server_debug_pipe_new (name, error);
|
||||||
|
|
||||||
if (server)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
|
|
@ -387,8 +431,13 @@ dbus_server_listen (const char *address,
|
||||||
address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
|
address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
|
||||||
goto bad_address;
|
goto bad_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (server)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
dbus_address_entries_free (entries);
|
dbus_address_entries_free (entries);
|
||||||
return server;
|
return server;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -917,8 +917,6 @@ static void
|
||||||
babysit (pid_t grandchild_pid,
|
babysit (pid_t grandchild_pid,
|
||||||
int parent_pipe)
|
int parent_pipe)
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
|
||||||
sigset_t empty_mask;
|
|
||||||
int sigchld_pipe[2];
|
int sigchld_pipe[2];
|
||||||
|
|
||||||
/* I thought SIGCHLD would just wake up the poll, but
|
/* I thought SIGCHLD would just wake up the poll, but
|
||||||
|
|
@ -934,11 +932,7 @@ babysit (pid_t grandchild_pid,
|
||||||
|
|
||||||
babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
|
babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
|
||||||
|
|
||||||
sigemptyset (&empty_mask);
|
_dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
|
||||||
act.sa_handler = babysit_signal_handler;
|
|
||||||
act.sa_mask = empty_mask;
|
|
||||||
act.sa_flags = 0;
|
|
||||||
sigaction (SIGCHLD, &act, 0);
|
|
||||||
|
|
||||||
write_pid (parent_pipe, grandchild_pid);
|
write_pid (parent_pipe, grandchild_pid);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2007,36 +2007,6 @@ _dbus_file_get_contents (DBusString *str,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static dbus_bool_t
|
|
||||||
append_unique_chars (DBusString *str)
|
|
||||||
{
|
|
||||||
static const char letters[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
||||||
int i;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
#define N_UNIQUE_CHARS 8
|
|
||||||
|
|
||||||
if (!_dbus_generate_random_bytes (str, N_UNIQUE_CHARS))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
len = _dbus_string_get_length (str);
|
|
||||||
i = len - N_UNIQUE_CHARS;
|
|
||||||
while (i < len)
|
|
||||||
{
|
|
||||||
_dbus_string_set_byte (str, i,
|
|
||||||
letters[_dbus_string_get_byte (str, i) %
|
|
||||||
(sizeof (letters) - 1)]);
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dbus_assert (_dbus_string_validate_ascii (str, len - N_UNIQUE_CHARS,
|
|
||||||
N_UNIQUE_CHARS));
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a string out to a file. If the file exists,
|
* Writes a string out to a file. If the file exists,
|
||||||
* it will be atomically overwritten by the new data.
|
* it will be atomically overwritten by the new data.
|
||||||
|
|
@ -2084,7 +2054,8 @@ _dbus_string_save_to_file (const DBusString *str,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!append_unique_chars (&tmp_filename))
|
#define N_TMP_FILENAME_RANDOM_BYTES 8
|
||||||
|
if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
|
||||||
{
|
{
|
||||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
@ -2487,13 +2458,52 @@ _dbus_directory_close (DBusDirIter *iter)
|
||||||
dbus_free (iter);
|
dbus_free (iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dbus_bool_t
|
||||||
|
pseudorandom_generate_random_bytes (DBusString *str,
|
||||||
|
int n_bytes)
|
||||||
|
{
|
||||||
|
int old_len;
|
||||||
|
unsigned long tv_usec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
old_len = _dbus_string_get_length (str);
|
||||||
|
|
||||||
|
/* fall back to pseudorandom */
|
||||||
|
_dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
|
||||||
|
n_bytes);
|
||||||
|
|
||||||
|
_dbus_get_current_time (NULL, &tv_usec);
|
||||||
|
srand (tv_usec);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < n_bytes)
|
||||||
|
{
|
||||||
|
double r;
|
||||||
|
unsigned int b;
|
||||||
|
|
||||||
|
r = rand ();
|
||||||
|
b = (r / (double) RAND_MAX) * 255.0;
|
||||||
|
|
||||||
|
if (!_dbus_string_append_byte (str, b))
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
_dbus_string_set_length (str, old_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the given number of random bytes,
|
* Generates the given number of random bytes,
|
||||||
* using the best mechanism we can come up with.
|
* using the best mechanism we can come up with.
|
||||||
*
|
*
|
||||||
* @param str the string
|
* @param str the string
|
||||||
* @param n_bytes the number of random bytes to append to string
|
* @param n_bytes the number of random bytes to append to string
|
||||||
* @returns #TRUE on success, #FALSE if no memory or other failure
|
* @returns #TRUE on success, #FALSE if no memory
|
||||||
*/
|
*/
|
||||||
dbus_bool_t
|
dbus_bool_t
|
||||||
_dbus_generate_random_bytes (DBusString *str,
|
_dbus_generate_random_bytes (DBusString *str,
|
||||||
|
|
@ -2502,58 +2512,70 @@ _dbus_generate_random_bytes (DBusString *str,
|
||||||
int old_len;
|
int old_len;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
/* FALSE return means "no memory", if it could
|
||||||
|
* mean something else then we'd need to return
|
||||||
|
* a DBusError. So we always fall back to pseudorandom
|
||||||
|
* if the I/O fails.
|
||||||
|
*/
|
||||||
|
|
||||||
old_len = _dbus_string_get_length (str);
|
old_len = _dbus_string_get_length (str);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
/* note, urandom on linux will fall back to pseudorandom */
|
/* note, urandom on linux will fall back to pseudorandom */
|
||||||
fd = open ("/dev/urandom", O_RDONLY);
|
fd = open ("/dev/urandom", O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
return pseudorandom_generate_random_bytes (str, n_bytes);
|
||||||
|
|
||||||
|
if (_dbus_read (fd, str, n_bytes) != n_bytes)
|
||||||
{
|
{
|
||||||
unsigned long tv_usec;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* fall back to pseudorandom */
|
|
||||||
_dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
|
|
||||||
n_bytes);
|
|
||||||
|
|
||||||
_dbus_get_current_time (NULL, &tv_usec);
|
|
||||||
srand (tv_usec);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (i < n_bytes)
|
|
||||||
{
|
|
||||||
double r;
|
|
||||||
unsigned int b;
|
|
||||||
|
|
||||||
r = rand ();
|
|
||||||
b = (r / (double) RAND_MAX) * 255.0;
|
|
||||||
|
|
||||||
if (!_dbus_string_append_byte (str, b))
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_dbus_read (fd, str, n_bytes) != n_bytes)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
_dbus_verbose ("Read %d bytes from /dev/urandom\n",
|
|
||||||
n_bytes);
|
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
|
_dbus_string_set_length (str, old_len);
|
||||||
return TRUE;
|
return pseudorandom_generate_random_bytes (str, n_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
failed:
|
_dbus_verbose ("Read %d bytes from /dev/urandom\n",
|
||||||
_dbus_string_set_length (str, old_len);
|
n_bytes);
|
||||||
if (fd >= 0)
|
|
||||||
close (fd);
|
close (fd);
|
||||||
return FALSE;
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the given number of random bytes, where the bytes are
|
||||||
|
* chosen from the alphanumeric ASCII subset.
|
||||||
|
*
|
||||||
|
* @param str the string
|
||||||
|
* @param n_bytes the number of random ASCII bytes to append to string
|
||||||
|
* @returns #TRUE on success, #FALSE if no memory or other failure
|
||||||
|
*/
|
||||||
|
dbus_bool_t
|
||||||
|
_dbus_generate_random_ascii (DBusString *str,
|
||||||
|
int n_bytes)
|
||||||
|
{
|
||||||
|
static const char letters[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
int i;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!_dbus_generate_random_bytes (str, n_bytes))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
len = _dbus_string_get_length (str);
|
||||||
|
i = len - n_bytes;
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
_dbus_string_set_byte (str, i,
|
||||||
|
letters[_dbus_string_get_byte (str, i) %
|
||||||
|
(sizeof (letters) - 1)]);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
|
||||||
|
n_bytes));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -3005,6 +3027,26 @@ _dbus_change_identity (unsigned long uid,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Installs a UNIX signal handler
|
||||||
|
*
|
||||||
|
* @param sig the signal to handle
|
||||||
|
* @param handler the handler
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_dbus_set_signal_handler (int sig,
|
||||||
|
DBusSignalHandler handler)
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
sigset_t empty_mask;
|
||||||
|
|
||||||
|
sigemptyset (&empty_mask);
|
||||||
|
act.sa_handler = handler;
|
||||||
|
act.sa_mask = empty_mask;
|
||||||
|
act.sa_flags = 0;
|
||||||
|
sigaction (sig, &act, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DBUS_BUILD_TESTS
|
#ifdef DBUS_BUILD_TESTS
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,8 @@ void _dbus_directory_close (DBusDirIter *iter);
|
||||||
|
|
||||||
dbus_bool_t _dbus_generate_random_bytes (DBusString *str,
|
dbus_bool_t _dbus_generate_random_bytes (DBusString *str,
|
||||||
int n_bytes);
|
int n_bytes);
|
||||||
|
dbus_bool_t _dbus_generate_random_ascii (DBusString *str,
|
||||||
|
int n_bytes);
|
||||||
|
|
||||||
const char *_dbus_errno_to_string (int errnum);
|
const char *_dbus_errno_to_string (int errnum);
|
||||||
const char* _dbus_error_from_errno (int error_number);
|
const char* _dbus_error_from_errno (int error_number);
|
||||||
|
|
@ -220,6 +222,12 @@ dbus_bool_t _dbus_change_identity (unsigned long uid,
|
||||||
unsigned long gid,
|
unsigned long gid,
|
||||||
DBusError *error);
|
DBusError *error);
|
||||||
|
|
||||||
|
typedef void (* DBusSignalHandler) (int sig);
|
||||||
|
|
||||||
|
void _dbus_set_signal_handler (int sig,
|
||||||
|
DBusSignalHandler handler);
|
||||||
|
|
||||||
|
|
||||||
DBUS_END_DECLS;
|
DBUS_END_DECLS;
|
||||||
|
|
||||||
#endif /* DBUS_SYSDEPS_H */
|
#endif /* DBUS_SYSDEPS_H */
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,13 @@ _dbus_transport_open (const char *address,
|
||||||
if (strcmp (method, "unix") == 0)
|
if (strcmp (method, "unix") == 0)
|
||||||
{
|
{
|
||||||
const char *path = dbus_address_entry_get_value (entries[i], "path");
|
const char *path = dbus_address_entry_get_value (entries[i], "path");
|
||||||
|
const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
|
||||||
|
|
||||||
|
if (tmpdir != NULL)
|
||||||
|
{
|
||||||
|
address_problem_other = "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on";
|
||||||
|
goto bad_address;
|
||||||
|
}
|
||||||
|
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -243,7 +250,7 @@ _dbus_transport_open (const char *address,
|
||||||
goto bad_address;
|
goto bad_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
transport = _dbus_transport_new_for_domain_socket (path, error);
|
transport = _dbus_transport_new_for_domain_socket (path, error);
|
||||||
}
|
}
|
||||||
else if (strcmp (method, "tcp") == 0)
|
else if (strcmp (method, "tcp") == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue