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 
23 #include "def.h"
24 #include "misc.h"
25 #include "imewrapper.h"
26 #include "cannaproto.h"
27 
28 typedef int (*intfunc_t)();
29 
30 intfunc_t wrapperfunc[] = {
31   imewrapper_initialize,
32   imewrapper_finalize,
33   imewrapper_create_context,
34   imewrapper_duplicate_context,
35   imewrapper_close_context,
36   imewrapper_get_dictionary_list,
37   imewrapper_get_directory_list,
38   imewrapper_mount_dictionary,
39   imewrapper_unmount_dictionary,
40   imewrapper_remount_dictionary,
41   imewrapper_get_mountdictionary_list,
42   imewrapper_query_dictionary,
43   imewrapper_define_word,
44   imewrapper_delete_word,
45   imewrapper_begin_convert,
46   imewrapper_end_convert,
47   imewrapper_get_candidacy_list,
48   imewrapper_get_yomi,
49   imewrapper_subst_yomi,
50   imewrapper_store_yomi,
51   imewrapper_store_range,
52   imewrapper_get_lastyomi,
53   imewrapper_flush_yomi,
54   imewrapper_remove_yomi,
55   imewrapper_get_simplekanji,
56   imewrapper_resize_pause,
57   imewrapper_get_hinshi,
58   imewrapper_get_lex,
59   imewrapper_get_status,
60   imewrapper_set_locale,
61   imewrapper_auto_convert,
62   imewrapper_query_extensions,
63   imewrapper_set_applicationname,
64   imewrapper_notice_groupname,
65   imewrapper_through,
66   imewrapper_kill_server
67 };
68 
69 intfunc_t wrapperfunc_e[] = {
70   imewrapper_get_serverinfo,
71   imewrapper_get_access_control_list,
72   imewrapper_create_dictionary,
73   imewrapper_delete_dictionary,
74   imewrapper_rename_dictionary,
75   imewrapper_get_wordtext_dictionary,
76   imewrapper_list_dictionary,
77   imewrapper_sync,
78   imewrapper_chmod_dictionary,
79   imewrapper_copy_dictionary
80 };
81 
82 static buffer_t packetbuf;
83 
84 char *protocol_name[] = {
85   "Initialize",
86   "Finalize",
87   "CreateContext",
88   "DupricateContext",
89   "CloseContext",
90   "GetDictionaryList",
91   "GetDirectoryList",
92   "MountDictionary",
93   "UnmountDictionary",
94   "RemountDictionary",
95   "GetMountDictionaryList",
96   "QueryDictionary",
97   "DefineWord",
98   "DeleteWord",
99   "BeginConvert",
100   "EndConvert",
101   "GetCandidacyList",
102   "GetYomi",
103   "SubstYomi",
104   "StoreYomi",
105   "StoreRange",
106   "GetLastYomi",
107   "FlushYomi",
108   "RemoveYomi",
109   "GetSimpleKanji",
110   "ResizePause",
111   "GetHinshi",
112   "GetLex",
113   "GetStatus",
114   "SetLocale",
115   "AutoConvert",
116   "QueryExtensions",
117   "SetApplicationName",
118   "NoticeGroupName",
119   "Through",
120   "KillServer",
121   NULL
122 };
123 
124 char *e_protocol_name[] = {
125   "GetServerInfo",
126   "GetAccessControlList",
127   "CreateDictionary",
128   "DeleteDictionary",
129   "RenameDictionary",
130   "GetWordTextDictionary",
131   "ListDictionary",
132   "Sync",
133   "ChmodDictionary",
134   "CopyDictionary",
135   NULL
136 };
137 
138 extern client_t client[];
139 
canna_proto_recv_request(int id)140 int canna_proto_recv_request(int id)
141 {
142   int datalen, extflag, type;
143   cannaheader_t *header;
144 
145   buffer_check(&packetbuf, 24);
146 
147   if (m_socket_read(client[id].sockfd, packetbuf.buf, 4) < 0) {
148     /* read ���顼�ϥ��饤����Ȥ�������������Ƚ�Ǥ��� */
149     return -1;
150   }
151 
152   header = (cannaheader_t *)(packetbuf.buf);
153 
154   if (header->type == 0x00) { /* Initialize */
155     if (m_socket_read(client[id].sockfd, (char *)(&datalen), 4) < 0)
156       return -1;
157     datalen = LSBMSB32(datalen);
158 
159     buffer_check(&packetbuf, datalen);
160 
161     if (m_socket_read(client[id].sockfd, packetbuf.buf, datalen) < 0)
162       return -1;
163 
164     return 0x01;
165   } else {
166     datalen = LSBMSB16(header->datalen);
167     extflag = header->extra ? 0x1000 : 0x0000;
168     type = header->type;
169 
170     if (datalen > 0) {
171       buffer_check(&packetbuf, datalen + 4);
172 
173       if (m_socket_read(client[id].sockfd, &(packetbuf.buf[4]), datalen) < 0)
174 	return -1;
175     }
176 
177     return (type | extflag);
178   }
179 }
180 
canna_proto_send_request(int id)181 int canna_proto_send_request(int id)
182 {
183   int datalen;
184   cannaheader_t *header;
185 
186   header = (cannaheader_t *)(packetbuf.buf);
187 
188   datalen = LSBMSB16(header->datalen) + 4;
189 
190   if (m_socket_write(client[id].sockfd, packetbuf.buf, datalen) < 0)
191     return -1;
192 
193   return 0;
194 }
195 
canna_proto_main(int id)196 int canna_proto_main(int id)
197 {
198   int type, ret;
199   int (*callfunc)();
200   char *reqname;
201 
202   if ((type = canna_proto_recv_request(id)) <= 0) {
203     client[id].need_terminate = TRUE; /* main.c �ǽ�λ�������Ƥ�餦 */
204     return 0;
205   }
206 
207   if ((0x01 <= type && type <= 0x24) || (0x1001 <= type && type <= 0x100a)) {
208     if (type & 0x1000) {
209       reqname = e_protocol_name[(type & 0xff) - 1];
210       callfunc = wrapperfunc_e[(type & 0xff) - 1];
211     } else {
212       reqname = protocol_name[type - 1];
213       callfunc = wrapperfunc[type - 1];
214     }
215 
216     m_msg_dbg("REQUEST %s called by %s@%s\n", reqname, client[id].user,
217 	      client[id].host);
218 
219     ret = (*callfunc)(id, &packetbuf);
220 
221     m_msg_dbg("Returned from request processing.\n");
222   } else {
223     /* �إå����ѡ�main.c �ǽ�λ�������Ƥ�餦���ꥯ�����Ȥϥ������֤� */
224     client[id].need_terminate = TRUE;
225     ret = 1;
226   }
227 
228   /* ret..1 ���� ret..0 ̤���� ret..-1 IME ����� */
229 
230   if (type == 0x01)
231     write(client[id].sockfd, packetbuf.buf, 4);
232   else
233     canna_proto_send_request(id);
234 
235   if (ret == 0)
236     m_msg_dbg("Request %x is under construction.\n", type);
237   else if (ret == -1) {
238     m_msg("IME terminated.\n");
239 
240     /* �Ƶ�ư�������롣���Ԥ������ϡ�-ime ���֤ꡢmain.c ��
241      * ���ƤΥ��饤����Ȥν�λ�������뤿�ᡢ-ime ���֤�
242      */
243 
244     return imewrapper_ime_aborted(client[id].ime);
245   }
246 
247   return 0;
248 }
249