about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2023-12-23 19:11:07 +0100
committerLeah Neukirchen <leah@vuxu.org>2023-12-23 19:11:07 +0100
commit5230dd78c4882e4b9d17aab9cc026718c89b7721 (patch)
tree2585b91588909ac22619eabcac34239b4da0c5b9
parente12a7cdb754e5564f931fa440b2e311b4aa939ce (diff)
downloadnitro-5230dd78c4882e4b9d17aab9cc026718c89b7721.tar.gz
nitro-5230dd78c4882e4b9d17aab9cc026718c89b7721.tar.xz
nitro-5230dd78c4882e4b9d17aab9cc026718c89b7721.zip
add a notification mechanism
To notify, send a datagram message to all unix sockets in a
notification directory that start with the service name (or ALL)
followed by a comma.  (Works a bit like s6-ftrig but has constant
memory and fd usage.)
-rw-r--r--nitro.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/nitro.c b/nitro.c
index 809c18f..bf14420 100644
--- a/nitro.c
+++ b/nitro.c
@@ -92,6 +92,8 @@ int selfpipe[2];
 int globallog[2];
 int globaloutfd = 2;
 DIR *cwd;
+DIR *notifydir;
+char notifypath[256];
 char logbuf[4096];
 char *logbufend = logbuf;
 
@@ -134,6 +136,7 @@ stat_slash(const char *dir, const char *name, struct stat *st)
 }
 
 void process_step(int i, enum process_events ev);
+void notify(int);
 
 void
 proc_launch(int i)
@@ -357,6 +360,8 @@ proc_cleanup(int i)
 		if (services[i].logpipe[1] > 0)
 			close(services[i].logpipe[1]);
 	}
+
+	notify(i);
 }
 
 void
@@ -527,6 +532,7 @@ process_step(int i, enum process_events ev)
 		case PROC_FATAL:
 			proc_cleanup(i);
 			services[i].state = PROC_FATAL;
+			notify(i);
 			break;
 
 		case PROC_SETUP:               /* can't happen */
@@ -548,6 +554,7 @@ process_step(int i, enum process_events ev)
 
 		case PROC_STARTING:
 			services[i].state = PROC_UP;
+			notify(i);
 			break;
 
 		case PROC_RESTART:
@@ -736,6 +743,12 @@ open_control_socket() {
 		dir[last_slash - path] = 0;
 		mkdir(dir, 0700);
 		// ignore errors
+
+		strcpy(notifypath, dir);
+		strcat(notifypath, "/notify/");
+		mkdir(notifypath, 0700);
+		// ignore errors
+		notifydir = opendir(notifypath);
 	}
 
 	struct sockaddr_un addr = { 0 };
@@ -759,6 +772,46 @@ open_control_socket() {
 	}
 }
 
+void
+notify(int i)
+{
+	printf("NOTIFY\n");
+
+	if (!notifydir)
+		return;
+
+	char notifybuf[128];
+	sprintf(notifybuf, "%c%s\n", 64 + services[i].state,
+	    services[i].name);
+
+	struct dirent *ent;
+	rewinddir(notifydir);
+	while ((ent = readdir(notifydir))) {
+		char *name = ent->d_name;
+
+		if (name[0] == '.')
+			continue;
+
+		printf("notify check %s\n", name);
+
+		if ((strncmp(name, services[i].name, strlen(services[i].name)) == 0 &&
+		    name[strlen(services[i].name)] == ',') ||
+		    (strncmp("ALL,", name, 4) == 0)) {
+
+			struct sockaddr_un addr = { 0 };
+			addr.sun_family = AF_UNIX;
+			strncpy(addr.sun_path, notifypath, sizeof addr.sun_path - 1);
+			strcat(addr.sun_path, name);
+
+			printf("notify to %s\n", addr.sun_path);
+
+			sendto(controlsock, notifybuf, strlen(notifybuf),
+			    MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof addr);
+		}
+	}
+
+}
+
 int
 charsig(char c)
 {