mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-30 07:10:10 +01:00
2003-05-04 Havoc Pennington <hp@pobox.com>
* tools/dbus-launch.c: implement * bus/main.c (main), bus/bus.c (bus_context_new): implement --print-pid and --fork
This commit is contained in:
parent
c0158234d0
commit
df01c98cc7
10 changed files with 824 additions and 19 deletions
|
|
@ -1,3 +1,10 @@
|
|||
2003-05-04 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* tools/dbus-launch.c: implement
|
||||
|
||||
* bus/main.c (main), bus/bus.c (bus_context_new):
|
||||
implement --print-pid and --fork
|
||||
|
||||
2003-05-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* dbus/dbus-address.c (dbus_parse_address): fix bug when a key in
|
||||
|
|
|
|||
40
bus/bus.c
40
bus/bus.c
|
|
@ -280,7 +280,9 @@ setup_server (BusContext *context,
|
|||
|
||||
BusContext*
|
||||
bus_context_new (const DBusString *config_file,
|
||||
dbus_bool_t force_fork,
|
||||
int print_addr_fd,
|
||||
int print_pid_fd,
|
||||
DBusError *error)
|
||||
{
|
||||
BusContext *context;
|
||||
|
|
@ -540,7 +542,7 @@ bus_context_new (const DBusString *config_file,
|
|||
_dbus_assert (context->policy != NULL);
|
||||
|
||||
/* Now become a daemon if appropriate */
|
||||
if (bus_config_parser_get_fork (parser))
|
||||
if (force_fork || bus_config_parser_get_fork (parser))
|
||||
{
|
||||
DBusString u;
|
||||
|
||||
|
|
@ -567,6 +569,42 @@ bus_context_new (const DBusString *config_file,
|
|||
/* keep around the pid filename so we can delete it later */
|
||||
context->pidfile = _dbus_strdup (pidfile);
|
||||
|
||||
/* Write PID if requested */
|
||||
if (print_pid_fd >= 0)
|
||||
{
|
||||
DBusString pid;
|
||||
int bytes;
|
||||
|
||||
if (!_dbus_string_init (&pid))
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
|
||||
!_dbus_string_append (&pid, "\n"))
|
||||
{
|
||||
_dbus_string_free (&pid);
|
||||
BUS_SET_OOM (error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
bytes = _dbus_string_get_length (&pid);
|
||||
if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Printing message bus PID: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
_dbus_string_free (&pid);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (print_pid_fd > 2)
|
||||
_dbus_close (print_pid_fd, NULL);
|
||||
|
||||
_dbus_string_free (&pid);
|
||||
}
|
||||
|
||||
/* Here we change our credentials if required,
|
||||
* as soon as we've set up our sockets and pidfile
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ typedef struct
|
|||
} BusLimits;
|
||||
|
||||
BusContext* bus_context_new (const DBusString *config_file,
|
||||
dbus_bool_t force_fork,
|
||||
int print_addr_fd,
|
||||
int print_pid_fd,
|
||||
DBusError *error);
|
||||
void bus_context_shutdown (BusContext *context);
|
||||
void bus_context_ref (BusContext *context);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ dbus-daemon-1 \- Message bus daemon
|
|||
.PP
|
||||
.B dbus-daemon-1
|
||||
dbus-daemon-1 [\-\-version] [\-\-session] [\-\-system] [\-\-config-file=FILE]
|
||||
[\-\-print-address[=DESCRIPTOR]]
|
||||
[\-\-print-address[=DESCRIPTOR]] [\-\-print-pid[=DESCRIPTOR]] [\-\-fork]
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
|
|
@ -62,11 +62,22 @@ The following options are supported:
|
|||
.I "--config-file=FILE"
|
||||
Use the given configuration file.
|
||||
.TP
|
||||
.I "--fork"
|
||||
Force the message bus to fork and become a daemon, even if
|
||||
the configuration file does not specify that it should.
|
||||
In most contexts the configuration file already gets this
|
||||
right, though.
|
||||
.TP
|
||||
.I "--print-address[=DESCRIPTOR]"
|
||||
Print the address of the message bus to standard output, or
|
||||
to the given file descriptor. This is used by programs that
|
||||
launch the message bus.
|
||||
.TP
|
||||
.I "--print-pid[=DESCRIPTOR]"
|
||||
Print the process ID of the message bus to standard output, or
|
||||
to the given file descriptor. This is used by programs that
|
||||
launch the message bus.
|
||||
.TP
|
||||
.I "--session"
|
||||
Use the standard configuration file for the per-login-session message
|
||||
bus.
|
||||
|
|
@ -185,7 +196,8 @@ privileges for writing.
|
|||
|
||||
.PP
|
||||
If present, the bus daemon becomes a real daemon (forks
|
||||
into the background, etc.).
|
||||
into the background, etc.). This is generally used
|
||||
rather than the \-\-fork command line option.
|
||||
|
||||
.TP
|
||||
.I "<listen>"
|
||||
|
|
|
|||
76
bus/main.c
76
bus/main.c
|
|
@ -47,7 +47,7 @@ signal_handler (int sig)
|
|||
static void
|
||||
usage (void)
|
||||
{
|
||||
fprintf (stderr, "dbus-daemon-1 [--version] [--session] [--system] [--config-file=FILE] [--print-address[=DESCRIPTOR]]\n");
|
||||
fprintf (stderr, "dbus-daemon-1 [--version] [--session] [--system] [--config-file=FILE] [--print-address[=DESCRIPTOR]] [--print-pid[=DESCRIPTOR]] [--fork]\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
|
@ -86,24 +86,45 @@ check_two_addr_descriptors (const DBusString *addr_fd,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_two_pid_descriptors (const DBusString *pid_fd,
|
||||
const char *extra_arg)
|
||||
{
|
||||
if (_dbus_string_get_length (pid_fd) > 0)
|
||||
{
|
||||
fprintf (stderr, "--%s specified but printing pid to %s already requested\n",
|
||||
extra_arg, _dbus_string_get_const_data (pid_fd));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
DBusError error;
|
||||
DBusString config_file;
|
||||
DBusString addr_fd;
|
||||
DBusString pid_fd;
|
||||
const char *prev_arg;
|
||||
int print_addr_fd;
|
||||
int print_pid_fd;
|
||||
int i;
|
||||
dbus_bool_t print_address;
|
||||
dbus_bool_t print_pid;
|
||||
dbus_bool_t force_fork;
|
||||
|
||||
if (!_dbus_string_init (&config_file))
|
||||
return 1;
|
||||
|
||||
if (!_dbus_string_init (&addr_fd))
|
||||
return 1;
|
||||
|
||||
if (!_dbus_string_init (&pid_fd))
|
||||
return 1;
|
||||
|
||||
print_address = FALSE;
|
||||
print_pid = FALSE;
|
||||
force_fork = FALSE;
|
||||
|
||||
prev_arg = NULL;
|
||||
i = 1;
|
||||
|
|
@ -117,6 +138,8 @@ main (int argc, char **argv)
|
|||
usage ();
|
||||
else if (strcmp (arg, "--version") == 0)
|
||||
version ();
|
||||
else if (strcmp (arg, "--fork") == 0)
|
||||
force_fork = TRUE;
|
||||
else if (strcmp (arg, "--system") == 0)
|
||||
{
|
||||
check_two_config_files (&config_file, "system");
|
||||
|
|
@ -179,6 +202,32 @@ main (int argc, char **argv)
|
|||
}
|
||||
else if (strcmp (arg, "--print-address") == 0)
|
||||
print_address = TRUE; /* and we'll get the next arg if appropriate */
|
||||
else if (strstr (arg, "--print-pid=") == arg)
|
||||
{
|
||||
const char *desc;
|
||||
|
||||
check_two_pid_descriptors (&pid_fd, "print-pid");
|
||||
|
||||
desc = strchr (arg, '=');
|
||||
++desc;
|
||||
|
||||
if (!_dbus_string_append (&pid_fd, desc))
|
||||
exit (1);
|
||||
|
||||
print_pid = TRUE;
|
||||
}
|
||||
else if (prev_arg &&
|
||||
strcmp (prev_arg, "--print-pid") == 0)
|
||||
{
|
||||
check_two_pid_descriptors (&pid_fd, "print-pid");
|
||||
|
||||
if (!_dbus_string_append (&pid_fd, arg))
|
||||
exit (1);
|
||||
|
||||
print_pid = TRUE;
|
||||
}
|
||||
else if (strcmp (arg, "--print-pid") == 0)
|
||||
print_pid = TRUE; /* and we'll get the next arg if appropriate */
|
||||
else
|
||||
usage ();
|
||||
|
||||
|
|
@ -213,9 +262,32 @@ main (int argc, char **argv)
|
|||
print_addr_fd = val;
|
||||
}
|
||||
}
|
||||
|
||||
print_pid_fd = -1;
|
||||
if (print_pid)
|
||||
{
|
||||
print_pid_fd = 1; /* stdout */
|
||||
if (_dbus_string_get_length (&pid_fd) > 0)
|
||||
{
|
||||
long val;
|
||||
int end;
|
||||
if (!_dbus_string_parse_int (&pid_fd, 0, &val, &end) ||
|
||||
end != _dbus_string_get_length (&pid_fd) ||
|
||||
val < 0 || val > _DBUS_INT_MAX)
|
||||
{
|
||||
fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
|
||||
_dbus_string_get_const_data (&pid_fd));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
print_pid_fd = val;
|
||||
}
|
||||
}
|
||||
|
||||
dbus_error_init (&error);
|
||||
context = bus_context_new (&config_file, print_addr_fd, &error);
|
||||
context = bus_context_new (&config_file, force_fork,
|
||||
print_addr_fd, print_pid_fd,
|
||||
&error);
|
||||
_dbus_string_free (&config_file);
|
||||
if (context == NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ bus_context_new_test (const DBusString *test_data_dir,
|
|||
}
|
||||
|
||||
dbus_error_init (&error);
|
||||
context = bus_context_new (&config_file, -1, &error);
|
||||
context = bus_context_new (&config_file, FALSE, -1, -1, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (&error);
|
||||
|
|
|
|||
12
configure.in
12
configure.in
|
|
@ -440,10 +440,6 @@ AC_SUBST(DBUS_QT_LIBS)
|
|||
|
||||
### X11 detection
|
||||
AC_PATH_XTRA
|
||||
DBUS_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
DBUS_X_CFLAGS="$X_CFLAGS"
|
||||
AC_SUBST(DBUS_X_CFLAGS)
|
||||
AC_SUBST(DBUS_X_LIBS)
|
||||
|
||||
## for now enable_x11 just tracks have_x11,
|
||||
## there's no --enable-x11
|
||||
|
|
@ -457,8 +453,16 @@ fi
|
|||
|
||||
if test x$enable_x11 = xyes ; then
|
||||
AC_DEFINE(DBUS_BUILD_X11,1,[Build X11-dependent code])
|
||||
DBUS_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
DBUS_X_CFLAGS="$X_CFLAGS"
|
||||
else
|
||||
DBUS_X_LIBS=
|
||||
DBUS_X_CFLAGS=
|
||||
fi
|
||||
|
||||
AC_SUBST(DBUS_X_CFLAGS)
|
||||
AC_SUBST(DBUS_X_LIBS)
|
||||
|
||||
### Documentation
|
||||
|
||||
AC_PATH_PROG(DOXYGEN, doxygen, no)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ dbus_launch_SOURCES= \
|
|||
|
||||
dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la
|
||||
dbus_monitor_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
|
||||
dbus_launch_LDADD= $(top_builddir)/dbus/libdbus-1.la
|
||||
## dbus-launch doesn't link to anything
|
||||
dbus_launch_LDADD= $(DBUS_X_LIBS)
|
||||
|
||||
man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1
|
||||
EXTRA_DIST = $(man_MANS)
|
||||
|
|
|
|||
|
|
@ -24,14 +24,19 @@ about D-BUS. See also the man page for \fIdbus-daemon-1\fP.
|
|||
|
||||
.PP
|
||||
Here is an example of how to use \fIdbus-launch\fP with an
|
||||
sh-compatible shell:
|
||||
sh-compatible shell to start the per-session bus daemon:
|
||||
.nf
|
||||
|
||||
VARIABLES=`dbus-launch`
|
||||
eval $VARIABLES
|
||||
echo "D-BUS per-session daemon address is: $DBUS_SESSION_BUS_ADDRESS"
|
||||
## test for an existing bus daemon, just to be safe
|
||||
if test -z "$DBUS_SESSION_BUS_ADDRESS" ; then
|
||||
## if not found, launch a new one
|
||||
eval `dbus-launch --exit-with-session`
|
||||
echo "D-BUS per-session daemon address is: $DBUS_SESSION_BUS_ADDRESS"
|
||||
export DBUS_SESSION_BUS_ADDRESS
|
||||
fi
|
||||
|
||||
.fi
|
||||
You might run something like that in your login scripts.
|
||||
|
||||
.SH OPTIONS
|
||||
The following options are supported:
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
*
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -30,10 +29,53 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef DBUS_BUILD_X11
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static void
|
||||
verbose (const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
static int verbose = TRUE;
|
||||
static int verbose_initted = FALSE;
|
||||
|
||||
/* things are written a bit oddly here so that
|
||||
* in the non-verbose case we just have the one
|
||||
* conditional and return immediately.
|
||||
*/
|
||||
if (!verbose)
|
||||
return;
|
||||
|
||||
if (!verbose_initted)
|
||||
{
|
||||
verbose = getenv ("DBUS_VERBOSE") != NULL;
|
||||
verbose_initted = TRUE;
|
||||
if (!verbose)
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (stderr, "%lu: ", (unsigned long) getpid ());
|
||||
|
||||
va_start (args, format);
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
|
|
@ -52,13 +94,462 @@ version (void)
|
|||
exit (0);
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
READ_STATUS_OK, /**< Read succeeded */
|
||||
READ_STATUS_ERROR, /**< Some kind of error */
|
||||
READ_STATUS_EOF /**< EOF returned */
|
||||
} ReadStatus;
|
||||
|
||||
static ReadStatus
|
||||
read_line (int fd,
|
||||
char *buf,
|
||||
size_t maxlen)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
ReadStatus retval;
|
||||
|
||||
memset (buf, '\0', maxlen);
|
||||
maxlen -= 1; /* ensure nul term */
|
||||
|
||||
retval = READ_STATUS_OK;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
size_t chunk;
|
||||
size_t to_read;
|
||||
|
||||
again:
|
||||
to_read = maxlen - bytes;
|
||||
|
||||
if (to_read == 0)
|
||||
break;
|
||||
|
||||
chunk = read (fd,
|
||||
buf + bytes,
|
||||
to_read);
|
||||
if (chunk < 0 && errno == EINTR)
|
||||
goto again;
|
||||
|
||||
if (chunk < 0)
|
||||
{
|
||||
retval = READ_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
else if (chunk == 0)
|
||||
{
|
||||
retval = READ_STATUS_EOF;
|
||||
break; /* EOF */
|
||||
}
|
||||
else /* chunk > 0 */
|
||||
bytes += chunk;
|
||||
}
|
||||
|
||||
if (retval == READ_STATUS_EOF &&
|
||||
bytes > 0)
|
||||
retval = READ_STATUS_OK;
|
||||
|
||||
/* whack newline */
|
||||
if (retval != READ_STATUS_ERROR &&
|
||||
bytes > 0 &&
|
||||
buf[bytes-1] == '\n')
|
||||
buf[bytes-1] = '\0';
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ReadStatus
|
||||
read_pid (int fd,
|
||||
pid_t *buf)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
ReadStatus retval;
|
||||
|
||||
retval = READ_STATUS_OK;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
size_t chunk;
|
||||
size_t to_read;
|
||||
|
||||
again:
|
||||
to_read = sizeof (pid_t) - bytes;
|
||||
|
||||
if (to_read == 0)
|
||||
break;
|
||||
|
||||
chunk = read (fd,
|
||||
((char*)buf) + bytes,
|
||||
to_read);
|
||||
if (chunk < 0 && errno == EINTR)
|
||||
goto again;
|
||||
|
||||
if (chunk < 0)
|
||||
{
|
||||
retval = READ_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
else if (chunk == 0)
|
||||
{
|
||||
retval = READ_STATUS_EOF;
|
||||
break; /* EOF */
|
||||
}
|
||||
else /* chunk > 0 */
|
||||
bytes += chunk;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
do_write (int fd, const void *buf, size_t count)
|
||||
{
|
||||
size_t bytes_written;
|
||||
int ret;
|
||||
|
||||
bytes_written = 0;
|
||||
|
||||
again:
|
||||
|
||||
ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Failed to write data to pipe!\n");
|
||||
exit (1); /* give up, we suck */
|
||||
}
|
||||
}
|
||||
else
|
||||
bytes_written += ret;
|
||||
|
||||
if (bytes_written < count)
|
||||
goto again;
|
||||
}
|
||||
|
||||
static void
|
||||
write_pid (int fd,
|
||||
pid_t pid)
|
||||
{
|
||||
do_write (fd, &pid, sizeof (pid));
|
||||
}
|
||||
|
||||
static int
|
||||
do_waitpid (pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
again:
|
||||
ret = waitpid (pid, NULL, 0);
|
||||
|
||||
if (ret < 0 &&
|
||||
errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static pid_t bus_pid_to_kill = -1;
|
||||
|
||||
static void
|
||||
kill_bus_and_exit (void)
|
||||
{
|
||||
verbose ("Killing message bus and exiting babysitter\n");
|
||||
|
||||
/* in case these point to any NFS mounts, get rid of them immediately */
|
||||
close (0);
|
||||
close (1);
|
||||
close (2);
|
||||
|
||||
kill (bus_pid_to_kill, SIGTERM);
|
||||
sleep (3);
|
||||
kill (bus_pid_to_kill, SIGKILL);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#ifdef DBUS_BUILD_X11
|
||||
static int
|
||||
x_io_error_handler (Display *xdisplay)
|
||||
{
|
||||
verbose ("X IO error\n");
|
||||
kill_bus_and_exit ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static int got_sighup = FALSE;
|
||||
|
||||
static void
|
||||
signal_handler (int sig)
|
||||
{
|
||||
switch (sig)
|
||||
{
|
||||
case SIGHUP:
|
||||
got_sighup = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kill_bus_when_session_ends (void)
|
||||
{
|
||||
int tty_fd;
|
||||
int x_fd;
|
||||
fd_set read_set;
|
||||
fd_set err_set;
|
||||
int ret;
|
||||
struct sigaction act;
|
||||
sigset_t empty_mask;
|
||||
#ifdef DBUS_BUILD_X11
|
||||
Display *xdisplay;
|
||||
#endif
|
||||
|
||||
/* install SIGHUP handler */
|
||||
got_sighup = FALSE;
|
||||
sigemptyset (&empty_mask);
|
||||
act.sa_handler = signal_handler;
|
||||
act.sa_mask = empty_mask;
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGHUP, &act, 0);
|
||||
|
||||
#ifdef DBUS_BUILD_X11
|
||||
xdisplay = XOpenDisplay (NULL);
|
||||
if (xdisplay != NULL)
|
||||
{
|
||||
verbose ("Successfully opened X display\n");
|
||||
x_fd = ConnectionNumber (xdisplay);
|
||||
XSetIOErrorHandler (x_io_error_handler);
|
||||
}
|
||||
else
|
||||
x_fd = -1;
|
||||
#else
|
||||
verbose ("Compiled without X11 support\n");
|
||||
x_fd = -1;
|
||||
#endif
|
||||
|
||||
if (isatty (0))
|
||||
tty_fd = 0;
|
||||
else
|
||||
tty_fd = -1;
|
||||
|
||||
if (tty_fd >= 0)
|
||||
verbose ("stdin isatty(), monitoring it\n");
|
||||
else
|
||||
verbose ("stdin was not a TTY, not monitoring it\n");
|
||||
|
||||
if (tty_fd < 0 && x_fd < 0)
|
||||
{
|
||||
fprintf (stderr, "No terminal on standard input and no X display; cannot attach message bus to session lifetime\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
FD_ZERO (&read_set);
|
||||
FD_ZERO (&err_set);
|
||||
|
||||
if (tty_fd >= 0)
|
||||
{
|
||||
FD_SET (tty_fd, &read_set);
|
||||
FD_SET (tty_fd, &err_set);
|
||||
}
|
||||
|
||||
if (x_fd >= 0)
|
||||
{
|
||||
FD_SET (x_fd, &read_set);
|
||||
FD_SET (x_fd, &err_set);
|
||||
}
|
||||
|
||||
ret = select (MAX (tty_fd, x_fd) + 1,
|
||||
&read_set, NULL, &err_set, NULL);
|
||||
|
||||
if (got_sighup)
|
||||
{
|
||||
verbose ("Got SIGHUP, exiting\n");
|
||||
kill_bus_and_exit ();
|
||||
}
|
||||
|
||||
#ifdef DBUS_BUILD_X11
|
||||
/* Dump events on the floor, and let
|
||||
* IO error handler run if we lose
|
||||
* the X connection
|
||||
*/
|
||||
if (x_fd >= 0)
|
||||
verbose ("X fd condition reading = %d error = %d\n",
|
||||
FD_ISSET (x_fd, &read_set),
|
||||
FD_ISSET (x_fd, &err_set));
|
||||
|
||||
if (xdisplay != NULL)
|
||||
{
|
||||
while (XPending (xdisplay))
|
||||
{
|
||||
XEvent ignored;
|
||||
XNextEvent (xdisplay, &ignored);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tty_fd >= 0)
|
||||
{
|
||||
if (FD_ISSET (tty_fd, &read_set))
|
||||
{
|
||||
int bytes_read;
|
||||
char discard[512];
|
||||
|
||||
verbose ("TTY ready for reading\n");
|
||||
|
||||
bytes_read = read (tty_fd, discard, sizeof (discard));
|
||||
|
||||
verbose ("Read %d bytes from TTY errno = %d\n",
|
||||
bytes_read, errno);
|
||||
|
||||
if (bytes_read == 0)
|
||||
kill_bus_and_exit (); /* EOF */
|
||||
else if (bytes_read < 0 && errno != EINTR)
|
||||
{
|
||||
/* This shouldn't happen I don't think; to avoid
|
||||
* spinning on the fd forever we exit.
|
||||
*/
|
||||
fprintf (stderr, "dbus-launch: error reading from stdin: %s\n",
|
||||
strerror (errno));
|
||||
kill_bus_and_exit ();
|
||||
}
|
||||
}
|
||||
else if (FD_ISSET (tty_fd, &err_set))
|
||||
{
|
||||
verbose ("TTY has error condition\n");
|
||||
|
||||
kill_bus_and_exit ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
babysit (int exit_with_session,
|
||||
pid_t child_pid,
|
||||
int read_bus_pid_fd, /* read pid from here */
|
||||
int write_bus_pid_fd) /* forward pid to here */
|
||||
{
|
||||
int ret;
|
||||
#define MAX_PID_LEN 64
|
||||
char buf[MAX_PID_LEN];
|
||||
long val;
|
||||
char *end;
|
||||
|
||||
/* We chdir ("/") since we are persistent and daemon-like, and fork
|
||||
* again so dbus-launch can reap the parent. However, we don't
|
||||
* setsid() or close fd 0,1,2 because the idea is to remain attached
|
||||
* to the tty and the X server in order to kill the message bus
|
||||
* when the session ends.
|
||||
*/
|
||||
|
||||
if (chdir ("/") < 0)
|
||||
{
|
||||
fprintf (stderr, "Could not change to root directory: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ret = fork ();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf (stderr, "fork() failed in babysitter: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
/* Parent reaps pre-fork part of bus daemon, then exits and is
|
||||
* reaped so the babysitter isn't a zombie
|
||||
*/
|
||||
|
||||
verbose ("=== Babysitter's intermediate parent continues again\n");
|
||||
|
||||
if (do_waitpid (child_pid) < 0)
|
||||
{
|
||||
/* shouldn't happen */
|
||||
fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
verbose ("Babysitter's intermediate parent exiting\n");
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* Child continues */
|
||||
verbose ("=== Babysitter process created\n");
|
||||
|
||||
verbose ("Reading PID from daemon\n");
|
||||
/* Now read data */
|
||||
switch (read_line (read_bus_pid_fd, buf, MAX_PID_LEN))
|
||||
{
|
||||
case READ_STATUS_OK:
|
||||
break;
|
||||
case READ_STATUS_EOF:
|
||||
fprintf (stderr, "EOF reading PID from bus daemon\n");
|
||||
exit (1);
|
||||
break;
|
||||
case READ_STATUS_ERROR:
|
||||
fprintf (stderr, "Error reading PID from bus daemon: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
break;
|
||||
}
|
||||
|
||||
end = NULL;
|
||||
val = strtol (buf, &end, 0);
|
||||
if (buf == end || end == NULL)
|
||||
{
|
||||
fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n",
|
||||
buf, strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
bus_pid_to_kill = val;
|
||||
|
||||
verbose ("Got PID %ld from daemon\n",
|
||||
(long) bus_pid_to_kill);
|
||||
|
||||
/* Write data to launcher */
|
||||
write_pid (write_bus_pid_fd, bus_pid_to_kill);
|
||||
close (write_bus_pid_fd);
|
||||
|
||||
if (exit_with_session)
|
||||
{
|
||||
/* Bus is now started and launcher has needed info;
|
||||
* we connect to X display and tty and wait to
|
||||
* kill bus if requested.
|
||||
*/
|
||||
|
||||
kill_bus_when_session_ends ();
|
||||
}
|
||||
|
||||
verbose ("Babysitter exiting\n");
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#define READ_END 0
|
||||
#define WRITE_END 1
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const char *prev_arg;
|
||||
dbus_bool_t exit_with_session;
|
||||
int exit_with_session;
|
||||
int i;
|
||||
|
||||
int ret;
|
||||
int bus_pid_to_launcher_pipe[2];
|
||||
int bus_pid_to_babysitter_pipe[2];
|
||||
int bus_address_to_launcher_pipe[2];
|
||||
|
||||
exit_with_session = FALSE;
|
||||
|
||||
prev_arg = NULL;
|
||||
|
|
@ -82,8 +573,181 @@ main (int argc, char **argv)
|
|||
|
||||
++i;
|
||||
}
|
||||
|
||||
verbose ("--exit-with-session provided\n");
|
||||
|
||||
if (pipe (bus_pid_to_launcher_pipe) < 0 ||
|
||||
pipe (bus_address_to_launcher_pipe) < 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to create pipe: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
bus_pid_to_babysitter_pipe[READ_END] = -1;
|
||||
bus_pid_to_babysitter_pipe[WRITE_END] = -1;
|
||||
|
||||
|
||||
ret = fork ();
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf (stderr, "Failed to fork: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Child */
|
||||
#define MAX_FD_LEN 64
|
||||
char write_pid_fd_as_string[MAX_FD_LEN];
|
||||
char write_address_fd_as_string[MAX_FD_LEN];
|
||||
|
||||
verbose ("=== Babysitter's intermediate parent created\n");
|
||||
|
||||
/* Fork once more to create babysitter */
|
||||
|
||||
if (pipe (bus_pid_to_babysitter_pipe) < 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to create pipe: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ret = fork ();
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf (stderr, "Failed to fork: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
/* In babysitter */
|
||||
verbose ("=== Babysitter's intermediate parent continues\n");
|
||||
|
||||
close (bus_pid_to_launcher_pipe[READ_END]);
|
||||
close (bus_address_to_launcher_pipe[READ_END]);
|
||||
close (bus_address_to_launcher_pipe[WRITE_END]);
|
||||
close (bus_pid_to_babysitter_pipe[WRITE_END]);
|
||||
|
||||
/* babysit() will fork *again*
|
||||
* and will also reap the pre-forked bus
|
||||
* daemon
|
||||
*/
|
||||
babysit (exit_with_session, ret,
|
||||
bus_pid_to_babysitter_pipe[READ_END],
|
||||
bus_pid_to_launcher_pipe[WRITE_END]);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
verbose ("=== Bus exec process created\n");
|
||||
|
||||
/* Now we are the bus process (well, almost;
|
||||
* dbus-daemon-1 itself forks again)
|
||||
*/
|
||||
close (bus_pid_to_launcher_pipe[READ_END]);
|
||||
close (bus_address_to_launcher_pipe[READ_END]);
|
||||
close (bus_pid_to_babysitter_pipe[READ_END]);
|
||||
close (bus_pid_to_launcher_pipe[WRITE_END]);
|
||||
|
||||
sprintf (write_pid_fd_as_string,
|
||||
"%d", bus_pid_to_babysitter_pipe[WRITE_END]);
|
||||
|
||||
sprintf (write_address_fd_as_string,
|
||||
"%d", bus_address_to_launcher_pipe[WRITE_END]);
|
||||
|
||||
verbose ("Calling exec()\n");
|
||||
|
||||
execlp ("dbus-daemon-1",
|
||||
"dbus-daemon-1",
|
||||
"--fork",
|
||||
"--session",
|
||||
"--print-pid", write_pid_fd_as_string,
|
||||
"--print-address", write_address_fd_as_string,
|
||||
NULL);
|
||||
|
||||
fprintf (stderr,
|
||||
"Failed to execute message bus daemon: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Parent */
|
||||
#define MAX_ADDR_LEN 512
|
||||
pid_t bus_pid;
|
||||
char bus_address[MAX_ADDR_LEN];
|
||||
|
||||
verbose ("=== Parent dbus-launch continues\n");
|
||||
|
||||
close (bus_pid_to_launcher_pipe[WRITE_END]);
|
||||
close (bus_address_to_launcher_pipe[WRITE_END]);
|
||||
|
||||
verbose ("Waiting for babysitter's intermediate parent\n");
|
||||
|
||||
/* Immediately reap parent of babysitter
|
||||
* (which was created just for us to reap)
|
||||
*/
|
||||
if (do_waitpid (ret) < 0)
|
||||
{
|
||||
fprintf (stderr, "Failed to waitpid() for babysitter intermediate process: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
verbose ("Reading address from bus\n");
|
||||
|
||||
/* Read the pipe data, print, and exit */
|
||||
switch (read_line (bus_address_to_launcher_pipe[READ_END],
|
||||
bus_address, MAX_ADDR_LEN))
|
||||
{
|
||||
case READ_STATUS_OK:
|
||||
break;
|
||||
case READ_STATUS_EOF:
|
||||
fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
|
||||
exit (1);
|
||||
break;
|
||||
case READ_STATUS_ERROR:
|
||||
fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
break;
|
||||
}
|
||||
|
||||
close (bus_address_to_launcher_pipe[READ_END]);
|
||||
|
||||
verbose ("Reading PID from babysitter\n");
|
||||
|
||||
switch (read_pid (bus_pid_to_launcher_pipe[READ_END], &bus_pid))
|
||||
{
|
||||
case READ_STATUS_OK:
|
||||
break;
|
||||
case READ_STATUS_EOF:
|
||||
fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
|
||||
exit (1);
|
||||
break;
|
||||
case READ_STATUS_ERROR:
|
||||
fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
|
||||
strerror (errno));
|
||||
exit (1);
|
||||
break;
|
||||
}
|
||||
|
||||
close (bus_pid_to_launcher_pipe[READ_END]);
|
||||
|
||||
printf ("DBUS_SESSION_BUS_ADDRESS='%s'\n",
|
||||
bus_address);
|
||||
|
||||
printf ("DBUS_SESSION_BUS_PID=%ld\n",
|
||||
(long) bus_pid);
|
||||
|
||||
verbose ("dbus-launch exiting\n");
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue