1 /*
2  * $Id: do_xjpdrct.c,v 1.2 2001/06/14 18:16:15 ura Exp $
3  */
4 
5 /*
6  * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
7  * This file is part of FreeWnn.
8  *
9  * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
10  * Copyright 1991, 1992 by Massachusetts Institute of Technology
11  *
12  * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with GNU Emacs; see the file COPYING.  If not, write to the
26  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  * Commentary:
29  *
30  * Change log:
31  *
32  * Last modified date: 8,Feb.1999
33  *
34  * Code:
35  *
36  */
37 
38 #if defined(XJPLIB) && defined(XJPLIB_DIRECT)
39 
40 #include <stdio.h>
41 #include <X11/Xlib.h>
42 #ifdef  X11R4
43 #define NEED_EVENTS     1
44 #include <X11/Xlibos.h>
45 #else /* X11R4 */
46 #include "Xlibnet.h"
47 
48 #ifndef X11R5
49 /* followings were included in Xlibnet.h, but none in X11R6 */
50 #include <netinet/in.h>
51 #include <sys/ioctl.h>
52 #include <netdb.h>
53 /* end */
54 #endif /* !X11R5 */
55 
56 #endif /* X11R4 */
57 #include <X11/Xos.h>
58 #if defined(TCPCONN) || defined(UNIXCONN)
59 #include <sys/socket.h>
60 #endif /* defined(TCPCONN) || defined(UNIXCONN) */
61 #ifdef  TCPCONN
62 #define XJP_PORT_IN    0x9494
63 #endif /* TCPCONN */
64 
65 #ifdef  UNIXCONN
66 #include <sys/un.h>
67 #ifndef XJP_UNIX_PATH
68 #define XJP_UNIX_PATH   "/tmp/xwnmo.V2"
69 #endif /* XJP_UNIX_PATH */
70 #endif /* UNIXCONN */
71 
72 #include "do_xjplib.h"
73 
74 #define XJP_UNIX_ACPT   3
75 #define XJP_INET_ACPT   4
76 
77 extern XIMCmblk accept_blk[];
78 extern XIMCmblk *cblk;
79 extern XIMCmblk *cur_cblk;
80 
81 extern int *all_socks;
82 extern int *ready_socks;
83 
84 extern int max_client;
85 extern int cur_sock;
86 
87 #define BINTSIZE        (sizeof(int)*8)
88 #define sock_set(array,pos)     (array[pos/BINTSIZE] |= (1<<(pos%BINTSIZE)))
89 #define sock_clr(array,pos)     (array[pos/BINTSIZE] &= ~(1<<(pos%BINTSIZE)))
90 #define sock_tst(array,pos)     (array[pos/BINTSIZE] & (1<<(pos%BINTSIZE)))
91 
92 extern XJpClientRec *xjp_clients;
93 extern XJpClientRec *xjp_cur_client;
94 extern XJpInputRec *xjp_inputs;
95 extern XJpInputRec *xjp_cur_input;
96 
97 static int need_write = 0;
98 
99 static int real_port = 0;
100 
101 int
XJp_get_xjp_port()102 XJp_get_xjp_port ()
103 {
104   return (real_port);
105 }
106 
107 static void
xjp_init_net_area()108 xjp_init_net_area ()
109 {
110 #ifdef  UNIXCONN
111   accept_blk[XJP_UNIX_ACPT].sd = -1;
112 #endif /* UNIXCONN */
113 #ifdef  TCPCONN
114   accept_blk[XJP_INET_ACPT].sd = -1;
115 #endif /* TCPCONN */
116 }
117 
118 #ifdef UNIXCONN
119 static int
xjp_init_net_un()120 xjp_init_net_un ()
121 {
122   int so;
123   struct sockaddr_un saddr_un;
124   extern int unlink (), socket (), bind (), shutdown (), listen ();
125 
126   unlink (XJP_UNIX_PATH);
127   saddr_un.sun_family = AF_UNIX;
128   strcpy (saddr_un.sun_path, XJP_UNIX_PATH);
129 
130   if ((so = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
131     {
132       return (-1);
133     }
134   if (bind (so, (struct sockaddr *) &saddr_un, strlen (saddr_un.sun_path) + 2) < 0)
135     {
136       shutdown (so, 2);
137       return (-1);
138     }
139   if (listen (so, 5) < 0)
140     {
141       shutdown (so, 2);
142       return (-1);
143     }
144   accept_blk[XJP_UNIX_ACPT].sd = so;
145   sock_set (all_socks, so);
146   return (0);
147 }
148 #endif /* UNIXCONN */
149 
150 #ifdef TCPCONN
151 static int
xjp_init_net_in()152 xjp_init_net_in ()
153 {
154   int so;
155   struct servent *sp;
156   struct sockaddr_in saddr_in;
157   unsigned short port;
158 #ifndef SOLARIS
159   int on = 1;
160 #else /* SOLARIS */
161   int on = 0;
162 #endif /* SOLARIS */
163   int i, ok = 0;
164   extern int setsockopt ();
165 
166   if ((sp = getservbyname ("xwnmo", "tcp")) == NULL)
167     {
168       real_port = port = XJP_PORT_IN;
169     }
170   else
171     {
172       real_port = port = ntohs (sp->s_port);
173     }
174   saddr_in.sin_family = AF_INET;
175   saddr_in.sin_port = htons (port);
176   saddr_in.sin_addr.s_addr = htonl (INADDR_ANY);
177 
178   for (i = 0; i < MAX_PORT_NUMBER; i++)
179     {
180       if ((so = socket (AF_INET, SOCK_STREAM, 0)) < 0)
181         {
182           return (-1);
183         }
184       setsockopt (so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (int));
185       if (bind (so, (struct sockaddr *) &saddr_in, sizeof (struct sockaddr_in)) == 0)
186         {
187           ok = 1;
188           break;
189         }
190       shutdown (so, 2);
191       if (port == real_port)
192         port += 0x10;
193       else
194         port += 1;
195       saddr_in.sin_port = htons (port);
196     }
197   if (ok == 0)
198     {
199       return (-1);
200     }
201   real_port = port;
202   if (listen (so, 5) < 0)
203     {
204       shutdown (so, 2);
205       return (-1);
206     }
207   accept_blk[XJP_INET_ACPT].sd = so;
208   sock_set (all_socks, so);
209   return (0);
210 }
211 #endif /* TCPCONN */
212 
213 void
XJp_init_net()214 XJp_init_net ()
215 {
216   xjp_init_net_area ();
217 #ifdef  UNIXCONN
218   if (xjp_init_net_un () < 0)
219     {
220       print_out ("Could not open UNIX domain socket for XJp protocol.");
221     }
222 #endif /* UNIXCONN */
223 #ifdef  TCPCONN
224   if (xjp_init_net_in () < 0)
225     {
226       print_out ("Could not open INET domain socket for XJp protocol.");
227     }
228 #endif /* TCPCONN */
229 }
230 
231 void
XJp_close_net()232 XJp_close_net ()
233 {
234   int trueFlag = 1;
235 #ifdef  UNIXCONN
236   struct sockaddr_un addr_un;
237 #endif /* UNIXCONN */
238 #ifdef  TCPCONN
239   struct sockaddr_in addr_in;
240 #endif /* TCPCONN */
241 #if defined(UNIXCONN) || defined(TCPCONN)
242   int addrlen;
243   extern int accept (), close ();
244 #endif
245 
246 #ifdef  UNIXCONN
247   if (accept_blk[XJP_UNIX_ACPT].sd != -1)
248     {
249 #ifndef SOLARIS
250 #if defined(FIONBIO)
251       ioctl (accept_blk[XJP_UNIX_ACPT].sd, FIONBIO, &trueFlag);
252 #endif
253 #else /* !SOLARIS */
254       fcntl (accept_blk[XJP_UNIX_ACPT].sd, F_SETFL, F_UNLCK);
255 #endif /* !SOLARIS */
256       for (;;)
257         {
258           addrlen = sizeof (addr_un);
259           if (accept (accept_blk[XJP_UNIX_ACPT].sd, (struct sockaddr *) &addr_un, &addrlen) < 0)
260             break;
261         }
262       shutdown (accept_blk[XJP_UNIX_ACPT].sd, 2);
263       close (accept_blk[XJP_UNIX_ACPT].sd);
264     }
265 #endif /* UNIXCONN */
266 
267 #ifdef  TCPCONN
268   if (accept_blk[XJP_INET_ACPT].sd != -1)
269     {
270 #ifndef SOLARIS
271 #if defined(FIONBIO)
272       ioctl (accept_blk[XJP_INET_ACPT].sd, FIONBIO, &trueFlag);
273 #endif
274 #else /* !SOLARIS */
275       fcntl (accept_blk[XJP_INET_ACPT].sd, F_SETFL, F_UNLCK);
276 #endif /* !SOLARIS */
277       for (;;)
278         {
279           addrlen = sizeof (addr_in);
280           if (accept (accept_blk[XJP_INET_ACPT].sd, (struct sockaddr *) &addr_in, &addrlen) < 0)
281             break;
282         }
283       shutdown (accept_blk[XJP_INET_ACPT].sd, 2);
284       close (accept_blk[XJP_INET_ACPT].sd);
285     }
286 #endif /* TCPCONN */
287 }
288 
289 int
XJp_return_sock(state,detail,open,keysym,string)290 XJp_return_sock (state, detail, open, keysym, string)
291      short state, detail;
292      int open;
293      KeySym keysym;
294      char *string;
295 {
296   unsigned short tmp_short;
297   unsigned long tmp_long;
298 
299   tmp_short = (unsigned short) htons (state);
300   if (_WriteToClient (&tmp_short, sizeof (short)) == -1)
301     return (-1);
302   tmp_short = (unsigned short) htons (detail);
303   if (_WriteToClient (&tmp_short, sizeof (short)) == -1)
304     return (-1);
305 
306   if (open == 0 && state == (short) 0)
307     {
308       tmp_long = (unsigned long) htonl (keysym);
309       if (_WriteToClient (&tmp_long, sizeof (KeySym)) == -1)
310         return (-1);
311       if (detail > (short) 0)
312         {
313           if (_WriteToClient (string, (int) detail) == -1)
314             return (-1);
315         }
316       need_write = 0;
317     }
318   if (_Send_Flush () == -1)
319     return (-1);
320   return (0);
321 }
322 
323 static int
xjp_new_cl_sock(fd)324 xjp_new_cl_sock (fd)
325      int fd;
326 {
327   register XJpClientRec *xjp;
328   register XIMClientRec *xc;
329   short detail;
330   char buf[32];
331   ximICValuesReq ic_req;
332   ximICAttributesReq pre_req, st_req;
333   XCharStruct cs;
334 
335   if ((_ReadFromClient (buf, 2) == -1) || (_ReadFromClient (buf, (int) buf[1]) == -1))
336     {
337       return (-1);
338     }
339   if ((xjp = (XJpClientRec *) Malloc (sizeof (XJpClientRec))) == NULL)
340     {
341       XJp_return_sock ((short) -1, (short) 7, 1, (KeySym) 0, NULL);
342       return (-1);
343     }
344   xjp->dispmode = XJP_ROOT;
345   xjp->w = 0;
346   XJp_xjp_to_xim (xjp, &ic_req, &pre_req, &st_req, &cs);
347   if ((xc = create_client (&ic_req, &pre_req, &st_req, NULL, NULL, 0, 0, NULL, NULL, NULL, &detail)) == NULL)
348     {
349       Free ((char *) xjp);
350       XJp_return_sock ((short) -1, (short) 7, 1, (KeySym) 0, NULL);
351       return (-1);
352     }
353   if (XJp_return_sock ((short) 0, (short) 0, 1, (KeySym) 0, NULL) < 0)
354     {
355       Free ((char *) xjp);
356       return (-1);
357     }
358   xc->xjp = 1;
359   xjp->xim_client = xc;
360   xjp->direct_fd = fd;
361   xjp->next = xjp_clients;
362   xjp->ref_count = 0;
363   xjp_clients = xjp;
364   return (0);
365 }
366 
367 static int
xjp_new_client_acpt(fd)368 xjp_new_client_acpt (fd)
369      int fd;
370 {
371 #ifdef  UNIXCONN
372   struct sockaddr_un addr_un;
373 #endif /* UNIXCONN */
374 #ifdef  TCPCONN
375   struct sockaddr_in addr_in;
376 #endif /* TCPCONN */
377 #if defined(UNIXCONN) || defined(TCPCONN)
378   register int i;
379   int addrlen;
380 #endif
381 
382 #ifdef  UNIXCONN
383   if (accept_blk[XJP_UNIX_ACPT].sd != -1)
384     {
385       if (fd == accept_blk[XJP_UNIX_ACPT].sd)
386         {
387           for (i = 0; i < max_client; i++)
388             {
389               if (cblk[i].use == 0)
390                 {
391                   addrlen = sizeof (addr_un);
392                   if ((cblk[i].sd = accept (fd, (struct sockaddr *) &addr_un, &addrlen)) < 0)
393                     {
394                       return (-1);
395                     }
396                   cur_cblk = &cblk[i];
397                   cur_cblk->use = 1;
398                   cur_cblk->xjp = 1;
399                   cur_cblk->byteOrder = False;
400                   cur_sock = cur_cblk->sd;
401                   if (xjp_new_cl_sock (cur_sock) == 0)
402                     {
403                       sock_set (all_socks, cur_sock);
404                     }
405                   return (0);
406                 }
407             }
408         }
409     }
410 #endif /* UNIXCONN */
411 #ifdef  TCPCONN
412   if (fd == accept_blk[XJP_INET_ACPT].sd)
413     {
414       for (i = 0; i < max_client; i++)
415         {
416           if (cblk[i].use == 0)
417             {
418               addrlen = sizeof (addr_in);
419               if ((cblk[i].sd = accept (fd, (struct sockaddr *) &addr_in, &addrlen)) < 0)
420                 {
421                   return (-1);
422                 }
423               cur_cblk = &cblk[i];
424               cur_cblk->use = 1;
425               cur_cblk->xjp = 1;
426               cur_cblk->byteOrder = False;
427               cur_sock = cur_cblk->sd;
428               if (xjp_new_cl_sock (cur_sock) == 0)
429                 {
430                   sock_set (all_socks, cur_sock);
431                 }
432               break;
433             }
434         }
435     }
436 #endif /* TCPCONN */
437   return (0);
438 }
439 
440 int
XJp_wait_for_socket()441 XJp_wait_for_socket ()
442 {
443 #ifdef  UNIXCONN
444   if (accept_blk[XJP_UNIX_ACPT].sd != -1)
445     {
446       if (sock_tst (ready_socks, accept_blk[XJP_UNIX_ACPT].sd))
447         {
448           sock_clr (ready_socks, accept_blk[XJP_UNIX_ACPT].sd);
449           cur_cblk = NULL;
450           cur_sock = -1;
451           xjp_new_client_acpt (accept_blk[XJP_UNIX_ACPT].sd);
452           return (XJP_DIRECT_TYPE);
453         }
454     }
455 #endif /* UNIXCONN */
456 #ifdef  TCPCONN
457   if (accept_blk[XJP_INET_ACPT].sd != -1)
458     {
459       if (sock_tst (ready_socks, accept_blk[XJP_INET_ACPT].sd))
460         {
461           sock_clr (ready_socks, accept_blk[XJP_INET_ACPT].sd);
462           cur_cblk = NULL;
463           cur_sock = -1;
464           xjp_new_client_acpt (accept_blk[XJP_INET_ACPT].sd);
465           return (XJP_DIRECT_TYPE);
466         }
467     }
468 #endif /* TCPCONN */
469   return (0);
470 }
471 
472 void
XJp_destroy_for_sock(fd)473 XJp_destroy_for_sock (fd)
474      int fd;
475 {
476   XJpClientRec *p, **prev_p;
477   XJpInputRec *i, **prev_i;
478 
479   for (prev_p = &xjp_clients; p = *prev_p; prev_p = &p->next)
480     {
481       if (p->direct_fd != -1 && p->direct_fd == fd)
482         {
483           if (p == xjp_cur_client)
484             {
485               xjp_cur_client = NULL;
486               xjp_cur_input = NULL;
487             }
488           destroy_client (p->xim_client);
489           for (prev_i = &xjp_inputs; i = *prev_i;)
490             {
491               if (i->pclient == p)
492                 {
493                   *prev_i = i->next;
494                   Free ((char *) i);
495                 }
496               else
497                 {
498                   prev_i = &i->next;
499                 }
500             }
501           *prev_p = p->next;
502           Free ((char *) p);
503           return;
504         }
505     }
506 }
507 
508 static void
xjp_buffer_to_xevent(buf,ev)509 xjp_buffer_to_xevent (buf, ev)
510      char *buf;
511      XEvent *ev;
512 {
513   ev->xkey.display = dpy;
514   ev->xkey.type = (int) buf[0];
515   ev->xkey.state = (unsigned int) buf[1];
516   ev->xkey.serial = (unsigned long) ntohs (*(short *) (buf + 2));
517   ev->xkey.time = (Time) ntohl (*(Time *) (buf + 4));
518   ev->xkey.root = (Window) ntohl (*(Window *) (buf + 8));
519   ev->xkey.window = (Window) ntohl (*(Window *) (buf + 12));
520   ev->xkey.subwindow = (Window) ntohl (*(Window *) (buf + 16));
521   ev->xkey.x_root = (int) ntohs (*(short *) (buf + 20));
522   ev->xkey.y_root = (int) ntohs (*(short *) (buf + 22));
523   ev->xkey.x = (int) ntohs (*(short *) (buf + 24));
524   ev->xkey.y = (int) ntohs (*(short *) (buf + 26));
525   ev->xkey.keycode = (unsigned int) ntohs (*(short *) (buf + 28));
526   ev->xkey.same_screen = (Bool) buf[30];
527 }
528 
529 static int
xjp_get_event(ev)530 xjp_get_event (ev)
531      XEvent *ev;
532 {
533   char readbuf[64];
534   register XJpClientRec *p;
535   register XJpInputRec *i;
536 
537   if (_ReadFromClient (readbuf, 32) == -1)
538     {
539       return (-1);
540     }
541   xjp_buffer_to_xevent (readbuf, ev);
542   for (p = xjp_clients; p; p = p->next)
543     {
544       if (p->direct_fd != -1 && p->direct_fd == cur_sock)
545         {
546           if (p->w == (Window) 0)
547             {
548               p->w = ev->xkey.window;
549             }
550           for (i = xjp_inputs; i; i = i->next)
551             {
552               if (i->pclient == p && i->w == ev->xkey.window)
553                 return (0);
554             }
555           if ((i = (XJpInputRec *) Malloc (sizeof (XJpInputRec))) == NULL)
556             {
557               malloc_error ("allocation of Focus data struct(XJp)");
558               return (-1);
559             }
560           i->w = ev->xkey.window;
561           i->pclient = p;
562           i->save_event = 0;
563           i->next = xjp_inputs;
564           xjp_inputs = i;
565           return (0);
566         }
567     }
568   return (-1);
569 }
570 
571 void
XJp_Direct_Dispatch()572 XJp_Direct_Dispatch ()
573 {
574   XEvent ev;
575   int buff[32], in;
576   int ret, i, n_bytes;
577 
578   if (xjp_get_event (&ev) == -1)
579     return;
580   ret = key_input (buff, &ev);
581   for (i = 0; i < ret;)
582     {
583       n_bytes = get_cswidth_by_char (in = buff[i++]);
584       for (; n_bytes > 1 && i < ret; n_bytes--, i++)
585         {
586           in = (in << 8) + buff[i];
587         }
588       in_put (in);
589     }
590   if (need_write)
591     {
592       XJp_return_sock ((short) 0, (short) 0, 0, (KeySym) 0, NULL);
593     }
594   return;
595 }
596 
597 static KeySym save_sock_keysym = (KeySym) 0;
598 static unsigned char save_sock_str[32];
599 static unsigned int save_sock_str_len = 0;
600 
601 void
XJp_save_sockbuf(len,str,keysym)602 XJp_save_sockbuf (len, str, keysym)
603      int len;
604      unsigned char *str;
605      KeySym keysym;
606 {
607   if (xjp_cur_client && xjp_cur_client->direct_fd != -1)
608     {
609       need_write = 1;
610       save_sock_keysym = keysym;
611       save_sock_str_len = len;
612       if (len > 0)
613         {
614           bcopy (str, save_sock_str, len);
615         }
616     }
617 }
618 
619 void
XJp_direct_send_cl_key()620 XJp_direct_send_cl_key ()
621 {
622   XJp_return_sock ((short) 0, (short) save_sock_str_len, 0, save_sock_keysym, save_sock_str);
623 }
624 
625 #endif /* defined(XJPLIB) && defined(XJPLIB_DIRECT) */
626