1/* Copyright 1994 NEC Corporation, Tokyo, Japan.
2 *
3 * Permission to use, copy, modify, distribute and sell this software
4 * and its documentation for any purpose is hereby granted without
5 * fee, provided that the above copyright notice appear in all copies
6 * and that both that copyright notice and this permission notice
7 * appear in supporting documentation, and that the name of NEC
8 * Corporation not be used in advertising or publicity pertaining to
9 * distribution of the software without specific, written prior
10 * permission.  NEC Corporation makes no representations about the
11 * suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
16 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#if !defined(lint) && !defined(__CODECENTER__)
24static char rcsid[]="@(#) 102.1 $Id: dic.c 14875 2005-11-12 21:25:31Z bonefish $";
25#endif
26/*LINTLIBRARY*/
27
28#include "RKintern.h"
29
30#include <stdio.h> /* for sprintf */
31#include <string.h>
32#include <unistd.h>
33#include <fcntl.h>
34
35#define dm_td		dm_extdata.ptr
36#define cx_gwt		cx_extdata.ptr
37#define Is_Gwt_CTX(cx)
38
39#define ND2RK(s)	((0x80 >> (int)(s)) & 0xff)
40#define	STRCMP(d, s)	strcmp((char *)(d), (char *)(s))
41
42#define FREQ_TEMPLATE	"frq%d.cld"
43#define USER_TEMPLATE	"usr%d.ctd"
44#define PERM_TEMPLATE	"bin%d.cbd"
45
46#define DEFAULT_PERMISSION	"w"
47
48static int locatepath(struct DD *userDDP[], struct DD *ddpath[], int mode);
49static struct td_n_tupple *pushTdn(struct RkContext *cx, struct TD *tdp);
50
51/* locatepath -- ¼­½ñ¥µ¡¼¥Á¥Ñ¥¹¤ò mode ¤Ë±þ¤¸¤ÆÄ¥¤ë
52
53   return value:
54       0: À®¸ù
55   ACCES: ¥¨¥é¡¼(¥°¥ë¡¼¥×¤ò»ØÄꤷ¤¿¤Î¤Ë DDPATH ¤Ë¸ºß¤·¤Ê¤¤)
56 */
57
58static int
59locatepath(struct DD *userDDP[], struct DD *ddpath[], int mode)
60{
61  /* find dictionary under system and user/group directory */
62  if (mode & RK_SYS_DIC) {
63    if (ddpath[2]) {
64      userDDP[0] = ddpath[2];
65    }
66    else {
67      return ACCES;
68    }
69  } else
70  if (mode & RK_GRP_DIC) {
71    if (ddpath[1] && ddpath[2]) {
72      /* ¥°¥ë¡¼¥×¼­½ñ¤È¥·¥¹¥Æ¥à¼­½ñ¤¬¤Á¤ã¤ó¤È¤¢¤ì¤Ð */
73      userDDP[0] = ddpath[1];
74    }
75    else {
76      return ACCES;
77    }
78  }
79  else { /* ¥æ¡¼¥¶¼­½ñ */
80    userDDP[0] = ddpath[0];
81  }
82  userDDP[1] = (struct DD*)0;
83  return 0;
84}
85
86
87/* int
88 * RkwCreateDic(cx_num, dicname, mode)
89 *
90 * °ú¤­¿ô
91 *         int            cx_num    ¥³¥ó¥Æ¥¯¥¹¥È¥Ê¥ó¥Ð¡¼
92 *	   unsigned char  *dicname  ¼­½ñ¤Ø¤Î¥Ý¥¤¥ó¥¿
93 *	   int            mode      ¼­½ñ¤Î¼ïÎà¤È¶¯À©¥â¡¼¥É¤ÎOR
94 *             ¼­½ñ¤Î¼ïÎà
95 *                 #define	Rk_MWD		0x80
96 *                 #define	Rk_SWD		0x40
97 *                 #define	Rk_PRE		0x20
98 *                 #define	Rk_SUC		0x10
99 *             ¶¯À©¥â¡¼¥É
100 *                 #define KYOUSEI	        0x01
101 *                 ¶¯À©¤·¤Ê¤¤¾ì¹ç           0x00
102#define PL_DIC		(0x0100)
103#define PL_ALLOW	(PL_DIC << 1)
104#define PL_INHIBIT	(PL_DIC << 2)
105#define PL_FORCE	(PL_DIC << 3)
106 *
107 * ¥ê¥¿¡¼¥óÃÍ
108 *             À®¸ù¤·¤¿¾ì¹ç                                 0
109 *             À®¸ù¤·¤¿¾ì¹ç(¾å½ñ¤­¤·¤¿¾ì¹ç)                 1
110 *             ¥¢¥í¥±¡¼¥·¥ç¥ó¤Ë¼ºÇÔ¤·¤¿¾ì¹ç                -6  NOTALC
111 *             ¼­½ñ¤¬¥Ð¥¤¥Ê¥ê¼­½ñ¤Ç¤¢¤Ã¤¿¾ì¹ç              -9    BADF
112 *             dics.dir¤Ë°Û¾ï¤¬¤¢¤Ã¤¿¾ì¹ç                 -10   BADDR
113 *             GetDicFilenameÊÖ¤êÃͤ¬-1¤Î¾ì¹ç           -13   ACCES
114 *             MakeDicFile¤Ë¼ºÇÔ¤·¤¿¾ì¹ç                  -13   ACCES
115 *             CreatDic¤Ë¼ºÇÔ¤·¤¿¾ì¹ç                     -13   ACCES
116 *             ¼­½ñ¤¬¥Þ¥¦¥ó¥ÈÃæ¤Ç¤¢¤Ã¤¿¾ì¹ç               -16   MOUNT
117 *             ¼­½ñ¤¬¤¹¤Ç¤Ë¤¢¤ë¾ì¹ç(¶¯À©¤Ç¤Ê¤¤¾ì¹ç)       -17   EXIST
118 *             ¼­½ñ¤¬»ÈÍÑÃæ¤Ç¤¢¤Ã¤¿¾ì¹ç                   -26  TXTBSY
119 *             mode¤¬°Û¾ïÃͤǤ¢¤Ã¤¿¾ì¹ç                   -99  BADARG
120 *             ¥³¥ó¥Æ¥¯¥¹¥È¹½Â¤ÂΤ¬Â¸ºß¤·¤Ê¤¤¾ì¹ç        -100 BADCONT
121 */
122
123int
124RkwCreateDic(int cx_num, char *dicname, int mode)
125{
126  struct RkParam	*sx = RkGetSystem();
127
128  struct RkContext	*cx = RkGetContext(cx_num);
129  struct DM             *sm, *um, *tm;
130  int			type;
131  struct DD		*userDDP[2], *systemDDP[2];
132  char	      		*filename, extent[5];
133  int ret;
134#ifndef USE_MALLOC_FOR_BIG_ARRAY
135  char            	spec[RK_LINE_BMAX];
136#else
137  char *spec = (char *)malloc(RK_LINE_BMAX);
138  if (!spec) {
139    return NOTALC;
140  }
141#endif
142
143  if(!dicname || !dicname[0]) {
144    ret = ACCES;
145    goto return_ret;
146  }
147  if (strlen(dicname) >= (unsigned)RK_NICK_BMAX) {
148    ret = INVAL;
149    goto return_ret;
150  }
151  if ( !cx || !cx->ddpath || !cx->ddpath[0] ) {
152    ret = BADCONT;
153    goto return_ret;
154  }
155  if ( !sx || !sx->ddpath || !sx->ddpath[0] ) {
156    ret = BADCONT;
157    goto return_ret;
158  }
159#ifndef STANDALONE /* Is it true ? */
160  if ( cx->ddpath[0] == sx->ddpath[0] ) {
161    ret = BADCONT;
162    goto return_ret;
163  }
164#endif
165
166  if (locatepath(userDDP, cx->ddpath, mode) < 0) {
167    ret = ACCES;
168    goto return_ret;
169  }
170  if (!(userDDP[0]->dd_flags & DD_WRITEOK)) {
171    ret = ACCES;
172    goto return_ret;
173  }
174
175  systemDDP[0] = sx->ddpath[0];
176  systemDDP[1] = (struct DD *)0;
177
178  type = (mode & PL_DIC) ? DF_FREQDIC : DF_TEMPDIC;
179/* find dictionary in current mount list */
180  sm = _RkSearchDDQ(systemDDP, dicname, type);
181  um = _RkSearchDDQ(userDDP, dicname, type);
182
183  if (um && !(mode & KYOUSEI)) {
184    ret = EXIST;
185    goto return_ret;
186  }
187
188  if (mode & PL_DIC) {
189    if (!sm) {
190      if(_RkSearchDDQ(systemDDP, dicname, DF_TEMPDIC)) {
191	ret = BADF;
192	goto return_ret;
193      }
194      ret = NOENT;
195      goto return_ret;
196    }
197    if (!um) {
198      struct DM	*dm;
199
200      if (!(filename = _RkCreateUniquePath(userDDP[0], FREQ_TEMPLATE))) {
201	ret = ACCES;
202	goto return_ret;
203      }
204      (void)sprintf(spec, "%s(%s) -%s--%s-\n",
205		    filename, sm->dm_dicname, sm->dm_nickname,
206		    DEFAULT_PERMISSION);
207      if (!DMcheck(spec, dicname)) {
208	ret = NOENT;
209	goto return_ret;
210      }
211      if (!(dm = DMcreate(userDDP[0], spec))) {
212	ret = NOTALC;
213	goto return_ret;
214      }
215      if (copyFile(sm, dm)) {
216	ret = ACCES;
217	goto return_ret;
218      }else{
219	ret = 0;
220	goto return_ret;
221      }
222    } else {
223      if (!(ND2RK(um->dm_class) & mode)) {
224	ret = INVAL;
225	goto return_ret;
226      }
227      if ( um->dm_rcount > 0 ) {
228	ret = TXTBSY;
229	goto return_ret;
230      }
231      if ( !um->dm_file ) {
232	ret = BADCONT;	/* INVAL SHOULD BE REPLACED... MAKO 1225 */
233	goto return_ret;
234      }
235
236      if(_RkRealizeDF(um->dm_file)) {/* ¤³¤ì¤¤¤é¤Ê¤¤¤ó¤¸¤ã¤Ê¤¤¡© kon 1993.11 */
237	ret = ACCES;
238	goto return_ret;
239      }
240      if ( copyFile(sm, um) ) {
241	ret = ACCES;
242	goto return_ret;
243      }else{
244	ret = 1;
245	goto return_ret;
246      }
247    }
248  } else {
249    /*    um = _RkSearchDDQ(userDDP, dicname, DF_TEMPDIC);*/
250    tm = _RkSearchDDP(userDDP, dicname);
251    if (tm != um) {
252      ret = BADF;
253      goto return_ret;
254    }
255    if (!um) {
256      if (!(filename = _RkCreateUniquePath(userDDP[0], USER_TEMPLATE))) {
257	ret = ACCES;
258	goto return_ret;
259      }
260      if (mode & Rk_MWD) {
261	  (void)strcpy(extent, "mwd");
262      } else if (mode & Rk_SWD) {
263	  (void)strcpy(extent, "swd");
264      } else if (mode & Rk_PRE) {
265	  (void)strcpy(extent, "pre");
266      } else if (mode & Rk_SUC) {
267	  (void)strcpy(extent, "suc");
268      } else {
269	  /* return INVAL;	*/
270	  (void)strcpy(extent, "mwd");
271      };
272      (void)sprintf(spec, "%s(.%s) -%s--%s-\n", filename, extent, dicname,
273		    DEFAULT_PERMISSION);
274      if (!DMcheck(spec, dicname)) {
275	ret = NOENT;
276	goto return_ret;
277      }
278      if (!DMcreate(userDDP[0], spec)) {
279	ret = NOTALC;
280	goto return_ret;
281      }
282      _RkRealizeDD(userDDP[0]);
283      ret = 0;
284      goto return_ret;
285    } else {
286      if ( um->dm_rcount > 0 ) {
287	ret = TXTBSY;
288	goto return_ret;
289      }
290      if ( !um->dm_file ) {
291	ret = BADCONT;	/* INVAL SHOULD BE REPLACED... MAKO 1225 */
292	goto return_ret;
293      }
294      sprintf(spec, "%s(%s) -%s--%s%s-\n",
295	      um->dm_file->df_link, um->dm_dicname, um->dm_nickname,
296	      (um->dm_flags & DM_READOK) ? "r" : "",
297	      (um->dm_flags & DM_WRITEOK) ? "w" : "");
298      if(_RkRealizeDF(um->dm_file)) {
299	ret = ACCES;
300	goto return_ret;
301      }
302      ret = 1;	/* backward compatiblity ... 1224 Xmas */
303    }
304  }
305 return_ret:
306#ifdef USE_MALLOC_FOR_BIG_ARRAY
307  free(spec);
308#endif
309  return ret;
310}
311
312int copyFile(struct DM *src, struct DM *dst)
313{
314  struct DF	*srcF = src->dm_file;
315  struct DD	*srcD = srcF->df_direct;
316  struct DF	*dstF = dst->dm_file;
317  struct DD	*dstD = dstF->df_direct;
318  char		*srcN, *dstN;
319#ifndef WIN
320  int		srcFd, dstFd;
321  int		n;
322#else
323  HANDLE srcFd, dstFd;
324  DWORD n, nextn;
325#endif
326  int		ecount = 0;
327
328  srcN = _RkCreatePath(srcD, srcF->df_link);
329  if (srcN) {
330#ifdef WIN
331    srcFd = CreateFile(srcN, GENERIC_READ,
332		       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
333		       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
334#else
335    srcFd = open(srcN, 0);
336#endif
337    free(srcN);
338    if
339#ifdef WIN
340      (srcFd != INVALID_HANDLE_VALUE)
341#else
342      (srcFd >= 0)
343#endif
344    {
345      dstN = _RkCreatePath(dstD, dstF->df_link);
346      if (dstN) {
347#ifdef WIN
348	dstFd = CreateFile(dstN, GENERIC_WRITE,
349			   FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
350			   CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
351#else
352	dstFd = creat(dstN, 0666);
353#endif
354	free(dstN);
355
356	if
357#ifdef WIN
358	  (dstFd != INVALID_HANDLE_VALUE)
359#else
360	  (dstFd >= 0)
361#endif
362	{
363	  char b[RK_BUFFER_SIZE];
364	  /* I will leave this array on the stack because it may be a rare
365	     case to use this function. 1996.6.5 kon */
366
367	  _RkRealizeDD(dstD);
368
369	  while
370#ifdef WIN
371	    (ReadFile(srcFd, b, RK_BUFFER_SIZE, &n, NULL) && n > 0)
372#else
373	    ((n = read(srcFd, b, RK_BUFFER_SIZE)) > 0)
374#endif
375	  { /* do copy */
376	    if
377#ifdef WIN
378	      (!WriteFile(dstFd, b, n, &nextn, NULL) || nextn != n)
379#else
380	      ( write(dstFd, b, n) != n )
381#endif
382	    {
383	      ecount++;
384	      break;
385	    }
386	  }
387	  if (
388#ifdef WIN
389	    !CloseHandle(dstFd)
390#else
391	    close(dstFd) < 0
392#endif
393	      || n < 0)
394	  {
395	    ecount++;
396	  }
397	}
398      }
399#ifdef WIN
400      CloseHandle(srcFd);
401#else
402      close(srcFd);
403#endif
404    }
405  }
406  return ecount ? -1 : 0;
407}
408
409/*
410 * RkwListDic(cx_num, dirname, buf, size)
411 * int  cx_num;             ¥³¥ó¥Æ¥¯¥¹¥È¥Ê¥ó¥Ð¡¼
412 * unsigned char *dirname;  ¼­½ñ¥ê¥¹¥È¤ò½ÐÎϤ·¤¿¤¤¥Ç¥£¥ì¥¯¥È¥ê̾
413 * unsigned char *buf;      ¼­½ñ¥ê¥¹¥È¤¬Ê֤äƤ¯¤ë¥Ð¥Ã¥Õ¥¡
414 * int  size;               ¥Ð¥Ã¥Õ¥¡¤Î¥µ¥¤¥º
415 *
416 * ¥ê¥¿¡¼¥óÃÍ
417 *             À®¸ù¤·¤¿¾ì¹ç                      ¼­½ñ¤Î¿ô
418 *             ¥³¥ó¥Æ¥¯¥¹¥È¥Ê¥ó¥Ð¡¼¤¬Éé¤Î¾ì¹ç          BADCONT
419 *             RkwCreateContext¤Ë¼ºÇÔ¤·¤¿¾ì¹ç           BADCONT
420 *             RkwSetDicPath¤Ë¼ºÇÔ¤·¤¿¾ì¹ç              NOTALC
421 */
422int
423RkwListDic(int cx_num, char *dirname, char *buf, int size)
424{
425  int dicscnt;
426  int new_cx_num;
427
428  if(!dirname || !strlen(dirname))
429    return 0;
430  if (cx_num < 0)
431    return BADCONT;
432  if((new_cx_num = RkwCreateContext()) < 0)
433    return BADCONT;
434  if (RkwSetDicPath(new_cx_num, dirname) == -1) {
435    RkwCloseContext(new_cx_num);
436    return NOTALC;
437  }
438  dicscnt = RkwGetDicList(new_cx_num, buf, size);
439  (void)RkwCloseContext(new_cx_num);
440  return (dicscnt);
441}
442
443/* int
444 * RkwRemoveDic(cx_num, dicname, mode)
445 *
446 * »ØÄꤵ¤ì¤¿¥³¥ó¥Æ¥¯¥¹¥È¤Ë»ØÄꤵ¤ì¤¿¼­½ñ¤¬Â¸ºß¤¹¤ì¤Ð
447 * ¤½¤Î¼­½ñ¤òºï½ü¤¹¤ë¡£
448 *
449 * °ú¤­¿ô
450 *             int            cx_num     ¥³¥ó¥Æ¥¯¥¹¥È¥Ê¥ó¥Ð¡¼
451 *             unsigned char  *dicname   ¼­½ñ̾
452 *
453 * ¥ê¥¿¡¼¥óÃÍ
454 *             À®¸ù¤·¤¿¾ì¹ç                             0
455 *             ¼­½ñ¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç                    -2   NOENT
456 *             ¼­½ñ¤¬¥Ð¥¤¥Ê¥ê¼­½ñ¤Ç¤¢¤Ã¤¿¾ì¹ç          -9    BADF
457 *             RemoveDic¤ÎÊÖ¤êÃͤ¬-1¤Î¾ì¹ç            -13   ACCES
458 *             ¥Þ¥¦¥ó¥È¤·¤Æ¤¤¤¿¾ì¹ç                   -26  TXTBSY
459 *             ¥³¥ó¥Æ¥¯¥¹¥È¹½Â¤ÂΤ¬Â¸ºß¤·¤Ê¤¤¾ì¹ç    -100 BADCONT
460 */
461int
462RkwRemoveDic(int cx_num, char *dicname, int mode)
463{
464  struct RkContext	*cx = RkGetContext(cx_num);
465/*  struct RkParam	*sx = RkGetSystem();	*/
466  struct DD		*userDDP[2], *dum_direct;
467  struct DM             *dm;
468  char			*path;
469  int res;
470
471  if(!dicname)
472    return NOENT;
473  if ( !cx || !cx->ddpath || !cx->ddpath[0] )
474      return BADCONT;
475
476  if (locatepath(userDDP, cx->ddpath, mode) < 0) {
477    return ACCES;
478  }
479
480  /* find dictionary in current mount list */
481  dm = _RkSearchDDP(userDDP, (char *)dicname);
482  if (!dm || ((mode & PL_DIC) && dm->dm_file->df_type != DF_FREQDIC)) {
483    return NOENT;
484  }
485  if ( dm->dm_rcount > 0 )
486	return TXTBSY;
487  if ( !dm->dm_file ) /* ? */
488	return BADCONT;
489  if (!(dm->dm_file->df_direct->dd_flags & DD_WRITEOK) ||
490      (!(dm->dm_flags & DM_WRITEOK) && !(mode & KYOUSEI))) {
491    return ACCES;
492  }
493  if (!(path = _RkMakePath(dm->dm_file)))
494	return NOTALC;
495  res = unlink(path);
496  free(path);
497  if(res)
498    return ACCES;
499  dum_direct = dm->dm_file->df_direct;
500  DMremove(dm);
501  (void)_RkRealizeDD(dum_direct);
502  return 0;
503}
504
505/* int
506 * RkwRenameDic(cx_num, oldnick, newnick, mode)
507 *
508 * »ØÄꤵ¤ì¤¿¥³¥ó¥Æ¥¯¥¹¥È¤Ë»ØÄꤵ¤ì¤¿¼­½ñ¤¬Â¸ºß¤¹¤ì¤Ð
509 * ¤½¤Î¼­½ñ¤Î̾Á°¤òÊѹ¹¤¹¤ë¡£
510 *
511 * °ú¤­¿ô
512 *          int            cx_num           ¥³¥ó¥Æ¥¯¥¹¥È¥Ê¥ó¥Ð¡¼
513 *          unsigned char  *oldnick        Êѹ¹¸µ¼­½ñ̾
514 *          unsigned char  *newnick        Êѹ¹Àè¼­½ñ̾
515 *          int            mode             ¶¯À©¥â¡¼¥É
516 *
517 * ÊÖ¤êÃÍ (RKdic.h»²¾È)
518 *          À®¸ù¤·¤¿¾ì¹ç                             0
519 *          oldnick¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç                -2     NOENT
520 *          RemoveDic¤ÎÊÖ¤êÃͤ¬-1¤Î¾ì¹ç             -2     NOENT
521 *          ¼­½ñ¤¬¥Ð¥¤¥Ê¥ê¼­½ñ¤Ç¤¢¤Ã¤¿¾ì¹ç          -9      BADF
522 *          RenameDicFile¤ÎÊÖ¤êÃͤ¬-1¤Î¾ì¹ç        -13     ACCES
523 *          newnick¤¬Â¸ºß¤¹¤ë¾ì¹ç                 -17     EXIST
524 *          oldnick¤ò¥Þ¥¦¥ó¥È¤·¤Æ¤¤¤¿¾ì¹ç         -26    TXTBSY
525 *          newnick¤ò¥Þ¥¦¥ó¥È¤·¤Æ¤¤¤¿¾ì¹ç         -26    TXTBSY
526 *          ¥³¥ó¥Æ¥¯¥¹¥È¹½Â¤ÂΤ¬Â¸ºß¤·¤Ê¤¤¾ì¹ç    -100   BADCONT
527 */
528int
529RkwRenameDic(int cx_num, char *old, char *newc, int mode)
530{
531  struct RkContext	*cx = RkGetContext(cx_num);
532  struct DD		*userDDP[2], *dd;
533  struct DM		*dm1, *dm2;
534  char			*path;
535  char            	spec[RK_LINE_BMAX];
536  /* I leave this array on the stack because this will not glow so big.
537   1996.6.5 kon */
538
539  if(!old || !*old)
540    return NOENT;
541  if(!newc || !*newc)
542    return ACCES;
543  if (!cx || !cx->ddpath || !cx->ddpath[0])
544    return BADCONT;
545  if (strlen((char *)newc) >= (unsigned)RK_NICK_BMAX) {
546    return INVAL;
547  }
548
549  if (locatepath(userDDP, cx->ddpath, mode) < 0) {
550    return ACCES;
551  }
552
553  dm1 = _RkSearchDDP(userDDP, (char *)old);
554  if (!dm1) {
555    return NOENT;
556  }
557
558  dd = dm1->dm_file->df_direct;
559  if (!(dd->dd_flags & DD_WRITEOK)) {
560    return ACCES;
561  }
562
563  dm2 = _RkSearchDDP(userDDP, (char *)newc);
564
565  if (dm1->dm_rcount > 0)
566    return TXTBSY;
567  if (dm2) { /* ¿·¤·¤¤Ì¾Á°¤¬¡¢´û¤Ë¼­½ñ¤È¤·¤Æ¸ºß¤¹¤ì¤Ð */
568    if (dm2->dm_rcount > 0)
569      return TXTBSY;
570    if (!(mode & KYOUSEI))
571      return EXIST;
572    if (!(path = _RkMakePath(dm2->dm_file)))
573      return NOTALC;
574    (void)unlink(path);
575    free(path);
576    DMremove(dm2);
577    DMrename(dm1, (unsigned char *)newc);
578    (void)_RkRealizeDD(dd);
579    return 1;
580  } else {
581    (void)sprintf(spec, "%s(.%s) -%s--%s%s-\n", "tmp.ctd", "mwd", newc,
582		  (dm1->dm_flags & DM_READOK) ? "r" : "",
583		  (dm1->dm_flags & DM_WRITEOK) ? "w" : "");
584    if (!DMcheck(spec, newc))
585      return NOENT; /* ¤Ê¤ó¤Ê¤ó¤À¤«Îɤ¯Ê¬¤«¤é¤Ê¤¤ (1993.11 º£) */
586    /* ¤¿¤á¤·¤Ë¤ä¤Ã¤Æ¤ß¤Æ¤¤¤ë¤Î¤«¤Ê¡© (1993.11 º£) */
587    DMrename(dm1, (unsigned char *)newc);
588    (void)_RkRealizeDD(dd);
589    return 0;
590  }
591}
592
593/* int
594 * RkwCopyDic(cx, dir, from, to, mode)
595 *
596 * ¼­½ñ¤ò¥³¥Ô¡¼¤¹¤ë¡£
597 *
598 * °ú¤­¿ô
599 *          int            cx              ¥³¥ó¥Æ¥¯¥¹¥È¥Ê¥ó¥Ð¡¼
600 *          char           *dir	           ¥Ç¥£¥ì¥¯¥È¥ê̾
601 *          char           *from           ¥³¥Ô¡¼¸µ¼­½ñ̾
602 *          char           *to             ¥³¥Ô¡¼Àè¼­½ñ̾
603 *          int            mode            ¥â¡¼¥É
604 *
605 * ÊÖ¤êÃÍ (RKdic.h»²¾È)
606 *          À®¸ù¤·¤¿¾ì¹ç                           0
607 *          oldnick¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç               -2     NOENT
608 *          RemoveDic¤ÎÊÖ¤êÃͤ¬-1¤Î¾ì¹ç           -2     NOENT
609 *          ¥Ç¥£¥ì¥¯¥È¥ê¤Î»ØÄ꤬¤ª¤«¤·¤¤¾ì¹ç      -9     BADF
610 *          RenameDicFile¤ÎÊÖ¤êÃͤ¬-1¤Î¾ì¹ç       -13    ACCES
611 *          ¥á¥â¥ê¤¬Â­¤ê¤Ê¤«¤Ã¤¿¾ì¹ç                     NOTALC
612 *          ¼­½ñ̾¤¬Ä¹¤¹¤®¤ë¾ì¹ç                         INVAL
613 *          newnick¤¬Â¸ºß¤¹¤ë¾ì¹ç                 -17    EXIST
614 *          oldnick¤ò¥Þ¥¦¥ó¥È¤·¤Æ¤¤¤¿¾ì¹ç         -26    TXTBSY
615 *          newnick¤ò¥Þ¥¦¥ó¥È¤·¤Æ¤¤¤¿¾ì¹ç         -26    TXTBSY
616 *          ¥³¥ó¥Æ¥¯¥¹¥È¹½Â¤ÂΤ¬Â¸ºß¤·¤Ê¤¤¾ì¹ç    -100   BADCONT
617 */
618
619int
620RkwCopyDic(int co, char *dir, char *from, char *to, int mode)
621{
622  struct RkContext	*cx;
623  struct DD		*userDDP[2];
624  struct DM		*dm1, *dm2;
625  char			*path, *perm = DEFAULT_PERMISSION;
626  char *myddname;
627  int res, v, con;
628
629  if (!dir || !*dir) {
630    return BADF;
631  }
632  if (!from || !*from)
633    return NOENT;
634  if (!to || !*to)
635    return ACCES;
636  if (strlen((char *)to) >= (unsigned)RK_NICK_BMAX) {
637    return INVAL;
638  }
639
640  res = BADCONT;
641  con = RkwCreateContext();
642
643  cx = RkGetContext(co);
644  if (!cx || !cx->ddpath || !cx->ddpath[0]) {
645    if (con >= 0)
646      RkwCloseContext(con);
647    return BADCONT;
648  }
649
650  if (con >= 0) {
651    int n = 2; /* for system dic */
652    switch (mode & (RK_GRP_DIC | RK_SYS_DIC)) {
653    case RK_GRP_DIC:
654      n = 1; /* for group dic */
655    case RK_SYS_DIC:
656      if (!cx->ddpath[2]) {
657	return BADCONT;
658      }
659      myddname = cx->ddpath[n]->dd_name;
660      break;
661    default:
662      myddname = cx->ddpath[0]->dd_name;
663      break;
664    }
665
666    res = NOTALC;
667    path = (char *)malloc(strlen(dir) + 1 + strlen(myddname) + 1);
668    if (path) {
669      sprintf(path, "%s:%s", dir, myddname);
670
671      res = NOTALC;
672      v = RkwSetDicPath(con, path);
673      free(path);
674      if (v >= 0) {
675	struct RkContext *cy = RkGetContext(con);
676
677	res = ACCES;
678	if (cy->ddpath[1]->dd_flags & DD_WRITEOK) {
679	  userDDP[0] = cy->ddpath[0];
680	  userDDP[1] = (struct DD *)0;
681
682	  res = NOENT;
683	  dm1 = _RkSearchDDP(userDDP, from);
684	  if (dm1) {
685	    int type = dm1->dm_file->df_type;
686
687	    res = BADF;
688	    if (type != DF_RUCDIC) {
689	      userDDP[0] = cy->ddpath[1];
690	      userDDP[1] = (struct DD *)0;
691
692	      dm2 = _RkSearchDDP(userDDP, to);
693	      if (dm2) { /* to ¤¬¤¢¤Ã¤Æ¡¢¶¯À©¥â¡¼¥É¤Ê¤é¾Ã¤¹ */
694		if (dm2->dm_rcount > 0) {
695		  res = TXTBSY;
696		  goto newdicUsed;
697		}
698		if (!(mode & KYOUSEI)) {
699		  res = EXIST;
700		  goto newdicUsed;
701		}
702		if (!(path = _RkMakePath(dm2->dm_file))) {
703		  res = NOTALC;
704		  goto newdicUsed;
705		}
706		(void)unlink(path);
707		free(path);
708		switch (dm2->dm_flags & (DM_READOK | DM_WRITEOK)) {
709		case (DM_READOK | DM_WRITEOK):
710		  perm = "rw";
711		  break;
712		case DM_READOK:
713		  perm = "r";
714		  break;
715		case DM_WRITEOK:
716		  perm = "w";
717		  break;
718		default:
719		  perm = "";
720		  break;
721		}
722		DMremove(dm2);
723	      }
724
725	      { /* ¤¤¤è¤¤¤è¼­½ñ¤òºî¤ë */
726		char *ptemplate, *filename;
727
728		RkwSync(co, from); /* sometimes, this failes to an error */
729		ptemplate =
730		  (type == DF_FREQDIC) ? (char*)FREQ_TEMPLATE :
731		    (type == DF_TEMPDIC) ? (char*)USER_TEMPLATE :
732		      (char*)PERM_TEMPLATE;
733
734		res = ACCES;
735		filename = _RkCreateUniquePath(userDDP[0], ptemplate);
736		if (filename) {
737		  char spec[RK_LINE_BMAX];
738  /* I leave this array on the stack because this will not glow so big.
739   1996.6.5 kon */
740
741		  (void)sprintf(spec, "%s(%s) -%s--%s-\n",
742				filename, dm1->dm_dicname, to, perm);
743		  res = NOTALC;
744		  dm2 = DMcreate(userDDP[0], spec);
745		  if (dm2) {
746		    res = ACCES;
747		    if (copyFile(dm1, dm2) == 0) {
748		      (void)_RkRealizeDD(userDDP[0]);
749		      res = 0;
750		    }
751		    else {
752		      DMremove(dm2);
753		    }
754		  }
755		}
756	      }
757	    }
758	  }
759	newdicUsed:;
760	}
761      }
762    }
763    RkwCloseContext(con);
764  }
765  return res;
766}
767
768/* int
769 * RkwChmodDic(cx_num, dicname, mode)
770 *
771 * ¼­½ñ¤Î¥â¡¼¥É¤òÊѹ¹¤¹¤ë¡£
772 *
773 * °ú¤­¿ô
774 *          int   cx_num           ¥³¥ó¥Æ¥¯¥¹¥È
775 *          char  dicname          ¼­½ñ̾
776 *          int   mode             ¥â¡¼¥É
777 *
778 * ÊÖ¤êÃÍ (RKdic.h»²¾È)
779 *          À®¸ù¤·¤¿¾ì¹ç                             0
780 *          dicname¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç                 -2     NOENT
781 *          DMchmod ¤ÎÊÖ¤êÃͤ¬-1¤Î¾ì¹ç             -13     ACCES
782 *          ¥³¥ó¥Æ¥¯¥¹¥È¹½Â¤ÂΤ¬Â¸ºß¤·¤Ê¤¤¾ì¹ç    -100   BADCONT
783 */
784int
785RkwChmodDic(int cx_num, char *dicname, int mode)
786{
787  struct RkContext	*cx = RkGetContext(cx_num);
788  struct DD		*dd, *userDDP[2];
789  struct DM		*dm;
790  int res;
791  unsigned dirmode;
792
793  res = BADCONT;
794  if (cx && cx->ddpath && cx->ddpath[0]) {
795    dirmode = mode & RK_DIRECTORY;
796    if (dirmode != 0) { /* ¥Ç¥£¥ì¥¯¥È¥ê */
797      switch (dirmode) {
798      case RK_SYS_DIR:
799	dd = (struct DD *)0; /* or SX.ddpath[0] */
800	break;
801      case RK_GRP_DIR:
802	if (cx->ddpath[1] && cx->ddpath[2]) {
803	  dd = cx->ddpath[1];
804	}
805	break;
806      default: /* RK_USR_DIR */
807	dd = cx->ddpath[0];
808	break;
809      }
810      res = dd ? DDchmod(dd, mode) : ACCES;
811    }
812    else { /* ¥Õ¥¡¥¤¥ë */
813      res = ACCES;
814      if (locatepath(userDDP, cx->ddpath, mode) == 0) {
815	res = NOENT;
816	if(dicname && *dicname) {
817	  dm = _RkSearchDDP(userDDP, dicname);
818	  res = NOENT;
819	  if (dm) {
820	    struct DD *dd = dm->dm_file->df_direct;
821
822	    res = DMchmod(dm, mode);
823	    if (res >= 0) {
824	      (void)_RkRealizeDD(dd);
825	    }
826	    else {
827	      res = ACCES;
828	    }
829	  }
830	}
831      }
832    }
833  }
834  return res;
835}
836
837/*
838 * GetLine(cx, gram, tdp, line)
839 * struct RkContext            *cx
840 * struct RkKxGram	*gram
841 * struct TD            *tdp
842 * WCHAR_T	*line
843 *
844 * ÊÖ¤êÃÍ À®¸ù  0
845 *        ¼ºÇÔ -1
846 */
847static struct td_n_tupple *
848pushTdn(struct RkContext *cx, struct TD *tdp)
849{
850  struct td_n_tupple	*newtd;
851  struct _rec		*gwt;
852  if (!cx || !(gwt = (struct _rec *)cx->cx_gwt) ||
853      !(newtd = (struct td_n_tupple *)malloc(sizeof(struct td_n_tupple)))) {
854    return (struct td_n_tupple *)0;
855  }
856  newtd->td = (char *)tdp;
857  newtd->n = 0;
858  newtd->next = (struct td_n_tupple *)gwt->tdn;
859  gwt->tdn = (struct td_n_tupple *)newtd;
860  return newtd;
861}
862
863void
864freeTdn(struct RkContext *cx)
865{
866  struct td_n_tupple *work;
867  struct _rec	*gwt = (struct _rec *)cx->cx_gwt;
868  if (gwt) {
869    while((work = gwt->tdn) != (struct td_n_tupple *)0) {
870      gwt->tdn = work->next;
871      free(work);
872    };
873  };
874}
875
876inline void
877popTdn(struct RkContext *cx)
878{
879  struct td_n_tupple *work;
880  struct _rec	*gwt = (struct _rec *)cx->cx_gwt;
881  work = gwt->tdn;
882  if (work) {
883    gwt->tdn = work->next;
884    free(work);
885  }
886}
887
888inline int
889GetLine(struct RkContext *cx, struct RkKxGram *gram, struct TD *tdp, WCHAR_T *line, int size)
890{
891  struct TD	*vtd;
892  struct TN	*vtn;
893  struct _rec	*gwt = (struct _rec *)cx->cx_gwt;
894
895  if (tdp) {
896    if (gwt->tdn)
897      freeTdn(cx);
898    if(!pushTdn(cx, tdp))
899      return NOTALC;
900  }
901  while (gwt->tdn && gwt->tdn->n >= (int)((struct TD *)gwt->tdn->td)->td_n)
902    popTdn(cx);
903  if (gwt->tdn == (struct td_n_tupple *)0)
904    return -1;
905  vtd = (struct TD *)gwt->tdn->td;
906  vtn = vtd->td_node + gwt->tdn->n;
907  while ( !IsWordNode(vtn) ) {
908    gwt->tdn->n++;
909    if(!pushTdn(cx, vtn->tn_tree))
910      return NOTALC;
911    vtd = (struct TD *)gwt->tdn->td;
912    vtn = vtd->td_node;
913  }
914  if (RkUparseWrec(gram, vtn->tn_word->word, line, size, vtn->tn_word->lucks)) {
915    gwt->tdn->n++;
916    return 0;
917  } else
918    return -1;
919}
920
921/*
922 * RkwGetWordTextDic(cx_num, dirname, dicname, info, infolen)
923 *
924 * int            cx_num      ¥³¥ó¥Æ¥¯¥¹¥ÈNO
925 * unsigned char  *dirname    ¥Ç¥£¥ì¥¯¥È¥ê̾
926 * unsigned char  *dicname    ¼­½ñ̾
927 * unsigned char  *info       ¥Ð¥Ã¥Õ¥¡
928 * int            infolen     ¥Ð¥Ã¥Õ¥¡¤ÎŤµ
929 *
930 * ÊÖ¤êÃÍ : ¼ÂºÝ¤Ëinfo¤ËÆþ¤Ã¤¿Ä¹¤µ
931 *          ºÇ¸å¤Þ¤ÇÆɤó¤Ç¤¤¤¿¤é          £°¤òÊÖ¤¹
932 *          RkwCreateContext¤Ë¼ºÇÔ¤·¤¿     BADCONT
933 *          RkwDuplicateContext¤Ë¼ºÇÔ¤·¤¿  BADCONT
934 *          RkGetContext¤Ë¼ºÇÔ¤·¤¿        BADCONT
935 *          RkwSetDicPath¤Ë¼ºÇÔ¤·¤¿        NOTALC
936 *          RkwMountDic¤Ë¼ºÇÔ¤·¤¿          NOENT
937 *          SearchUDDP¤Ë¼ºÇÔ¤·¤¿          NOENT
938 *          ¥Ð¥¤¥Ê¥ê¼­½ñ¤À¤Ã¤¿                          -9   BADF
939 *          dics.dir¤Ë°Û¾ï¤¬¤¢¤Ã¤¿¾ì¹ç                 -10   BADDR
940 */
941int
942RkwGetWordTextDic(int cx_num, unsigned char *dirname, unsigned char *dicname, WCHAR_T *info, int infolen)
943{
944  struct RkContext *new_cx, *cx;
945  struct DM *dm;
946  int new_cx_num;
947  struct TD *initial_td;
948  unsigned size;
949  unsigned char *buff = 0;
950  struct _rec	*gwt;
951
952  if (!dicname || !dirname || !info || !(cx = RkGetContext(cx_num)) ||
953      !(gwt = (struct _rec *)cx->cx_gwt))
954    return BADCONT;
955
956  if(dicname[0] != '\0') {
957    size = strlen((char *)dicname) + 1;
958    if (!(buff = (unsigned char *)malloc(size)))
959      return (NOTALC);
960    (void)strcpy((char *)buff, (char *)dicname);
961
962    if(dirname[0] != '\0') {
963      if((new_cx_num = RkwCreateContext()) < 0) {
964	free(buff);
965	return BADCONT;
966      }
967      if(RkwSetDicPath(new_cx_num, (char *)dirname) < 0) {
968	RkwCloseContext(new_cx_num);
969	free(buff);
970	return NOTALC;
971      }
972    } else {
973      if ((new_cx_num = RkwDuplicateContext(cx_num)) < 0) {
974	free(buff);
975	return BADCONT;
976      }
977    }
978    if (!(cx = RkGetContext(cx_num)) || !(gwt = (struct _rec *)cx->cx_gwt)) {
979      RkwCloseContext(new_cx_num);
980      free(buff);
981      return BADCONT;
982    }
983
984    if (!(new_cx = RkGetContext(new_cx_num))) {
985      if(dirname[0] != '\0') {
986	RkwCloseContext(new_cx_num);
987	free(buff);
988	return BADCONT;
989      }
990    }
991    if (gwt->gwt_cx >= 0) {
992      RkwCloseContext(gwt->gwt_cx);
993      gwt->gwt_cx = -1;
994    }
995
996    if(!STRCMP(dirname, SYSTEM_DDHOME_NAME)) {
997      if (!(dm = _RkSearchDDP(new_cx->ddpath, (char *)dicname))) {
998	if (dirname[0] != '\0') {
999	  RkwCloseContext(new_cx_num);
1000	}
1001	free(buff);
1002	return NOENT;
1003      }
1004    } else {
1005      if (!(dm = _RkSearchUDDP(new_cx->ddpath, dicname))) {
1006	if(dirname[0] != '\0') {
1007	  RkwCloseContext(new_cx_num);
1008	}
1009	free(buff);
1010	return NOENT;
1011      }
1012    }
1013    if (DM2TYPE(dm) != DF_TEMPDIC ) {
1014      if(dirname[0] != '\0') {
1015	RkwCloseContext(new_cx_num);
1016      }
1017      free(buff);
1018      return BADF;
1019    }
1020    if(RkwMountDic(new_cx_num, (char *)dicname,0) == -1) {
1021      RkwCloseContext(new_cx_num);
1022      free(buff);
1023      return NOMOUNT;
1024    }
1025
1026    if (!_RkSearchDDP(new_cx->ddpath, (char *)dicname)) {
1027      RkwCloseContext(new_cx_num);
1028      free(buff);
1029      return BADDR;
1030    }
1031    gwt->gwt_cx = new_cx_num;
1032    if (gwt->gwt_dicname)
1033      free(gwt->gwt_dicname);
1034    gwt->gwt_dicname = buff;
1035    initial_td = (struct TD *)dm->dm_td;
1036  }
1037  else {
1038    if ((new_cx_num = gwt->gwt_cx) < 0
1039	|| !(new_cx = RkGetContext(new_cx_num))) {
1040      if (gwt->gwt_dicname)
1041	free(gwt->gwt_dicname);
1042      gwt->gwt_dicname = (unsigned char *)0;
1043      return BADCONT;
1044    }
1045    initial_td = (struct TD *)0;
1046  }
1047  if (GetLine(new_cx, cx->gram->gramdic, (struct TD *)initial_td,
1048	      info, infolen) < 0) {
1049    RkwUnmountDic(new_cx_num, (char *)gwt->gwt_dicname);
1050    RkwCloseContext(new_cx_num);
1051    gwt->gwt_cx = -1;
1052    return 0;
1053  }
1054  infolen = uslen((WCHAR_T *)info);
1055  return infolen;
1056}
1057