1/*	$NetBSD: ipc_method.c,v 1.5 2013/11/27 20:50:45 christos Exp $	*/
2/*-
3 * Copyright (c) 1996
4 *	Rob Zimmermann.  All rights reserved.
5 * Copyright (c) 1996
6 *	Keith Bostic.  All rights reserved.
7 *
8 * See the LICENSE file for redistribution information.
9 */
10
11#include "config.h"
12
13#include <sys/types.h>
14#include <sys/queue.h>
15#include <sys/stat.h>
16
17#include <bitstring.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#include <sys/uio.h>
26
27#include "../common/common.h"
28#include "ip.h"
29
30static int vi_send_ __P((IPVIWIN   *, int));
31static int vi_send_1 __P((IPVIWIN   *, int, u_int32_t  ));
32static int vi_send_12 __P((IPVIWIN *ipvi, int code, u_int32_t val1, u_int32_t val2));
33#if 0
34static int vi_send_ab1 __P((IPVIWIN *ipvi, int code,
35	    const char *str1, u_int32_t len1,
36	    const char *str2, u_int32_t len2, u_int32_t val));
37static int vi_send_a1 __P((IPVIWIN *ipvi, int code, const char *str, u_int32_t len,
38	   u_int32_t val));
39#endif
40static int vi_send_a __P((IPVIWIN *ipvi, int code, const char *str, u_int32_t len));
41
42#include "ipc_gen.c"
43
44static int vi_set_ops __P((IPVIWIN *, IPSIOPS *));
45static int vi_win_close __P((IPVIWIN *));
46
47static int vi_close __P((IPVI *));
48static int vi_new_window __P((IPVI *, IPVIWIN **, int));
49
50/*
51 * vi_create
52 *
53 * PUBLIC: int vi_create __P((IPVI **, u_int32_t));
54 */
55int
56vi_create(IPVI **ipvip, u_int32_t flags)
57{
58	IPVI	*ipvi;
59
60	MALLOC_GOTO(NULL, ipvi, IPVI*, sizeof(IPVI));
61	memset(ipvi, 0, sizeof(IPVI));
62
63	ipvi->flags = flags;
64
65	ipvi->run = vi_run;
66	ipvi->new_window = vi_new_window;
67	ipvi->close = vi_close;
68
69	*ipvip = ipvi;
70
71	return 0;
72
73alloc_err:
74	return 1;
75}
76
77static int
78vi_new_window (IPVI *ipvi, IPVIWIN **ipviwinp, int fd)
79{
80	IPVIWIN	*ipviwin;
81
82	MALLOC_GOTO(NULL, ipviwin, IPVIWIN*, sizeof(IPVIWIN));
83	memset(ipviwin, 0, sizeof(IPVIWIN));
84
85	if (0) {
86	ipviwin->ifd = ipvi->ifd;
87	ipviwin->ofd = ipvi->ofd;
88	} else {
89	int sockets[2];
90	struct msghdr   mh;
91	IPCMSGHDR	    ch;
92	char	    dummy;
93	struct iovec    iov;
94
95	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) == -1)
96		goto alloc_err;
97
98	memset(&mh, 0, sizeof(mh));
99	mh.msg_namelen = 0;
100	mh.msg_iovlen = 1;
101	mh.msg_iov = &iov;
102	mh.msg_controllen = sizeof(ch);
103	mh.msg_control = (void *)&ch;
104
105	iov.iov_len = 1;
106	iov.iov_base = &dummy;
107
108	ch.header.cmsg_level = SOL_SOCKET;
109	ch.header.cmsg_type = SCM_RIGHTS;
110	ch.header.cmsg_len = sizeof(ch);
111
112	*(int *)CMSG_DATA(&ch.header) = sockets[1];
113	if (sendmsg(ipvi->ofd, &mh, 0) == -1)
114		goto alloc_err;
115	dummy = (fd == -1) ? ' ' : 'F';
116	*(int *)CMSG_DATA(&ch.header) = sockets[1];
117	sendmsg(sockets[0], &mh, 0);
118	close(sockets[1]);
119
120	if (fd != -1) {
121		*(int *)CMSG_DATA(&ch.header) = fd;
122		if (sendmsg(sockets[0], &mh, 0) == -1)
123			goto alloc_err;
124		close(fd);
125	}
126
127	ipviwin->ifd = sockets[0];
128	ipviwin->ofd = sockets[0];
129	}
130
131#define IPVISET(func) \
132	ipviwin->func = vi_##func;
133
134	IPVISET(c_bol);
135	IPVISET(c_bottom);
136	IPVISET(c_del);
137	IPVISET(c_eol);
138	IPVISET(c_insert);
139	IPVISET(c_left);
140	IPVISET(c_right);
141	IPVISET(c_top);
142	IPVISET(c_settop);
143	IPVISET(resize);
144	IPVISET(string);
145	IPVISET(quit);
146	IPVISET(wq);
147
148	IPVISET(input);
149	/*
150	IPVISET(close);
151	*/
152	ipviwin->close = vi_win_close;
153	IPVISET(set_ops);
154
155	*ipviwinp = ipviwin;
156
157	return 0;
158
159alloc_err:
160	if (fd != -1)
161		close(fd);
162	return 1;
163}
164
165static int
166vi_set_ops(IPVIWIN *ipvi, IPSIOPS *ops)
167{
168	ipvi->si_ops = ops;
169	return 0;
170}
171
172static int  vi_close(IPVI *ipvi)
173{
174	memset(ipvi, 6, sizeof(IPVI));
175	free(ipvi);
176	return 0;
177}
178
179static int  vi_win_close(IPVIWIN *ipviwin)
180{
181	memset(ipviwin, 6, sizeof(IPVIWIN));
182	free(ipviwin);
183	return 0;
184}
185
186
187static int
188vi_send_(IPVIWIN *ipvi, int code)
189{
190	IP_BUF	ipb;
191
192	memset(&ipb, 0, sizeof(ipb));
193	ipb.code = code;
194	return vi_send(ipvi->ofd, NULL, &ipb);
195}
196
197static int
198vi_send_1(IPVIWIN *ipvi, int code, u_int32_t val)
199{
200	IP_BUF	ipb;
201
202	memset(&ipb, 0, sizeof(ipb));
203	ipb.code = code;
204	ipb.val1 = val;
205	return vi_send(ipvi->ofd, "1", &ipb);
206}
207
208static int
209vi_send_12(IPVIWIN *ipvi, int code, u_int32_t val1, u_int32_t val2)
210{
211	IP_BUF	ipb;
212
213	memset(&ipb, 0, sizeof(ipb));
214	ipb.val1 = val1;
215	ipb.val2 = val2;
216	ipb.code = code;
217	return vi_send(ipvi->ofd, "12", &ipb);
218}
219
220static int
221vi_send_a(IPVIWIN *ipvi, int code, const char *str, u_int32_t len)
222{
223	IP_BUF	ipb;
224
225	memset(&ipb, 0, sizeof(ipb));
226	ipb.str1 = str;
227	ipb.len1 = len;
228	ipb.code = code;
229	return vi_send(ipvi->ofd, "a", &ipb);
230}
231
232#if 0
233static int
234vi_send_a1(IPVIWIN *ipvi, int code, const char *str, u_int32_t len,
235	   u_int32_t val)
236{
237	IP_BUF	ipb;
238
239	memset(&ipb, 0, sizeof(ipb));
240	ipb.str1 = str;
241	ipb.len1 = len;
242	ipb.val1 = val;
243	ipb.code = code;
244	return vi_send(ipvi->ofd, "a1", &ipb);
245}
246
247static int
248vi_send_ab1(IPVIWIN *ipvi, int code, const char *str1, u_int32_t len1,
249	    const char *str2, u_int32_t len2, u_int32_t val)
250{
251	IP_BUF	ipb;
252
253	memset(&ipb, 0, sizeof(ipb));
254	ipb.str1 = str1;
255	ipb.len1 = len1;
256	ipb.str2 = str2;
257	ipb.len2 = len2;
258	ipb.val1 = val;
259	ipb.code = code;
260	return vi_send(ipvi->ofd, "ab1", &ipb);
261}
262#endif
263