1 #include <u.h>
2 #include <libc.h>
3 #include "cec.h"
4
5 typedef struct {
6 char type;
7 char pad[3];
8 Pkt p;
9 } Muxmsg;
10
11 typedef struct {
12 int fd;
13 int type;
14 int pid;
15 } Muxproc;
16
17 struct Mux {
18 Muxmsg m;
19 Muxproc p[2];
20 int pfd[2];
21 int inuse;
22 };
23
24 static Mux smux = {
25 .inuse = -1,
26 };
27
28 void
muxcec(int,int cfd)29 muxcec(int, int cfd)
30 {
31 Muxmsg m;
32 int l;
33
34 m.type = Fcec;
35 while((l = netget(&m.p, sizeof m.p)) > 0)
36 if(write(cfd, &m, l+4) != l+4)
37 break;
38 exits("");
39 }
40
41 void
muxkbd(int kfd,int cfd)42 muxkbd(int kfd, int cfd)
43 {
44 Muxmsg m;
45
46 m.type = Fkbd;
47 while((m.p.len = read(kfd, m.p.data, sizeof m.p.data)) > 0)
48 if(write(cfd, &m, m.p.len+22) != m.p.len+22)
49 break;
50 m.type = Ffatal;
51 write(cfd, &m, 4);
52 exits("");
53 }
54
55 int
muxproc(Mux * m,Muxproc * p,int fd,void (* f)(int,int),int type)56 muxproc(Mux *m, Muxproc *p, int fd, void (*f)(int, int), int type)
57 {
58 memset(p, 0, sizeof p);
59 p->type = -1;
60 switch(p->pid = rfork(RFPROC|RFFDG)){
61 case -1:
62 return -1;
63 case 0:
64 close(m->pfd[0]);
65 f(fd, m->pfd[1]);
66 default:
67 p->fd = fd;
68 p->type = type;
69 return p->pid;
70 }
71 }
72
73 void
muxfree(Mux * m)74 muxfree(Mux *m)
75 {
76 close(m->pfd[0]);
77 close(m->pfd[1]);
78 postnote(PNPROC, m->p[0].pid, "this note goes to 11");
79 postnote(PNPROC, m->p[1].pid, "this note goes to 11");
80 waitpid();
81 waitpid();
82 memset(m, 0, sizeof *m);
83 m->inuse = -1;
84 }
85
86 Mux*
mux(int fd[2])87 mux(int fd[2])
88 {
89 Mux *m;
90
91 if(smux.inuse != -1)
92 sysfatal("mux in use");
93 m = &smux;
94 m->inuse = 1;
95 if(pipe(m->pfd) == -1)
96 sysfatal("pipe: %r");
97 muxproc(m, m->p+0, fd[0], muxkbd, Fkbd);
98 muxproc(m, m->p+1, fd[1], muxcec, Fcec);
99 close(m->pfd[1]);
100 return m;
101 }
102
103 int
muxread(Mux * m,Pkt * p)104 muxread(Mux *m, Pkt *p)
105 {
106 if(read(m->pfd[0], &m->m, sizeof m->m) == -1)
107 return -1;
108 memcpy(p, &m->m.p, sizeof *p);
109 return m->m.type;
110 }
111