19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <fcall.h>
49a747e4fSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include <9p.h>
69a747e4fSDavid du Colombier #include "dat.h"
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier Channel *fschan;
99a747e4fSDavid du Colombier Channel *writechan;
109a747e4fSDavid du Colombier
119a747e4fSDavid du Colombier static File *devcons, *devnew;
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier static void
fsread(Req * r)149a747e4fSDavid du Colombier fsread(Req *r)
159a747e4fSDavid du Colombier {
169a747e4fSDavid du Colombier Fsevent e;
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier if(r->fid->file == devnew){
199a747e4fSDavid du Colombier if(r->fid->aux==nil){
209a747e4fSDavid du Colombier respond(r, "phase error");
219a747e4fSDavid du Colombier return;
229a747e4fSDavid du Colombier }
239a747e4fSDavid du Colombier readstr(r, r->fid->aux);
249a747e4fSDavid du Colombier respond(r, nil);
259a747e4fSDavid du Colombier return;
269a747e4fSDavid du Colombier }
279a747e4fSDavid du Colombier
289a747e4fSDavid du Colombier assert(r->fid->file == devcons);
299a747e4fSDavid du Colombier e.type = 'r';
309a747e4fSDavid du Colombier e.r = r;
319a747e4fSDavid du Colombier send(fschan, &e);
329a747e4fSDavid du Colombier }
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier static void
fsflush(Req * r)359a747e4fSDavid du Colombier fsflush(Req *r)
369a747e4fSDavid du Colombier {
379a747e4fSDavid du Colombier Fsevent e;
389a747e4fSDavid du Colombier
399a747e4fSDavid du Colombier e.type = 'f';
409a747e4fSDavid du Colombier e.r = r;
419a747e4fSDavid du Colombier send(fschan, &e);
429a747e4fSDavid du Colombier }
439a747e4fSDavid du Colombier
449a747e4fSDavid du Colombier static void
fswrite(Req * r)459a747e4fSDavid du Colombier fswrite(Req *r)
469a747e4fSDavid du Colombier {
47*9bcb9353SDavid du Colombier static Event *e[4]; /* ours, not the one from event.h */
48*9bcb9353SDavid du Colombier static int n, partial;
499a747e4fSDavid du Colombier Event *ep;
508cd281c0SDavid du Colombier int i, j, ei, nb, wid, pid;
519a747e4fSDavid du Colombier Rune rune;
529a747e4fSDavid du Colombier char *s;
539a747e4fSDavid du Colombier char tmp[UTFmax], *t;
549a747e4fSDavid du Colombier
559a747e4fSDavid du Colombier if(r->fid->file == devnew){
569a747e4fSDavid du Colombier if(r->fid->aux){
579a747e4fSDavid du Colombier respond(r, "already created a window");
589a747e4fSDavid du Colombier return;
599a747e4fSDavid du Colombier }
609a747e4fSDavid du Colombier s = emalloc(r->ifcall.count+1);
619a747e4fSDavid du Colombier memmove(s, r->ifcall.data, r->ifcall.count);
629a747e4fSDavid du Colombier s[r->ifcall.count] = 0;
639a747e4fSDavid du Colombier pid = strtol(s, &t, 0);
649a747e4fSDavid du Colombier if(*t==' ')
659a747e4fSDavid du Colombier t++;
669a747e4fSDavid du Colombier i = newpipewin(pid, t);
679a747e4fSDavid du Colombier free(s);
689a747e4fSDavid du Colombier s = emalloc(32);
699a747e4fSDavid du Colombier sprint(s, "%lud", (ulong)i);
709a747e4fSDavid du Colombier r->fid->aux = s;
719a747e4fSDavid du Colombier r->ofcall.count = r->ifcall.count;
729a747e4fSDavid du Colombier respond(r, nil);
739a747e4fSDavid du Colombier return;
749a747e4fSDavid du Colombier }
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier assert(r->fid->file == devcons);
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier if(e[0] == nil){
799a747e4fSDavid du Colombier for(i=0; i<nelem(e); i++){
809a747e4fSDavid du Colombier e[i] = emalloc(sizeof(Event));
819a747e4fSDavid du Colombier e[i]->c1 = 'S';
829a747e4fSDavid du Colombier }
839a747e4fSDavid du Colombier }
849a747e4fSDavid du Colombier
859a747e4fSDavid du Colombier ep = e[n];
869a747e4fSDavid du Colombier n = (n+1)%nelem(e);
87*9bcb9353SDavid du Colombier /*
88*9bcb9353SDavid du Colombier * lib9p ensures that r->ifcall.count is <= srv->msize - IOHDRSZ,
89*9bcb9353SDavid du Colombier * where srv == &fs.
90*9bcb9353SDavid du Colombier */
91*9bcb9353SDavid du Colombier assert((int)r->ifcall.count >= 0);
929a747e4fSDavid du Colombier nb = r->ifcall.count;
93*9bcb9353SDavid du Colombier if (partial + nb >= sizeof ep->b)
94*9bcb9353SDavid du Colombier sysfatal("EVENTSIZE < MAXRPC; increase EVENTSIZE & recompile");
959a747e4fSDavid du Colombier memmove(ep->b+partial, r->ifcall.data, nb);
969a747e4fSDavid du Colombier nb += partial;
979a747e4fSDavid du Colombier ep->b[nb] = '\0';
989a747e4fSDavid du Colombier if(strlen(ep->b) < nb){ /* nulls in data */
999a747e4fSDavid du Colombier t = ep->b;
1009a747e4fSDavid du Colombier for(i=j=0; i<nb; i++)
1019a747e4fSDavid du Colombier if(ep->b[i] != '\0')
1029a747e4fSDavid du Colombier t[j++] = ep->b[i];
1039a747e4fSDavid du Colombier nb = j;
1049a747e4fSDavid du Colombier t[j] = '\0';
1059a747e4fSDavid du Colombier }
106*9bcb9353SDavid du Colombier ei = nb>EVENTSIZE? EVENTSIZE: nb;
1079a747e4fSDavid du Colombier /* process bytes into runes, transferring terminal partial runes into next buffer */
1088cd281c0SDavid du Colombier for(i=j=0; i<ei && fullrune(ep->b+i, ei-i); i+=wid,j++)
1099a747e4fSDavid du Colombier wid = chartorune(&rune, ep->b+i);
1109a747e4fSDavid du Colombier memmove(tmp, ep->b+i, nb-i);
111*9bcb9353SDavid du Colombier // partial = nb-i; /* redundant */
1129a747e4fSDavid du Colombier ep->nb = i;
1139a747e4fSDavid du Colombier ep->nr = j;
1149a747e4fSDavid du Colombier ep->b[i] = '\0';
1159a747e4fSDavid du Colombier if(i != 0){
1169a747e4fSDavid du Colombier sendp(win->cevent, ep);
1179a747e4fSDavid du Colombier recvp(writechan);
1189a747e4fSDavid du Colombier }
1199a747e4fSDavid du Colombier partial = nb-i;
1209a747e4fSDavid du Colombier memmove(e[n]->b, tmp, partial);
1219a747e4fSDavid du Colombier r->ofcall.count = r->ifcall.count;
1229a747e4fSDavid du Colombier respond(r, nil);
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier void
fsdestroyfid(Fid * fid)1269a747e4fSDavid du Colombier fsdestroyfid(Fid *fid)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier if(fid->aux)
1299a747e4fSDavid du Colombier free(fid->aux);
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier Srv fs = {
1339a747e4fSDavid du Colombier .read= fsread,
1349a747e4fSDavid du Colombier .write= fswrite,
1359a747e4fSDavid du Colombier .flush= fsflush,
1369a747e4fSDavid du Colombier .destroyfid= fsdestroyfid,
1376b6b9ac8SDavid du Colombier .leavefdsopen= 1,
1389a747e4fSDavid du Colombier };
1399a747e4fSDavid du Colombier
1409a747e4fSDavid du Colombier void
mountcons(void)1419a747e4fSDavid du Colombier mountcons(void)
1429a747e4fSDavid du Colombier {
1439a747e4fSDavid du Colombier fschan = chancreate(sizeof(Fsevent), 0);
1449a747e4fSDavid du Colombier writechan = chancreate(sizeof(void*), 0);
1459a747e4fSDavid du Colombier fs.tree = alloctree("win", "win", DMDIR|0555, nil);
1469a747e4fSDavid du Colombier devcons = createfile(fs.tree->root, "cons", "win", 0666, nil);
1479a747e4fSDavid du Colombier if(devcons == nil)
1489a747e4fSDavid du Colombier sysfatal("creating /dev/cons: %r");
1499a747e4fSDavid du Colombier devnew = createfile(fs.tree->root, "wnew", "win", 0666, nil);
1509a747e4fSDavid du Colombier if(devnew == nil)
1519a747e4fSDavid du Colombier sysfatal("creating /dev/wnew: %r");
1529a747e4fSDavid du Colombier threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
1539a747e4fSDavid du Colombier }
154