ispell.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:5k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. /*
  6. ** $Id: ispell.c,v 1.2 1999/12/08 06:00:38 mrsam Exp $
  7. */
  8. #include "ispell.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #if HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #if HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #include <sys/types.h>
  18. #if HAVE_SYS_WAIT_H
  19. #include <sys/wait.h>
  20. #endif
  21. #include <signal.h>
  22. #include <string.h>
  23. static pid_t ispell_pid;
  24. static RETSIGTYPE (*prevsighandler)(int);
  25. #ifndef ISPELL
  26. #define ISPELL "/usr/bin/ispell"
  27. #endif
  28. static void wait4pid()
  29. {
  30. int waitstat;
  31. if (prevsighandler == SIG_DFL)
  32. while ( wait(&waitstat) != ispell_pid)
  33. ;
  34. }
  35. static int fork_ispell(const char *ispellline, const char *dict,
  36. struct ispell *isp)
  37. {
  38. int fdbuf[2], fdbuf2[2];
  39. size_t l;
  40. int waitstat;
  41. int c;
  42. FILE *ispell_resp;
  43. size_t ispell_resp_buf_size=0;
  44. const char *args[6];
  45. int argn;
  46. isp->ispell_buf=0;
  47. prevsighandler=signal(SIGCHLD, SIG_DFL);
  48. signal(SIGCHLD, prevsighandler);
  49. if (pipe(fdbuf) < 0) return (-1);
  50. switch (ispell_pid=fork()) {
  51. case -1:
  52. close(fdbuf[0]);
  53. close(fdbuf[1]);
  54. return (-1);
  55. case 0:
  56. if (pipe(fdbuf2) < 0) _exit(-1);
  57. /*
  58. ** First child will fork and run the real ispell, and write to
  59. ** it on stdin.
  60. */
  61. switch (ispell_pid=fork()) {
  62. case -1:
  63. _exit(-1);
  64. case 0:
  65. close(0);
  66. close(1);
  67. dup(fdbuf2[0]);
  68. dup(fdbuf[1]);
  69. close(fdbuf[0]);
  70. close(fdbuf[1]);
  71. close(fdbuf2[0]);
  72. close(fdbuf2[1]);
  73. argn=0;
  74. args[argn++]="ispell";
  75. args[argn++]="-a";
  76. if (dict)
  77. {
  78. args[argn++]="-d";
  79. args[argn++]=dict;
  80. }
  81. args[argn]=0;
  82. execv(ISPELL, (char **)args);
  83. _exit(1);
  84. }
  85. close(fdbuf[0]);
  86. close(fdbuf[1]);
  87. close(fdbuf2[0]);
  88. signal(SIGCHLD, SIG_DFL);
  89. l=strlen(ispellline);
  90. while (l)
  91. {
  92. int n=write(fdbuf2[1], ispellline, l);
  93. if (n <= 0) _exit(1);
  94. ispellline += n;
  95. l -= n;
  96. }
  97. if (write(fdbuf2[1], "n", 1) != 1) _exit(1);
  98. close(fdbuf2[1]);
  99. while ( wait(&waitstat) != ispell_pid)
  100. ;
  101. _exit(0);
  102. }
  103. close(fdbuf[1]);
  104. ispell_resp=fdopen(fdbuf[0], "r");
  105. if (!ispell_resp)
  106. {
  107. close(fdbuf[0]);
  108. wait4pid();
  109. return (-1);
  110. }
  111. l=0;
  112. for (;;)
  113. {
  114. if (l >= ispell_resp_buf_size)
  115. {
  116. char *newbuf;
  117. size_t l=ispell_resp_buf_size + BUFSIZ;
  118. newbuf=isp->ispell_buf ? realloc(isp->ispell_buf, l)
  119. :malloc(l);
  120. if (!newbuf)
  121. {
  122. if (isp->ispell_buf) free(isp->ispell_buf);
  123. isp->ispell_buf=0;
  124. wait4pid();
  125. fclose(ispell_resp);
  126. return (-1);
  127. }
  128. isp->ispell_buf=newbuf;
  129. ispell_resp_buf_size=l;
  130. }
  131. if ( (c=getc(ispell_resp)) == EOF )
  132. break;
  133. isp->ispell_buf[l++]=c;
  134. }
  135. isp->ispell_buf[l]=0;
  136. fclose(ispell_resp);
  137. wait4pid();
  138. return (0);
  139. }
  140. struct ispell *ispell_run(const char *dict, const char *line)
  141. {
  142. char *p, *q;
  143. struct ispell *isp;
  144. struct ispell_misspelled **islistptr, *ip;
  145. int c;
  146. int nmisses;
  147. struct ispell_suggestion **sp;
  148. if ((isp=(struct ispell *)malloc(sizeof(struct ispell))) == 0)
  149. return (0);
  150. isp->ispell_buf=0;
  151. isp->first_misspelled=0;
  152. islistptr=&isp->first_misspelled;
  153. if (fork_ispell(line, dict, isp))
  154. {
  155. ispell_free(isp);
  156. return (0);
  157. }
  158. if ((p=strchr(isp->ispell_buf, 'n')) == 0)
  159. {
  160. ispell_free(isp);
  161. return (0);
  162. }
  163. ++p;
  164. q=0;
  165. islistptr= &isp->first_misspelled;
  166. for ( ; p && *p != 'n'; p=q)
  167. {
  168. if ((q=strchr(p, 'n')) != 0)
  169. *q++=0;
  170. if ( *p != '&' && *p != '?' && *p != '#') continue;
  171. if ( (ip=*islistptr=(struct ispell_misspelled *)
  172. malloc(sizeof(struct ispell_misspelled))) == 0)
  173. {
  174. ispell_free(isp);
  175. return (0);
  176. }
  177. ip->next=0;
  178. islistptr= &ip->next;
  179. c=*p++;
  180. while (*p == ' ') ++p;
  181. ip->misspelled_word=p;
  182. while (*p && *p != ' ') ++p;
  183. if (*p) *p++=0;
  184. nmisses=0;
  185. while (*p == ' ') ++p;
  186. if (c == '&')
  187. {
  188. while (*p >= '0' && *p <= '9')
  189. nmisses=nmisses * 10 + *p++ - '0';
  190. while (*p == ' ') ++p;
  191. }
  192. ip->word_pos=0;
  193. while (*p >= '0' && *p <= '9')
  194. ip->word_pos=ip->word_pos * 10 + *p++ - '0';
  195. ip->first_suggestion=0;
  196. if (nmisses == 0 || *p != ':') continue;
  197. ++p;
  198. sp= &ip->first_suggestion;
  199. while (nmisses)
  200. {
  201. if ( (*sp=(struct ispell_suggestion *)
  202. malloc(sizeof(struct ispell_suggestion)))
  203. == 0)
  204. {
  205. ispell_free(isp);
  206. return (0);
  207. }
  208. (*sp)->suggested_word=strtok(p, ", ");
  209. p=0;
  210. (*sp)->next=0;
  211. sp= &(*sp)->next;
  212. --nmisses;
  213. }
  214. }
  215. return (isp);
  216. }
  217. void ispell_free(struct ispell *isp)
  218. {
  219. struct ispell_misspelled *msp;
  220. while ((msp=isp->first_misspelled) != 0)
  221. {
  222. struct ispell_suggestion *sgp;
  223. isp->first_misspelled=msp->next;
  224. while ((sgp=msp->first_suggestion) != 0)
  225. {
  226. msp->first_suggestion=sgp->next;
  227. free(sgp);
  228. }
  229. free(msp);
  230. }
  231. if (isp->ispell_buf) free(isp->ispell_buf);
  232. free(isp);
  233. }