summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--catsit.88
-rw-r--r--catsit.sh2
-rw-r--r--daemon.c11
-rw-r--r--daemon.h1
-rw-r--r--service.c8
5 files changed, 24 insertions, 6 deletions
diff --git a/catsit.8 b/catsit.8
index d901359..ae4de38 100644
--- a/catsit.8
+++ b/catsit.8
@@ -1,4 +1,4 @@
-.Dd August 15, 2020
+.Dd August 16, 2020
 .Dt CATSIT 8
 .Os
 .
@@ -9,7 +9,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl c Ar control
-.Cm start|stop|restart|status Ns | Ns Ar signal
+.Cm start|stop|restart|status|drop Ns | Ns Ar signal
 .Ar service ...
 .
 .Sh DESCRIPTION
@@ -55,6 +55,10 @@ then stopped services will be started.
 .It Cm status
 Log the current status of any matching services.
 .
+.It Cm drop
+Drop any matching stopped services
+from the services list.
+.
 .It Ar signal
 Send the named signal
 to the processes of any matching started services.
diff --git a/catsit.sh b/catsit.sh
index 0e2a7e1..6433109 100644
--- a/catsit.sh
+++ b/catsit.sh
@@ -27,7 +27,7 @@ fi
 [ $# -lt 2 ] && die 'service name required'
 
 action=$(echo "${1}" | tr 'A-Z' 'a-z')
-for valid in start stop restart status $(kill -l | tr 'A-Z' 'a-z'); do
+for valid in start stop restart status drop $(kill -l | tr 'A-Z' 'a-z'); do
 	[ "${action}" = "${valid}" ] && break
 done
 if [ "${action}" != "${valid}" ]; then
diff --git a/daemon.c b/daemon.c
index 0e15c12..969675f 100644
--- a/daemon.c
+++ b/daemon.c
@@ -126,6 +126,7 @@ static void parseControl(char *command) {
 		return;
 	}
 
+	bool drop = false;
 	Action *fn = NULL;
 	int signal = 0;
 	if (!strcmp(action, "start")) {
@@ -136,6 +137,8 @@ static void parseControl(char *command) {
 		fn = serviceRestart;
 	} else if (!strcmp(action, "status")) {
 		fn = serviceStatus;
+	} else if (!strcmp(action, "drop")) {
+		drop = true;
 	} else {
 		for (int i = 1; i < NSIG; ++i) {
 			if (strcasecmp(action, sys_signame[i])) continue;
@@ -143,7 +146,7 @@ static void parseControl(char *command) {
 			break;
 		}
 	}
-	if (!fn && !signal) {
+	if (!drop && !fn && !signal) {
 		syslog(LOG_NOTICE, "unknown action or signal %s", action);
 		return;
 	}
@@ -151,10 +154,12 @@ static void parseControl(char *command) {
 	while (command) {
 		bool found = false;
 		char *pattern = strsep(&command, WS);
-		for (size_t i = 0; i < services.len; ++i) {
+		for (size_t i = services.len - 1; i < services.len; --i) {
 			struct Service *service = &services.ptr[i];
 			if (fnmatch(pattern, service->name, 0)) continue;
-			if (signal) {
+			if (drop) {
+				serviceDrop(i);
+			} else if (signal) {
 				serviceSignal(service, signal);
 			} else {
 				fn(service);
diff --git a/daemon.h b/daemon.h
index 0398db9..b397f8e 100644
--- a/daemon.h
+++ b/daemon.h
@@ -130,6 +130,7 @@ extern struct Services {
 } services;
 
 int serviceAdd(const char *name, const char *command);
+void serviceDrop(size_t index);
 void serviceStatus(struct Service *service);
 void serviceStart(struct Service *service);
 void serviceStop(struct Service *service);
diff --git a/service.c b/service.c
index 78890b8..9a3b157 100644
--- a/service.c
+++ b/service.c
@@ -119,6 +119,14 @@ err:
 	return -1;
 }
 
+void serviceDrop(size_t index) {
+	struct Service *service = &services.ptr[index];
+	if (service->state != Stop) return;
+	syslog(LOG_NOTICE, "%s[] dropped", service->name);
+	serviceFree(service);
+	services.ptr[index] = services.ptr[--services.len];
+}
+
 void serviceStatus(struct Service *service) {
 	if (service->state == Stop && service->intent == Stop) {
 		syslog(LOG_NOTICE, "%s[] is stopped", service->name);