xref: /plan9/sys/src/cmd/cec/mux.c (revision 68de9c9388a1b0174f2979e40f3c4361793bf05a)
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