1 /*
2 * dbskkd.c
3 * inetd-style SKK Server for Berkeley-DBnized dictionary file
4 * Version dbskkd-0.2beta
5 * based on SKK Version 3.9.3
6 * Copyright (c) 1996 by Kenji Rikitake <kenji@reseau.toyonaka.osaka.jp>
7 * Original copyright notice at the end of this source file
8 * $Id: dbskkd.c,v 1.9 1996/11/09 12:16:39 kenji Exp $
9 */
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/ioctl.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17
18 #include <stdio.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <netdb.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <limits.h>
25 #include <syslog.h>
26 #include <db.h>
27
28 /* dbskkd working directory */
29 #ifndef SERVER_DIR
30 #define SERVER_DIR "/usr/local/etc/dbskkd/"
31 #endif /* SERVER_DIR */
32
33 /* dbskkd dictionary file (path relative to SERVER_DIR) */
34 #ifndef JISHO_FILE
35 #define JISHO_FILE "./SKK-JISYO.L.db"
36 #endif /* JISHO_FILE */
37
38 #define BUFSIZE 1024 /* max size of a request */
39
40 #define CLIENT_END '0'
41 #define CLIENT_REQUEST '1'
42 #define CLIENT_VERSION '2'
43 #define CLIENT_HOST '3'
44
45 #define SERVER_ERROR "0"
46 #define SERVER_FOUND "1"
47 #define SERVER_NOT_FOUND "4"
48
49 #define STDIN (fileno(stdin))
50 #define STDOUT (fileno(stdout))
51
52 void err __P((const char *, ...));
53 void setproctitle __P((const char *, ...));
54
55 char pgmver[] = "dbskkd-0.2 "; /* version number */
56
57 char hname[BUFSIZ]; /* hostname and IP address */
58 DB *jisho_dbp; /* DB structure for the shared dictionary */
59 HASHINFO jisho_hash; /* HASHINFO for the shared dictionary */
60
61 /*
62 * main server loop:
63 * DB-style hashed database search
64 */
65
search()66 int search()
67 {
68 unsigned char combuf[BUFSIZE];
69 register unsigned char *pbuf;
70 int length, errcode, get_status;
71 DBT key, data;
72
73 if ((length = read(STDIN, &combuf[0], BUFSIZE)) <= 0) {
74 err("read error from stdin: %s", strerror(errno));
75 /* NOTREACHED */
76 }
77
78 switch (combuf[0]) {
79
80 case CLIENT_END:
81 syslog(LOG_NOTICE, "end of conversion requested");
82 return -1;
83 /* NOTREACHED */
84 break; /* foolproof */
85
86 case CLIENT_VERSION:
87 if (write(STDOUT, pgmver, strlen(pgmver)) < 0) {
88 err("write error (version string): %s",
89 strerror(errno));
90 /* NOTREACHED */
91 }
92 return 0;
93 /* NOTREACHED */
94 break; /* foolproof */
95
96 case CLIENT_HOST:
97 if (write(STDOUT, hname, strlen(hname)) < 0) {
98 err("write error (host info): %s", strerror(errno));
99 /* NOTREACHED */
100 }
101 return 0;
102 /* NOTREACHED */
103 break; /* foolproof */
104
105 case CLIENT_REQUEST:
106 /* get size of key */
107 key.data = &combuf[1];
108 for (pbuf = &combuf[1];
109 *pbuf != ' ' && pbuf != &combuf[length - 1];
110 pbuf++) {}
111 key.size = pbuf - &combuf[1];
112
113 if (key.size <= 0) {
114 err("invalid keysize = %d", key.size);
115 /* NOTREACHED */
116 }
117 else {
118 get_status = jisho_dbp->get(jisho_dbp, &key, &data, 0);
119 }
120 switch (get_status) {
121 case -1:
122 err("fatal error on DB get routine: %s", strerror(errno));
123 /* NOTREACHED */
124 break; /* foolproof */
125 case 0: /* found */
126 /* sending found code and the result data string with LF */
127 if ((errcode = write(STDOUT, SERVER_FOUND, 1)) >= 0) {
128 if ((errcode = write(STDOUT, data.data, data.size)) >= 0) {
129 errcode = write(STDOUT, "\n", 1);
130 if (errcode < 0) {
131 err("write error (converted data): %s",
132 strerror(errno));
133 /* NOTREACHED */
134 }
135 return 0;
136 /* NOTREACHED */
137 }
138 }
139 break;
140 case 1: /* NOT found */
141 /* sending error code and the key string with LF */
142 /* this action is required by skkinput */
143 if ((errcode = write(STDOUT, SERVER_NOT_FOUND, 1)) >= 0) {
144 if ((errcode = write(STDOUT, key.data, key.size)) >= 0) {
145 errcode = write(STDOUT, "\n", 1);
146 if (errcode < 0) {
147 err("write error (NOT_FOUND message): %s",
148 strerror(errno));
149 /* NOTREACHED */
150 }
151 return 0;
152 /* NOTREACHED */
153 }
154 }
155 return 0;
156 /* NOTREACHED */
157 break; /* foolproof */
158 default: /* unknown value */
159 err("unknown return value %d from DB get routine", get_status);
160 /* NOTREACHED */
161 break; /* foolproof */
162 }
163 break;
164 default:
165 err("unknown client request code %d", combuf[0]);
166 /* NOTREACHED */
167 break; /* foolproof */
168 }
169 /* NOTREACHED */
170 }
171
172 /*
173 * main program
174 */
175
main(argc,argv)176 int main(argc, argv)
177 int argc;
178 char *argv[];
179 {
180 struct hostent *hp;
181 char **p, *lp;
182 struct in_addr addr;
183 struct sockaddr_in sin;
184 int sval;
185
186 /* open syslog */
187 openlog("dbskkd", LOG_PID | LOG_CONS, LOG_DAEMON);
188
189 /* chdir to server directory */
190 if (chdir(SERVER_DIR) != 0) {
191 err("cannot chdir() to %s: %s", SERVER_DIR, strerror(errno));
192 }
193 /* set umask to g-w, o-rwx */
194 (void)umask(027);
195
196 /* open dictionary db file */
197 if ((jisho_dbp = dbopen(JISHO_FILE, O_RDONLY, S_IRUSR, DB_HASH, &jisho_hash)) == NULL) {
198 err("cannot dbopen() the dictionary file %s: %s", JISHO_FILE,
199 strerror(errno));
200 /* NOTREACHED */
201 }
202
203 /* get host info */
204 if (gethostname(hname, BUFSIZE) < 0) {
205 err("gethostname: %s", strerror(errno));
206 /* NOTREACHED */
207 }
208 hp = gethostbyname(hname);
209 p = hp->h_addr_list;
210 while (*p != NULL) {
211 strcat(hname, ":");
212 memcpy(&addr.s_addr, *p, hp->h_length);
213 strcat(hname, inet_ntoa(addr));
214 p++;
215 }
216 strcat(hname, ": ");
217
218 /* get peer info */
219 sval = sizeof(sin);
220 if (getpeername(0, (struct sockaddr *)&sin, &sval) < 0) {
221 err("getpeername: %s", strerror(errno));
222 /* NOTREACHED */
223 }
224 if (hp = gethostbyaddr((char *)&sin.sin_addr.s_addr,
225 sizeof(sin.sin_addr.s_addr), AF_INET))
226 lp = hp->h_name;
227 else
228 lp = inet_ntoa(sin.sin_addr);
229
230 #ifdef LOG_PEERINFO
231 /* log peer info */
232 syslog(LOG_NOTICE, "connected from %s", lp);
233 #endif /* LOG_PEERINFO */
234 /* set process status string */
235 setproctitle("serving %s", lp);
236
237 /* command loop */
238 while(search() == 0) {}
239
240 /* close dictionary db file */
241 if (jisho_dbp->close(jisho_dbp))
242 err("cannot dbp->close() the dictionary file: %s", strerror(errno));
243 /* NOTREACHED */
244
245 exit(0);
246 }
247
248 /*
249 * the function err() for syslog retains
250 * the following copyright conditions
251 */
252 /*
253 * Copyright (c) 1983, 1993
254 * The Regents of the University of California. All rights reserved.
255 *
256 * Redistribution and use in source and binary forms, with or without
257 * modification, are permitted provided that the following conditions
258 * are met:
259 * 1. Redistributions of source code must retain the above copyright
260 * notice, this list of conditions and the following disclaimer.
261 * 2. Redistributions in binary form must reproduce the above copyright
262 * notice, this list of conditions and the following disclaimer in the
263 * documentation and/or other materials provided with the distribution.
264 * 3. All advertising materials mentioning features or use of this software
265 * must display the following acknowledgement:
266 * This product includes software developed by the University of
267 * California, Berkeley and its contributors.
268 * 4. Neither the name of the University nor the names of its contributors
269 * may be used to endorse or promote products derived from this software
270 * without specific prior written permission.
271 *
272 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
273 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
274 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
275 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
276 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
277 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
279 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
280 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
282 * SUCH DAMAGE.
283 */
284
285 #if __STDC__
286 #include <stdarg.h>
287 #else
288 #include <varargs.h>
289 #endif
290
291 void
292 #if __STDC__
err(const char * fmt,...)293 err(const char *fmt, ...)
294 #else
295 err(fmt, va_alist)
296 char *fmt;
297 va_dcl
298 #endif
299 {
300 va_list ap;
301 #if __STDC__
302 va_start(ap, fmt);
303 #else
304 va_start(ap);
305 #endif
306 (void)vsyslog(LOG_ERR, fmt, ap);
307 va_end(ap);
308 exit(1);
309 /* NOTREACHED */
310 }
311
312 /* end of program */
313
314 /* original skkserv comment follows */
315
316 /* skkserv.c
317 * SKK Server Version 3.9.3 of Jun 17, 1994
318 * Copyright (C) 1994 Yukiyoshi Kameyama (kam@riec.tohoku.ac.jp)
319 *
320 * Programmed by
321 * Yukiyoshi Kameyama (kam@riec.tohoku.ac.jp)
322 * Research Institute of Electrical Communication
323 * Tohoku University
324 *
325 * Contributed by
326 * Nobu Takahashi (nt@hpycla.yhp.co.jp) for System V patch
327 * Chikahiro Kimura (kimura@2oa.kb.nec.co.jp) for "ntohs" bug
328 * Koji Kawaguchi (guchi@pfu.fujitsu.co.jp) for various improvement
329 * Hironobu Takahashi (takahasi@tiny.or.jp) for patch for char/int typing
330 * Kazushi Marukawa (kazushi@kubota.co.jp) for cleaning up behavior in PRIVATE mode
331 * TSUMURA Kazumasa (tsumura@fml.ec.tmit.ac.jp) for pointing out a bug in okuri-ari/nasi test
332 *
333 * This program is free software; you can redistribute it and/or modify
334 * it under the terms of the GNU General Public License as published by
335 * the Free Software Foundation; either versions 2, or (at your option)
336 * any later version.
337 *
338 * This program is distributed in the hope that it will be useful
339 * but WITHOUT ANY WARRANTY; without even the implied warranty of
340 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
341 * GNU General Public License for more details.
342 *
343 * You should have received a copy of the GNU General Public License
344 * along with SKK, see the file COPYING. If not, write to the Free
345 * Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
346 */
347 /*
348 * Description
349 * "skkserv" is a server daemon for an SKK/Nemacs client, which
350 * provides a facility of fast looking-up of an SKK-dictionary.
351 * skkserv and an SKK/Nemacs client can run on different hosts
352 * which are connected by a TCP/IP network.
353 *
354 * An old-style SKK-dictionary is a sorted sequence of lines in
355 * the form:
356 * YOMI /TANGO1/TANGO2/.../TANGOn/
357 * A new-style SKK-dictionary consists of two parts:
358 * The first part begins with the line
359 * ;; okuri-ari entries.
360 * followed by the reverse-sorted sequence of lines in the same
361 * form as old-style. In the first part, all the YOMI entries
362 * have "okurigana".
363 * The second part begins with the line
364 * ;; okuri-nasi entries.
365 * followed by the sorted sequence of lines in the same form as
366 * old-style. In the second part, all the YOMI entries do NOT
367 * have "okurigana".
368 * Other lines whose first two characters are ";;" will be ignored.
369 *
370 * NOTE: the "sort" and "reverse-sort" should be emacs-sort, not
371 * UNIX sort (unsigned char, shorter is earlier).
372 *
373 * Once invoked with a dictionary, the server runs permanently,
374 * and waits for client's requests.
375 * A client, usually invoked by SKK/Nemacs, requests the server
376 * to transform a string (YOMI) to another string(/TANGO1/.../).
377 * Communication between the server and a client is done through
378 * a TCP-port "skkserv" by a UNIX socket.
379 * The server looks up the dictionary with the input string
380 * as the key, and replies its value to the client.
381 * If the input string is not found in the dictionary it replies
382 * 'Not Found'.
383 */
384
385 /*
386 * Client Request Form
387 * "0" end of connection
388 * "1eee " eee is keyword in EUC code with ' ' at the end
389 * "2" skkserv version number
390 * "3" hostname and its IP addresses
391 *
392 * Server Reply Form for "1eee"
393 * "0" Error
394 * "1eee" eee is the associated line separated by '/'
395 * "4" Not Found
396 *
397 * Server Reply Form for "2"
398 * "A.B " A for major version number, B for minor version number
399 * followed by a space
400 *
401 * Server Reply Form for "3"
402 * "string:addr1:...: " string for hostname, addr1 for an IP address
403 * followed by a space
404 * addrs should be in dotted quad form
405 */
406
407 /* end of source file */
408