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