ref: 7f0728b7f446a77b8606ed3dffd48deb48697384
parent: 8cb7211a42d8811302968dd75cd14e1fc47a289c
author: cinap_lenrek <cinap_lenrek@felloff.net>
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