summaryrefslogtreecommitdiff
path: root/acme/bin/source/win/_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'acme/bin/source/win/_fs.c')
-rw-r--r--acme/bin/source/win/_fs.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/acme/bin/source/win/_fs.c b/acme/bin/source/win/_fs.c
new file mode 100644
index 000000000..6791a21f2
--- /dev/null
+++ b/acme/bin/source/win/_fs.c
@@ -0,0 +1,146 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "dat.h"
+
+Channel *fschan;
+Channel *writechan;
+
+static File *devcons, *devnew;
+
+static void
+fsread(Req *r)
+{
+ Fsevent e;
+
+ if(r->fid->file == devnew){
+ if(r->fid->aux==nil){
+ respond(r, "phase error");
+ return;
+ }
+ readstr(r, r->fid->aux);
+ respond(r, nil);
+ return;
+ }
+
+ assert(r->fid->file == devcons);
+ e.type = 'r';
+ e.r = r;
+ send(fschan, &e);
+}
+
+static void
+fsflush(Req *r)
+{
+ Fsevent e;
+
+ e.type = 'f';
+ e.r = r;
+ send(fschan, &e);
+}
+
+static void
+fswrite(Req *r)
+{
+ static Event *e[4];
+ Event *ep;
+ int i, j, nb, wid, pid;
+ Rune rune;
+ char *s;
+ char tmp[UTFmax], *t;
+ static int n, partial;
+
+ if(r->fid->file == devnew){
+ if(r->fid->aux){
+ respond(r, "already created a window");
+ return;
+ }
+ s = emalloc(r->ifcall.count+1);
+ memmove(s, r->ifcall.data, r->ifcall.count);
+ s[r->ifcall.count] = 0;
+ pid = strtol(s, &t, 0);
+ if(*t==' ')
+ t++;
+ i = newpipewin(pid, t);
+ free(s);
+ s = emalloc(32);
+ sprint(s, "%lud", (ulong)i);
+ r->fid->aux = s;
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ return;
+ }
+
+ assert(r->fid->file == devcons);
+
+ if(e[0] == nil){
+ for(i=0; i<nelem(e); i++){
+ e[i] = emalloc(sizeof(Event));
+ e[i]->c1 = 'S';
+ }
+ }
+
+ ep = e[n];
+ n = (n+1)%nelem(e);
+ assert(r->ifcall.count <= 8192); /* is this guaranteed by lib9p? */
+ nb = r->ifcall.count;
+ memmove(ep->b+partial, r->ifcall.data, nb);
+ nb += partial;
+ ep->b[nb] = '\0';
+ if(strlen(ep->b) < nb){ /* nulls in data */
+ t = ep->b;
+ for(i=j=0; i<nb; i++)
+ if(ep->b[i] != '\0')
+ t[j++] = ep->b[i];
+ nb = j;
+ t[j] = '\0';
+ }
+ /* process bytes into runes, transferring terminal partial runes into next buffer */
+ for(i=j=0; i<nb && fullrune(ep->b+i, nb-i); i+=wid,j++)
+ wid = chartorune(&rune, ep->b+i);
+ memmove(tmp, ep->b+i, nb-i);
+ partial = nb-i;
+ ep->nb = i;
+ ep->nr = j;
+ ep->b[i] = '\0';
+ if(i != 0){
+ sendp(win->cevent, ep);
+ recvp(writechan);
+ }
+ partial = nb-i;
+ memmove(e[n]->b, tmp, partial);
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+}
+
+void
+fsdestroyfid(Fid *fid)
+{
+ if(fid->aux)
+ free(fid->aux);
+}
+
+Srv fs = {
+.read= fsread,
+.write= fswrite,
+.flush= fsflush,
+.destroyfid= fsdestroyfid,
+.leavefdsopen= 1,
+};
+
+void
+mountcons(void)
+{
+ fschan = chancreate(sizeof(Fsevent), 0);
+ writechan = chancreate(sizeof(void*), 0);
+ fs.tree = alloctree("win", "win", DMDIR|0555, nil);
+ devcons = createfile(fs.tree->root, "cons", "win", 0666, nil);
+ if(devcons == nil)
+ sysfatal("creating /dev/cons: %r");
+ devnew = createfile(fs.tree->root, "wnew", "win", 0666, nil);
+ if(devnew == nil)
+ sysfatal("creating /dev/wnew: %r");
+ threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
+}