tcp.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * TCP/IP stream emulation for GNU Emacs.
  3. * Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
  4. * Author: Masanobu Umeda
  5. * Maintainer: umerin@mse.kyutech.ac.jp
  6. This file is part of GNU Emacs.
  7. GNU Emacs is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with GNU Emacs; see the file COPYING. If not, write to
  17. the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  18. Boston, MA 02111-1307, USA.
  19. *
  20. * Yasunari, Itoh at PFU limited contributed for Fujitsu UTS and SX/A.
  21. *
  22. * Thu Apr 6 13:47:37 JST 1989
  23. * USG fixes by Sakaeda <saka@mickey.trad.pf.fujitsu.junet>
  24. *
  25. * For Fujitsu UTS compile with:
  26. * cc -O -o tcp tcp.c -DFUJITSU_UTS -lu -lsocket
  27. */
  28. #include <stdio.h>
  29. #include <fcntl.h>
  30. #include <ctype.h>
  31. #include <sys/types.h>
  32. #ifdef FUJITSU_UTS
  33. #define USG
  34. #include <sys/ucbtypes.h>
  35. #include <sys/tisp/socket.h>
  36. #include <netdb.h>
  37. #include <sys/tisp/in.h>
  38. #else
  39. #include <sys/socket.h>
  40. #include <netdb.h>
  41. #include <netinet/in.h>
  42. #endif
  43. #ifdef USG
  44. #include <sys/stat.h>
  45. #include <signal.h>
  46. #endif
  47. #ifdef FUJITSU_UTS
  48. #define bcopy(f, t, n) memcpy (t, f, n)
  49. #define bcmp(b1, b2, n) (memcmp (b1, b2, n)!=0)
  50. #define bzero(b, n) memset (b, 0, n)
  51. #endif
  52. #ifdef USG
  53. int selectable = 1;
  54. sigout ()
  55. {
  56. fcntl (fileno (stdin), F_SETFL, 0);
  57. exit (-1);
  58. }
  59. #endif
  60. main (argc, argv)
  61. int argc;
  62. char *argv[];
  63. {
  64. struct hostent *host;
  65. struct sockaddr_in sockin, sockme;
  66. struct servent *serv;
  67. char *hostname = NULL;
  68. char *service = "nntp";
  69. int port;
  70. int readfds;
  71. int writefds;
  72. int server; /* NNTP Server */
  73. int emacsIn = fileno (stdin); /* Emacs intput */
  74. int emacsOut = fileno (stdout); /* Emacs output */
  75. char buffer[1024];
  76. int nbuffer; /* Number of bytes in buffer */
  77. int wret;
  78. char *retry; /* retry bufferp */
  79. int false = 0; /* FALSE flag for setsockopt () */
  80. if (argc < 2)
  81. {
  82. fprintf (stderr, "Usage: %s HOST [SERVICE]\n", argv[0]);
  83. exit (1);
  84. }
  85. if (argc >= 2)
  86. hostname = argv[1];
  87. if (argc >= 3)
  88. service = argv[2];
  89. if ((host = gethostbyname (hostname)) == NULL)
  90. {
  91. perror ("gethostbyname");
  92. exit (1);
  93. }
  94. if (isdigit (service[0]))
  95. port = atoi (service);
  96. else
  97. {
  98. serv = getservbyname (service, "tcp");
  99. if (serv == NULL)
  100. {
  101. perror ("getservbyname");
  102. exit (1);
  103. }
  104. port = serv->s_port;
  105. }
  106. bzero (&sockin, sizeof (sockin));
  107. sockin.sin_family = host->h_addrtype;
  108. bcopy (host->h_addr, &sockin.sin_addr, host->h_length);
  109. sockin.sin_port = htons (port);
  110. if ((server = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  111. {
  112. perror ("socket");
  113. exit (1);
  114. }
  115. if (setsockopt (server, SOL_SOCKET, SO_REUSEADDR, &false, sizeof (false)))
  116. {
  117. perror ("setsockopt");
  118. exit (1);
  119. }
  120. bzero (&sockme, sizeof (sockme));
  121. sockme.sin_family = sockin.sin_family;
  122. sockme.sin_addr.s_addr = INADDR_ANY;
  123. if (bind (server, &sockme, sizeof (sockme)) < 0)
  124. {
  125. perror ("bind");
  126. exit (1);
  127. }
  128. if (connect (server, &sockin, sizeof (sockin)) < 0)
  129. {
  130. perror ("connect");
  131. close (server);
  132. exit (1);
  133. }
  134. #ifdef O_NDELAY
  135. fcntl (server, F_SETFL, O_NDELAY);
  136. #ifdef USG
  137. /* USG pipe cannot not select emacsIn */
  138. {
  139. struct stat statbuf;
  140. fstat (emacsIn, &statbuf);
  141. if (statbuf.st_mode & 010000)
  142. selectable = 0;
  143. if (!selectable)
  144. {
  145. signal (SIGINT, sigout);
  146. fcntl (emacsIn, F_SETFL, O_NDELAY);
  147. }
  148. }
  149. #endif
  150. #endif
  151. /* Connection established. */
  152. while (1)
  153. {
  154. readfds = (1 << server) | (1 << emacsIn);
  155. if (select (32, &readfds, NULL, NULL, (struct timeval *)NULL) == -1)
  156. {
  157. perror ("select");
  158. exit (1);
  159. }
  160. if (readfds & (1 << emacsIn))
  161. {
  162. /* From Emacs */
  163. nbuffer = read (emacsIn, buffer, sizeof buffer -1);
  164. #ifdef USG
  165. if (selectable && nbuffer == 0)
  166. {
  167. goto finish;
  168. }
  169. else if (!(readfds & (1 << server)) && nbuffer == 0)
  170. {
  171. sleep (1);
  172. }
  173. else
  174. #else
  175. if (nbuffer == 0)
  176. goto finish;
  177. #endif
  178. for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
  179. {
  180. writefds = 1 << server;
  181. if (select (server+1, NULL, &writefds, NULL, (struct timeval*)NULL) == -1)
  182. {
  183. perror ("select");
  184. exit (1);
  185. }
  186. wret = write (server, retry, nbuffer);
  187. if (wret < 0) goto finish;
  188. }
  189. }
  190. if (readfds & (1 << server))
  191. {
  192. /* From NNTP server */
  193. nbuffer = read (server, buffer, sizeof buffer -1);
  194. if (nbuffer == 0)
  195. goto finish;
  196. for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
  197. {
  198. writefds = 1 << emacsOut;
  199. #ifdef USG
  200. if (selectable)
  201. #endif
  202. if (select (emacsOut+1, NULL, &writefds, NULL, (struct timeval*)NULL) == -1)
  203. {
  204. perror ("select");
  205. exit (1);
  206. }
  207. wret = write (emacsOut, retry, nbuffer);
  208. if (wret < 0) goto finish;
  209. }
  210. }
  211. }
  212. /* End of communication. */
  213. finish:
  214. close (server);
  215. #ifdef USG
  216. if (!selectable) fcntl (emacsIn, F_SETFL, 0);
  217. #endif
  218. close (emacsIn);
  219. close (emacsOut);
  220. exit (0);
  221. }