shithub: svc

Download patch

ref: ab79325966de7ae86d5ed5f470930f103e252e6a
parent: d47a99e0e2c8268d0d15d2748643387ed1c967a2
author: Michael Misch <michaelmisch1985@gmail.com>
date: Sun Feb 8 03:13:33 EST 2026

Update so feed and the main ctl work about the same

--- a/TODO
+++ b/TODO
@@ -9,12 +9,6 @@
 exec /bin/exportfs -r /mnt/oftc
 ```
 
-## Client
-
-- Add in command to toggle markup
-- Reads on feed do not close cleanly when buffers change
-- Make sure reads block so we can just cat /path/to/feed
-
 ## Notifications:
 
 - Create and update, clear when read
--- a/client.c
+++ b/client.c
@@ -237,34 +237,35 @@
 	case Qfeed:
 		// Catch EOF
 		if(f->cl->fd < 0 || !f->cl->current){
-			r->ofcall.count = 0;
-			r->ofcall.data[0] = 0;
-			respond(r, nil);
+			respond(r, "no feed");
 			return;
 		}
 		srvrelease(fs);
 		b = f->cl->current;
 Again:
-		// Check if we have a tag here, abort early if so.
-		if(b->tag != flushtag){
-			memset(buf, 0, sizeof(buf));
-			n = pread(f->cl->fd, buf, sizeof(buf), r->ifcall.offset);
-			if(n > 0){
-				// cut off the EOF
-			 	buf[n] = 0;
-				readstr(r, buf);
-			} else {
-				qlock(&b->l);
-				b->unread = 0;
-				rsleep(&b->rz);
-				qunlock(&b->l);
-				goto Again;
-			}
-		} else
+		if(b->tag == flushtag){
 			flushtag = -1;
-		srvacquire(fs);
-		respond(r, nil);
-		return;
+			r->ofcall.count = 0;
+			srvacquire(fs);
+			respond(r, nil);
+			return;
+		}
+		n = pread(f->cl->fd, r->ofcall.data, r->ifcall.count,	r->ifcall.offset);
+		if(n > 0){
+			r->ofcall.count = n;
+			srvacquire(fs);
+			respond(r, nil);
+			return;
+		} else if(n < 0) {
+			srvacquire(fs);
+			responderror(r);
+			return;
+		}
+		qlock(&b->l);
+		b->unread = 0;
+		rsleep(&b->rz);
+		qunlock(&b->l);
+		goto Again;
 	case Qtitle:
 		if(f->cl->current && f->cl->current->title){
 			b = f->cl->current;
--- a/service.c
+++ b/service.c
@@ -11,6 +11,7 @@
 enum {
 	Qsroot,
 		Qclone,
+		Qlist,
 		Qservices,
 			Qctl,
 	Qmax,
@@ -19,6 +20,7 @@
 static char *svctab[] = {
 	"/",
 		"clone",
+		"list",
 		nil,
 			"ctl",
 	nil,
@@ -62,6 +64,7 @@
 static Srv *fs;
 Service service[64];
 int nservice;
+Lock svclock;
 
 static Service*
 newservice(void)
@@ -69,6 +72,7 @@
 	Service *svc;
 	int i;
 
+	lock(&svclock);
 	for(i = 0; i < nservice; i++)
 		if(service[i].ref == 0)
 			break;
@@ -84,11 +88,29 @@
 	svc->cmds = chancreate(sizeof(Cmd*), 8);
 	svc->base = bufferCreate(svc->cmds, svc->input);
 	svc->isInitialized = 0;
-	
+	unlock(&svclock);
 	return svc;
 }
 
 static void
+rmservice(Service *s)
+{
+	int i, found = 0;
+
+	lock(&svclock);
+	for(i = 0; i < nservice; i++){
+		if(service[i].name == s->name)
+			found++;
+		/* Shift  back */
+		if(found && i < nservice)
+			service[i] = service[i+1];
+	}
+	if(found)
+		nservice--;
+	unlock(&svclock);
+}
+
+static void
 freeservice(Service *s)
 {
 	if(s == nil)
@@ -141,7 +163,9 @@
 		break;
 	case Qctl:
 	case Qclone:
+	case Qlist:
 		d->mode = 0666;
+		/* Fallthrough */
 	default:
 		d->name = estrdup(svctab[level]);
 	}
@@ -188,6 +212,7 @@
 	if(strcmp(name, "..")==0){
 		switch(f->level){
 		case Qsroot:
+		case Qlist:
 			break;
 		case Qservices:
 			f->level = Qsroot;
@@ -291,9 +316,9 @@
 {
 
 	Cmd *cmd;
-
 	char buf[CmdSize];
 	Svcfid *f;
+	int i, n;
 
 	f = r->fid->aux;
 	memset(buf, 0, CmdSize);
@@ -307,24 +332,33 @@
 		dirread9p(r, servicegen, nil);
 		respond(r, nil);
 		return;
+	case Qlist:
+		n = 0;
+		for(i = 0; i < nservice; i++)
+			n += snprint(buf+n, sizeof(buf) - n, "%s\n", service[i].name);
+		readstr(r, buf);
+		respond(r, nil);
+		return;
 	case Qctl:
-		// NOTE: This stays here so we always get a good ID back on the client from the initial read
+		/* NOTE: This stays here so we always get a good ID back on the client from the initial read */
 		if(!f->svc->isInitialized) {
 			snprint(buf, sizeof(buf), "%d\n", SERVICEID(f->svc));
 			readstr(r, buf);
 			respond(r, nil);
+			return;
 		} else {
-			// Wait for any data/command from the client
+			/* Wait for any data/command from the client */
 			srvrelease(fs);
-		 	cmd = recvp(f->svc->cmds);
+			while((cmd = recvp(f->svc->cmds)) == nil)
+				;
 			srvacquire(fs);
-			if(cmd){
-				snprint(buf, sizeof(buf), "%C", cmd);
-				readstr(r, buf);
+			if(cmd->type != FlushCmd){
+				n = snprint(r->ofcall.data, r->ifcall.count, "%C", cmd);
+				r->ofcall.count = n;
 			}
 			respond(r, nil);
+			return;
 		}
-		return;
 
 	}
 	respond(r, "not implemented");
@@ -359,7 +393,7 @@
 				close(create(path, OREAD, DMDIR | 0755));
 				clfs.aux = f->svc->base;
 				f->svc->childpid = threadpostsrv(&clfs, strdup(cmd.data));
-				if(f->svc->childpid >= 0){
+				if(f->svc->childpid > 0){
 					s = emalloc(10+strlen(cmd.data));
 					strcpy(s, "/srv/");
 					strcat(s, cmd.data);
@@ -366,6 +400,7 @@
 					d = dirstat(s);
 					d->mode = 0666;
 					if(dirwstat(s, d) < 0){
+						rmservice(f->svc);
 						respond(r, "unable to set mode");
 						goto Out;
 					}
@@ -373,8 +408,10 @@
 					f->svc->isInitialized++;
 					r->fid->aux = f;
 					respond(r, nil);
-				} else 
+				} else {
+					rmservice(f->svc);
 					respond(r, "Unable to post to srv");
+				}
 				goto Out;
 			}
 			// Ignore, something weird going on.
--