mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-02-05 07:40:35 +01:00
2003-06-01 Havoc Pennington <hp@pobox.com>
* tools/dbus-cleanup-sockets.c: add utility to clean up sockets in /tmp (though on Linux this will end up being useless, when we add abstract namespace support) * configure.in: define DBUS_SESSION_SOCKET_DIR in addition to subst'ing it
This commit is contained in:
parent
a2e144132e
commit
0e024fc53a
6 changed files with 484 additions and 4 deletions
5
COPYING
5
COPYING
|
|
@ -1,6 +1,9 @@
|
|||
D-BUS is licensed to you under your choice of the Academic Free
|
||||
License version 1.2, or the GNU General Public License version 2.
|
||||
Both licenses are included here.
|
||||
Both licenses are included here. Some of the standalone binaries are
|
||||
under the GPL only; in particular, but not limited to,
|
||||
tools/dbus-cleanup-sockets.c and test/decode-gcov.c. Each source code
|
||||
file is marked with the proper copyright information.
|
||||
|
||||
Academic Free License
|
||||
Version 1.2
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
2003-06-01 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* tools/dbus-cleanup-sockets.c: add utility to clean up sockets
|
||||
in /tmp (though on Linux this will end up being useless,
|
||||
when we add abstract namespace support)
|
||||
|
||||
* configure.in: define DBUS_SESSION_SOCKET_DIR in addition to
|
||||
subst'ing it
|
||||
|
||||
2003-05-28 Colin Walters <walters@verbum.org>
|
||||
|
||||
* tools/dbus-monitor.c (main): Fix silly typo (s/--session/--system/).
|
||||
|
|
|
|||
|
|
@ -633,6 +633,7 @@ if ! test -z "$with_session_socket_dir" ; then
|
|||
else
|
||||
DBUS_SESSION_SOCKET_DIR=$DEFAULT_SOCKET_DIR
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(DBUS_SESSION_SOCKET_DIR, "$DBUS_SESSION_SOCKET_DIR", [Where per-session bus puts its sockets])
|
||||
AC_SUBST(DBUS_SESSION_SOCKET_DIR)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ else
|
|||
GLIB_TOOLS=
|
||||
endif
|
||||
|
||||
bin_PROGRAMS=dbus-send $(GLIB_TOOLS) dbus-launch
|
||||
bin_PROGRAMS=dbus-send $(GLIB_TOOLS) dbus-launch dbus-cleanup-sockets
|
||||
|
||||
dbus_send_SOURCES= \
|
||||
dbus-print-message.c \
|
||||
|
|
@ -21,10 +21,12 @@ dbus_monitor_SOURCES= \
|
|||
dbus_launch_SOURCES= \
|
||||
dbus-launch.c
|
||||
|
||||
dbus_cleanup_sockets_SOURCES= \
|
||||
dbus-cleanup-sockets.c
|
||||
|
||||
dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la
|
||||
dbus_monitor_LDADD= $(top_builddir)/glib/libdbus-glib-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
|
||||
man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1
|
||||
EXTRA_DIST = $(man_MANS)
|
||||
|
|
|
|||
30
tools/dbus-cleanup-sockets.1
Normal file
30
tools/dbus-cleanup-sockets.1
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
.\"
|
||||
.\" dbus-cleanup-sockets manual page.
|
||||
.\" Copyright (C) 2003 Red Hat, Inc.
|
||||
.\"
|
||||
.TH dbus-cleanup-sockets 1
|
||||
.SH NAME
|
||||
dbus-cleanup-sockets \- clean up leftover sockets in a directory
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
.B dbus-cleanup-sockets [DIRECTORY]
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
The \fIdbus-cleanup-sockets\fP command cleans up sockets used for
|
||||
D-BUS connections. See http://www.freedesktop.org/software/dbus/ for
|
||||
more information about the big picture.
|
||||
|
||||
.PP
|
||||
If given no arguments, \fIdbus-cleanup-sockets\fP cleans up sockets
|
||||
in the standard default socket directory for the
|
||||
per-user-login-session message bus; this is usually /tmp.
|
||||
Optionally, you can pass a different directory on the command line.
|
||||
|
||||
.SH AUTHOR
|
||||
dbus-cleanup-sockets was adapted by Havoc Pennington from
|
||||
linc-cleanup-sockets written by Michael Meeks.
|
||||
|
||||
.SH BUGS
|
||||
Please send bug reports to the D-BUS mailing list or bug tracker,
|
||||
see http://www.freedesktop.org/software/dbus/
|
||||
435
tools/dbus-cleanup-sockets.c
Normal file
435
tools/dbus-cleanup-sockets.c
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-cleanup-sockets.c dbus-cleanup-sockets utility
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2002 Michael Meeks
|
||||
*
|
||||
* Note that this file is NOT licensed under the Academic Free License,
|
||||
* as it is based on linc-cleanup-sockets which is LGPL.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*) 0)
|
||||
#endif
|
||||
|
||||
static void*
|
||||
xmalloc (size_t bytes)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if (bytes == 0)
|
||||
return NULL;
|
||||
|
||||
mem = malloc (bytes);
|
||||
|
||||
if (mem == NULL)
|
||||
{
|
||||
fprintf (stderr, "Allocation of %d bytes failed\n",
|
||||
(int) bytes);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void*
|
||||
xrealloc (void *old, size_t bytes)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if (bytes == 0)
|
||||
{
|
||||
free (old);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem = realloc (old, bytes);
|
||||
|
||||
if (mem == NULL)
|
||||
{
|
||||
fprintf (stderr, "Reallocation of %d bytes failed\n",
|
||||
(int) bytes);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
#ifdef AF_UNIX
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SOCKET_UNKNOWN,
|
||||
SOCKET_FAILED_TO_HANDLE,
|
||||
SOCKET_DEAD,
|
||||
SOCKET_ALIVE,
|
||||
SOCKET_UNLINKED
|
||||
} SocketStatus;
|
||||
|
||||
static int alive_count = 0;
|
||||
static int cleaned_count = 0;
|
||||
static int unhandled_count = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int fd;
|
||||
SocketStatus status;
|
||||
int n_retries;
|
||||
} SocketEntry;
|
||||
|
||||
static SocketEntry*
|
||||
socket_entry_new (const char *dir,
|
||||
const char *fname)
|
||||
{
|
||||
SocketEntry *se;
|
||||
int len;
|
||||
|
||||
se = xmalloc (sizeof (SocketEntry));
|
||||
|
||||
len = strlen (dir) + strlen (fname) + 2; /* 2 = nul and '/' */
|
||||
se->name = xmalloc (len);
|
||||
|
||||
strcpy (se->name, dir);
|
||||
strcat (se->name, "/");
|
||||
strcat (se->name, fname);
|
||||
|
||||
se->fd = -1;
|
||||
|
||||
se->status = SOCKET_UNKNOWN;
|
||||
|
||||
se->n_retries = 0;
|
||||
|
||||
return se;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
free_socket_entry (SocketEntry *se)
|
||||
{
|
||||
free (se->name);
|
||||
if (se->fd >= 0)
|
||||
close (se->fd);
|
||||
free (se);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
read_sockets (const char *dir,
|
||||
SocketEntry ***entries_p,
|
||||
int *n_entries_p)
|
||||
{
|
||||
DIR *dirh;
|
||||
struct dirent *dent;
|
||||
SocketEntry **entries;
|
||||
int n_entries;
|
||||
int allocated;
|
||||
|
||||
n_entries = 0;
|
||||
allocated = 2;
|
||||
entries = xmalloc (sizeof (SocketEntry*) * allocated);
|
||||
|
||||
dirh = opendir (dir);
|
||||
if (dirh == NULL)
|
||||
{
|
||||
fprintf (stderr, "Failed to open directory %s: %s\n",
|
||||
dir, strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while ((dent = readdir (dirh)))
|
||||
{
|
||||
SocketEntry *se;
|
||||
|
||||
if (strncmp (dent->d_name, "dbus-", 5) != 0)
|
||||
continue;
|
||||
|
||||
se = socket_entry_new (dir, dent->d_name);
|
||||
|
||||
if (n_entries == allocated)
|
||||
{
|
||||
allocated *= 2;
|
||||
entries = xrealloc (entries, sizeof (SocketEntry*) * allocated);
|
||||
}
|
||||
|
||||
entries[n_entries] = se;
|
||||
n_entries += 1;
|
||||
}
|
||||
|
||||
closedir (dirh);
|
||||
|
||||
*entries_p = entries;
|
||||
*n_entries_p = n_entries;
|
||||
}
|
||||
|
||||
static SocketStatus
|
||||
open_socket (SocketEntry *se)
|
||||
{
|
||||
int ret;
|
||||
struct sockaddr_un saddr;
|
||||
|
||||
if (se->n_retries > 5)
|
||||
{
|
||||
fprintf (stderr, "Warning: giving up on socket %s after several retries; unable to determine socket's status\n",
|
||||
se->name);
|
||||
return SOCKET_FAILED_TO_HANDLE;
|
||||
}
|
||||
|
||||
se->n_retries += 1;
|
||||
|
||||
se->fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (se->fd < 0)
|
||||
{
|
||||
fprintf (stderr, "Warning: failed to open a socket to use for connecting: %s\n",
|
||||
strerror (errno));
|
||||
return SOCKET_UNKNOWN;
|
||||
}
|
||||
|
||||
if (fcntl (se->fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
{
|
||||
fprintf (stderr, "Warning: failed set socket %s nonblocking: %s\n",
|
||||
se->name, strerror (errno));
|
||||
return SOCKET_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
memset (&saddr, '\0', sizeof (saddr)); /* nul-terminates the sun_path */
|
||||
|
||||
saddr.sun_family = AF_UNIX;
|
||||
strncpy (saddr.sun_path, se->name, sizeof (saddr.sun_path) - 1);
|
||||
|
||||
do
|
||||
{
|
||||
ret = connect (se->fd, (struct sockaddr*) &saddr, sizeof (saddr));
|
||||
}
|
||||
while (ret < 0 && errno == EINTR);
|
||||
|
||||
if (ret >= 0)
|
||||
return SOCKET_ALIVE;
|
||||
else
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EINPROGRESS:
|
||||
case EAGAIN:
|
||||
return SOCKET_UNKNOWN;
|
||||
case ECONNREFUSED:
|
||||
return SOCKET_DEAD;
|
||||
default:
|
||||
fprintf (stderr, "Warning: unexpected error connecting to socket %s: %s\n",
|
||||
se->name, strerror (errno));
|
||||
return SOCKET_FAILED_TO_HANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
handle_sockets (SocketEntry **entries,
|
||||
int n_entries)
|
||||
{
|
||||
int i;
|
||||
int n_unknown;
|
||||
|
||||
n_unknown = 0;
|
||||
|
||||
i = 0;
|
||||
while (i < n_entries)
|
||||
{
|
||||
SocketEntry *se;
|
||||
SocketStatus status;
|
||||
|
||||
se = entries[i];
|
||||
++i;
|
||||
|
||||
if (se->fd >= 0)
|
||||
{
|
||||
fprintf (stderr, "Internal error, socket has fd kept open while status = %d\n",
|
||||
se->status);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (se->status != SOCKET_UNKNOWN)
|
||||
continue;
|
||||
|
||||
status = open_socket (se);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SOCKET_DEAD:
|
||||
cleaned_count += 1;
|
||||
if (unlink (se->name) < 0)
|
||||
{
|
||||
fprintf (stderr, "Warning: Failed to delete %s: %s\n",
|
||||
se->name, strerror (errno));
|
||||
|
||||
se->status = SOCKET_FAILED_TO_HANDLE;
|
||||
}
|
||||
else
|
||||
se->status = SOCKET_UNLINKED;
|
||||
break;
|
||||
|
||||
case SOCKET_ALIVE:
|
||||
alive_count += 1;
|
||||
/* FALL THRU */
|
||||
|
||||
case SOCKET_FAILED_TO_HANDLE:
|
||||
case SOCKET_UNKNOWN:
|
||||
se->status = status;
|
||||
break;
|
||||
|
||||
case SOCKET_UNLINKED:
|
||||
fprintf (stderr, "Bad status from open_socket(), should not happen\n");
|
||||
exit (1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (se->fd >= 0)
|
||||
{
|
||||
close (se->fd);
|
||||
se->fd = -1;
|
||||
}
|
||||
|
||||
if (se->status == SOCKET_UNKNOWN)
|
||||
n_unknown += 1;
|
||||
}
|
||||
|
||||
return n_unknown == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clean_dir (const char *dir)
|
||||
{
|
||||
SocketEntry **entries;
|
||||
int n_entries;
|
||||
|
||||
read_sockets (dir, &entries, &n_entries);
|
||||
|
||||
/* open_socket() will fail conclusively after
|
||||
* several retries, so this loop is guaranteed
|
||||
* to terminate eventually
|
||||
*/
|
||||
while (!handle_sockets (entries, n_entries))
|
||||
{
|
||||
fprintf (stderr, "Unable to determine state of some sockets, retrying in 2 seconds\n");
|
||||
sleep (2);
|
||||
}
|
||||
|
||||
unhandled_count += (n_entries - alive_count - cleaned_count);
|
||||
}
|
||||
|
||||
#endif /* AF_UNIX */
|
||||
|
||||
static void
|
||||
usage (int ecode)
|
||||
{
|
||||
fprintf (stderr, "dbus-cleanup-sockets [--version] [--help] <socketdir>\n");
|
||||
exit (ecode);
|
||||
}
|
||||
|
||||
static void
|
||||
version (void)
|
||||
{
|
||||
printf ("D-BUS Socket Cleanup Utility %s\n"
|
||||
"Copyright (C) 2003 Red Hat, Inc.\n"
|
||||
"Copyright (C) 2002 Michael Meeks\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
|
||||
VERSION);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const char *prev_arg;
|
||||
int i;
|
||||
int saw_doubledash;
|
||||
const char *dirname;
|
||||
|
||||
saw_doubledash = FALSE;
|
||||
dirname = NULL;
|
||||
prev_arg = NULL;
|
||||
i = 1;
|
||||
while (i < argc)
|
||||
{
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (strcmp (arg, "--help") == 0 ||
|
||||
strcmp (arg, "-h") == 0 ||
|
||||
strcmp (arg, "-?") == 0)
|
||||
usage (0);
|
||||
else if (strcmp (arg, "--version") == 0)
|
||||
version ();
|
||||
else if (!saw_doubledash)
|
||||
{
|
||||
if (strcmp (arg, "--") == 0)
|
||||
saw_doubledash = TRUE;
|
||||
else if (*arg == '-')
|
||||
usage (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dirname != NULL)
|
||||
{
|
||||
fprintf (stderr, "dbus-cleanup-sockets only supports a single directory name\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
dirname = arg;
|
||||
}
|
||||
|
||||
prev_arg = arg;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Default to session socket dir, usually /tmp */
|
||||
if (dirname == NULL)
|
||||
dirname = DBUS_SESSION_SOCKET_DIR;
|
||||
|
||||
#ifdef AF_UNIX
|
||||
clean_dir (dirname);
|
||||
|
||||
printf ("Cleaned up %d sockets in %s; %d sockets are still in use; %d in unknown state\n",
|
||||
cleaned_count, dirname, alive_count, unhandled_count);
|
||||
#else
|
||||
printf ("This system does not support UNIX domain sockets, so dbus-cleanup-sockets does nothing\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue