1 /*
2  * Copyright (c) 1991-1994  Sony Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Except as contained in this notice, the name of Sony Corporation
24  * shall not be used in advertising or otherwise to promote the sale, use
25  * or other dealings in this Software without prior written authorization
26  * from Sony Corporation.
27  *
28  */
29 
30 /*
31  * $SonyRCSfile: depend.c,v $
32  * $SonyRevision: 1.4 $
33  * $SonyDate: 1997/10/07 07:39:45 $
34  */
35 
36 
37 
38 #include <stdlib.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <sys/types.h>
42 #include "sj_kcnv.h"
43 #include <errno.h>
44 #include <sys/file.h>
45 #include <sys/stat.h>
46 #include "Dict.h"
47 #include "sj3err.h"
48 
49 #include "sj_kanakan.h"
50 
51 #if defined(__FD_SET) && !defined(FD_SET)
52 # define FD_SET __FD_SET
53 # define FD_CLR __FD_CLR
54 #endif
55 
56 DictFile *dictlink = NULL;
57 StdyFile *stdylink = NULL;
58 
59 static long
get4byte(Uchar * p)60 get4byte(Uchar *p)
61 {
62 	long	i;
63 
64 	i = *p;
65 	i = (i << 8) + *++p;
66 	i = (i << 8) + *++p;
67 	return ((i << 8) + *++p);
68 }
69 static void
Put4byte(Uchar * p,long n)70 Put4byte(Uchar *p, long n)
71 {
72 	p += 3;
73 	*p-- = n; n >>= 8;
74 	*p-- = n; n >>= 8;
75 	*p-- = n; n >>= 8;
76 	*p = n;
77 }
78 #define put4byte(p, n)	Put4byte((p), (long)(n))
79 
80 
81 
82 static int
fgetfile(FILE * fp,long pos,long len,Uchar * p)83 fgetfile(FILE *fp, long pos, long len, Uchar *p)
84 {
85 	if (fseek(fp, pos, 0) == ERROR) {
86 		serv_errno = SJ3_FileSeekError; return ERROR;
87 	}
88 	if (fread(p, len, 1, fp) != 1) {
89 		serv_errno = SJ3_FileReadError; return ERROR;
90 	}
91 	return SJ3_NormalEnd;
92 }
93 static int
fputfile(FILE * fp,long pos,int len,Uchar * p)94 fputfile(FILE *fp, long pos, int len, Uchar *p)
95 {
96 	if (fseek(fp, pos, 0) == ERROR) {
97 		serv_errno = SJ3_FileSeekError; return ERROR;
98 	}
99 	if (fwrite(p, len, 1, fp) != 1) {
100 		serv_errno = SJ3_FileWriteError; return ERROR;
101 	}
102 	return SJ3_NormalEnd;
103 }
104 static int
getfile(int fd,int pos,int len,Uchar * p)105 getfile(int fd, int pos, int len, Uchar *p)
106 {
107 	if (lseek(fd, pos, L_SET) == ERROR) {
108 		serv_errno = SJ3_FileSeekError; return ERROR;
109 	}
110 	if (read(fd, p, len) != len) {
111 		serv_errno = SJ3_FileReadError; return ERROR;
112 	}
113 	return SJ3_NormalEnd;
114 }
115 static int
putfile(int fd,int pos,int len,Uchar * p)116 putfile(int fd, int pos, int len, Uchar *p)
117 {
118 	if (lseek(fd, pos, L_SET) == ERROR) {
119 		serv_errno = SJ3_FileSeekError; return ERROR;
120 	}
121 	if (write(fd, p, len) != len) {
122 		serv_errno = SJ3_FileWriteError; return ERROR;
123 	}
124 	return SJ3_NormalEnd;
125 }
126 
127 
128 
129 static int
check_passwd(Uchar * buf,char * passwd)130 check_passwd(Uchar *buf, char *passwd)
131 {
132 	buf += PasswdPos;
133 	return (*buf && strncmp(passwd, buf, PasswdLen)) ? FALSE : TRUE;
134 }
135 static void
set_passwd(Uchar * buf,char * passwd)136 set_passwd(Uchar *buf, char *passwd)
137 {
138 	strncpy(buf + PasswdPos, passwd, PasswdLen);
139 }
140 
141 
142 
143 static int
check_dictfile(Uchar * buf)144 check_dictfile(Uchar *buf)
145 {
146 	return (DictVersion != get4byte(buf + VersionPos)) ? FALSE : TRUE;
147 }
148 
149 
150 
151 static DictFile *
search_same_dict(ino_t ino)152 search_same_dict(ino_t ino)
153 {
154 	DictFile *p;
155 
156 	for (p = dictlink ; p != NULL ; p = p -> link)
157 		if (p->dict.dicid == ino) return p;
158 
159 	return NULL;
160 }
161 
162 
163 
164 static Int
getofs(DictFile * dp)165 getofs(DictFile *dp)
166 {
167 	idxofs = dp -> ofsptr;
168 	return 0;
169 }
170 static Int
getidx(DictFile * dp)171 getidx(DictFile *dp)
172 {
173 	idxbuf = dp -> buffer + dp -> idxstrt;
174 	return 0;
175 }
176 /* XXX: not IFunc */
177 static Int
getdic(DictFile * dp,TypeDicSeg seg)178 getdic(DictFile *dp, TypeDicSeg seg)
179 {
180 	if (seg >= dp->dict.segunit) return -1;
181 	dicbuf = dp->buffer + dp->segstrt + dp->dict.seglen * seg;
182 	return 0;
183 }
184 static Int
putidx(DictFile * dp)185 putidx(DictFile *dp)
186 {
187 	return putfile(dp->fd, dp->idxstrt, dp->dict.idxlen, idxbuf);
188 }
189 /* XXX: not IFunc */
190 static Int
putdic(DictFile * dp,TypeDicSeg seg)191 putdic(DictFile *dp, TypeDicSeg seg)
192 {
193 	Uchar	*p;
194 	long	i, j;
195 
196 	if (seg >= dp->dict.maxunit) return -1;
197 	i = dp->segstrt + dp->dict.seglen * (seg + 1);
198 	if (i > dp->bufsiz) {
199 		if (!(p = (Uchar *)malloc(i))) return -1;
200 		memcpy(p, dp->buffer, dp->bufsiz);
201 
202 		if (idxbuf - dp->buffer == dp->idxstrt)
203 			idxbuf = p + dp->idxstrt;
204 		if ((dicbuf >= dp->buffer) &&
205 		    ((j = dicbuf - dp->buffer) < dp->bufsiz))
206 			dicbuf = p + j;
207 
208 		free((char *)(dp -> buffer));
209 		dp -> buffer = p;
210 		dp -> bufsiz = i;
211 	}
212 
213 	i = dp->segstrt + dp->dict.seglen * seg;
214 	if ((p = dp->buffer + i) != dicbuf) memcpy(p, dicbuf, dp->dict.seglen);
215 
216 	return putfile(dp->fd, i, dp->dict.seglen, p);
217 }
218 /* XXX: not IFunc */
219 static Int
rszdic(DictFile * dp,TypeDicSeg seg)220 rszdic(DictFile *dp, TypeDicSeg seg)
221 {
222 	long	i;
223 	Uchar	*p;
224 
225 	i = dp->segstrt + dp->dict.seglen * seg;
226 	if (dp->bufsiz != i) {
227 		if (!(p = (Uchar *)malloc(i))) return -1;
228 		memcpy(p, dp->buffer, ((i > dp->bufsiz) ? dp->bufsiz : i));
229 
230 		if (idxbuf - dp->buffer == dp->idxstrt)
231 			idxbuf = p + dp->idxstrt;
232 		if ((dicbuf >= dp->buffer) &&
233 		    ((i = dicbuf - dp->buffer) < dp->bufsiz))
234 			dicbuf = p + i;
235 
236 		free((char *)(dp -> buffer));
237 		dp -> buffer = p;
238 		dp -> bufsiz = i;
239 		if (ftruncate(dp->fd, i) == -1) return -1;
240 	}
241 	put4byte(dp->buffer + DictSegNum, seg);
242 	return putfile(dp->fd, 0, HeaderLength, dp->buffer);
243 }
244 
245 
246 
247 DictFile *
opendict(char * name,char * passwd)248 opendict(char *name, char *passwd)
249 {
250 	FILE		*fp;
251 	struct stat	sbuf;
252 	DictFile	*dfp;
253 	Uchar		tmp[HeaderLength];
254 	int		i;
255 	Uchar		*dp;
256 
257 
258 	if (stat(name, &sbuf) == ERROR) {
259 		if (errno == ENOENT)
260 			serv_errno = SJ3_FileNotExist;
261 		else
262 			serv_errno = SJ3_CannotAccessFile;
263 		return NULL;
264 	}
265 
266 
267 	if ((dfp = search_same_dict(sbuf.st_ino)) != NULL) {
268 		dfp -> refcnt++; return dfp;
269 	}
270 
271 
272 	if ((fp = fopen(name, "r+")) == NULL) {
273 		if ((fp = fopen(name, "r")) == NULL) {
274 			serv_errno = SJ3_CannotOpenFile; return NULL;
275 		}
276 		i = FALSE;
277 	}
278 	else
279 		i = TRUE;
280 
281 
282 	if (fgetfile(fp, 0L, sizeof(tmp), tmp) == ERROR) goto error1;
283 
284 
285 	if (!check_dictfile(tmp)) {
286 		serv_errno = SJ3_IllegalDictFile; goto error1;
287 	}
288 
289 
290 	if (!check_passwd(tmp, passwd)) {
291 		serv_errno = SJ3_IncorrectPasswd; goto error1;
292 	}
293 
294 	if ((dp = (Uchar *)malloc((long)sbuf.st_size)) == NULL) {
295 		serv_errno = SJ3_NotEnoughMemory; goto error1;
296 	}
297 	if ((dfp = (DictFile *)malloc(sizeof(*dfp))) == NULL) {
298 		serv_errno = SJ3_NotEnoughMemory; goto error2;
299 	}
300 	memset(dfp, '\0', sizeof(*dfp));
301 
302 	if (fgetfile(fp, 0L, (long)sbuf.st_size, dp) == ERROR) goto error3;
303 
304 	dfp -> dict.dicid   = sbuf.st_ino;
305 	dfp -> dict.idxlen  = get4byte(dp + DictIdxLen);
306 	dfp -> dict.seglen  = get4byte(dp + DictSegLen);
307 	dfp -> dict.segunit = get4byte(dp + DictSegNum);
308 	dfp -> dict.maxunit = i ? get4byte(dp + DictSegMax) : 0 ;
309 	dfp -> dict.getofs  = getofs;
310 	dfp -> dict.getidx  = getidx;
311 	dfp -> dict.getdic  = getdic;
312 	dfp -> dict.putidx  = putidx;
313 	dfp -> dict.putdic  = putdic;
314 	dfp -> dict.rszdic  = rszdic;
315 	dfp -> refcnt       = 1;
316 	dfp -> fp           = fp;
317 	dfp -> fd           = fileno(fp);
318 	dfp -> buffer       = dp;
319 	dfp -> bufsiz       = sbuf.st_size;
320 	dfp -> idxstrt      = get4byte(dp + DictIdxPos);
321 	dfp -> segstrt      = get4byte(dp + DictSegPos);
322 
323 	i = dfp -> dict.segunit;
324 	if (i < dfp -> dict.maxunit) i = dfp -> dict.maxunit;
325 	i *= sizeof(TypeIdxOfs);
326 	if ((dfp -> ofsptr = (TypeIdxOfs *)malloc(i)) == NULL) {
327 		serv_errno = SJ3_NotEnoughMemory; goto error3;
328 	}
329 	mkidxtbl(&(dfp -> dict));
330 
331 	dfp -> link         = dictlink;
332 	dictlink = dfp;
333 
334 	return dfp;
335 
336 
337 
338 error3:	free((char *)dfp);
339 error2:	free((char *)dp);
340 error1:	fclose(fp);
341 
342 	return NULL;
343 }
344 
345 
346 
347 int
closedict(DictFile * dfp)348 closedict(DictFile *dfp)
349 {
350 	DictFile	*df;
351 
352 
353 	if (--dfp->refcnt > 0) return 0;
354 
355 
356 	if (dictlink == dfp)
357 		dictlink = dfp -> link;
358 	else {
359 		for (df = dictlink ; df ; df = df -> link)
360 			if (df -> link == dfp) {
361 				df -> link = dfp -> link;
362 				break;
363 			}
364 	}
365 
366 
367 	if (dfp -> fp) fclose(dfp ->fp);
368 
369 
370 	free((char *)(dfp -> ofsptr));
371 	free((char *)(dfp -> buffer));
372 	free((char *)dfp);
373 
374 	return 0;
375 }
376 
377 
378 
379 static	fd_set	zero_fd_set = { 0 };
380 void
lock_dict(DictFile * p,int fd)381 lock_dict(DictFile *p, int fd)
382 {
383 	FD_SET(fd, &(p -> lock));
384 }
385 void
unlock_dict(DictFile * p,int fd)386 unlock_dict(DictFile *p, int fd)
387 {
388 	FD_CLR(fd, &(p -> lock));
389 }
is_dict_locked(DictFile * p)390 int is_dict_locked(DictFile *p)
391 {
392 	return memcmp(&(p -> lock), &zero_fd_set, sizeof(zero_fd_set));
393 }
394 
395 
396 
397 static int
check_stdyfile(Uchar * buf)398 check_stdyfile(Uchar *buf)
399 {
400 	return (StdyVersion != get4byte(buf + VersionPos)) ? FALSE : TRUE;
401 }
402 
403 
404 
405 static StdyFile *
search_same_stdy(ino_t ino)406 search_same_stdy(ino_t ino)
407 {
408 	StdyFile *p;
409 
410 	for (p = stdylink ; p != NULL ; p = p -> link)
411 		if (p -> inode == ino) return p;
412 
413 	return NULL;
414 }
415 
416 
417 
418 StdyFile *
openstdy(char * name,char * passwd)419 openstdy(char *name, char *passwd)
420 {
421 	FILE		*fp;
422 	struct stat	sbuf;
423 	StdyFile	*sfp;
424 	Uchar		*hd;
425 	STDYIN		*sp;
426 	Ushort		*cip;
427 	Uchar		*clp;
428 	long		stdycnt, stdypos, stdylen, stdymax;
429 	long		clidxpos, clidxlen;
430 	long		clstdypos, clstdylen, clstdystep;
431 	long		len;
432 
433 
434 	if (stat(name, &sbuf) == ERROR) {
435 		if (errno == ENOENT)
436 			serv_errno = SJ3_FileNotExist;
437 		else
438 			serv_errno = SJ3_CannotAccessFile;
439 		return NULL;
440 	}
441 
442 
443 	if ((sfp = search_same_stdy(sbuf.st_ino)) != NULL) {
444 		sfp -> refcnt++; return sfp;
445 	}
446 
447 
448 	if ((hd = (Uchar *)malloc(HeaderLength+CommentLength)) == NULL) {
449 		serv_errno = SJ3_NotEnoughMemory; return NULL;
450 	}
451 
452 
453 	if ((fp = fopen(name, "r+")) == NULL) {
454 		serv_errno = SJ3_CannotOpenFile; goto error0;
455 	}
456 
457 
458 	if (fgetfile(fp, 0L, HeaderLength+CommentLength, hd) == ERROR)
459 		goto error1;
460 
461 
462 	if (!check_stdyfile(hd)) {
463 		serv_errno = SJ3_IllegalStdyFile; goto error1;
464 	}
465 
466 
467 	if (!check_passwd(hd, passwd)) {
468 		serv_errno = SJ3_IncorrectPasswd; goto error1;
469 	}
470 
471 
472 	stdycnt    = get4byte(hd + StdyNormCnt);
473 	stdypos    = get4byte(hd + StdyNormPos);
474 	stdylen    = get4byte(hd + StdyNormLen);
475 	stdymax    = get4byte(hd + StdyNormNum);
476 	clidxpos   = get4byte(hd + StdyClIdxPos);
477 	clidxlen   = get4byte(hd + StdyClIdxLen);
478 	clstdypos  = get4byte(hd + StdyClSegPos);
479 	clstdylen  = get4byte(hd + StdyClSegLen);
480 	clstdystep = get4byte(hd + StdyClIdxStep);
481 	len = sizeof(STDYIN) * stdymax;
482 
483 
484 	if ((sfp = (StdyFile *)malloc(sizeof(*sfp))) == NULL) {
485 		serv_errno = SJ3_NotEnoughMemory; goto error1;
486 	}
487 	memset(sfp, '\0', sizeof(*sfp));
488 	if ((sp = (STDYIN *)malloc(len)) == NULL) {
489 		serv_errno = SJ3_NotEnoughMemory; goto error2;
490 	}
491 	if ((cip = (Ushort *)malloc(clidxlen)) == NULL) {
492 		serv_errno = SJ3_NotEnoughMemory; goto error3;
493 	}
494 	if ((clp = (Uchar *)malloc(clstdylen)) == NULL) {
495 		serv_errno = SJ3_NotEnoughMemory; goto error4;
496 	}
497 
498 
499 	if (fgetfile(fp, clidxpos, clidxlen, (Uchar *)cip) == ERROR) goto error5; /* XXX */
500 	if (fgetfile(fp, clstdypos, clstdylen, (Uchar *)clp) == ERROR) goto error5; /* XXX */
501 	if (fgetfile(fp, stdypos, len, (Uchar *)sp) == ERROR) stdycnt = 0; /* XXX */
502 
503 
504 	sfp -> stdy.stdycnt    = stdycnt;
505 	sfp -> stdy.stdymax    = stdymax;
506 	sfp -> stdy.stdydic    = sp;
507 	sfp -> stdy.clstdystep = clstdystep;
508 	sfp -> stdy.clstdyidx  = cip;
509 	sfp -> stdy.clstdylen  = clstdylen;
510 	sfp -> stdy.clstdydic  = clp;
511 	sfp -> refcnt          = 1;
512 	sfp -> inode           = sbuf.st_ino;
513 	sfp -> fp              = fp;
514 	sfp -> fd              = fileno(fp);
515 	sfp -> header          = hd;
516 
517 	sfp -> link            = stdylink;
518 	stdylink = sfp;
519 
520 	return sfp;
521 
522 
523 
524 error5:	free((char *)clp);
525 error4:	free((char *)cip);
526 error3:	free((char *)sp);
527 error2:	free((char *)sfp);
528 error1:	fclose(fp);
529 error0:	free((char *)hd);
530 
531 	return NULL;
532 }
533 
534 
535 
536 int
closestdy(StdyFile * sfp)537 closestdy(StdyFile *sfp)
538 {
539 	StdyFile	*sf;
540 
541 
542 	if (--sfp->refcnt > 0) return 0;
543 
544 
545 	if (stdylink == sfp)
546 		stdylink = sfp -> link;
547 	else {
548 		for (sf = stdylink ; sf ; sf = sf -> link)
549 			if (sf -> link == sfp) {
550 				sf -> link = sfp -> link;
551 				break;
552 			}
553 	}
554 
555 
556 	if (sfp -> fp) fclose(sfp ->fp);
557 
558 
559 	free((char *)sfp -> stdy.stdydic);
560 	free((char *)sfp -> stdy.clstdyidx);
561 	free((char *)sfp -> stdy.clstdydic);
562 	free((char *)sfp -> header);
563 	free((char *)sfp);
564 
565 	return 0;
566 }
567 
568 
569 
570 int
putstydic()571 putstydic()
572 {
573 	int	fd;
574 	Uchar	*hd;
575 	StdyFile *sf;
576 	long	len;
577 
578 	sf = (StdyFile *)stdy_base;
579 	fd = sf -> fd;
580 	hd = sf -> header;
581 
582 
583 	put4byte(hd + StdyNormCnt, sf -> stdy.stdycnt);
584 
585 
586 	len = sizeof(STDYIN) * sf -> stdy.stdymax;
587 	put4byte(hd + StdyNormLen, len);
588 
589 
590 	if (putfile(fd, 0, HeaderLength+CommentLength, hd)) return ERROR;
591 
592 
593 	return putfile(fd, get4byte(hd + StdyNormPos), len, (Uchar *)sf -> stdy.stdydic);
594 }
595 int
putcldic()596 putcldic()
597 {
598 	int	fd;
599 	Uchar	*hd;
600 	StdyFile *sf;
601 
602 	sf = (StdyFile *)stdy_base;
603 	fd = sf -> fd;
604 	hd = sf -> header;
605 
606 	if (putfile(fd, get4byte(hd + StdyClIdxPos),
607 		get4byte(hd + StdyClIdxLen), (Uchar *)sf -> stdy.clstdyidx)) /* XXX */
608 		return ERROR;
609 	return putfile(fd, get4byte(hd + StdyClSegPos),
610 			get4byte(hd + StdyClSegLen), sf -> stdy.clstdydic);
611 }
612 
613 
614 int
makedict(char * path,int idxlen,int seglen,int segnum)615 makedict(char *path, int idxlen, int seglen, int segnum)
616 {
617 	FILE	*fp;
618 	Uchar	tmp[HeaderLength + CommentLength];
619 	long	pos = HeaderLength + CommentLength;
620 	int	ret = ERROR;
621 	int	i;
622 
623 
624 	if (idxlen < MinIdxLen || seglen < MinSegLen || segnum < MinSegNum) {
625 		serv_errno = SJ3_IllegalParameter; return ret;
626 	}
627 
628 	if (!(fp = fopen(path, "w"))) {
629 		serv_errno = SJ3_CannotCreateFile; return ret;
630 	}
631 	memset(tmp, '\0', sizeof(tmp));
632 	put4byte(tmp + VersionPos, DictVersion);
633 
634 
635 	put4byte(tmp + DictIdxPos, pos);
636 	put4byte(tmp + DictIdxLen, idxlen);
637 	if (fseek(fp, pos, 0) == ERROR) {
638 		serv_errno = SJ3_FileSeekError; goto error;
639 	}
640 	for (i = 0 ; i < idxlen ; i++)
641 		if (putc(0, fp))  {
642 			serv_errno = SJ3_FileWriteError; goto error;
643 		}
644 	pos += idxlen;
645 
646 
647 	put4byte(tmp + DictSegPos, pos);
648 	put4byte(tmp + DictSegLen, seglen);
649 	put4byte(tmp + DictSegNum, 1);
650 	put4byte(tmp + DictSegMax, segnum);
651 	if (fseek(fp, pos, 0) == ERROR) {
652 		serv_errno = SJ3_FileSeekError; goto error;
653 	}
654 	if (putc(0, fp)) {
655 			serv_errno = SJ3_FileWriteError; goto error;
656 	}
657 	for (i = 1 ; i < seglen ; i++)
658 		if (putc(0xff, fp) != 0xff) {
659 			serv_errno = SJ3_FileWriteError; goto error;
660 		}
661 
662 
663 	if (fputfile(fp, 0L, sizeof(tmp), tmp) == SJ3_NormalEnd)
664 		ret = SJ3_NormalEnd;
665 error:
666 	fclose(fp);
667 	if (ret != SJ3_NormalEnd) unlink(path);
668 	return ret;
669 }
670 
671 
672 int
makestdy(char * path,int stynum,int clstep,int cllen)673 makestdy(char *path, int stynum, int clstep, int cllen)
674 {
675 	FILE	*fp;
676 	Uchar	tmp[HeaderLength + CommentLength];
677 	long	pos = HeaderLength + CommentLength;
678 	int	ret = ERROR;
679 	int	i, j;
680 
681 
682 	if (stynum == 0) stynum = MinStyNum;
683 	if (clstep == 0) clstep = MinClStep;
684 	if (cllen == 0) cllen = MinClLen;
685 
686 
687 	if (stynum < MinStyNum || clstep < MinClStep || cllen < MinClLen) {
688 		serv_errno = SJ3_IllegalParameter; return ret;
689 	}
690 	if (stynum > MaxStyNum || clstep > MaxClStep || cllen > MaxClLen) {
691 		serv_errno = SJ3_IllegalParameter; return ret;
692 	}
693 
694 	if (!(fp = fopen(path, "w"))) {
695 		serv_errno = SJ3_CannotCreateFile; return ret;
696 	}
697 	memset(tmp, '\0', sizeof(tmp));
698 	put4byte(tmp + VersionPos, StdyVersion);
699 
700 
701 	j = 256 * sizeof(Ushort);
702 	put4byte(tmp + StdyClIdxPos, pos);
703 	put4byte(tmp + StdyClIdxLen, j);
704 	put4byte(tmp + StdyClIdxStep, clstep);
705 	if (fseek(fp, pos, 0) == ERROR) {
706 		serv_errno = SJ3_FileSeekError; goto error;
707 	}
708 	for (i = 0 ; i < j ; i++)
709 		if (putc(0, fp)) {
710 			serv_errno = SJ3_FileWriteError; goto error;
711 		}
712 	pos += j;
713 
714 
715 	put4byte(tmp + StdyClSegPos, pos);
716 	put4byte(tmp + StdyClSegLen, cllen);
717 	if (fseek(fp, pos, 0) == ERROR) {
718 		serv_errno = SJ3_FileSeekError; goto error;
719 	}
720 	for (i = 0 ; i < cllen ; i++)
721 		if (putc(0, fp)) {
722 			serv_errno = SJ3_FileWriteError; goto error;
723 		}
724 	pos += cllen;
725 
726 
727 	j = sizeof(STDYIN) * stynum;
728 	put4byte(tmp + StdyNormPos, pos);
729 	put4byte(tmp + StdyNormLen, j);
730 	put4byte(tmp + StdyNormNum, stynum);
731 	put4byte(tmp + StdyNormCnt, 0);
732 	if (fseek(fp, pos, 0) == ERROR) {
733 		serv_errno = SJ3_FileSeekError; goto error;
734 	}
735 	for (i = 0 ; i < j ; i++) {
736 		if (putc(0, fp)) {
737 			serv_errno = SJ3_FileWriteError; goto error;
738 		}
739 	}
740 	pos += j;
741 
742 
743 	if (fputfile(fp, 0L, sizeof(tmp), tmp) == SJ3_NormalEnd)
744 		ret = SJ3_NormalEnd;
745 error:
746 	fclose(fp);
747 	if (ret != SJ3_NormalEnd) unlink(path);
748 	return ret;
749 }
750 
751 
752 
753 void
sj_closeall()754 sj_closeall()
755 {
756 	while (dictlink) closedict(dictlink);
757 	while (stdylink) closestdy(stdylink);
758 }
759 
760 
761 int
set_dictpass(DictFile * dp,char * pass)762 set_dictpass(DictFile *dp, char *pass)
763 {
764 	set_passwd(dp -> buffer, pass);
765 	return putfile(dp->fd, 0, HeaderLength+CommentLength, dp->buffer);
766 }
767 int
set_stdypass(char * pass)768 set_stdypass(char *pass)
769 {
770 	StdyFile	*sp;
771 
772 	sp = (StdyFile *)stdy_base;
773 	set_passwd(sp -> header, pass);
774 	return putfile(sp->fd, 0, HeaderLength+CommentLength, sp->header);
775 }
776 
777 
778 
779 static
780 void
set_comment(Uchar * buf,char * comment)781 set_comment(Uchar *buf, char *comment)
782 {
783 	strlcpy(buf + HeaderLength, comment, CommentLength);
784 }
785 
786 int
set_dictcmnt(DictFile * dp,char * cmnt)787 set_dictcmnt(DictFile *dp, char *cmnt)
788 {
789 	set_comment(dp -> buffer, cmnt);
790 	return putfile(dp->fd, 0, HeaderLength+CommentLength, dp->buffer);
791 }
792 int
set_stdycmnt(char * cmnt)793 set_stdycmnt(char *cmnt)
794 {
795 	StdyFile	*sp;
796 
797 	sp = (StdyFile *)stdy_base;
798 	set_comment(sp -> header, cmnt);
799 	return putfile(sp->fd, 0, HeaderLength+CommentLength, sp->header);
800 }
801 
802 
803 int
get_stdysize(int * stynum,int * clstep,int * cllen)804 get_stdysize(int *stynum, int *clstep, int *cllen)
805 {
806 	*stynum = StudyMax;
807 	*clstep = ClStudyStep;
808 	*cllen  = ClStudyLen;
809 }
810