]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vt/fs.c
merge
[plan9front.git] / sys / src / cmd / vt / fs.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4
5 #include "cons.h"
6
7 #include <thread.h>
8 #include <fcall.h>
9 #include <9p.h>
10
11 extern Channel *hc[2];
12
13 static File *devcons, *devconsctl;
14
15 static Channel *readreq;
16 static Channel *flushreq;
17
18 static void
19 fsreader(void*)
20 {
21         Req *r, *fr;
22         char *s, *p;
23
24         r = nil;
25         s = p = nil;
26         for(;;){
27                 Alt a[] = {
28                         { flushreq, &fr, CHANRCV },
29                         { readreq, &r, r == nil ? CHANRCV : CHANNOP },
30                         { hc[0], &s, s == nil ? CHANRCV : CHANNOP },
31                         { nil, nil, s == nil || r == nil ? CHANEND : CHANNOBLK },
32                 };
33                 if(alt(a) == 0){
34                         if(fr->oldreq == r){
35                                 respond(r, "interrupted");
36                                 r = nil;
37                         }
38                         respond(fr, nil);
39                 }
40                 if(s == nil || r == nil)
41                         continue;
42                 if(p == nil)
43                         p = s;
44                 r->ofcall.count = 0;
45                 while(r->ifcall.count > r->ofcall.count){
46                         if(*p == 0)
47                                 break;
48                         r->ofcall.data[r->ofcall.count++] = *p++;
49                         if(*p == 0){
50                                 free(s);
51                                 if((p = s = nbrecvp(hc[0])) == nil)
52                                         break;
53                         }
54                 }
55                 respond(r, nil);
56                 r = nil;
57         }
58 }
59
60 static void
61 fsread(Req *r)
62 {
63         if(r->fid->file == devcons){
64                 sendp(readreq, r);
65                 return;
66         }
67         respond(r, "not implemented");
68 }
69
70 typedef struct Partutf Partutf;
71 struct Partutf
72 {
73         int     n;
74         char    s[UTFmax];
75 };
76
77 static Rune*
78 cvtc2r(char *b, int n, Partutf *u)
79 {
80         char *cp, *ep;
81         Rune *rp, *rb;
82
83         cp = b, ep = b + n;
84         rp = rb = emalloc9p(sizeof(Rune)*(n+2));
85
86         while(u->n > 0 && cp < ep){
87                 u->s[u->n++] = *cp++;
88                 if(fullrune(u->s, u->n)){
89                         chartorune(rp, u->s);
90                         if(*rp != 0)
91                                 rp++;
92                         u->n = 0;
93                         break;
94                 }
95         }
96         if(u->n == 0){
97                 while(cp < ep && fullrune(cp, ep - cp)){
98                         cp += chartorune(rp, cp);
99                         if(*rp != 0)
100                                 rp++;
101                 }
102                 n = ep - cp;
103                 if(n > 0){
104                         memmove(u->s, cp, n);
105                         u->n = n;
106                 }
107         }
108         if(rb == rp){
109                 free(rb);
110                 return nil;
111         }
112         *rp = 0;
113
114         return rb;
115 }
116
117 static void
118 fswrite(Req *r)
119 {
120         if(r->fid->file == devcons){
121                 Partutf *u;
122                 Rune *rp;
123
124                 if((u = r->fid->aux) == nil)
125                         u = r->fid->aux = emalloc9p(sizeof(*u));
126                 if((rp = cvtc2r((char*)r->ifcall.data, r->ifcall.count, u)) != nil)
127                         sendp(hc[1], rp);
128
129                 r->ofcall.count = r->ifcall.count;
130                 respond(r, nil);
131                 return;
132         }
133         if(r->fid->file == devconsctl){
134                 char *s = r->ifcall.data;
135                 int n = r->ifcall.count;
136
137                 if(n >= 5 && strncmp(s, "rawon", 5) == 0)
138                         cs->raw = 1;
139                 else if(n >= 6 && strncmp(s, "rawoff", 6) == 0)
140                         cs->raw = 0;
141                 else if(n >= 6 && strncmp(s, "holdon", 6) == 0)
142                         cs->hold = 1;
143                 else if(n >= 7 && strncmp(s, "holdoff", 7) == 0)
144                         cs->hold = 0;
145                 else if(n >= 7 && strncmp(s, "winchon", 7) == 0)
146                         cs->winch = 1;
147                 else if(n >= 8 && strncmp(s, "winchoff", 8) == 0)
148                         cs->winch = 0;
149
150                 r->ofcall.count = r->ifcall.count;
151                 respond(r, nil);
152                 return;
153         }
154
155         respond(r, "not implemented");
156 }
157
158 static void
159 fsflush(Req *r)
160 {
161         sendp(flushreq, r);
162 }
163
164 static void
165 fsdestroyfid(Fid *f)
166 {
167         if(f->file == devconsctl && f->omode >= 0){
168                 cs->raw = 0;
169                 cs->hold = 0;
170                 cs->winch = 0;
171         }
172         if(f->aux != nil){
173                 free(f->aux);
174                 f->aux = nil;
175         }
176 }
177
178 static void
179 fsstart(Srv*)
180 {
181         flushreq = chancreate(sizeof(Req*), 4);
182         readreq = chancreate(sizeof(Req*), 4);
183         proccreate(fsreader, nil, 16*1024);
184 }
185
186 static void
187 fsend(Srv*)
188 {
189         sendp(hc[1], nil);
190 }
191
192 Srv fs = {
193 .read=fsread,
194 .write=fswrite,
195 .flush=fsflush,
196 .destroyfid=fsdestroyfid,
197 .start=fsstart,
198 .end=fsend,
199 };
200
201 void
202 mountcons(void)
203 {
204         fs.tree = alloctree("vt", "vt", DMDIR|0555, nil);
205         devcons = createfile(fs.tree->root, "cons", "vt", 0666, nil);
206         if(devcons == nil)
207                 sysfatal("creating /dev/cons: %r");
208         devconsctl = createfile(fs.tree->root, "consctl", "vt", 0666, nil);
209         if(devconsctl == nil)
210                 sysfatal("creating /dev/consctl: %r");
211         threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
212 }