1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <thread.h>
5 #include <9p.h>
6 #include "dat.h"
7
8 Channel *fschan;
9 Channel *writechan;
10
11 static File *devcons, *devnew;
12
13 static void
fsread(Req * r)14 fsread(Req *r)
15 {
16 Fsevent e;
17
18 if(r->fid->file == devnew){
19 if(r->fid->aux==nil){
20 respond(r, "phase error");
21 return;
22 }
23 readstr(r, r->fid->aux);
24 respond(r, nil);
25 return;
26 }
27
28 assert(r->fid->file == devcons);
29 e.type = 'r';
30 e.r = r;
31 send(fschan, &e);
32 }
33
34 static void
fsflush(Req * r)35 fsflush(Req *r)
36 {
37 Fsevent e;
38
39 e.type = 'f';
40 e.r = r;
41 send(fschan, &e);
42 }
43
44 static void
fswrite(Req * r)45 fswrite(Req *r)
46 {
47 static Event *e[4];
48 Event *ep;
49 int i, j, ei, nb, wid, pid;
50 Rune rune;
51 char *s;
52 char tmp[UTFmax], *t;
53 static int n, partial;
54
55 if(r->fid->file == devnew){
56 if(r->fid->aux){
57 respond(r, "already created a window");
58 return;
59 }
60 s = emalloc(r->ifcall.count+1);
61 memmove(s, r->ifcall.data, r->ifcall.count);
62 s[r->ifcall.count] = 0;
63 pid = strtol(s, &t, 0);
64 if(*t==' ')
65 t++;
66 i = newpipewin(pid, t);
67 free(s);
68 s = emalloc(32);
69 sprint(s, "%lud", (ulong)i);
70 r->fid->aux = s;
71 r->ofcall.count = r->ifcall.count;
72 respond(r, nil);
73 return;
74 }
75
76 assert(r->fid->file == devcons);
77
78 if(e[0] == nil){
79 for(i=0; i<nelem(e); i++){
80 e[i] = emalloc(sizeof(Event));
81 e[i]->c1 = 'S';
82 }
83 }
84
85 ep = e[n];
86 n = (n+1)%nelem(e);
87 assert(r->ifcall.count <= 8192); /* is this guaranteed by lib9p? */
88 nb = r->ifcall.count;
89 memmove(ep->b+partial, r->ifcall.data, nb);
90 nb += partial;
91 ep->b[nb] = '\0';
92 if(strlen(ep->b) < nb){ /* nulls in data */
93 t = ep->b;
94 for(i=j=0; i<nb; i++)
95 if(ep->b[i] != '\0')
96 t[j++] = ep->b[i];
97 nb = j;
98 t[j] = '\0';
99 }
100 ei = nb>8192? 8192 : nb;
101 /* process bytes into runes, transferring terminal partial runes into next buffer */
102 for(i=j=0; i<ei && fullrune(ep->b+i, ei-i); i+=wid,j++)
103 wid = chartorune(&rune, ep->b+i);
104 memmove(tmp, ep->b+i, nb-i);
105 partial = nb-i;
106 ep->nb = i;
107 ep->nr = j;
108 ep->b[i] = '\0';
109 if(i != 0){
110 sendp(win->cevent, ep);
111 recvp(writechan);
112 }
113 partial = nb-i;
114 memmove(e[n]->b, tmp, partial);
115 r->ofcall.count = r->ifcall.count;
116 respond(r, nil);
117 }
118
119 void
fsdestroyfid(Fid * fid)120 fsdestroyfid(Fid *fid)
121 {
122 if(fid->aux)
123 free(fid->aux);
124 }
125
126 Srv fs = {
127 .read= fsread,
128 .write= fswrite,
129 .flush= fsflush,
130 .destroyfid= fsdestroyfid,
131 .leavefdsopen= 1,
132 };
133
134 void
mountcons(void)135 mountcons(void)
136 {
137 fschan = chancreate(sizeof(Fsevent), 0);
138 writechan = chancreate(sizeof(void*), 0);
139 fs.tree = alloctree("win", "win", DMDIR|0555, nil);
140 devcons = createfile(fs.tree->root, "cons", "win", 0666, nil);
141 if(devcons == nil)
142 sysfatal("creating /dev/cons: %r");
143 devnew = createfile(fs.tree->root, "wnew", "win", 0666, nil);
144 if(devnew == nil)
145 sysfatal("creating /dev/wnew: %r");
146 threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
147 }
148