1 /*  esecannaserver --- pseudo canna server that wraps another IME.
2  *  Copyright (C) 1999-2000 Yasuhiro Take
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 
19 #define __USE_GNU
20 #define _GNU_SOURCE
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 #include <sys/ioctl.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <time.h>
35 
36 #define __misc_c__
37 
38 #include "misc.h"
39 
40 struct {
41   uchar zen[3];
42   uchar c;
43 } zen_han_table[] = {
44   {{0x81, 0x49, 0}, '!'},
45   {{0x81, 0x68, 0}, '"'},
46   {{0x81, 0x94, 0}, '#'},
47   {{0x81, 0x90, 0}, '$'},
48   {{0x81, 0x93, 0}, '%'},
49   {{0x81, 0x95, 0}, '&'},
50   {{0x81, 0x66, 0}, 0x27}, /* ' */
51   {{0x81, 0x69, 0}, '('},
52   {{0x81, 0x6a, 0}, ')'},
53   {{0x81, 0x96, 0}, '*'},
54   {{0x81, 0x7b, 0}, '+'},
55   {{0x81, 0x43, 0}, ','},
56   {{0x81, 0x7c, 0}, '-'},
57   {{0x81, 0x44, 0}, '.'},
58   {{0x81, 0x5e, 0}, '/'},
59   {{0x81, 0x46, 0}, ':'},
60   {{0x81, 0x47, 0}, ';'},
61   {{0x81, 0x83, 0}, '<'},
62   {{0x81, 0x81, 0}, '='},
63   {{0x81, 0x84, 0}, '!'},
64   {{0x81, 0x48, 0}, '?'},
65   {{0x81, 0x97, 0}, '@'},
66   {{0x81, 0x6b, 0}, '['},
67   {{0x81, 0x8f, 0}, '\\'},
68   {{0x81, 0x6e, 0}, ']'},
69   {{0x81, 0x4f, 0}, '^'},
70   {{0x81, 0x51, 0}, '_'},
71   {{0x81, 0x4d, 0}, '`'},
72   {{0x81, 0x6f, 0}, '{'},
73   {{0x81, 0x62, 0}, '|'},
74   {{0x81, 0x70, 0}, '}'},
75   {{0x81, 0x60, 0}, '~'},
76   {{0x81, 0x50, 0}, '~'},
77   {{0x81, 0x42, 0}, 0xa1}, /*��*/
78   {{0x81, 0x75, 0}, 0xa2}, /*��*/
79   {{0x81, 0x76, 0}, 0xa3}, /*��*/
80   {{0x81, 0x41, 0}, 0xa4}, /*��*/
81   {{0x81, 0x45, 0}, 0xa5}, /*��*/
82   {{0x81, 0x5b, 0}, 0xb0}, /*��*/
83   {{0x81, 0x4a, 0}, 0xde}, /*��*/
84   {{0x81, 0x4b, 0}, 0xdf}, /*��*/
85   {{   0,    0, 0},    0}
86 };
87 
88 #define MOD_TEN  0x01 /* �� �������褿���,����(�� + ��= ��)���뤫 */
89 #define MOD_MARU 0x02 /* �� �������褿���,�������뤫 */
90 #define MOD_TM   0x03 /* �ϹԤ�, �� �� �� ξ�������դ��� */
91 
92 /*
93   MOD_xxx �ϡ�ñ�ʤ�ե饰�Ȥ��Ƥ����Ϥʤ���
94   ʸ�����¤Ӥϡ��֤Ƥ�Ƥ�ʤ��ס֤Ƥ�Ƥ���ס֤ޤ뤢��פν硣
95   ���ʤ�����֥�������...�� �֥ϥХѥҥӥ�...�פΤ褦���¤֡�
96   ��äơ��㤨�� �֥��פ�, MOD_TEN ��­���С��֥��פˤʤ�Τ���
97 */
98 
99 
100 struct {
101   uchar han_start, han_end;  /* 0xa1 - 0xdf */
102   uchar modifiers:4,         /* MOD_xxx �� OR */
103     offset:4;                /* ���Х��Ȥ��Ȥ˸���뤫 */
104   uchar zenkaku2_start;      /* euc �Σ��Х����� */
105 } kana_table[] = {
106   {0xa6, 0xa6,       0, 0, 0xf2}, /* �� */
107   {0xa7, 0xab,       0, 2, 0xa1}, /* �� - �� */
108   {0xac, 0xae,       0, 2, 0xe3}, /* �� - �� */
109   {0xaf, 0xaf,       0, 0, 0xc3}, /* �� */
110   {0xb1, 0xb5,       0, 2, 0xa2}, /* �� - �� */
111   {0xb3, 0xb3, MOD_TEN, 0, 0xf3}, /* �� */
112   {0xb6, 0xba, MOD_TEN, 2, 0xab}, /* �� - �� �� - �� */
113   {0xbb, 0xbf, MOD_TEN, 2, 0xb5}, /* �� - �� �� �� �� */
114   {0xc0, 0xc1, MOD_TEN, 2, 0xbf}, /* �� - �� �� �� �� */
115   {0xc2, 0xc2, MOD_TEN, 0, 0xc4}, /* �� �� */
116   {0xc3, 0xc4, MOD_TEN, 2, 0xc6}, /* �� - �� �� - �� */
117   {0xc5, 0xc9,       0, 1, 0xca}, /* �� �� �� */
118   {0xca, 0xce,  MOD_TM, 3, 0xcf}, /* �� �� �� �� - �� �� �� �� */
119   {0xcf, 0xd3,       0, 1, 0xde}, /* �� - �� */
120   {0xd4, 0xd6,       0, 2, 0xe4}, /* �� - �� */
121   {0xd7, 0xdb,       0, 1, 0xe9}, /* �� - �� */
122   {0xdc, 0xdc,       0, 0, 0xef}, /* �� */
123   {0xdd, 0xdd,       0, 0, 0xf3}, /* �� */
124   {   0,    0,       0, 0,    0}
125 };
126 
127 /*
128  * Daemonize. from iMultiMouse...
129  */
130 
131 static pid_t child;
132 static char *pid_file_path;
133 
m_quit_parent()134 static void m_quit_parent()
135 {
136   FILE *fp;
137 
138   if (pid_file_path != NULL && (fp = fopen(pid_file_path, "w")) != NULL) {
139     fprintf(fp, "%d\n", child);
140     fclose(fp);
141   }
142 
143   exit(0);
144 }
145 
m_daemonize(char * pid_path)146 int m_daemonize(char *pid_path)
147 {
148   pid_t parent;
149   int fd;
150 
151   pid_file_path = pid_path;
152 
153   parent = getpid();
154 
155   close(fileno(stdin));
156   close(fileno(stdout));
157 
158   if ((child = fork()) == -1) {
159     perror("");
160     return(EOF);
161   }
162 
163   if (child)
164     m_quit_parent();
165 
166   signal(SIGHUP, SIG_IGN);
167 
168   setsid();
169 
170   close(fileno(stderr));
171 
172   if ((fd = open("/dev/null", 2)) >= 0) {
173     if (fd != 0)
174       dup2(fd, 0);
175     if (fd != 1)
176       dup2(fd, 1);
177     if (fd != 2)
178       dup2(fd, 2);
179     if (fd != 0 && fd != 1 && fd != 2)
180       close(fd);
181   }
182 
183   chdir("/");
184 
185   return(0);
186 }
187 
188 /*
189  * m_message ... derived from Report* function, written by Morita Akio.
190  */
191 
192 static FILE *logfp = NULL;
193 static ino_t loginode = 0;
194 static char *logfile;
195 
m_message_log_open()196 static int m_message_log_open()
197 {
198   struct stat st;
199 
200   if (logfile) {
201     if ((logfp = fopen(logfile, "a")) != NULL) {
202       if (fstat(fileno(logfp), &st) == 0) {
203 	loginode = st.st_ino;
204 
205 	return 0;
206       }
207 
208       loginode = 0;
209 
210       fclose(logfp);
211     }
212 
213     free(logfile);
214     logfile = NULL;
215   }
216 
217   logfp = stderr;
218 
219   m_msg_dbg("Logging to file failed.\n");
220 
221   return -1;
222 }
223 
m_message_log_close()224 static int m_message_log_close()
225 {
226   if (logfp != NULL && logfp != stderr) {
227     fclose(logfp);
228     logfp = stderr;
229   }
230 
231   return 0;
232 }
233 
m_message_log_check()234 static int m_message_log_check()
235 {
236   struct stat st;
237   static char recall_flag;
238 
239   if (recall_flag)
240     return 0;
241 
242   recall_flag = 1;
243 
244   if (loginode) {
245     if (stat(logfile, &st) < 0 || st.st_ino != loginode) {
246       m_msg("Logfile rotated. Try to reopen...\n");
247 
248       m_message_log_close();
249       if (m_message_log_open() == 0)
250 	m_msg("Reopening logfile succeeded.\n");
251       else
252 	m_msg("Reopening logfile failed.\n");
253     }
254   }
255 
256   recall_flag = 0;
257 
258   return 0;
259 }
260 
m_message_init(char * logfilepath)261 int m_message_init(char *logfilepath)
262 {
263   if (logfilepath) {
264     logfile = strdup(logfilepath);
265 
266     m_message_log_open();
267   } else
268     logfp = stderr;
269 
270   return 0;
271 }
272 
m_message_term()273 int m_message_term()
274 {
275   m_message_log_close();
276 
277   return 0;
278 }
279 
m_message_output(int level,const char * msg)280 int m_message_output(int level, const char *msg)
281 {
282   time_t tm;
283   char *timebuf, buf[26];
284 
285   if (logfp && level == MSG_NOTICE) {
286     m_message_log_check();
287 
288     tm = time(0);
289     timebuf = ctime(&tm);
290     memcpy(buf, &timebuf[4], 16);
291     buf[15] = 0;
292 
293     fprintf(logfp, "%s: %s", buf, msg);
294     fflush(logfp);
295   } else {
296     fprintf(stderr, "%s", msg);
297     fflush(stderr);
298   }
299 
300   return 0;
301 }
302 
m_message_debug(const char * fmt,...)303 int m_message_debug(const char *fmt, ...)
304 {
305 #if HAVE_VASPRINTF
306   char *formated;
307 #else
308   char formated[1024]; /* FIXME:too ad-hoc!! */
309 #endif
310   va_list ap;
311 
312   va_start(ap, fmt);
313 #if HAVE_VASPRINTF
314   vasprintf(&formated, fmt, ap);
315 #else
316 #if HAVE_VSNPRINTF
317   vsnprintf(formated, 1024, fmt, ap);
318 #else
319   vsprintf(formated, fmt, ap);
320 #endif
321 #endif
322   va_end(ap);
323 
324   if (formated != NULL) {
325     m_message_output(MSG_DEBUG, formated);
326 #if HAVE_VASPRINTF
327     free((void *)formated);
328 #endif
329     return 0;
330   } else {
331     m_message_output(MSG_DEBUG, "out of memory!\n");
332     return -1;
333   }
334 }
335 
m_message_notice(const char * fmt,...)336 int m_message_notice(const char *fmt, ...)
337 {
338 #if HAVE_VASPRINTF
339   char *formated;
340 #else
341   char formated[1024];
342 #endif
343   va_list ap;
344 
345   va_start(ap, fmt);
346 #if HAVE_VASPRINTF
347   vasprintf(&formated, fmt, ap);
348 #else
349 #if HAVE_VSNPRINTF
350   vsnprintf(formated, 1024, fmt, ap);
351 #else
352   vsprintf(formated, fmt, ap);
353 #endif
354 #endif
355   va_end(ap);
356 
357   if (formated != NULL) {
358     m_message_output(MSG_NOTICE, formated);
359 #if HAVE_VASPRINTF
360     free((void *)formated);
361 #endif
362     return 0;
363   } else {
364     m_message_output(MSG_NOTICE, "out of memory!\n");
365     return -1;
366   }
367 }
368 
369 /*
370  * buffer_
371  */
372 
buffer_free(buffer_t * b)373 int buffer_free(buffer_t *b)
374 {
375   if (b->buf && b->size)
376     free(b->buf);
377 
378   b->buf = NULL;
379   b->size = 0;
380 
381   return 0;
382 }
383 
buffer_check(buffer_t * b,size_t required_size)384 int buffer_check(buffer_t *b, size_t required_size)
385 {
386   char *buf;
387   size_t size;
388 
389 #ifdef DEBUG /* for Memory Allocate Stress Test */
390   size = required_size;
391   if (size > 0) {
392     if ((buf = malloc(size)) != NULL) {
393       memset(buf, 0, size);
394       if (b->size > 0) {
395 	if (size > b->size) {
396 	  memcpy(buf, b->buf, b->size); /* Copy  Buffer */
397 	} else {
398 	  memcpy(buf, b->buf, size); /* Copy  Buffer */
399 	}
400 	memset(b->buf, 0, b->size);   /* Clear Old Buffer */
401 	free(b->buf);                 /* Free  Old Buffer */
402       }
403 
404       /*
405       m_message_debug("Buffer Rellocate Request %d (%d -> %d reallcated)",
406 		      equired_size, b->size, size);
407 		      */
408 
409       b->buf = buf;
410       b->size = size;
411 
412       return 0;
413     } else {
414       return -1;
415     }
416   } else {
417     memset(b->buf, 0, b->size); /* Clear Old Buffer */
418     free(b->buf);               /* Free  Old Buffer */
419     b->size = 0;
420 
421     /*
422       m_message_debug("Buffer Rellocate Request %d (%d -> %d reallcated)",
423                       required_size, b->size, size);
424 		      */
425     return 0;
426   }
427 #else
428   if (required_size > b->size) {
429     size = ((required_size + 127) / 128) * 128;
430     if ((buf = realloc(b->buf, size)) != NULL) {
431       if (b->size == 0)
432 	memset(buf, 0, size);
433 
434       /*
435       m_message_debug("Buffer Rellocate Request %d (%d -> %d reallcated)",
436                       required_size, b->size, size);
437 		      */
438 
439       b->buf = buf;
440       b->size = size;
441 
442       return 0;
443     } else {
444       return -1;
445     }
446   }
447 #endif
448   return 0;
449 }
450 
buffer_clear(buffer_t * b)451 int buffer_clear(buffer_t *b)
452 {
453   if (b->buf)
454     memset(b->buf, 0, b->size);
455   return 0;
456 }
457 
458 /* m_conf1_parse() : ����ե�����Τ����Ԥ���Ϥ���
459  *            ʸˡ : OpeCode=String
460  *          ������ : 0..Success -1..Error
461  *                 - line  ... �ե�����ιԡ���¸����ʤ���
462  *                 - ope_r ... OpeCode ��ʸ������֤�
463  *                 - val_r ... String ��ʸ������֤�
464  */
465 
m_conf1_parse(char * line,char ** ope_r,char ** val_r)466 int m_conf1_parse(char *line, char **ope_r, char **val_r)
467 {
468   char *p;
469 
470   if ((p = strchr(line, '\n')) != NULL)
471     *p = '\0';
472   if ((p = strchr(line, '=')) != NULL) {
473     *p = '\0';
474     *val_r = p + 1;
475     *ope_r = line;
476 
477     return 0;
478   }
479 
480   return -1;
481 }
482 
m_conf_string(char * ope,char * opestr,char * val,char ** val_r)483 int m_conf_string(char *ope, char *opestr, char *val, char **val_r)
484 {
485   if (strcmp(ope, opestr) == 0) {
486     if (*val_r)
487       free(*val_r);
488 
489     if (val[0])
490       *val_r = strdup(val);
491     else
492       *val_r = NULL;
493 
494     return 1;
495   }
496 
497   return 0;
498 }
499 
m_conf_multiple_choice(char * ope,char * opestr,char * val,char ** choice,int choice_n,int case_sensitive)500 int m_conf_multiple_choice(char *ope, char *opestr, char *val, char **choice,
501 			   int choice_n, int case_sensitive)
502 {
503   int i;
504   int (*compare)(const char *, const char *);
505 
506   compare = (case_sensitive) ? strcmp : strcasecmp;
507 
508   if (strcmp(ope, opestr) == 0) {
509     for (i = 0; i < choice_n; i++) {
510       if (compare(val, choice[i]) == 0)
511 	return i + 1;
512     }
513   }
514 
515   return 0;
516 }
517 
m_conf_tof(char * ope,char * opestr,char * val,char * str1,char * str2,int case_sensitive)518 int m_conf_tof(char *ope, char *opestr, char *val, char *str1, char *str2,
519 	       int case_sensitive)
520 {
521   char *choice[2];
522 
523   choice[0] = str1;
524   choice[1] = str2;
525 
526   return m_conf_multiple_choice(ope, opestr, val, choice, 2, case_sensitive);
527 }
528 
m_conf_isequal(char * ope,char * opestr,char * val,char * valstr)529 int m_conf_isequal(char *ope, char *opestr, char *val, char *valstr)
530 {
531   if (strcmp(ope, opestr) == 0) {
532     if (strcmp(val, valstr) == 0)
533       return 2;
534     else
535       return 1;
536   }
537 
538   return 0;
539 }
540 
541 /*
542  * m_memdup()
543  */
544 
m_memdup(void * src,size_t n)545 void *m_memdup(void *src, size_t n)
546 {
547   char *dst;
548 
549   dst = malloc(n);
550   memcpy(dst, src, n);
551 
552   return (void *)dst;
553 }
554 
555 
556 /*
557  * m_makepath m_splitpath
558  */
559 
m_makepath(char * dir,char * file)560 char *m_makepath(char *dir, char *file)
561 {
562   int dirlen, filelen;
563   char *path;
564 
565   dirlen = strlen(dir);
566   filelen = strlen(file);
567 
568   path = malloc(dirlen + 1 + filelen + 1);
569 
570   if (path) {
571     strcpy(path, dir);
572 
573     if (dirlen > 0 && dir[dirlen - 1] != '/')
574       strcat(path, "/");
575 
576     strcat(path, file);
577   }
578 
579   return path;
580 }
581 
m_splitpath(char * path,char ** dir,char ** file)582 int m_splitpath(char *path, char **dir, char **file)
583 {
584   char *lastslash, *buf;
585 
586   buf = strdup(path);
587   lastslash = strrchr(buf, '/');
588 
589   if (dir != NULL) {
590     if (lastslash != NULL) {
591       *lastslash = '\0';
592 
593       if ((*dir = strdup(buf)) == NULL) {
594 	free(buf);
595 	return -1;
596       }
597 
598       lastslash++;
599     } else {
600       *dir = NULL;
601       lastslash = buf;
602     }
603   } else {
604     if (lastslash == NULL)
605       lastslash = buf;
606   }
607 
608   if (file != NULL) {
609     if ((*file = strdup(lastslash)) == NULL) {
610       free(buf);
611       return -1;
612     }
613   }
614 
615   free(buf);
616 
617   return 0;
618 }
619 
620 /*
621  * m_netaddr2ascii()
622  */
623 
m_netaddr2ascii(uint netaddr,char * ascii)624 char *m_netaddr2ascii(uint netaddr, char *ascii)
625 {
626 #ifdef WORDS_BIGENDIAN
627   sprintf(ascii, "%d,%d,%d,%d",
628 	  (netaddr >> 24) & 0xff, (netaddr >> 16) & 0xff,
629 	  (netaddr >> 8) & 0xff, (netaddr) & 0xff);
630 #else
631   sprintf(ascii, "%d.%d.%d.%d",
632 	  (netaddr) & 0xff, (netaddr >> 8) & 0xff,
633 	  (netaddr >> 16) & 0xff, (netaddr >> 24) & 0xff);
634 #endif /* WORDS_BIGENDIAN */
635 
636   return ascii;
637 }
638 
639 /*
640  * analyze canna converting mode...
641  */
642 
m_count_canna_mode(int mode)643 int m_count_canna_mode(int mode)
644 {
645   int ret = 0;
646 
647   while (mode) {
648     mode = mode >> 4;
649     ret++;
650   }
651 
652   return ret;
653 }
654 
m_get_canna_mode(int mode,int n)655 int m_get_canna_mode(int mode, int n)
656 {
657   int ret;
658 
659   ret = (mode >> (4 * n)) & 0x0f;
660 
661   /* ret..1: HIRAGANA 2: HANKAKU 3: KATAKANA 4: ZENKAKU */
662 
663   return ret;
664 }
665 
m_count_valid_canna_mode(int mode)666 int m_count_valid_canna_mode(int mode)
667 {
668   int ret = 0;
669   int i, max, cmode;
670 
671   max = m_count_canna_mode(mode);
672 
673   for (i = 0; i < max; i++) {
674     cmode = m_get_canna_mode(mode, i);
675 
676     if (cmode == 1 || cmode == 3)
677       ret++;
678   }
679 
680   return ret;
681 }
682 
683 /*
684  * convert coding system...
685  */
686 
cannawc2euc(ushort * src,int srclen,char * dest,int destlen)687 int cannawc2euc(ushort *src, int srclen, char *dest, int destlen)
688 {
689   register int i, j;
690   register uchar *c;
691 
692   for (i = 0, j = 0 ; i < srclen && j + 2 < destlen ; i++) {
693     c = (unsigned char *)(&src[i]);
694     switch ((c[0] | (c[1] << 8)) & 0x8080) {
695       case 0:
696 	/* ASCII */
697 	// dest[j++] = (char)(((unsigned)wc & 0x7f00) >> 8);
698 	dest[j++] = c[1];
699 	break;
700       case 0x8000:
701 	/* Ⱦ�ѥ��� */
702 	dest[j++] = (char)0x8e; /* SS2 */
703 	// dest[j++] = (char)((((unsigned)wc & 0x7f00) >> 8) | 0x80);
704 	dest[j++] = c[1] | 0x80;
705 	break;
706       case 0x0080:
707 	/* ���� */
708 	dest[j++] = (char)0x8f;
709 	// dest[j++] = (char)(((unsigned)wc & 0x7f) | 0x80);
710 	// dest[j++] = (char)((((unsigned)wc & 0x7f00) >> 8) | 0x80);
711 	dest[j++] = c[0] | 0x80;
712 	dest[j++] = c[1] | 0x80;
713 	break;
714       case 0x8080:
715 	/* ���� */
716 	// dest[j++] = (char)(((unsigned)wc & 0x7f) | 0x80);
717 	// dest[j++] = (char)((((unsigned)wc & 0x7f00) >> 8) | 0x80);
718 	dest[j++] = c[0] | 0x80;
719 	dest[j++] = c[1] | 0x80;
720 	break;
721     }
722   }
723   dest[j] = '\0';
724   return j;
725 }
726 
euc2cannawc(char * src,int srclen,ushort * dest,int destlen)727 int euc2cannawc(char *src, int srclen, ushort *dest, int destlen)
728 {
729   register int i, j;
730   register unsigned ec;
731   uchar *c;
732 
733   for (i = 0, j = 0 ; i < srclen && j + 1 < destlen ; i++) {
734     ec = (unsigned)(unsigned char)src[i];
735     c = (unsigned char *)(&dest[j++]);
736     if (ec & 0x80) {
737       switch (ec) {
738 	case 0x8e: /* SS2 */
739 	  // dest[j++] = (ushort)((0x80 | ((unsigned)src[++i] & 0x7f)) << 8);
740 	  c[0] = 0;
741 	  c[1] = src[++i] | 0x80;
742 	  break;
743 	case 0x8f: /* SS3 */
744 	  // dest[j++] = (ushort)(0x0080
745 	  //	       | ((unsigned)src[i + 1] & 0x7f)
746 	  //	       | (((unsigned)src[i + 2] & 0x7f) << 8));
747 	  c[0] = 0x80 | src[i + 1];
748 	  c[1] = src[i + 2] & 0x7f;
749 
750 	  i += 2;
751 	  break;
752 	default:
753 	  // dest[j++] = (ushort)(0x8080 | ((unsigned)src[i] & 0x7f)
754 	  //		       | (((unsigned)src[i + 1] & 0x7f) << 8));
755 	  c[0] = 0x80 | src[i];
756 	  c[1] = 0x80 | src[i + 1];
757 
758 	  i++;
759 	  break;
760       }
761     }
762     else {
763       // dest[j++] = (ushort)(ec << 8);
764       c[0] = 0;
765       c[1] = ec;
766     }
767   }
768   dest[j] = 0;
769   return j;
770 }
771 
cannawcstrlen(ushort * ws)772 int cannawcstrlen(ushort *ws)
773 {
774   int res = 0;
775   while (*ws++) {
776     res++;
777   }
778   return res;
779 }
780 
cannawcstrdup(ushort * ws)781 ushort *cannawcstrdup(ushort *ws)
782 {
783   ushort *p;
784   int len;
785 
786   len = cannawcstrlen(ws) * 2 + 2;
787 
788   p = (ushort *)malloc(len);
789   memcpy(p, ws, len);
790 
791   return (ushort *)p;
792 }
793 
cannawcstrcat(ushort * p1,ushort * p2)794 ushort *cannawcstrcat(ushort *p1, ushort *p2)
795 {
796   uint l1, l2;
797 
798   l1 = cannawcstrlen(p1);
799   l2 = cannawcstrlen(p2);
800 
801   memcpy(&(p1[l1]), p2, l2);
802   p1[l1 + l2] = 0;
803 
804   return p1;
805 }
806 
807 /* src ��ˤ����Ĥ� key ������뤫������ */
808 
cannawcnumstr(ushort * src,ushort * key)809 int cannawcnumstr(ushort *src, ushort *key)
810 {
811   int i, len1, len2, ret;
812 
813   len1 = cannawcstrlen(src);
814   len2 = cannawcstrlen(key);
815   ret = 0;
816 
817   for (i = 0; i <= len1 - len2;) {
818     if (memcmp(&(src[i]), key, len2 * 2) == 0) {
819       ret++;
820       i += len2;
821     } else {
822       i++;
823     }
824   }
825 
826   return ret;
827 }
828 
829 
euc2sjis(uchar * euc,int euclen,uchar * sjis,int sjislen)830 int euc2sjis(uchar *euc, int euclen, uchar *sjis, int sjislen)
831 {
832   int euc_pnt = 0, sjis_pnt = 0;
833   uint hi, lo;
834 
835   while (euc[euc_pnt] && euc_pnt < euclen && sjis_pnt < sjislen) {
836     if (euc[euc_pnt] & 0x80) {
837       if (euc[euc_pnt] == 0x8e) { /* Ⱦ�ѥ��� */
838 	euc_pnt++;
839 	sjis[sjis_pnt++] = euc[euc_pnt++];
840       } else { /* ����ʸ�� */
841 	hi = euc[euc_pnt++] & 0x7f;
842 	lo = euc[euc_pnt++] & 0x7f;
843 
844 	if ((hi & 1) == 0) {
845 	  lo += 0x5e;
846 	  hi--;
847 	}
848 
849 	hi = ((hi - 0x21) >> 1) + 0x81;
850 	lo += (0x40 - 0x21);
851 
852 	if (lo >= 0x7f)
853 	  lo++;
854 	if (hi >= 0xa0)
855 	  hi += 0x40;
856 
857 	sjis[sjis_pnt++] = hi;
858 	sjis[sjis_pnt++] = lo;
859       }
860     } else { /* ANK */
861       sjis[sjis_pnt++] = euc[euc_pnt++];
862     }
863   }
864 
865   if (sjis_pnt < sjislen)
866     sjis[sjis_pnt] = '\0';
867   else
868     sjis[sjislen - 1] = '\0';
869 
870   return sjis_pnt;
871 }
872 
sjis2euc(uchar * sjis,int sjislen,uchar * euc,int euclen)873 int sjis2euc(uchar *sjis, int sjislen, uchar *euc, int euclen)
874 {
875   int euc_pnt = 0, sjis_pnt = 0;
876   int hi, lo;
877 
878   while (sjis[sjis_pnt] && sjis_pnt < sjislen && euc_pnt < euclen) {
879     if (ISSJISKANJI1(sjis[sjis_pnt])) { /* ����ʸ�� */
880       hi = sjis[sjis_pnt++] & 0xff;
881       lo = sjis[sjis_pnt++] & 0xff;
882 
883       if (hi >= 0xe0)
884 	hi -= 0x40;
885       if (lo >= 0x80)
886 	lo--;
887 
888       lo -= (0x40 - 0x21);
889       hi = ((hi - 0x81) << 1) + 0x21;
890 
891       if (lo >= 0x7f) {
892 	lo -= 0x5e;
893 	hi++;
894       }
895 
896       euc[euc_pnt++] = hi | 0x80;
897       euc[euc_pnt++] = lo | 0x80;
898     } else if (ISSJISKANA(sjis[sjis_pnt])) { /* Ⱦ�ѥ��� */
899       euc[euc_pnt++] = 0x8e;
900       euc[euc_pnt++] = sjis[sjis_pnt++];
901     } else {
902       euc[euc_pnt++] = sjis[sjis_pnt++];
903     }
904   }
905 
906   if (euc_pnt < euclen)
907     euc[euc_pnt] = '\0';
908   else
909     euc[euclen - 1] = '\0';
910 
911   return euc_pnt;
912 }
913 
914 /*
915  * signal setup...
916  */
917 
m_setup_signal(signalhandler_t handler)918 int m_setup_signal(signalhandler_t handler)
919 {
920   signal(SIGINT, (void(*)())handler);
921   signal(SIGTERM, (void(*)())handler);
922   signal(SIGHUP, SIG_IGN);
923   signal(SIGQUIT, SIG_IGN);
924   signal(SIGPIPE, SIG_IGN);
925 
926   return 0;
927 }
928 
929 /*
930  * copy file...
931  */
932 
m_copy_file_fp(FILE * from,FILE * to)933 int m_copy_file_fp(FILE *from, FILE *to)
934 {
935   char buf[1024];
936   int i;
937 
938   do {
939     i = fread(buf, 1, 1024, from);
940     fwrite(buf, 1, i, to);
941   } while (i == 1024);
942 
943   return 0;
944 }
945 
m_copy_file(char * from,char * to)946 int m_copy_file(char *from, char *to)
947 {
948   FILE *fp1, *fp2;
949   char buf[1024];
950   int i;
951 
952   if ((fp1 = fopen(from, "r")) != NULL) {
953     if ((fp2 = fopen(to, "w")) != NULL) {
954       do {
955 	i = fread(buf, 1, 1024, fp1);
956 	fwrite(buf, 1, i, fp2);
957       } while (i == 1024);
958 
959       fclose(fp2);
960       fclose(fp1);
961 
962       return 0;
963     }
964     fclose(fp1);
965   }
966 
967   return -1;
968 }
969 
970 /*
971  * system() ��Ʊ���δؿ�
972  */
973 
974 static char m_system_opened_file[FOPEN_MAX];
975 
m_system_clear()976 int m_system_clear()
977 {
978   memset(m_system_opened_file, 0, FOPEN_MAX);
979   return 0;
980 }
981 
m_system_register_file(int fd)982 int m_system_register_file(int fd)
983 {
984   m_system_opened_file[fd] = 0xff;
985   return 0;
986 }
987 
m_system(char * command)988 int m_system(char *command)
989 {
990   int i, status, pid;
991   char *argv[4];
992 
993   if (command == NULL)
994     return -1;
995 
996   pid = fork();
997 
998   if (pid == -1)
999     return -1;
1000 
1001   if (pid == 0) {
1002     for (i = 0; i < FOPEN_MAX; i++)
1003       if (m_system_opened_file[i])
1004 	close(m_system_opened_file[i]);
1005 
1006     argv[0] = "sh";
1007     argv[1] = "-c";
1008     argv[2] = command;
1009     argv[3] = NULL;
1010 
1011     execv("/bin/sh", argv);
1012 
1013     exit(127);
1014   }
1015 
1016   for (;;) {
1017     if (waitpid(pid, &status, 0) == -1) {
1018       if (errno != EINTR)
1019 	return -1;
1020     } else
1021       return status;
1022   }
1023 }
1024 
1025 /*
1026  * read/write from/to socket functions...
1027  */
1028 
m_socket_read(int fd,char * ptr,int totalsize)1029 int m_socket_read(int fd, char *ptr, int totalsize)
1030 {
1031   int size, ret;
1032 
1033   size = 0;
1034   while (size < totalsize) {
1035     if ((ret = read(fd, &ptr[size], totalsize - size)) <= 0)
1036       return -1;
1037 
1038     size += ret;
1039   }
1040 
1041   return 0;
1042 }
1043 
m_socket_write(int fd,char * ptr,int totalsize)1044 int m_socket_write(int fd, char *ptr, int totalsize)
1045 {
1046   int size, ret;
1047 
1048   size = 0;
1049   while (size < totalsize) {
1050     if ((ret = write(fd, &ptr[size], totalsize - size)) < 0)
1051       return -1;
1052 
1053     size += ret;
1054   }
1055 
1056   return 0;
1057 }
1058 
1059 /*
1060  * string modifier...
1061  */
1062 
m_replace_string(uchar * eucbuf,char * pre,char * post)1063 int m_replace_string(uchar *eucbuf, char *pre, char *post)
1064 {
1065   char *p;
1066   int slen, prelen, postlen;
1067 
1068   prelen = strlen(pre);
1069   postlen = strlen(post);
1070 
1071   while ((p = strstr(eucbuf, pre)) != NULL) {
1072     slen = strlen(p);
1073 
1074     memmove(p + postlen, p + prelen, slen - prelen + 1);
1075     memcpy(p, post, postlen);
1076   }
1077 
1078   return strlen(eucbuf);
1079 }
1080 
m_convert_zen2han(uchar * sjisbuf)1081 int m_convert_zen2han(uchar *sjisbuf)
1082 {
1083   int i = 0;
1084 
1085   if (sjisbuf[0] == 0x82) { /* Alphabet */
1086     if (0x60 <= sjisbuf[1] && sjisbuf[1] < 0x60 + 26) /* A-Z */
1087       return 'A' + sjisbuf[1] - 0x60;
1088     if (0x81 <= sjisbuf[1] && sjisbuf[1] < 0x81 + 26) /* a-z */
1089       return 'a' + sjisbuf[1] - 0x81;
1090   }
1091   if (sjisbuf[0] == 0x82 && 0x4f <= sjisbuf[1] && sjisbuf[1] <= 0x58) /* 0-9 */
1092     return '0' + sjisbuf[1] - 0x4f;
1093 
1094   if (sjisbuf[0] == 0x81) { /* ������ */
1095     while (zen_han_table[i].c) {
1096       if (zen_han_table[i].zen[1] == sjisbuf[1])
1097 	return zen_han_table[i].c;
1098       i++;
1099     }
1100   }
1101 
1102   return 0;
1103 }
1104 
m_lookup_kana_table(uchar kana,int mod)1105 static int m_lookup_kana_table(uchar kana, int mod)
1106 {
1107   int i, j;
1108 
1109   j = -1; i = 0;
1110   while (kana_table[i].han_start) {
1111     if (kana_table[i].han_start <= kana && kana <= kana_table[i].han_end) {
1112       j = i;
1113 
1114       if (mod == 0 || (kana_table[i].modifiers & mod) != 0)
1115 	break;
1116     }
1117     i++;
1118   }
1119 
1120   return j;
1121 }
1122 
m_convert_hankana2zenkana(uchar * euc,int len)1123 int m_convert_hankana2zenkana(uchar *euc, int len)
1124 {
1125   int i, j;
1126   uchar mod, c;
1127 
1128   for (i = 0; i < len; i++) {
1129     mod = 0;
1130 
1131     if (euc[i] == 0x8e) { /* non-ascii ��Ⱦ��ʸ���ʤ� */
1132       if (euc[i + 1] == 0xde) { /* ���� �� �ʤ� */
1133 	euc[i] = 0xa1;
1134 	euc[i + 1] = 0xab;
1135 	i++;
1136       } else if (euc[i + 1] == 0xdf) { /* ���� �� �ʤ� */
1137 	euc[i] = 0xa1;
1138 	euc[i + 1] = 0xac;
1139 	i++;
1140       } else { /* ���̤�Ⱦ�ѥ������ʤʤ� */
1141 	if (i + 3 < len) {
1142 	  if (euc[i + 2] == 0x8e && euc[i + 3] == 0xde)  /* ���� �� �ʤ� */
1143 	    mod = MOD_TEN;
1144 	  if (euc[i + 2] == 0x8e && euc[i + 3] == 0xdf) /* ���� �� �ʤ� */
1145 	    mod = MOD_MARU;
1146 	}
1147 
1148 	if ((j = m_lookup_kana_table(euc[i + 1], mod)) != -1) {
1149 	  mod &= kana_table[j].modifiers; /* mod �ϡ֤Ƥ�Ƥ�ʤ��פ����
1150 					     ���ե��åȤ��� */
1151 	  c = kana_table[j].zenkaku2_start;
1152 	  c += (euc[i + 1] - kana_table[j].han_start) * kana_table[j].offset;
1153 	  c += mod;
1154 
1155 	  euc[i] = 0xa5; euc[i + 1] = c;
1156 
1157 	  if (mod) {
1158 	    memmove(&(euc[i + 2]), &(euc[i + 4]), len - (i + 4) + 1);
1159 	    len -= 2;
1160 	  }
1161 
1162 	  i++;
1163 	}
1164       }
1165     }
1166   }
1167 
1168   euc[len] = '\0';
1169 
1170   return len;
1171 }
1172 
m_convert_zenkana2zenhira(uchar * src,uchar * dst,int len)1173 int m_convert_zenkana2zenhira(uchar *src, uchar *dst, int len)
1174 {
1175   int i = 0;
1176   uchar euc[10];
1177 
1178   while (i < len) {
1179     dst[i] = 0x82;
1180     dst[i + 1] = src[i + 1] + (0x9f - 0x40);
1181     if (src[i + 1] >= 0x80)
1182       dst[i + 1] -= 1;
1183 
1184     i += 2;
1185   }
1186 
1187   sjis2euc(dst, len, euc, 10);
1188 
1189   return 0;
1190 }
1191 
m_exist_hankata(uchar * euc)1192 int m_exist_hankata(uchar *euc)
1193 {
1194   uchar *p;
1195 
1196   p = euc;
1197 
1198   while (*p) {
1199     if (*p & 0x80) {
1200       if (*p == 0x8e)
1201 	return 1;
1202       else
1203 	p += 2;
1204     } else {
1205       p++;
1206     }
1207   }
1208 
1209   return 0;
1210 }
1211 
m_is_zenkata_string(uchar * euc)1212 int m_is_zenkata_string(uchar *euc)
1213 {
1214   uchar *p;
1215 
1216   p = euc;
1217 
1218   while (*p) {
1219     if (*p == 0xa5)
1220       p += 2;
1221     else
1222       return 0;
1223   }
1224 
1225   return 1;
1226 }
1227 
m_is_hiragana_string(uchar * euc)1228 int m_is_hiragana_string(uchar *euc)
1229 {
1230   uchar *p;
1231   int vu_flag = 0, hira_flag = 0;
1232 
1233   p = euc;
1234 
1235   while (*p) {
1236     if (*p == 0xa4) {
1237       hira_flag = 1;
1238       p += 2;
1239     } else if (*p == 0xa5 && *(p + 1) == 0xf4) { /* �� �ξ�� */
1240       vu_flag = 1;
1241       p += 2;
1242     } else
1243       return 0;
1244   }
1245 
1246   if (vu_flag && hira_flag == 0)
1247     return 0; /* �� �����ξ��ϥ������ʤ�Ƚ�� */
1248 
1249   return 1;
1250 }
1251 
m_convert_zenhira2zenkata(uchar * euc_hira,int slen,uchar * euc_kata)1252 int m_convert_zenhira2zenkata(uchar *euc_hira, int slen, uchar *euc_kata)
1253 {
1254   int i, j;
1255 
1256   for (i = j = 0; i < slen;) {
1257     if (euc_hira[i] == 0xa4) {
1258       if (i + 4 <= slen && euc_hira[i + 1] == 0xa6 &&
1259 	  euc_hira[i + 2] == 0xa1 && euc_hira[i + 3] == 0xab) {
1260 	/* ���� �ξ�� */
1261 	euc_kata[j] = 0xa5;
1262 	euc_kata[j + 1] = 0xf4;
1263 	j += 2;
1264 	i += 4;
1265       } else {
1266 	euc_kata[j] = 0xa5;
1267 	euc_kata[j + 1] = euc_hira[i + 1];
1268 	j += 2;
1269 	i += 2;
1270       }
1271     } else if (euc_hira[i] & 0x80) {
1272       euc_kata[j++] = euc_hira[i++];
1273       euc_kata[j++] = euc_hira[i++];
1274     } else {
1275       euc_kata[j++] = euc_hira[i++];
1276     }
1277   }
1278 
1279   euc_kata[j] = 0;
1280 
1281   return j;
1282 }
1283 
1284 /* reconvroma.c */
1285 
1286 typedef struct {
1287   uchar roma[5];
1288   uchar hira[10];
1289 } romatbl_t;
1290 
1291 static romatbl_t romatbl[] = {
1292   "a", "��",
1293   "i", "��",
1294   "u", "��",
1295   "e", "��",
1296   "o", "��",
1297   "ka", "��",
1298   "ki", "��",
1299   "ku", "��",
1300   "ke", "��",
1301   "ko", "��",
1302   "ga", "��",
1303   "gi", "��",
1304   "gu", "��",
1305   "ge", "��",
1306   "go", "��",
1307   "sa", "��",
1308   "si", "��",
1309   "su", "��",
1310   "se", "��",
1311   "so", "��",
1312   "za", "��",
1313   "zi", "��",
1314   "zu", "��",
1315   "ze", "��",
1316   "zo", "��",
1317   "ta", "��",
1318   "ti", "��",
1319   "tu", "��",
1320   "te", "��",
1321   "to", "��",
1322   "da", "��",
1323   "di", "��",
1324   "du", "��",
1325   "de", "��",
1326   "do", "��",
1327   "na", "��",
1328   "ni", "��",
1329   "nu", "��",
1330   "ne", "��",
1331   "no", "��",
1332   "nn", "��",
1333   "ha", "��",
1334   "hi", "��",
1335   "fu", "��",
1336   "he", "��",
1337   "ho", "��",
1338   "ba", "��",
1339   "bi", "��",
1340   "bu", "��",
1341   "be", "��",
1342   "bo", "��",
1343   "pa", "��",
1344   "pi", "��",
1345   "pu", "��",
1346   "pe", "��",
1347   "po", "��",
1348   "ma", "��",
1349   "mi", "��",
1350   "mu", "��",
1351   "me", "��",
1352   "mo", "��",
1353   "ya", "��",
1354   "yu", "��",
1355   "yo", "��",
1356   "ra", "��",
1357   "ri", "��",
1358   "ru", "��",
1359   "re", "��",
1360   "ro", "��",
1361   "wa", "��",
1362   "wi", "��",
1363   "we", "��",
1364   "wo", "��",
1365   "xa", "��",
1366   "xi", "��",
1367   "xu", "��",
1368   "xe", "��",
1369   "xo", "��",
1370   "xwa", "��",
1371   "xtu", "��",
1372   "xya", "��",
1373   "xyu", "��",
1374   "xyo", "��",
1375 };
1376 
1377 static char *glyph =
1378 " ,.,./:;?!  '` ^~_         -- /\\  |   ' \"()  []{}<>  []{}  +-   = <>       '\" \\$  %#&*@       ";
1379 
1380 #define romatbl_num (sizeof(romatbl) / sizeof(romatbl_t))
1381 
reconvroma_lookup(uchar * hira)1382 static int reconvroma_lookup(uchar *hira)
1383 {
1384   int i;
1385 
1386   for (i = 0; i < romatbl_num; i++) {
1387     if (hira[1] == romatbl[i].hira[1])
1388       return i;
1389   }
1390 
1391   return -1;
1392 }
1393 
reconvroma_katakana2hiragana(uchar * src)1394 static uchar *reconvroma_katakana2hiragana(uchar *src)
1395 {
1396   int slen, i, j;
1397   uchar *p;
1398   static buffer_t zbuf;
1399 
1400   slen = strlen(src);
1401   buffer_check(&zbuf, slen * 2);
1402   p = zbuf.buf;
1403 
1404   if (p) {
1405     for (i = j = 0; i < slen;) {
1406       if (src[i] == 0xa5) { /* �������ʤξ�� */
1407 	switch (src[i + 1]) {
1408 	  case 0xf4: /* �� */
1409 	    memcpy(&(p[j]), "����", 4);
1410 	    j += 4;
1411 	    break;
1412 	  case 0xf5:
1413 	  case 0xf6:
1414 	    memcpy(&(p[j]), "��", 2);
1415 	    j += 2;
1416 	    break;
1417 	  default:
1418 	    p[j++] = 0xa4;
1419 	    p[j++] = src[i + 1];
1420 	}
1421 
1422 	i += 2;
1423       } else if (src[i] & 0x80) {
1424 	p[j++] = src[i++];
1425 	p[j++] = src[i++];
1426       } else {
1427 	p[j++] = src[i++];
1428       }
1429     }
1430 
1431     p[j] = 0;
1432   }
1433 
1434   return p;
1435 }
1436 
1437 /*
1438  * �Ҥ餬�ʡ��������ʡ�����ե��٥åȡ��������鹽��������ɤߤ�
1439  * ���޻����Ѵ����롣
1440  * ����ե��٥åȤ˴ؤ��Ƥϡ�0x80 �� OR ���롣
1441  */
1442 
m_reconvroma(uchar * src,uchar * dst)1443 int m_reconvroma(uchar *src, uchar *dst)
1444 {
1445   int src_pnt, i, srclen;
1446   uchar *p, buf[2];
1447 
1448   p = reconvroma_katakana2hiragana(src); /* �������ʤ�Ҥ餬�ʤ��Ѵ� */
1449   srclen = strlen(p);
1450   dst[0] = '\0';
1451   src_pnt = 0;
1452 
1453   while (p[src_pnt]) {
1454     switch (p[src_pnt]) {
1455       case 0xa4: /* �Ҥ餬�� */
1456 	if (src_pnt + 4 <= srclen && p[src_pnt + 1] == 0xa6 &&
1457 	    p[src_pnt + 2] == 0xa1 && p[src_pnt + 3] == 0xab) {
1458 	  /* �֤����פΤФ��� */
1459 	  strcat(dst, "vu");
1460 	  src_pnt += 4;
1461 	} else {
1462 	  if ((i = reconvroma_lookup(&(p[src_pnt]))) != -1) {
1463 	    strcat(dst, romatbl[i].roma);
1464 	    src_pnt += 2;
1465 	  } else {
1466 	    fprintf(stderr, "UNEXPECTED YOMI %d:%s\n", src_pnt, &(p[src_pnt]));
1467 	    free(p);
1468 	    return -1;
1469 	  }
1470 	}
1471 	break;
1472       case 0xa1: /* ���� */
1473 	if (glyph[p[src_pnt + 1] - 0xa1] != ' ') {
1474 	  buf[0] = glyph[p[src_pnt + 1] - 0xa1];
1475 	  buf[1] = 0;
1476 	  strcat(dst, buf);
1477 	  src_pnt += 2;
1478 	} else {
1479 	  fprintf(stderr, "UNEXPECTED GLYPH:%d:%s\n", src_pnt, &(p[src_pnt]));
1480 	  free(p);
1481 	  return -1;
1482 	}
1483 	break;
1484       case 0xa3: /* ����,����ե��٥å� */
1485 	if (0xb0 <= p[src_pnt + 1] && p[src_pnt + 1] <= 0xb9) {
1486 	  buf[0] = '0' + (p[src_pnt + 1] - 0xb0);
1487 	  buf[1] = 0;
1488 	  strcat(dst, buf);
1489 	  src_pnt += 2;
1490 	} else if (0xc1 <= p[src_pnt + 1] && p[src_pnt + 1] <= 0xda) {
1491 	  buf[0] = ('A' + (p[src_pnt + 1] - 0xc1)) | 0x80;
1492 	  buf[1] = 0;
1493 	  strcat(dst, buf);
1494 	  src_pnt += 2;
1495 	} else if (0xe1 <= p[src_pnt + 1] && p[src_pnt + 1] <= 0xfa) {
1496 	  buf[0] = ('a' + (p[src_pnt + 1] - 0xe1)) | 0x80;
1497 	  buf[1] = 0;
1498 	  strcat(dst, buf);
1499 	  src_pnt += 2;
1500 	} else {
1501 	  fprintf(stderr, "UNEXPECTED ALNUM:%d:%s\n", src_pnt, &(p[src_pnt]));
1502 	  free(p);
1503 	  return -1;
1504 	}
1505 	break;
1506       default:
1507 	if ((p[src_pnt] & 0x80) == 0) {
1508 	  buf[0] = p[src_pnt] | 0x80;
1509 	  buf[1] = 0;
1510 	  strcat(dst, buf);
1511 	  src_pnt++;
1512 	} else {
1513 	  fprintf(stderr, "UNEXPECTED:%d:%s\n", src_pnt, &(p[src_pnt]));
1514 	  free(p);
1515 	  return -1;
1516 	}
1517     }
1518   }
1519 
1520   return 0;
1521 }
1522 
1523 
1524