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