1d012387afef0ba02185ebe27bc6bb15551912e92Havoc Pennington/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
20e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington/* dbus-cleanup-sockets.c  dbus-cleanup-sockets utility
30e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington *
40e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * Copyright (C) 2003 Red Hat, Inc.
50e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * Copyright (C) 2002 Michael Meeks
60e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington *
70e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * Note that this file is NOT licensed under the Academic Free License,
80e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * as it is based on linc-cleanup-sockets which is LGPL.
90e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington *
100e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * This program is free software; you can redistribute it and/or modify
110e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * it under the terms of the GNU General Public License as published by
120e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * the Free Software Foundation; either version 2 of the License, or
130e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * (at your option) any later version.
140e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington *
150e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * This program is distributed in the hope that it will be useful,
160e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * but WITHOUT ANY WARRANTY; without even the implied warranty of
170e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
180e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * GNU General Public License for more details.
190e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington *
200e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * You should have received a copy of the GNU General Public License
210e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington * along with this program; if not, write to the Free Software
225baf2f856a9c6625993234855b07680da1c8916fTobias Mueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
230e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington *
240e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington */
250e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <config.h>
260e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <sys/types.h>
270e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <sys/stat.h>
280e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <stdio.h>
290e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <fcntl.h>
300e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <unistd.h>
310e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <dirent.h>
320e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <sys/socket.h>
330e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <sys/un.h>
340e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <errno.h>
350e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <stdlib.h>
360e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#include <string.h>
370e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
380e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#ifndef TRUE
390e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#define TRUE (1)
400e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#endif
410e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
420e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#ifndef FALSE
430e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#define FALSE (0)
440e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#endif
450e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
460e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#ifndef NULL
470e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#define NULL ((void*) 0)
480e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#endif
490e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
500e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void*
510e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonxmalloc (size_t bytes)
520e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
530e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  void *mem;
540e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
550e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (bytes == 0)
560e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    return NULL;
570e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
580e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  mem = malloc (bytes);
590e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
600e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (mem == NULL)
610e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
620e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Allocation of %d bytes failed\n",
630e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington               (int) bytes);
640e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      exit (1);
650e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
660e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
670e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  return mem;
680e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
690e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
700e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void*
710e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonxrealloc (void *old, size_t bytes)
720e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
730e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  void *mem;
740e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
750e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (bytes == 0)
760e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
770e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      free (old);
780e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      return NULL;
790e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
800e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
810e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  mem = realloc (old, bytes);
820e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
830e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (mem == NULL)
840e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
850e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Reallocation of %d bytes failed\n",
860e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington               (int) bytes);
870e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      exit (1);
880e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
890e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
900e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  return mem;
910e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
920e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
930e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#ifdef AF_UNIX
940e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
950e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtontypedef enum
960e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  {
970e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    SOCKET_UNKNOWN,
980e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    SOCKET_FAILED_TO_HANDLE,
990e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    SOCKET_DEAD,
1000e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    SOCKET_ALIVE,
1010e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    SOCKET_UNLINKED
1020e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  } SocketStatus;
1030e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1040e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic int alive_count = 0;
1050e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic int cleaned_count = 0;
1060e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic int unhandled_count = 0;
1070e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1080e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtontypedef struct
1090e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
1100e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  char *name;
1110e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int   fd;
1120e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  SocketStatus status;
1130e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int   n_retries;
1140e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington} SocketEntry;
1150e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1160e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic SocketEntry*
1170e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonsocket_entry_new (const char *dir,
1180e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington                  const char *fname)
1190e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
1200e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  SocketEntry *se;
1210e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int len;
1220e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1230e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se = xmalloc (sizeof (SocketEntry));
1240e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1250e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  len = strlen (dir) + strlen (fname) + 2; /* 2 = nul and '/' */
1260e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se->name = xmalloc (len);
1270e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1280e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  strcpy (se->name, dir);
1290e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  strcat (se->name, "/");
1300e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  strcat (se->name, fname);
1310e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1320e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se->fd = -1;
1330e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1340e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se->status = SOCKET_UNKNOWN;
1350e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1360e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se->n_retries = 0;
1370e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1380e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  return se;
1390e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
1400e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1410e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#if 0
1420e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void
1430e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonfree_socket_entry (SocketEntry *se)
1440e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
1450e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  free (se->name);
1460e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (se->fd >= 0)
1470e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    close (se->fd);
1480e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  free (se);
1490e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
1500e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#endif
1510e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1520e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void
1530e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonread_sockets (const char    *dir,
1540e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington              SocketEntry ***entries_p,
1550e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington              int           *n_entries_p)
1560e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
1570e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  DIR   *dirh;
1580e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  struct dirent *dent;
1590e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  SocketEntry **entries;
1600e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int n_entries;
1610e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int allocated;
1620e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1630e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  n_entries = 0;
1640e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  allocated = 2;
1650e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  entries = xmalloc (sizeof (SocketEntry*) * allocated);
1660e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1670e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  dirh = opendir (dir);
1680e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (dirh == NULL)
1690e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
1700e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Failed to open directory %s: %s\n",
1710e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington               dir, strerror (errno));
1720e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      exit (1);
1730e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
1740e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1750e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  while ((dent = readdir (dirh)))
1760e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
1770e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      SocketEntry *se;
1780e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1790e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (strncmp (dent->d_name, "dbus-", 5) != 0)
1800e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        continue;
1810e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1820e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      se = socket_entry_new (dir, dent->d_name);
1830e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1840e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (n_entries == allocated)
1850e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        {
1860e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          allocated *= 2;
1870e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          entries = xrealloc (entries, sizeof (SocketEntry*) * allocated);
1880e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        }
1890e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1900e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      entries[n_entries] = se;
1910e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      n_entries += 1;
1920e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
1930e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1940e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  closedir (dirh);
1950e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
1960e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  *entries_p = entries;
1970e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  *n_entries_p = n_entries;
1980e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
1990e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2000e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic SocketStatus
2010e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonopen_socket (SocketEntry *se)
2020e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
2030e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int ret;
2040e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  struct sockaddr_un saddr;
2050e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2060e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (se->n_retries > 5)
2070e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
2080e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Warning: giving up on socket %s after several retries; unable to determine socket's status\n",
2090e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington               se->name);
2100e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      return SOCKET_FAILED_TO_HANDLE;
2110e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
2120e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2130e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se->n_retries += 1;
2140e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2150e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  se->fd = socket (AF_UNIX, SOCK_STREAM, 0);
2160e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (se->fd < 0)
2170e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
2180e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Warning: failed to open a socket to use for connecting: %s\n",
2190e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington               strerror (errno));
2200e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      return SOCKET_UNKNOWN;
2210e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
2220e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2230e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (fcntl (se->fd, F_SETFL, O_NONBLOCK) < 0)
2240e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
2250e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Warning: failed set socket %s nonblocking: %s\n",
2260e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington               se->name, strerror (errno));
2270e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      return SOCKET_UNKNOWN;
2280e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
2290e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2300e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2310e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  memset (&saddr, '\0', sizeof (saddr)); /* nul-terminates the sun_path */
2320e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2330e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  saddr.sun_family = AF_UNIX;
2340e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  strncpy (saddr.sun_path, se->name, sizeof (saddr.sun_path) - 1);
2350e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2360e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  do
2370e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
2380e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      ret = connect (se->fd, (struct sockaddr*) &saddr, sizeof (saddr));
2390e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
2400e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  while (ret < 0 && errno == EINTR);
2410e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2420e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (ret >= 0)
2430e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    return SOCKET_ALIVE;
2440e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  else
2450e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
2460e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      switch (errno)
2470e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        {
2480e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case EINPROGRESS:
2490e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case EAGAIN:
2500e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          return SOCKET_UNKNOWN;
2510e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case ECONNREFUSED:
2520e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          return SOCKET_DEAD;
2530e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        default:
2540e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          fprintf (stderr, "Warning: unexpected error connecting to socket %s: %s\n",
2550e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington                   se->name, strerror (errno));
2560e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          return SOCKET_FAILED_TO_HANDLE;
2570e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        }
2580e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
2590e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
2600e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2610e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic int
2620e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonhandle_sockets (SocketEntry **entries,
2630e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington                int           n_entries)
2640e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
2650e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int i;
2660e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int n_unknown;
2670e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2680e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  n_unknown = 0;
2690e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2700e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  i = 0;
2710e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  while (i < n_entries)
2720e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
2730e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      SocketEntry *se;
2740e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      SocketStatus status;
2750e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2760e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      se = entries[i];
2770e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      ++i;
2780e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2790e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (se->fd >= 0)
2800e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        {
2810e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          fprintf (stderr, "Internal error, socket has fd  kept open while status = %d\n",
2820e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington                   se->status);
2830e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          exit (1);
2840e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        }
2850e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2860e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (se->status != SOCKET_UNKNOWN)
2870e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        continue;
2880e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2890e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      status = open_socket (se);
2900e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
2910e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      switch (status)
2920e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        {
2930e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case SOCKET_DEAD:
2940e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          cleaned_count += 1;
2950e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          if (unlink (se->name) < 0)
2960e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            {
2970e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington              fprintf (stderr, "Warning: Failed to delete %s: %s\n",
2980e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington                       se->name, strerror (errno));
2990e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3000e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington              se->status = SOCKET_FAILED_TO_HANDLE;
3010e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            }
3020e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          else
3030e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            se->status = SOCKET_UNLINKED;
3040e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          break;
3050e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3060e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case SOCKET_ALIVE:
3070e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          alive_count += 1;
3080e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          /* FALL THRU */
3090e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3100e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case SOCKET_FAILED_TO_HANDLE:
3110e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case SOCKET_UNKNOWN:
3120e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          se->status = status;
3130e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          break;
3140e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3150e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        case SOCKET_UNLINKED:
3160e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          fprintf (stderr, "Bad status from open_socket(), should not happen\n");
3170e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          exit (1);
3180e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          break;
3190e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        }
3200e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3210e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (se->fd >= 0)
3220e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        {
3230e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          close (se->fd);
3240e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          se->fd = -1;
3250e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        }
3260e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3270e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (se->status == SOCKET_UNKNOWN)
3280e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        n_unknown += 1;
3290e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
3300e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3310e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  return n_unknown == 0;
3320e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
3330e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3340e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void
3350e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonclean_dir (const char *dir)
3360e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
3370e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  SocketEntry **entries;
3380e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int n_entries;
3390e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3400e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  read_sockets (dir, &entries, &n_entries);
3410e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3420e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  /* open_socket() will fail conclusively after
3430e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington   * several retries, so this loop is guaranteed
3440e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington   * to terminate eventually
3450e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington   */
3460e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  while (!handle_sockets (entries, n_entries))
3470e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
3480e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      fprintf (stderr, "Unable to determine state of some sockets, retrying in 2 seconds\n");
3490e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      sleep (2);
3500e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
3510e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3520e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  unhandled_count += (n_entries - alive_count - cleaned_count);
3530e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
3540e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3550e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#endif /* AF_UNIX */
3560e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3570e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void
3580e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonusage (int ecode)
3590e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
3600e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  fprintf (stderr, "dbus-cleanup-sockets [--version] [--help] <socketdir>\n");
3610e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  exit (ecode);
3620e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
3630e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3640e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonstatic void
3650e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonversion (void)
3660e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
3677652304bff969afb3969603149bb385efe861fe8John (J  printf ("D-Bus Socket Cleanup Utility %s\n"
3680e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          "Copyright (C) 2003 Red Hat, Inc.\n"
3690e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          "Copyright (C) 2002 Michael Meeks\n"
3700e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          "This is free software; see the source for copying conditions.\n"
3710e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
3720e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          VERSION);
3730e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  exit (0);
3740e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
3750e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3760e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonint
3770e024fc53a5effadedd56427ffe261c417e45222Havoc Penningtonmain (int argc, char **argv)
3780e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington{
3790e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int i;
3800e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  int saw_doubledash;
3810e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  const char *dirname;
3820e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3830e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  saw_doubledash = FALSE;
3840e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  dirname = NULL;
3850e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  i = 1;
3860e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  while (i < argc)
3870e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    {
3880e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      const char *arg = argv[i];
3890e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
3900e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      if (strcmp (arg, "--help") == 0 ||
3910e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          strcmp (arg, "-h") == 0 ||
3920e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          strcmp (arg, "-?") == 0)
3930e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        usage (0);
3940e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      else if (strcmp (arg, "--version") == 0)
3950e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        version ();
3960e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      else if (!saw_doubledash)
3970e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington	{
3980e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          if (strcmp (arg, "--") == 0)
3990e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            saw_doubledash = TRUE;
4000e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          else if (*arg == '-')
4010e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            usage (1);
4020e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington	}
4030e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      else
4040e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        {
4050e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          if (dirname != NULL)
4060e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            {
4070e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington              fprintf (stderr, "dbus-cleanup-sockets only supports a single directory name\n");
4080e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington              exit (1);
4090e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington            }
4100e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
4110e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          dirname = arg;
4120e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington        }
4130e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
4140e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington      ++i;
4150e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    }
4160e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
4170e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  /* Default to session socket dir, usually /tmp */
4180e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  if (dirname == NULL)
4190e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington    dirname = DBUS_SESSION_SOCKET_DIR;
4200e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
4210e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#ifdef AF_UNIX
4220e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  clean_dir (dirname);
4230e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
4240e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  printf ("Cleaned up %d sockets in %s; %d sockets are still in use; %d in unknown state\n",
4250e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington          cleaned_count, dirname, alive_count, unhandled_count);
4260e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#else
4270e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  printf ("This system does not support UNIX domain sockets, so dbus-cleanup-sockets does nothing\n");
4280e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington#endif
4290e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington
4300e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington  return 0;
4310e024fc53a5effadedd56427ffe261c417e45222Havoc Pennington}
432