148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris/*
248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * restorecond
348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris *
448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * Copyright (C) 2006-2009 Red Hat
548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * see file 'COPYING' for use and warranty information
648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris *
748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * This program is free software; you can redistribute it and/or
848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * modify it under the terms of the GNU General Public License as
948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * published by the Free Software Foundation; either version 2 of
1048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * the License, or (at your option) any later version.
1148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris *
1248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * This program is distributed in the hope that it will be useful,
1348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * but WITHOUT ANY WARRANTY; without even the implied warranty of
1448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * GNU General Public License for more details.
1648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris.*
1748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * You should have received a copy of the GNU General Public License
1848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * along with this program; if not, write to the Free Software
1948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * 02111-1307  USA
2148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris *
2248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris * Authors:
2348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris *   Dan Walsh <dwalsh@redhat.com>
2448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris *
2548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris*/
2648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
2748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#define _GNU_SOURCE
2848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <sys/inotify.h>
2948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <errno.h>
3048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <stdio.h>
3148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <stdlib.h>
3248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <signal.h>
3348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <string.h>
3448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <unistd.h>
3548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <ctype.h>
3648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <sys/types.h>
3748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <sys/stat.h>
3848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <syslog.h>
3948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <limits.h>
4048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <fcntl.h>
4148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
4248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include "restorecond.h"
4348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include "stringslist.h"
4448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <glib.h>
4548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#ifdef HAVE_DBUS
4648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <dbus/dbus.h>
4748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <dbus/dbus-glib.h>
4848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <dbus/dbus-glib-lowlevel.h>
4948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
5048681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
5148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
5248681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic const char *PATH="/org/selinux/Restorecond";
5348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris//static const char *BUSNAME="org.selinux.Restorecond";
5448681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic const char *INTERFACE="org.selinux.RestorecondIface";
5548681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
5648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
57f2051b20fa10f66a27e7da394b6dede346064f50Dan Walshstatic int local_lock_fd = -1;
5848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
5948681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic DBusHandlerResult
6048681bb49c032d4c399e8331126c5dca020e0b3eEric Parissignal_filter (DBusConnection *connection  __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
6148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris{
6248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  /* User data is the event loop we are running in */
6348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  GMainLoop *loop = user_data;
6448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
6548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  /* A signal from the bus saying we are about to be disconnected */
6648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  if (dbus_message_is_signal
6748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris        (message, INTERFACE, "Stop")) {
6848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
6948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris      /* Tell the main loop to quit */
7048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris      g_main_loop_quit (loop);
7148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris      /* We have handled this message, don't pass it on */
7248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris      return DBUS_HANDLER_RESULT_HANDLED;
7348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  }
7448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  /* A Ping signal on the com.burtonini.dbus.Signal interface */
7548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
7648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    DBusError error;
7748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    dbus_error_init (&error);
7848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    g_print("Start received\n");
7948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    return DBUS_HANDLER_RESULT_HANDLED;
8048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  }
8148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
8248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris}
8348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
8448681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic int dbus_server(GMainLoop *loop) {
8548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    DBusConnection *bus;
8648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    DBusError error;
8748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    dbus_error_init (&error);
8848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
8948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    if (bus) {
9048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	dbus_connection_setup_with_g_main (bus, NULL);
9148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
9248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	/* listening to messages from all objects as no path is specified */
9348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
9448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	dbus_connection_add_filter (bus, signal_filter, loop, NULL);
9548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	return 0;
9648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    }
9748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    return -1;
9848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris}
9948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
10048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#endif
10148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <selinux/selinux.h>
10248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#include <sys/file.h>
10348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
10448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris/* size of the event structure, not counting name */
10548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#define EVENT_SIZE  (sizeof (struct inotify_event))
10648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris/* reasonable guess as to size of 1024 events */
10748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#define BUF_LEN        (1024 * (EVENT_SIZE + 16))
10848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
10948681bb49c032d4c399e8331126c5dca020e0b3eEric Parisstatic gboolean
11048681bb49c032d4c399e8331126c5dca020e0b3eEric Parisio_channel_callback
11148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris (GIOChannel *source,
11248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  GIOCondition condition,
11348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  gpointer data __attribute__((__unused__)))
11448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris{
11548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
11648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  char buffer[BUF_LEN+1];
11748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  gsize bytes_read;
11848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  unsigned int i = 0;
11948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
12048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  if (condition & G_IO_IN) {
12148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    /* Data is available. */
122137604222aff76aab24253853e7add87366a4e1cDan Walsh    g_io_channel_read_chars
12348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris      (source, buffer,
12448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris       sizeof (buffer),
125137604222aff76aab24253853e7add87366a4e1cDan Walsh       &bytes_read, NULL);
12648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
1274a145b76d02a0ff179758773e028333e020184f7Dan Walsh    if (! bytes_read) {
1284a145b76d02a0ff179758773e028333e020184f7Dan Walsh	    /* Sesssion/Terminal Ended */
1294a145b76d02a0ff179758773e028333e020184f7Dan Walsh	    exit(0);
1304a145b76d02a0ff179758773e028333e020184f7Dan Walsh    }
1314a145b76d02a0ff179758773e028333e020184f7Dan Walsh
13248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    while (i < bytes_read) {
13348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	    struct inotify_event *event;
13448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	    event = (struct inotify_event *)&buffer[i];
13548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	    if (debug_mode)
13648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		    printf("wd=%d mask=%u cookie=%u len=%u\n",
13748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			   event->wd, event->mask,
13848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			   event->cookie, event->len);
13948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	    if (event->len)
14048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		    watch_list_find(event->wd, event->name);
14148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
14248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	    i += EVENT_SIZE + event->len;
14348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    }
14448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  }
14548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
14648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  /* An error happened while reading
14748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris     the file. */
14848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
14948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  if (condition & G_IO_NVAL)
15048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    return FALSE;
15148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
15248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  /* We have reached the end of the
15348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris     file. */
15448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
15548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  if (condition & G_IO_HUP) {
156137604222aff76aab24253853e7add87366a4e1cDan Walsh    g_io_channel_shutdown (source, 0, NULL);
1574a145b76d02a0ff179758773e028333e020184f7Dan Walsh    exit(0);
15848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    return FALSE;
15948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  }
16048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
16148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  /* Returning TRUE will make sure
16248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris     the callback remains associated
16348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris     to the channel. */
16448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
16548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris  return TRUE;
16648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris}
16748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
16848681bb49c032d4c399e8331126c5dca020e0b3eEric Parisint start() {
16948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#ifdef HAVE_DBUS
17048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	DBusConnection *bus;
17148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	DBusError error;
17248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	DBusMessage *message;
17348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
17448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	/* Get a connection to the session bus */
17548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	dbus_error_init (&error);
17648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
17748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	if (!bus) {
17848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		if (debug_mode)
17948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
18048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		dbus_error_free (&error);
18148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		return 1;
18248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	}
18348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
18448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
18548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	/* Create a new signal "Start" on the interface,
18648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	 * from the object  */
18748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	message = dbus_message_new_signal (PATH,
18848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris					   INTERFACE, "Start");
18948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	/* Send the signal */
19048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	dbus_connection_send (bus, message, NULL);
19148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	/* Free the signal now we have finished with it */
19248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	dbus_message_unref (message);
19348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#endif /* HAVE_DBUS */
19448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	return 0;
19548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris}
19648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
197c4a4a1a7ed42c167a7d4bae06a1fffa8c6c9cb8dNicolas Ioossstatic int local_server(void) {
19848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	// ! dbus, run as local service
19948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	char *ptr=NULL;
2009961ca64990f9547f5f7921d1766f57905098e10Dan Walsh	if (asprintf(&ptr, "%s/.restorecond", homedir) < 0) {
2019961ca64990f9547f5f7921d1766f57905098e10Dan Walsh		if (debug_mode)
2029961ca64990f9547f5f7921d1766f57905098e10Dan Walsh			perror("asprintf");
2039961ca64990f9547f5f7921d1766f57905098e10Dan Walsh		return -1;
2049961ca64990f9547f5f7921d1766f57905098e10Dan Walsh	}
205f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh	local_lock_fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
20648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	if (debug_mode)
20748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		g_warning ("Lock file: %s", ptr);
20848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
20948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	free(ptr);
210f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh	if (local_lock_fd < 0) {
21148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		if (debug_mode)
21248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			perror("open");
21348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		return -1;
21448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	}
215f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh	if (flock(local_lock_fd, LOCK_EX | LOCK_NB) < 0) {
216f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh		close(local_lock_fd);
21748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		if (debug_mode)
21848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			perror("flock");
21948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		return -1;
22048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	}
2214a145b76d02a0ff179758773e028333e020184f7Dan Walsh	/* watch for stdin/terminal going away */
2224a145b76d02a0ff179758773e028333e020184f7Dan Walsh	GIOChannel *in = g_io_channel_unix_new(0);
2234a145b76d02a0ff179758773e028333e020184f7Dan Walsh	g_io_add_watch_full( in,
2244a145b76d02a0ff179758773e028333e020184f7Dan Walsh			     G_PRIORITY_HIGH,
2254a145b76d02a0ff179758773e028333e020184f7Dan Walsh			     G_IO_IN|G_IO_ERR|G_IO_HUP,
2264a145b76d02a0ff179758773e028333e020184f7Dan Walsh			     io_channel_callback, NULL, NULL);
2274a145b76d02a0ff179758773e028333e020184f7Dan Walsh
22848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris	return 0;
22948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris}
23048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
231f2051b20fa10f66a27e7da394b6dede346064f50Dan Walshstatic void end_local_server(void) {
232f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh	if (local_lock_fd >= 0)
233f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh		close(local_lock_fd);
234f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh	local_lock_fd = -1;
235f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh}
236f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh
23748681bb49c032d4c399e8331126c5dca020e0b3eEric Parisint server(int master_fd, const char *watch_file) {
23848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    GMainLoop *loop;
23948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
24048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    loop = g_main_loop_new (NULL, FALSE);
24148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
24248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#ifdef HAVE_DBUS
24348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    if (dbus_server(loop) != 0)
24448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris#endif /* HAVE_DBUS */
2454a145b76d02a0ff179758773e028333e020184f7Dan Walsh	    if (local_server())
24648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris		    goto end;
24748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
24848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    read_config(master_fd, watch_file);
24948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
25048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    if (watch_list_isempty()) goto end;
25148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
25248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
25348681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
25448681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    GIOChannel *c = g_io_channel_unix_new(master_fd);
25548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
25648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    g_io_add_watch_full( c,
25748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			 G_PRIORITY_HIGH,
25848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			 G_IO_IN|G_IO_ERR|G_IO_HUP,
25948681bb49c032d4c399e8331126c5dca020e0b3eEric Paris			 io_channel_callback, NULL, NULL);
26048681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
26148681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    g_main_loop_run (loop);
26248681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
26348681bb49c032d4c399e8331126c5dca020e0b3eEric Parisend:
264f2051b20fa10f66a27e7da394b6dede346064f50Dan Walsh    end_local_server();
26548681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    g_main_loop_unref (loop);
26648681bb49c032d4c399e8331126c5dca020e0b3eEric Paris    return 0;
26748681bb49c032d4c399e8331126c5dca020e0b3eEric Paris}
26848681bb49c032d4c399e8331126c5dca020e0b3eEric Paris
269