1 /* esecannaserver --- pseudo canna server that wraps another IME.
2 * Copyright (C) 1999-2000 Yasuhiro Take
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <sys/un.h>
30 #include <netdb.h>
31 #include <errno.h>
32
33 #include "def.h"
34 #include "misc.h"
35
36 static struct sockaddr_un unaddr;
37 static struct sockaddr_in inaddr;
38 static int canna_unixfd, canna_inetfd;
39
40 extern client_t client[];
41
42 /*
43 * canna_socket_open_unix : unix �ɥᥤ��Υ����åȤ���������
44 * : �ե�����ǥ�������ץ����֤�
45 */
46
canna_socket_open_unix()47 static int canna_socket_open_unix()
48 {
49 int old_umask;
50 int fd;
51
52 old_umask = umask(0);
53
54 mkdir(CANNA_UNIX_DOMAIN_DIR, 0777);
55
56 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
57 m_msg("Cannot open unix domain socket.\n");
58 return -1;
59 }
60
61 unaddr.sun_family = AF_UNIX;
62 strcpy(unaddr.sun_path, CANNA_UNIX_DOMAIN_PATH);
63
64 if (bind(fd, (struct sockaddr *)(&unaddr), sizeof unaddr)) {
65 close(fd);
66 m_msg("Cannot bind.\n");
67 m_msg("Another cannaserver detected.\n");
68 m_msg("If you're sure cannaserver is not running,\n");
69 m_msg("remove /tmp/.iroha_unix/IROHA.\n");
70 return -1;
71 }
72
73 if (listen(fd, 5)) {
74 close(fd);
75 m_msg("Cannot listen.\n");
76 return -1;
77 }
78
79 umask(old_umask);
80
81 return fd;
82 }
83
84 /*
85 * canna_socket_open_inet : inet �ɥᥤ��Υ����åȤ���������
86 * : �ե�����ǥ�������ץ����֤�
87 */
88
canna_socket_open_inet()89 static int canna_socket_open_inet()
90 {
91 struct servent *s;
92 int one = 1, fd, i;
93
94 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
95 m_msg("Cannot open inet domain socket.\n");
96 return -1;
97 }
98
99 #ifdef SO_REUSEADDR
100 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&one),
101 sizeof (int));
102 #endif
103
104 s = getservbyname(CANNA_SERVICE_NAME, "tcp");
105
106 memset((char *)&inaddr, 0, sizeof inaddr);
107 inaddr.sin_family = AF_INET;
108 inaddr.sin_port = s ? s->s_port : htons(CANNA_DEFAULT_PORT);
109 inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
110
111 if ((i = bind(fd, (struct sockaddr *)(&inaddr), sizeof inaddr)) != 0) {
112 m_msg("Bind refused.\n");
113 return -1;
114 }
115
116 if (listen (fd, 5)) {
117 close(fd);
118 m_msg("Cannot listen.\n");
119 return -1;
120 }
121
122 return fd;
123 }
124
125 /*
126 * canna_socket_open : unix, inet �ɥᥤ��Υ����åȤ��������롣
127 */
128
canna_socket_open(int * ufd,int * ifd)129 int canna_socket_open(int *ufd, int *ifd)
130 {
131 if ((canna_unixfd = canna_socket_open_unix()) == -1)
132 m_msg("unix domain not created.\n");
133 if ((canna_inetfd = canna_socket_open_inet()) == -1)
134 m_msg("inet domain not created.\n");
135
136 if (canna_unixfd == -1 || canna_inetfd == -1)
137 return -1;
138
139 *ufd = canna_unixfd;
140 *ifd = canna_inetfd;
141
142 return 0;
143 }
144
canna_socket_close()145 int canna_socket_close()
146 {
147 close(canna_unixfd);
148 close(canna_inetfd);
149
150 unlink(CANNA_UNIX_DOMAIN_PATH);
151
152 return 0;
153 }
154
155 /*
156 * canna_socket_accept_new_connection : ��³��������
157 * fd = canna_unixfd or canna_inetfd
158 * : �ե�����ǥ�������ץ����֤�
159 */
160
canna_socket_accept_new_connection(int fd)161 static int canna_socket_accept_new_connection(int fd)
162 {
163 int i, newfd;
164 int localhost_inaddr, myhost_inaddr, *ip;
165 char buf[128], *host = NULL;
166 int size;
167 struct sockaddr_un addr_un;
168 struct sockaddr_in addr_in;
169 struct hostent *hp;
170
171
172 size = sizeof(struct sockaddr_un);
173
174 if ((newfd = accept(fd, (struct sockaddr *)(&addr_un), &size)) < 0) {
175 m_msg("Cannot open new socket. Connection refused.\n");
176 return -1;
177 }
178
179 if (addr_un.sun_family == AF_INET) {
180 memcpy(&addr_in, (struct sockaddr *)(&addr_un),sizeof(struct sockaddr_in));
181
182 if (gethostname(buf, 128) == 0) {
183 if ((hp = gethostbyname(buf)) != NULL) {
184 ip = (int *)(hp->h_addr_list[0]);
185 myhost_inaddr = *ip;
186 } else {
187 myhost_inaddr = 0;
188 }
189 } else {
190 myhost_inaddr = 0;
191 }
192
193 if ((hp = gethostbyname("localhost")) != NULL) {
194 ip = (int *)(hp->h_addr_list[0]);
195 localhost_inaddr = *ip;
196 } else {
197 localhost_inaddr = 0;
198 }
199
200 if (addr_in.sin_addr.s_addr != myhost_inaddr &&
201 addr_in.sin_addr.s_addr != localhost_inaddr) {
202 m_netaddr2ascii(addr_in.sin_addr.s_addr, buf);
203
204 m_msg("REFUSE THE CONNECTION REQUEST FROM %s.\n", buf);
205 close(newfd);
206 return -1;
207 } else {
208 m_netaddr2ascii(addr_in.sin_addr.s_addr, buf);
209
210 hp = gethostbyaddr((char *)&addr_in.sin_addr, sizeof(struct in_addr),
211 AF_INET);
212
213 if (hp && hp->h_name)
214 host = strdup(hp->h_name);
215 else
216 host = strdup(buf);
217 }
218 } else {
219 host = strdup("UNIX");
220 }
221
222 for (i = USER_CLIENT; i < MAX_CLIENT_NUM; i++) {
223 if (client[i].sockfd == -1) {
224 client[i].sockfd = newfd;
225 client[i].host = host;
226 client[i].user[0] = 0;
227
228 m_msg("New client #%d@%s accepted.\n", i, host);
229
230 return 0;
231 }
232 }
233
234 m_msg("Too many users. Connection from %s refused.\n", host);
235 close(newfd);
236
237 if (host != NULL)
238 free(host);
239
240 return -1;
241 }
242
243 /*
244 * canna_socket_check_connection : ��³��ͭ����Ĵ�٤�
245 */
246
canna_socket_check_connection()247 static int canna_socket_check_connection()
248 {
249 struct timeval tv;
250 fd_set set;
251 int i;
252
253 for (i = USER_CLIENT; i < MAX_CLIENT_NUM; i++) {
254 if (client[i].sockfd != -1) {
255 FD_ZERO(&set);
256 FD_SET(client[i].sockfd, &set);
257
258 tv.tv_sec = tv.tv_usec = 0;
259
260 if (select(client[i].sockfd + 1, &set, NULL, NULL, &tv) < 0)
261 client[i].need_terminate = TRUE; /* main.c �ǽ�λ�����Ƥ�餦 */
262 }
263 }
264
265 return 0;
266 }
267
canna_socket_wait_trigger()268 int canna_socket_wait_trigger()
269 {
270 fd_set set;
271 int i;
272 int maxfd = 0;
273
274 FD_ZERO(&set);
275
276 for (i = USER_CLIENT; i < MAX_CLIENT_NUM; i++)
277 if (client[i].sockfd != -1) {
278 FD_SET(client[i].sockfd, &set);
279 maxfd = client[i].sockfd > maxfd ? client[i].sockfd : maxfd;
280 }
281 if (canna_unixfd != -1) FD_SET(canna_unixfd, &set);
282 if (canna_inetfd != -1) FD_SET(canna_inetfd, &set);
283 if (canna_unixfd > maxfd) maxfd = canna_unixfd;
284 if (canna_inetfd > maxfd) maxfd = canna_inetfd;
285
286 if (select(maxfd + 1, &set, NULL, NULL, NULL) < 0) {
287 if (errno == EBADF)
288 canna_socket_check_connection();
289 return -1;
290 }
291
292 for (i = USER_CLIENT; i < MAX_CLIENT_NUM; i++)
293 if (client[i].sockfd != -1)
294 if (FD_ISSET(client[i].sockfd, &set))
295 client[i].data_received = 1;
296
297 if (canna_unixfd != -1 && FD_ISSET(canna_unixfd, &set))
298 canna_socket_accept_new_connection(canna_unixfd);
299
300 if (canna_inetfd != -1 && FD_ISSET(canna_inetfd, &set))
301 canna_socket_accept_new_connection(canna_inetfd);
302
303 return 0;
304 }
305