shithub: riscv

Download patch

ref: 7f0728b7f446a77b8606ed3dffd48deb48697384
parent: 8cb7211a42d8811302968dd75cd14e1fc47a289c
author: cinap_lenrek <[email protected]>
date: Wed Apr 22 23:17:25 EDT 2015

aux/listen: removing service script sholud kill listener (thanks mischief)

mischief spotted that the only way for listeners to go away was
truncating (but not removing) a service script. this is wrong and
not as described in the manpage.

this change makes removing (or truncating) a listen script stop
the listener.

scandir() first marks all current announces, then reads the service
directory adding announces which will clear the marks for the ones
already there or add a new unmarked one. finally, we shoot down and
remove all still marked announces.

--- a/sys/src/cmd/aux/listen.c
+++ b/sys/src/cmd/aux/listen.c
@@ -16,9 +16,10 @@
 struct Announce
 {
 	Announce	*next;
-	char	*a;
 	int	announced;
-	int	whined;
+	char	whined;
+	char	mark;
+	char	a[];
 };
 
 int	readstr(char*, char*, char*, int);
@@ -292,66 +293,33 @@
 	/* look for duplicate */
 	l = &announcements;
 	for(a = announcements; a; a = a->next){
-		if(strcmp(str, a->a) == 0)
+		if(strcmp(str, a->a) == 0){
+			a->mark = 0;
 			return;
+		}
 		l = &a->next;
 	}
 
 	/* accept it */
 	a = mallocz(sizeof(*a) + strlen(str) + 1, 1);
-	if(a == 0)
+	if(a == nil)
 		return;
-	a->a = ((char*)a)+sizeof(*a);
 	strcpy(a->a, str);
-	a->announced = 0;
 	*l = a;
 }
 
-/*
- *  delete a service for announcement list
- */
 void
-delannounce(char *str)
-{
-	Announce *a, **l;
-
-	/* look for service */
-	l = &announcements;
-	for(a = announcements; a; a = a->next){
-		if(strcmp(str, a->a) == 0)
-			break;
-		l = &a->next;
-	}
-	if (a == nil)
-		return;
-	*l = a->next;			/* drop from the list */
-	if (a->announced > 0)
-		postnote(PNPROC, a->announced, "die");
-	a->announced = 0;
-	free(a);
-}
-
-static int
-ignore(char *srvdir, char *name)
-{
-	int rv;
-	char *file = smprint("%s/%s", srvdir, name);
-	Dir *d = dirstat(file);
-
-	rv = !d || d->length <= 0;	/* ignore unless it's non-empty */
-	free(d);
-	free(file);
-	return rv;
-}
-
-void
 scandir(char *proto, char *protodir, char *dname)
 {
+	Announce *a, **l;
 	int fd, i, n, nlen;
 	char *nm;
 	char ds[128];
 	Dir *db;
 
+	for(a = announcements; a != nil; a = a->next)
+		a->mark = 1;
+
 	fd = open(dname, OREAD);
 	if(fd < 0)
 		return;
@@ -360,20 +328,31 @@
 	while((n=dirread(fd, &db)) > 0){
 		for(i=0; i<n; i++){
 			nm = db[i].name;
-			if(!(db[i].qid.type&QTDIR) &&
-			    strncmp(nm, proto, nlen) == 0) {
-				snprint(ds, sizeof ds, "%s!*!%s", protodir,
-					nm + nlen);
-				if (ignore(dname, nm))
-					delannounce(ds);
-				else
-					addannounce(ds);
-			}
+			if(db[i].qid.type&QTDIR)
+				continue;
+			if(db[i].length <= 0)
+				continue;
+			if(strncmp(nm, proto, nlen) != 0)
+				continue;
+			snprint(ds, sizeof ds, "%s!*!%s", protodir, nm + nlen);
+			addannounce(ds);
 		}
 		free(db);
 	}
 
 	close(fd);
+
+	l = &announcements;
+	while((a = *l) != nil){
+		if(a->mark){
+			*l = a->next;
+			if (a->announced > 0)
+				postnote(PNPROC, a->announced, "die");
+			free(a);
+			continue;
+		}
+		l = &a->next;
+	}
 }
 
 void