Add mapper-wait-until-removed

This option will do the opposite of mapper wait
by blocking if a dbus object exists until that
object is removed.

Change-Id: Ia460b1ffdb912ba475b15ae5f8499a177e801dfd
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/libmapper/mapper.c b/libmapper/mapper.c
index 962b4e0..ad64d4a 100644
--- a/libmapper/mapper.c
+++ b/libmapper/mapper.c
@@ -35,6 +35,11 @@
 	"interface='org.freedesktop.DBus.ObjectManager',"
 	"member='InterfacesAdded'";
 
+static const char *async_wait_interfaces_removed_match =
+	"type='signal',"
+	"interface='org.freedesktop.DBus.ObjectManager',"
+	"member='InterfacesRemoved'";
+
 static const int mapper_busy_retries = 5;
 static const uint64_t mapper_busy_delay_interval_usec = 1000000;
 
@@ -51,6 +56,7 @@
 	int count;
 	int finished;
 	int r;
+	bool added;
 };
 
 struct async_wait_callback_data
@@ -157,8 +163,12 @@
 		goto exit;
 
 	r = sd_bus_message_get_errno(m);
-	if(r == ENOENT)
-		goto exit;
+	if(r == ENOENT) {
+		if (wait->added)
+			goto exit;
+		else
+			r = 0;
+	}
 
 	if(r == EBUSY && data->retry < mapper_busy_retries) {
 		r = sd_event_now(wait->loop,
@@ -296,7 +306,8 @@
 		char *objs[],
 		void (*callback)(int, void *),
 		void *userdata,
-		mapper_async_wait **w)
+		mapper_async_wait **w,
+		bool added)
 {
 	int r;
 	mapper_async_wait *wait = NULL;
@@ -313,6 +324,7 @@
 	wait->count = sarraylen(objs);
 	if(!wait->count)
 		return 0;
+	wait->added = added;
 
 	wait->objs = sarraydup(objs);
 	if(!wait->objs) {
@@ -327,26 +339,39 @@
 	}
 	memset(wait->status, 0, sizeof(*wait->status) * wait->count);
 
-	r = sd_bus_add_match(conn,
-			&wait->introspection_slot,
-			async_wait_introspection_match,
-			async_wait_match_introspection_complete,
-			wait);
-	if(r < 0) {
-		fprintf(stderr, "Error adding match rule: %s\n",
-				strerror(-r));
-		goto free_status;
-	}
+	if (wait->added) {
+		r = sd_bus_add_match(conn,
+				&wait->introspection_slot,
+				async_wait_introspection_match,
+				async_wait_match_introspection_complete,
+				wait);
+		if(r < 0) {
+			fprintf(stderr, "Error adding match rule: %s\n",
+					strerror(-r));
+			goto free_status;
+		}
 
-	r = sd_bus_add_match(conn,
-                        &wait->intf_slot,
-			async_wait_interfaces_added_match,
-                        async_wait_match_introspection_complete,
-                        wait);
-	if(r < 0) {
-		fprintf(stderr, "Error adding match rule: %s\n",
-				strerror(-r));
-		goto unref_name_slot;
+		r = sd_bus_add_match(conn,
+				&wait->intf_slot,
+				async_wait_interfaces_added_match,
+				async_wait_match_introspection_complete,
+				wait);
+		if(r < 0) {
+			fprintf(stderr, "Error adding match rule: %s\n",
+					strerror(-r));
+			goto unref_name_slot;
+		}
+	} else {
+		r = sd_bus_add_match(conn,
+				&wait->intf_slot,
+				async_wait_interfaces_removed_match,
+				async_wait_match_introspection_complete,
+				wait);
+		if(r < 0) {
+			fprintf(stderr, "Error adding match rule: %s\n",
+					strerror(-r));
+			goto unref_name_slot;
+		}
 	}
 
 	r = async_wait_get_objects(wait);