1 /*
2 * $Id: bdic.c,v 1.13 2005/06/12 17:14:22 aonoto 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 Kyoto University Research Institute for Mathematical Sciences
10 * 1987, 1988, 1989, 1990, 1991, 1992
11 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
12 * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
13 * Copyright FreeWnn Project 1999, 2000, 2002, 2003, 2004, 2005
14 *
15 * Maintainer: FreeWnn Project <freewnn@tomo.gr.jp>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31
32 /*
33 Binary (Updatable, Stable) dictionary common routine.
34 */
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
38
39 #if defined (JS)
40 # define JS_STATIC static
41 #else /* !JS */
42 # define JS_STATIC
43 #endif /* !JS */
44
45 #if defined(JSERVER) || defined(JS)
46 # ifdef WRITE_CHECK
47 # define BDIC_WRITE_CHECK
48 # endif
49 #endif /* defined(JSERVER) || defined(JS) */
50
51 #include <sys/types.h>
52 #include <stdio.h>
53 #if STDC_HEADERS
54 # include <string.h>
55 #elif HAVE_STRINGS_H
56 # include <strings.h>
57 #endif /* STDC_HEADERS */
58
59 #ifndef JS
60 # include <sys/stat.h>
61 # if HAVE_UNISTD_H
62 # include <unistd.h>
63 # endif
64 # include "commonhd.h"
65 # include "jslib.h"
66 # include "jh.h"
67 #endif /* JS */
68 #include "jdata.h"
69 #include "wnn_os.h"
70 #include "wnn_string.h"
71
72 #ifdef JSERVER
73 # ifndef BDIC_WRITE_CHECK
74 # define vputc(X, pt) ((pt)? putc((X), (pt)):xputc_cur(X))
75 # endif /* !BDIC_WRITE_CHECK */
76 # define vgetc(pt) ((pt)? getc((pt)):xgetc_cur())
77 extern int xgetc_cur ();
78 #else /* !JSERVER */
79 # ifdef JS
80 # ifndef BDIC_WRITE_CHECK
81 # define vputc(X, pt) putc((X), (pt))
82 # endif /* !BDIC_WRITE_CHECK */
83 # define vgetc(pt) getc(pt)
84 # else /* !JS */
85 # define vputc(X, pt) putc((X), (pt))
86 # define vgetc(pt) getc(pt)
87 # endif /* !JS */
88 #endif /* !JSERVER */
89
90 #ifndef min
91 # define min(a, b) ((a > b)? b:a)
92 # define max(a, b) ((a < b)? b:a)
93 #endif
94
95 /* XXX: function prototypes to be moved to some header file. */
96 /* bdic.c */
97 /* following functions are only used in bdic.c
98 * put_null, put_nstring, put_int
99 * get_null, get_nstring
100 */
101 JS_STATIC int put_null (FILE* ofpter, int n);
102 JS_STATIC int put_nstring (FILE* ofpter, char* c, int n);
103 JS_STATIC int put_n_EU_str (FILE* ofpter, w_char* c, int n);
104 JS_STATIC int put_short (FILE* ofpter, int i);
105 JS_STATIC int put_int (FILE* ofpter, int i);
106 JS_STATIC int get_null (FILE* ifpter, int n);
107 JS_STATIC int get_nstring (FILE* ifpter, int n, char* st);
108 JS_STATIC int get_int (int* ip, FILE* ifpter);
109
110 #ifndef JS
111 void udytoS (w_char* yomi, int tnum, char* hostart, struct uind1 * tary);
112 #endif /* !JS */
113
114 #ifdef BDIC_WRITE_CHECK
115 JS_STATIC void check_backup (char* n);
116 JS_STATIC void delete_tmp_file (char* n);
117 JS_STATIC char* make_backup_file (char* n);
118 JS_STATIC char* make_tmp_file (char* n, int copy, FILE** ret_fp);
119 JS_STATIC void move_tmp_to_org (char* tmp_name, char* org_name, int copy);
120 #endif /* BDIC_WRITE_CHECK */
121
122 JS_STATIC int create_file_header (FILE* ofpter, int file_type, char* file_passwd);
123 JS_STATIC int output_file_header (FILE* ofpter, struct wnn_file_head* hp);
124 JS_STATIC int input_file_header (FILE* ifpter, struct wnn_file_head* hp);
125 JS_STATIC int output_file_uniq (struct wnn_file_uniq* funiq, FILE* ofpter);
126 JS_STATIC int input_file_uniq (struct wnn_file_uniq* funiq, FILE* ifpter);
127 JS_STATIC int check_inode (FILE* f, struct wnn_file_head* fh);
128 JS_STATIC int change_file_uniq (struct wnn_file_head* fh, char* n);
129 JS_STATIC int change_file_uniq1 (
130 FILE* ofpter, int file_type, char* file_passwd,
131 struct wnn_file_uniq* file_uniq);
132
133 #ifdef JSERVER
134 int f_uniq_cmp (struct wnn_file_uniq *a, struct wnn_file_uniq* b);
135 #endif /* JSERVER */
136
137 #if !defined(JS) && !defined(JSERVER)
138 void vputs (char* c, FILE* fp);
139 int vputws (w_char* w, FILE* fp);
140 int put_yomi_str (w_char* yomi, FILE* ofpter);
141 #endif /* !JS && !JSERVER */
142
143 #ifndef JS
144 void Get_knj2 (UCHAR* kptr, int kanji2, w_char* kouho, w_char* yomi, w_char* comment);
145 void get_kanji_str (UCHAR* kptr, w_char* kanji, w_char* yomi, w_char* comment);
146 void Get_kanji_str_r (UCHAR* kptr, w_char** tmpk, w_char** tmpy, w_char** tmpc);
147 UCHAR kanjiaddr (UCHAR* d0, w_char* kanji, w_char* yomi, w_char* comment);
148 #endif /* !JS */
149
150 JS_STATIC int create_null_dic (
151 char* fn, w_char* comm, char* passwd, char* hpasswd, int which);
152 JS_STATIC int create_hindo_file (
153 struct wnn_file_uniq* funiq,
154 char* fn, w_char* comm, char* passwd, int serial);
155
156 /* XXX: input_* are not used in JSlib */
157 JS_STATIC int input_header_jt (FILE* ifpter, struct JT* jt1);
158 JS_STATIC int output_header_jt (FILE* ofpter, struct JT* jt1);
159 JS_STATIC int input_header_hjt (FILE* ifpter, struct HJT* hjt1);
160 JS_STATIC int output_header_hjt (FILE* ofpter, struct HJT* hjt1);
161
162 #if !defined(JS) && !defined(JSERVER)
163 /* Only used in JUTIL */
164 void Print_entry (
165 w_char* yomi, w_char* kstr, w_char* cstr,
166 int hindo, int ima, int hinsi, int serial,
167 FILE* ofpter, int esc_exp);
168 #endif /* !JS && !JSERVER */
169
170 /* XXX: prototype of functions in other files.
171 * should be replaced to including some header files. */
172 JS_STATIC void new_pwd (char*, char*); /* in etc/pwd.c */
173 char *wnn_get_hinsi_name (int); /* in etc/gethinsi.c */
174 #ifdef JSERVER
175 void xputc_cur (unsigned char); /* in jserver/snd_rcv.c */
176 #endif /* JSERVER */
177
178
179 #ifdef BDIC_WRITE_CHECK
180
181 static int
vputc(char c,FILE * fp)182 vputc (char c, FILE* fp)
183 {
184 # ifdef JSERVER
185 if (fp)
186 {
187 if (fwrite (&c, sizeof (char), 1, fp) <= 0)
188 return (-1);
189 }
190 else
191 {
192 xputc_cur (c);
193 }
194 # else /* !JSERVER */
195 if (fwrite (&c, sizeof (char), 1, fp) <= 0)
196 return (-1);
197 # endif /* !JSERVER */
198
199 return (0);
200 }
201 #endif /* BDIC_WRITE_CHECK */
202
203 /* XXX note 2004.07.08 Hiroo Ono
204 * It used to return int only if BDIC_WRITE_CHECK was defined,
205 * otherwise it was a void function.
206 * For the sake of source code simplicity, I unified the funtion to always
207 * return int: It returns the write status when BDIC_WRITE_CHECK is defined
208 * and just 0 when not. No testing on performace was performed (though I
209 * believe it does not have significant effect).
210 * Similar changes are also applied to following functions.
211 */
212 JS_STATIC int
put_null(FILE * ofpter,int n)213 put_null (FILE* ofpter, int n)
214 {
215 for (; n; n--)
216 {
217 #ifdef BDIC_WRITE_CHECK
218 if (vputc ('\0', ofpter) == -1)
219 return (-1);
220 #else /* !BDIC_WRITE_CHECK */
221 vputc ('\0', ofpter);
222 #endif /* !BDIC_WRITE_CHECK */
223 }
224
225 return (0);
226 }
227
228 /* XXX was void when BDIC_WRITE_CHECK was not defined. cf put_null() above. */
229 JS_STATIC int
put_nstring(FILE * ofpter,char * c,int n)230 put_nstring (FILE* ofpter, char* c, int n)
231 {
232 for (; n; n--)
233 {
234 #ifdef BDIC_WRITE_CHECK
235 if (vputc (*c++, ofpter) == -1)
236 return (-1);
237 #else /* !BDIC_WRITE_CHECK */
238 vputc (*c++, ofpter);
239 #endif /* !BDIC_WRITE_CHECK */
240 }
241
242 return (0);
243 }
244
245 /* XXX was void when BDIC_WRITE_CHECK was not defined. cf put_null() above. */
246 JS_STATIC int
put_n_EU_str(FILE * ofpter,w_char * c,int n)247 put_n_EU_str (FILE* ofpter, w_char* c, int n)
248 {
249 for (; n; n--)
250 {
251 #ifdef BDIC_WRITE_CHECK
252 if (put_short (ofpter, (int) (*c++)) == -1)
253 return (-1);
254 #else /* !BDIC_WRITE_CHECK */
255 put_short (ofpter, (int) (*c++));
256 #endif /* !BDIC_WRITE_CHECK */
257 }
258
259 return (0);
260 }
261
262 /* XXX was void when BDIC_WRITE_CHECK was not defined. cf put_null() above. */
263 JS_STATIC int
put_short(FILE * ofpter,int i)264 put_short (FILE* ofpter, int i)
265 {
266 #ifdef BDIC_WRITE_CHECK
267 if ((vputc (i >> 8, ofpter) == -1) || (vputc (i, ofpter) == -1))
268 return (-1);
269 #else /* BDIC_WRITE_CHECK */
270 vputc (i >> 8, ofpter);
271 vputc (i, ofpter);
272 #endif /* BDIC_WRITE_CHECK */
273
274 return (0);
275 }
276
277 /* XXX was void when BDIC_WRITE_CHECK was not defined. cf put_null() above. */
278 JS_STATIC int
put_int(FILE * ofpter,int i)279 put_int (FILE* ofpter, int i)
280 {
281 #ifdef BDIC_WRITE_CHECK
282 if ((vputc (i >> 24, ofpter) == -1)
283 || (vputc (i >> 16, ofpter) == -1)
284 || (vputc (i >> 8, ofpter) == -1)
285 || (vputc (i, ofpter) == -1))
286 return (-1);
287 #else /* BDIC_WRITE_CHECK */
288 vputc (i >> 24, ofpter);
289 vputc (i >> 16, ofpter);
290 vputc (i >> 8, ofpter);
291 vputc (i, ofpter);
292 #endif /* BDIC_WRITE_CHECK */
293
294 return (0);
295 }
296
297 JS_STATIC int
get_null(FILE * ifpter,int n)298 get_null (FILE* ifpter, int n)
299 {
300 int k;
301
302 for (; n; n--)
303 {
304 k = vgetc (ifpter);
305 if (k == -1)
306 return (-1);
307 }
308
309 return (0);
310 }
311
312 JS_STATIC int
get_nstring(FILE * ifpter,int n,char * st)313 get_nstring (FILE* ifpter, int n, char* st)
314 {
315 int k;
316
317 for (; n; n--)
318 {
319 k = vgetc (ifpter);
320 *st++ = k;
321 if (k == -1)
322 return (-1);
323 }
324 return (0);
325 }
326
327
328 /*
329 * Note for get_n_EU_str() / get_short() :
330 * Moved to dtoa.c for now (currently we don't use them in other files) ...
331 */
332
333 JS_STATIC int
get_int(int * ip,FILE * ifpter)334 get_int (int* ip, FILE* ifpter)
335 {
336 int i = 0;
337 int k;
338
339 i |= (k = vgetc (ifpter)) << 24;
340 if (k == -1)
341 return (-1);
342 i |= (k = vgetc (ifpter)) << 16;
343 if (k == -1)
344 return (-1);
345 i |= (k = vgetc (ifpter)) << 8;
346 if (k == -1)
347 return (-1);
348 i |= (k = vgetc (ifpter));
349 if (k == -1)
350 return (-1);
351 *ip = i;
352 return (0);
353 }
354
355 #ifndef JS
356 void
udytoS(w_char * yomi,int tnum,char * hostart,struct uind1 * tary)357 udytoS (w_char* yomi, int tnum, char* hostart, struct uind1 * tary)
358 {
359 struct uind2 *hop;
360 int len;
361
362 hop = (struct uind2 *) ((char *) hostart + tary[tnum].pter);
363 yomi[0] = tary[tnum].yomi1 >> 16;
364 yomi[1] = tary[tnum].yomi1 & 0xffff;
365 if (yomi[1])
366 {
367 yomi[2] = tary[tnum].yomi2 >> 16;
368 if (yomi[2])
369 {
370 yomi[3] = tary[tnum].yomi2 & 0xffff;
371 }
372 }
373 len = hop->yomi[0];
374 /*Strncpy(yomi + 4, (hop->yomi) + 1, len - 4);
375 In order not to use ../etc/strings.c */
376 bcopy ((char *) ((hop->yomi) + 1), (char *) (yomi + 4), max (0, ((len - 4)) * 2));
377 yomi[len] = 0;
378 }
379 #endif /* !JS */
380
381 #ifdef BDIC_WRITE_CHECK
382 static char *
make_tmp_name(char * n)383 make_tmp_name (char* n)
384 {
385 static char buf[256];
386
387 if (n == NULL || *n == '\0')
388 return NULL;
389 sprintf (buf, "%s~", n);
390 return (buf);
391 }
392
393 static char *
make_backup_name(char * n)394 make_backup_name (char* n)
395 {
396 static char buf[256];
397
398 if (n == NULL || *n == '\0')
399 return NULL;
400 sprintf (buf, "%s#", n);
401 return (buf);
402 }
403
404
405 JS_STATIC void
check_backup(char * n)406 check_backup (char* n)
407 {
408 char *p;
409
410 if ((p = make_tmp_name (n)) && (access (p, F_OK) != -1))
411 unlink (p);
412 if ((p = make_backup_name (n)) && (access (p, F_OK) != -1))
413 {
414 unlink (n);
415 link (p, n);
416 unlink (p);
417 }
418 }
419
420 static int
copy_file_to_file(FILE * from,FILE * to)421 copy_file_to_file (FILE* from, FILE* to)
422 {
423 char buf[1024];
424 int r_len, w_len, i;
425
426 for (;;)
427 {
428 r_len = fread (buf, 1, 1024, from);
429 if (r_len <= 0)
430 break;
431 for (i = 0; i < r_len; i += w_len)
432 {
433 w_len = fwrite (&buf[i], 1, r_len - i, to);
434 if (w_len <= 0)
435 {
436 fseek (from, 0, 0);
437 fseek (to, 0, 0);
438 return (-1);
439 }
440 if (w_len >= r_len)
441 break;
442 }
443 }
444 fseek (from, 0, 0);
445 fseek (to, 0, 0);
446 return (0);
447 }
448
449 JS_STATIC void
delete_tmp_file(char * n)450 delete_tmp_file (char* n)
451 {
452 if (n && *n)
453 unlink (n);
454 }
455
456 JS_STATIC char*
make_backup_file(char * n)457 make_backup_file (char* n)
458 {
459 FILE *fp, *fp2;
460 char *p, *p2;
461
462 if ((p = make_backup_name (n)) == NULL)
463 return (NULL);
464 if ((p2 = make_tmp_name (n)) == NULL)
465 return (NULL);
466 if (((fp = fopen (p2, "w+")) == NULL) || ((fp2 = fopen (n, "r")) == NULL))
467 {
468 return NULL;
469 }
470 if (copy_file_to_file (fp2, fp) == -1)
471 {
472 fclose (fp);
473 fclose (fp2);
474 return (NULL);
475 }
476 fclose (fp);
477 fclose (fp2);
478 if (access (p, F_OK) != -1)
479 unlink (p);
480 link (p2, p);
481 unlink (p2);
482 return (p);
483 }
484
485 JS_STATIC char*
make_tmp_file(char * n,int copy,FILE ** ret_fp)486 make_tmp_file (char* n, int copy, FILE** ret_fp)
487 {
488 FILE *fp, *fp2;
489 struct wnn_file_head fh;
490 char *p;
491
492 p = make_tmp_name (n);
493 if ((fp = fopen (p, "w+")) == NULL)
494 {
495 *ret_fp = NULL;
496 return NULL;
497 }
498 if (copy && (fp2 = fopen (n, "r")) != NULL)
499 {
500 input_file_header (fp2, &fh);
501 fseek (fp2, 0, 0);
502 if ((copy_file_to_file (fp2, fp) == -1) || (create_file_header (fp, fh.file_type, fh.file_passwd) == -1))
503 {
504 fclose (fp);
505 fclose (fp2);
506 *ret_fp = NULL;
507 return NULL;
508 }
509 fseek (fp, 0, 0);
510 fclose (fp2);
511 }
512 *ret_fp = fp;
513 return p;
514 }
515
516 JS_STATIC void
move_tmp_to_org(char * tmp_name,char * org_name,int copy)517 move_tmp_to_org (char* tmp_name, char* org_name, int copy)
518 {
519 FILE *org, *tmp;
520
521 if (copy)
522 {
523 if (((tmp = fopen (tmp_name, "r")) == NULL) || ((org = fopen (org_name, "w+")) == NULL))
524 {
525 return;
526 }
527 copy_file_to_file (tmp, org);
528 fclose (tmp);
529 fclose (org);
530 }
531 else
532 {
533 unlink (org_name);
534 link (tmp_name, org_name);
535 }
536 unlink (tmp_name);
537 }
538 #endif /* BDIC_WRITE_CHECK */
539
540 JS_STATIC int
create_file_header(FILE * ofpter,int file_type,char * file_passwd)541 create_file_header (FILE* ofpter, int file_type, char* file_passwd)
542 {
543 struct stat buf;
544 char hostname[WNN_HOSTLEN];
545 struct wnn_file_head fh;
546
547 if (fstat (fileno (ofpter), &buf) == -1)
548 {
549 return (-1);
550 }
551 gethostname (hostname, WNN_HOSTLEN);
552 hostname[WNN_HOSTLEN - 1] = '\0';
553
554 fh.file_uniq.time = (int) buf.st_ctime;
555 fh.file_uniq.dev = (int) buf.st_dev;
556 fh.file_uniq.inode = (int) buf.st_ino;
557 bzero (fh.file_uniq.createhost, WNN_HOSTLEN);
558 strcpy (fh.file_uniq.createhost, hostname);
559
560 /* file_uniq_org */
561 fh.file_uniq_org.time = (int) buf.st_ctime;
562 fh.file_uniq_org.dev = (int) buf.st_dev;
563 fh.file_uniq_org.inode = (int) buf.st_ino;
564 bzero (fh.file_uniq_org.createhost, WNN_HOSTLEN);
565 strcpy (fh.file_uniq_org.createhost, hostname);
566
567 fh.file_type = file_type;
568 if (file_passwd)
569 {
570 strncpy (fh.file_passwd, file_passwd, WNN_PASSWD_LEN);
571 }
572 else
573 {
574 bzero (fh.file_passwd, WNN_PASSWD_LEN);
575 }
576 if (output_file_header (ofpter, &fh) == -1)
577 return (-1);
578 return (0);
579 }
580
581 /* 128 Bytes File Header */
582
583 JS_STATIC int
output_file_header(FILE * ofpter,struct wnn_file_head * hp)584 output_file_header (FILE* ofpter, struct wnn_file_head* hp)
585 {
586 #ifdef BDIC_WRITE_CHECK
587 if ((put_nstring (ofpter, WNN_FILE_STRING, WNN_FILE_STRING_LEN) == -1)
588 || (put_int (ofpter, hp->file_type) == -1)
589 || (output_file_uniq (&hp->file_uniq, ofpter) == -1)
590 || (output_file_uniq (&hp->file_uniq_org, ofpter) == -1)
591 || (put_nstring (ofpter, hp->file_passwd, WNN_PASSWD_LEN) == -1)
592 || (put_null (ofpter, 36) == -1))
593 return (-1); /* Future Use */
594 #else /* BDIC_WRITE_CHECK */
595 put_nstring (ofpter, WNN_FILE_STRING, WNN_FILE_STRING_LEN);
596 put_int (ofpter, hp->file_type);
597 output_file_uniq (&hp->file_uniq, ofpter);
598 output_file_uniq (&hp->file_uniq_org, ofpter);
599 put_nstring (ofpter, hp->file_passwd, WNN_PASSWD_LEN);
600 put_null (ofpter, 36); /* Future Use */
601 #endif /* BDIC_WRITE_CHECK */
602
603 return (0);
604 }
605
606 JS_STATIC int
input_file_header(FILE * ifpter,struct wnn_file_head * hp)607 input_file_header (FILE* ifpter, struct wnn_file_head* hp)
608 {
609 char wnn_file_string[WNN_FILE_STRING_LEN + 1];
610 int err = 0;
611
612 get_nstring (ifpter, WNN_FILE_STRING_LEN, wnn_file_string);
613 if (strncmp (wnn_file_string, WNN_FILE_STRING, WNN_FILE_STRING_LEN))
614 err = -1;
615 if (get_int ((&hp->file_type), ifpter) == -1)
616 err = -1;
617 if (input_file_uniq (&(hp->file_uniq), ifpter) == -1)
618 err = -1;
619 if (input_file_uniq (&(hp->file_uniq_org), ifpter) == -1)
620 err = -1;
621 get_nstring (ifpter, WNN_PASSWD_LEN, hp->file_passwd);
622 get_null (ifpter, 36);
623
624 return (err);
625 }
626
627 /* XXX was void when BDIC_WRITE_CHECK was not defined. cf put_null() above. */
628 JS_STATIC int
output_file_uniq(struct wnn_file_uniq * funiq,FILE * ofpter)629 output_file_uniq (struct wnn_file_uniq* funiq, FILE* ofpter)
630 {
631 #ifdef BDIC_WRITE_CHECK
632 if ((put_int (ofpter, funiq->time) == -1)
633 || (put_int (ofpter, funiq->dev) == -1)
634 || (put_int (ofpter, funiq->inode) == -1)
635 || (put_nstring (ofpter, funiq->createhost, strlen (funiq->createhost)) == -1)
636 || (put_null (ofpter, WNN_HOSTLEN - strlen (funiq->createhost)) == -1))
637 return (-1);
638 #else /* BDIC_WRITE_CHECK */
639 put_int (ofpter, funiq->time);
640 put_int (ofpter, funiq->dev);
641 put_int (ofpter, funiq->inode);
642 put_nstring (ofpter, funiq->createhost, strlen (funiq->createhost));
643 put_null (ofpter, WNN_HOSTLEN - strlen (funiq->createhost));
644 #endif /* BDIC_WRITE_CHECK */
645
646 return (0);
647 }
648
649 JS_STATIC int
input_file_uniq(struct wnn_file_uniq * funiq,FILE * ifpter)650 input_file_uniq (struct wnn_file_uniq* funiq, FILE* ifpter)
651 {
652 if (get_int (&(funiq->time), ifpter) == -1
653 || get_int (&(funiq->dev), ifpter) == -1
654 || get_int (&(funiq->inode), ifpter) == -1
655 || get_nstring (ifpter, WNN_HOSTLEN, funiq->createhost) == -1)
656 return (-1);
657
658 return (0);
659 }
660
661 JS_STATIC int
check_inode(FILE * f,struct wnn_file_head * fh)662 check_inode (FILE* f, struct wnn_file_head* fh)
663 {
664 struct stat buf;
665 if (fstat (fileno (f), &buf) == -1)
666 {
667 return (-1);
668 }
669 if ((int) buf.st_ino != fh->file_uniq.inode)
670 {
671 return (-1);
672 }
673 return (0);
674 }
675
676 JS_STATIC int
change_file_uniq(struct wnn_file_head * fh,char * n)677 change_file_uniq (struct wnn_file_head* fh, char* n)
678 {
679 int x;
680 FILE *fp;
681 #ifdef BDIC_WRITE_CHECK
682 char *tmp, *backup = NULL;
683 backup = make_backup_file (n);
684 if ((tmp = make_tmp_file (n, 1, &fp)) == NULL)
685 {
686 delete_tmp_file (backup);
687 #else /* BDIC_WRITE_CHECK */
688 if ((fp = fopen (n, "r+")) == NULL)
689 {
690 #endif /* BDIC_WRITE_CHECK */
691 return (-1);
692 }
693 #ifdef BDIC_WRITE_CHECK
694 if (change_file_uniq1 (fp, fh->file_type, fh->file_passwd, &(fh->file_uniq)) == -1)
695 {
696 fclose (fp);
697 delete_tmp_file (tmp);
698 delete_tmp_file (backup);
699 return (-1);
700 }
701 #else /* BDIC_WRITE_CHECK */
702 change_file_uniq1 (fp, fh->file_type, fh->file_passwd, &(fh->file_uniq));
703 #endif /* BDIC_WRITE_CHECK */
704 fseek (fp, 0, 0);
705 x = input_file_header (fp, fh); /* It must not occur. */
706 fclose (fp);
707
708 if (x == -1)
709 {
710 #ifdef BDIC_WRITE_CHECK
711 delete_tmp_file (tmp);
712 delete_tmp_file (backup);
713 #endif /* BDIC_WRITE_CHECK */
714 return (-1);
715 }
716
717 #ifdef BDIC_WRITE_CHECK
718 move_tmp_to_org (tmp, n, 0);
719 delete_tmp_file (backup);
720 #endif /* BDIC_WRITE_CHECK */
721
722 return (0);
723 }
724
725 JS_STATIC int
726 change_file_uniq1 (
727 FILE* ofpter,
728 int file_type,
729 char* file_passwd,
730 struct wnn_file_uniq* file_uniq)
731 {
732 struct stat buf;
733 char hostname[WNN_HOSTLEN];
734 struct wnn_file_head fh;
735
736 if (fstat (fileno (ofpter), &buf) == -1)
737 {
738 return (-1);
739 }
740 gethostname (hostname, WNN_HOSTLEN);
741 hostname[WNN_HOSTLEN - 1] = '\0';
742
743 fh.file_uniq.time = (int) buf.st_ctime;
744 fh.file_uniq.dev = (int) buf.st_dev;
745 fh.file_uniq.inode = (int) buf.st_ino;
746 bzero (fh.file_uniq.createhost, WNN_HOSTLEN);
747 strcpy (fh.file_uniq.createhost, hostname);
748
749 /* file_uniq_org */
750 fh.file_uniq_org.time = file_uniq->time;
751 fh.file_uniq_org.dev = file_uniq->dev;
752 fh.file_uniq_org.inode = file_uniq->inode;
753 bzero (fh.file_uniq_org.createhost, WNN_HOSTLEN);
754 strcpy (fh.file_uniq_org.createhost, file_uniq->createhost);
755
756 fh.file_type = file_type;
757 if (file_passwd)
758 {
759 strncpy (fh.file_passwd, file_passwd, WNN_PASSWD_LEN);
760 }
761 else
762 {
763 bzero (fh.file_passwd, WNN_PASSWD_LEN);
764 }
765 if (output_file_header (ofpter, &fh) == -1)
766 return (-1);
767 return (0);
768 }
769
770
771
772 #ifdef JSERVER
773 int
774 f_uniq_cmp (struct wnn_file_uniq *a, struct wnn_file_uniq* b)
775 {
776 return bcmp (a, b, sizeof (struct wnn_file_uniq));
777 }
778 #endif
779
780 #if !defined(JS) && !defined(JSERVER)
781 void
782 vputs (char* c, FILE* fp)
783 {
784 while (*c)
785 {
786 vputc (*c++, fp);
787 }
788 }
789
790 int
791 vputws (w_char* w, FILE* fp)
792 {
793 int n;
794 UCHAR tmp[LENGTHYOMI * 3];
795
796 n = wnn_sStrcpy (tmp, w);
797 vputs (tmp, fp);
798 return (n);
799 }
800 #endif /* !JS && !JSERVER */
801
802
803 #if !defined(JS) && !defined(JSERVER)
804 int
805 put_yomi_str (w_char* yomi, FILE* ofpter)
806 {
807 int c;
808 int i = 0;
809 UCHAR tmp[LENGTHYOMI * 3], *p;
810
811 wnn_sStrcpy (tmp, yomi);
812 for (p = tmp; *p; p++)
813 {
814 c = (int) *p;
815 if (c == '\\')
816 {
817 vputc ('\\', ofpter);
818 vputc ('\\', ofpter);
819 i += 2;
820 }
821 else if (c > 0x20)
822 {
823 vputc (c, ofpter);
824 i += 1;
825 }
826 else
827 {
828 char tmp[8];
829 sprintf (tmp, "\\0%o\\", c);
830 vputs (tmp, ofpter);
831 i += strlen (tmp);
832 }
833 }
834 return (i);
835 }
836 #endif /* !JS && !JSERVER */
837
838 #ifndef JS
839 void
840 Get_knj2 (UCHAR* kptr, int kanji2, w_char* kouho, w_char* yomi, w_char* comment)
841 {
842 int tcnt;
843 for (tcnt = 0; tcnt < kanji2; tcnt++)
844 {
845 kptr += *kptr;
846 }
847 get_kanji_str (kptr, kouho, yomi, comment);
848
849 return;
850 }
851
852 void
853 get_kanji_str (UCHAR* kptr, w_char* kanji, w_char* yomi, w_char* comment)
854 {
855 w_char *tmpy;
856 w_char *tmpk;
857 w_char *tmpc;
858 extern void Get_kanji_str_r ();
859
860 Get_kanji_str_r (kptr, &tmpk, &tmpy, &tmpc);
861
862 # ifdef CONVERT_from_TOP /* Don't worry. Only used in server and jutil */
863 if (kanji && tmpk)
864 wnn_Strcpy (kanji, tmpk);
865 if (yomi && tmpy)
866 wnn_Strcpy (yomi, tmpy);
867 # else /* !CONVERT_from_TOP */
868 if (kanji && tmpk)
869 wnn_Sreverse (kanji, tmpk);
870 if (yomi && tmpy)
871 wnn_Sreverse (yomi, tmpy);
872 # endif /* !CONVERT_from_TOP */
873 if (comment && tmpc)
874 wnn_Strcpy (comment, tmpc);
875 }
876
877
878 void
879 Get_kanji_str_r (UCHAR* kptr, w_char** tmpk, w_char** tmpy, w_char** tmpc)
880 {
881 int state = *(kptr + 1);
882 static w_char dmy = 0; /* Must not be allocated on Stack!! */
883 int adres;
884
885 if (state & FORWARDED)
886 {
887 /* Forward occures when comment-set is used */
888 adres = (*(w_char *) (kptr + 2)) << 16 | (*(w_char *) (kptr + 4));
889 Get_kanji_str_r (kptr + adres, tmpk, tmpy, tmpc);
890 return;
891 }
892 /* get_kanji_str_r(kptr, tmpk, tmpy, comment); */
893 if (state & HAS_YOMI)
894 {
895 *tmpy = ((w_char *) (kptr + 2));
896 *tmpk = *tmpy + wnn_Strlen (*tmpy) + 1;
897 }
898 else
899 {
900 *tmpy = &dmy;
901 *tmpk = ((w_char *) (kptr + 2));
902 }
903 if (state & HAS_COMMENT)
904 {
905 *tmpc = *tmpk + wnn_Strlen (*tmpk) + 1;
906 }
907 else
908 {
909 *tmpc = &dmy;
910 }
911 }
912
913 # ifdef nodef
914 int
915 Get_kanji_len (UCHAR* kptr, int which)
916 {
917 w_char tmp[LENGTHYOMI];
918
919 if (which == D_KANJI)
920 {
921 get_kanji_str_r (kptr, tmp, NULL, NULL);
922 }
923 else
924 {
925 get_kanji_str_r (kptr, NULL, tmp, NULL);
926 }
927 return (wnn_Strlen (tmp));
928 }
929
930 void
931 get_kanji_str_r (UCHAR* kptr, w_char* kanji, w_char* yomi, w_char* comment)
932 {
933 w_char *c;
934 int n, k;
935
936 n = *kptr++ - 1;
937 c = kanji;
938 if (comment)
939 *comment = 0;
940 if (yomi)
941 *yomi = 0;
942 for (k = 0; k < n;)
943 {
944 if (*kptr == DIC_COMMENT_CHAR)
945 {
946 if (c)
947 *c = 0;
948 c = comment;
949 kptr++;
950 k++;
951 }
952 else if (*kptr == DIC_YOMI_CHAR)
953 {
954 if (c)
955 *c = 0;
956 c = yomi;
957 kptr++;
958 k++;
959 }
960 else if (*kptr & 0x80)
961 { /* kanji char */
962 if (c)
963 *c++ = ((int) *kptr << 8 | *(kptr + 1));
964 kptr += 2;
965 k += 2;
966 }
967 else
968 {
969 if (c)
970 *c++ = *kptr;
971 kptr++;
972 k++;
973 }
974 }
975 if (c)
976 *c = 0;
977 }
978 # endif /* nodef */
979
980 UCHAR
981 kanjiaddr (UCHAR* d0, w_char* kanji, w_char* yomi, w_char* comment)
982 {
983 w_char *dest = (w_char *) (d0 + 2);
984 int state = 0;
985 w_char *pt;
986
987 if (yomi && *yomi)
988 {
989 # ifdef CONVERT_from_TOP /* Don't worry. Only used in server and jutil */
990 pt = yomi;
991 for (; *pt;)
992 {
993 *dest++ = *pt++;
994 }
995 # else /* !CONVERT_from_TOP */
996 pt = yomi + wnn_Strlen (yomi) - 1;
997 for (; pt >= yomi;)
998 {
999 *dest++ = *pt--;
1000 }
1001 # endif /* !CONVERT_from_TOP */
1002 state |= HAS_YOMI;
1003 *dest++ = 0;
1004 }
1005
1006 # ifdef CONVERT_from_TOP /* Don't worry. Only used in server and jutil */
1007 pt = kanji;
1008 for (; *pt;)
1009 {
1010 *dest++ = *pt++;
1011 }
1012 # else /* !CONVERT_from_TOP */
1013 pt = kanji + wnn_Strlen (kanji) - 1;
1014 for (; pt >= kanji;)
1015 {
1016 *dest++ = *pt--;
1017 }
1018 # endif /* !CONVERT_from_TOP */
1019 *dest++ = 0;
1020
1021 if (comment && *comment)
1022 {
1023 pt = comment;
1024 for (; *pt;)
1025 {
1026 *dest++ = *pt++;
1027 }
1028 state |= HAS_COMMENT;
1029 *dest++ = 0;
1030 }
1031 *d0 = (UCHAR) ((UCHAR *) dest - d0);
1032 *(d0 + 1) = state;
1033 return (*d0);
1034 }
1035
1036 #endif /* JS */
1037
1038
1039 JS_STATIC int
1040 create_null_dic (
1041 char* fn,
1042 w_char* comm,
1043 char* passwd,
1044 char* hpasswd, /* not encoded */
1045 int which)
1046 {
1047 FILE *fp;
1048 struct JT jt;
1049 char epasswd[WNN_PASSWD_LEN];
1050
1051 jt.total = 0;
1052 jt.gosuu = 0;
1053 if (hpasswd)
1054 {
1055 new_pwd (hpasswd, jt.hpasswd);
1056 }
1057 else
1058 {
1059 bzero (jt.hpasswd, WNN_PASSWD_LEN);
1060 }
1061 jt.syurui = which;
1062 jt.maxserial = 0;
1063 jt.maxtable = 0;
1064 jt.maxhontai = (which == WNN_UD_DICT) ? 4 : 0;
1065 jt.maxkanji = 0;
1066 if (comm)
1067 {
1068 jt.maxcomment = wnn_Strlen (comm);
1069 }
1070 else
1071 {
1072 jt.maxcomment = 0;
1073 }
1074 jt.maxhinsi_list = 0;
1075 jt.maxri1[D_YOMI] = 0;
1076 jt.maxri1[D_KANJI] = 0;
1077 jt.maxri2 = 0;
1078
1079 if ((fp = fopen (fn, "w")) == NULL)
1080 {
1081 /* error1( "Jserver:create_null_ud:No file %s.\n", fn); */
1082 return (-1);
1083 }
1084 if (passwd)
1085 {
1086 new_pwd (passwd, epasswd);
1087 }
1088 else
1089 {
1090 bzero (epasswd, WNN_PASSWD_LEN);
1091 }
1092 if (create_file_header (fp, WNN_FT_DICT_FILE, epasswd) == -1
1093 || output_header_jt (fp, &jt) == -1)
1094 {
1095 fclose (fp);
1096 return (-1);
1097 }
1098 #ifdef BDIC_WRITE_CHECK
1099 if (put_n_EU_str (fp, comm, jt.maxcomment) == -1)
1100 {
1101 fclose (fp);
1102 return (-1);
1103 }
1104 #else /* BDIC_WRITE_CHECK */
1105 put_n_EU_str (fp, comm, jt.maxcomment);
1106 #endif /* BDIC_WRITE_CHECK */
1107 if (which == WNN_UD_DICT)
1108 {
1109 #ifdef BDIC_WRITE_CHECK
1110 if (put_int (fp, 0) == -1)
1111 { /* hontai[0] */
1112 fclose (fp);
1113 return (-1);
1114 }
1115 #else /* BDIC_WRITE_CHECK */
1116 put_int (fp, 0); /* hontai[0] */
1117 #endif /* BDIC_WRITE_CHECK */
1118 }
1119
1120 #if HAVE_FCHMOD
1121 fchmod (fileno (fp), 0664);
1122 fclose (fp);
1123 #else /* !HAVE_FCHMOD */
1124 fclose (fp);
1125 chmod (fn, 0664);
1126 #endif /* !HAVE_FCHMOD */
1127 return (0);
1128 }
1129
1130
1131 JS_STATIC int
1132 create_hindo_file (
1133 struct wnn_file_uniq* funiq,
1134 char* fn,
1135 w_char* comm,
1136 char* passwd, /* Not encoded */
1137 int serial)
1138 {
1139 FILE *fp;
1140 struct HJT hjt;
1141 char epasswd[WNN_PASSWD_LEN];
1142 w_char tmp[1];
1143
1144 tmp[0] = 0;
1145 if (comm == NULL)
1146 comm = tmp;
1147 bcopy (funiq, &(hjt.dic_file_uniq), WNN_F_UNIQ_LEN);
1148 hjt.maxcomment = wnn_Strlen (comm);
1149
1150 hjt.maxserial = serial;
1151
1152 if ((fp = fopen (fn, "w")) == NULL)
1153 {
1154 return (-1);
1155 }
1156 if (passwd)
1157 {
1158 new_pwd (passwd, epasswd);
1159 }
1160 else
1161 {
1162 bzero (epasswd, WNN_PASSWD_LEN);
1163 }
1164 if (create_file_header (fp, WNN_FT_HINDO_FILE, epasswd) == -1)
1165 {
1166 fclose (fp);
1167 return (-1);
1168 }
1169 #ifdef BDIC_WRITE_CHECK
1170 if ((output_header_hjt (fp, &hjt) == -1)
1171 || (put_n_EU_str (fp, comm, hjt.maxcomment) == -1)
1172 || (put_null (fp, serial) == -1))
1173 {
1174 fclose (fp);
1175 return (-1);
1176 }
1177 #else /* BDIC_WRITE_CHECK */
1178 output_header_hjt (fp, &hjt);
1179 put_n_EU_str (fp, comm, hjt.maxcomment);
1180 put_null (fp, serial);
1181 #endif /* BDIC_WRITE_CHECK */
1182
1183 #if HAVE_FCHMOD
1184 fchmod (fileno (fp), 0664);
1185 fclose (fp);
1186 #else /* !HAVE_FCHMOD */
1187 fclose (fp);
1188 chmod (fn, 0664);
1189 #endif /* !HAVE_FCHMOD */
1190 return (0);
1191 }
1192
1193 /* Header Total 128 Bytes */
1194
1195 JS_STATIC int
1196 input_header_jt (FILE* ifpter, struct JT* jt1)
1197 {
1198 if (get_int (&jt1->syurui, ifpter) == -1
1199 || get_int (&jt1->maxcomment, ifpter) == -1
1200 || get_int (&jt1->maxhinsi_list, ifpter) == -1
1201 || get_int (&jt1->maxserial, ifpter) == -1
1202 || get_int (&jt1->maxkanji, ifpter) == -1
1203 || get_int (&jt1->maxtable, ifpter) == -1
1204 || get_int (&jt1->maxhontai, ifpter) == -1
1205 || get_int (&jt1->gosuu, ifpter) == -1
1206 || get_nstring (ifpter, WNN_PASSWD_LEN, jt1->hpasswd) == -1
1207 || get_int (&jt1->total, ifpter) == -1
1208 || get_int (&jt1->maxri1[D_YOMI], ifpter) == -1
1209 || get_int (&jt1->maxri1[D_KANJI], ifpter) == -1
1210 || get_int (&jt1->maxri2, ifpter) == -1
1211 || get_null (ifpter, 56) == -1)
1212 return (-1);
1213
1214 return (0);
1215 }
1216
1217 JS_STATIC int
1218 output_header_jt (FILE* ofpter, struct JT* jt1)
1219 {
1220 #ifdef BDIC_WRITE_CHECK
1221 if ((put_int (ofpter, jt1->syurui) == -1)
1222 || (put_int (ofpter, jt1->maxcomment) == -1)
1223 || (put_int (ofpter, jt1->maxhinsi_list) == -1)
1224 || (put_int (ofpter, jt1->maxserial) == -1)
1225 || (put_int (ofpter, jt1->maxkanji) == -1)
1226 || (put_int (ofpter, jt1->maxtable) == -1)
1227 || (put_int (ofpter, jt1->maxhontai) == -1)
1228 || (put_int (ofpter, jt1->gosuu) == -1)
1229 || (put_nstring (ofpter, jt1->hpasswd, WNN_PASSWD_LEN) == -1)
1230 || (put_int (ofpter, jt1->total) == -1)
1231 || (put_int (ofpter, jt1->maxri1[D_YOMI]) == -1)
1232 || (put_int (ofpter, jt1->maxri1[D_KANJI]) == -1)
1233 || (put_int (ofpter, jt1->maxri2) == -1)
1234 || (put_null (ofpter, 56) == -1))
1235 return (-1);
1236 #else /* BDIC_WRITE_CHECK */
1237 put_int (ofpter, jt1->syurui);
1238 put_int (ofpter, jt1->maxcomment);
1239 put_int (ofpter, jt1->maxhinsi_list);
1240 put_int (ofpter, jt1->maxserial);
1241 put_int (ofpter, jt1->maxkanji);
1242 put_int (ofpter, jt1->maxtable);
1243 put_int (ofpter, jt1->maxhontai);
1244 put_int (ofpter, jt1->gosuu);
1245 put_nstring (ofpter, jt1->hpasswd, WNN_PASSWD_LEN);
1246 put_int (ofpter, jt1->total);
1247 put_int (ofpter, jt1->maxri1[D_YOMI]);
1248 put_int (ofpter, jt1->maxri1[D_KANJI]);
1249 put_int (ofpter, jt1->maxri2);
1250 put_null (ofpter, 56);
1251 #endif /* BDIC_WRITE_CHECK */
1252
1253 return (0);
1254 }
1255
1256 /* Header 64 Byte */
1257 JS_STATIC int
1258 input_header_hjt (FILE* ifpter, struct HJT* hjt1)
1259 {
1260 if (input_file_uniq (&hjt1->dic_file_uniq, ifpter) == -1 /* 7 * 4 */
1261 || get_int (&hjt1->maxcomment, ifpter) == -1
1262 || get_int (&hjt1->maxserial, ifpter) == -1
1263 || get_null (ifpter, 28) == -1)
1264 return (-1);
1265
1266 return (0);
1267 }
1268
1269 JS_STATIC int
1270 output_header_hjt (FILE* ofpter, struct HJT* hjt1)
1271 {
1272 #ifdef BDIC_WRITE_CHECK
1273 if ((output_file_uniq (&hjt1->dic_file_uniq, ofpter) == -1)
1274 || (put_int (ofpter, hjt1->maxcomment) == -1)
1275 || (put_int (ofpter, hjt1->maxserial) == -1)
1276 || (put_null (ofpter, 28) == -1))
1277 return (-1);
1278 #else /* BDIC_WRITE_CHECK */
1279 output_file_uniq (&hjt1->dic_file_uniq, ofpter);
1280 put_int (ofpter, hjt1->maxcomment);
1281 put_int (ofpter, hjt1->maxserial);
1282 put_null (ofpter, 28);
1283 #endif /* BDIC_WRITE_CHECK */
1284
1285 return (0);
1286 }
1287
1288
1289 #if !defined(JS) && !defined(JSERVER)
1290 /* Only used in JUTIL */
1291 void
1292 Print_entry (
1293 w_char* yomi,
1294 w_char* kstr,
1295 w_char* cstr,
1296 int hindo,
1297 int ima,
1298 int hinsi,
1299 int serial,
1300 FILE* ofpter,
1301 int esc_exp)
1302 {
1303 int len;
1304 char *k;
1305 char buf[32];
1306 static w_char revy[LENGTHKANJI];
1307 extern void kanji_esc_str ();
1308
1309 if (serial != -1)
1310 {
1311 sprintf (buf, "%d\t", serial);
1312 vputs (buf, ofpter);
1313 }
1314
1315 len = put_yomi_str (yomi, ofpter);
1316 if (len < 8)
1317 vputc ('\t', ofpter);
1318 if (len < 16)
1319 vputc ('\t', ofpter);
1320 vputc ('\t', ofpter);
1321
1322 if (esc_exp)
1323 {
1324 #ifdef CONVERT_from_TOP /* Don't warry. Only use in jutil */
1325 wnn_Strcpy (revy, yomi);
1326 #else /* conver from bottom */
1327 wnn_Sreverse (revy, yomi);
1328 #endif /* CONVERT_from_TOP */
1329 kanji_esc_str (kstr, revy, wnn_Strlen (yomi));
1330 len = put_yomi_str (kstr, ofpter);
1331 }
1332 else
1333 {
1334 len = vputws (kstr, ofpter);
1335 }
1336 if (len < 8)
1337 vputc ('\t', ofpter);
1338 if (len < 16)
1339 vputc ('\t', ofpter);
1340 vputc ('\t', ofpter);
1341
1342 k = wnn_get_hinsi_name (hinsi);
1343 if (k)
1344 {
1345 vputs (k, ofpter);
1346 if ((int) strlen (k) < 8)
1347 vputc ('\t', ofpter);
1348 vputc ('\t', ofpter);
1349 }
1350 else
1351 {
1352 sprintf (buf, "%d\t\t", hinsi);
1353 vputs (buf, ofpter);
1354 }
1355
1356 if (ima)
1357 vputc ('*', ofpter);
1358 if (hindo == -1)
1359 { /* Real hindo == -1 means Not to use it */
1360 vputs ("-", ofpter);
1361 }
1362 else
1363 {
1364 sprintf (buf, "%d", hindo);
1365 vputs (buf, ofpter);
1366 }
1367 if (cstr && cstr[0])
1368 {
1369 vputc ('\t', ofpter);
1370 len = vputws (cstr, ofpter);
1371 }
1372 vputc ('\n', ofpter);
1373 }
1374 #endif /* !JS && !JSERVER */
1375
1376 #ifdef BDIC_WRITE_CHECK
1377 #undef BDIC_WRITE_CHECK
1378 #endif
1379