Commit | Line | Data |
---|---|---|
2b24132f DM |
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 | |
3b7ad313 EN |
22 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
23 | Boston, MA 02111-1307, USA. | |
2b24132f DM |
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 FUJITSU_UTS | |
58 | #define bcopy(f, t, n) memcpy (t, f, n) | |
59 | #define bcmp(b1, b2, n) (memcmp (b1, b2, n)!=0) | |
60 | #define bzero(b, n) memset (b, 0, n) | |
61 | #endif | |
62 | ||
63 | #ifdef USG | |
64 | int selectable = 1; | |
65 | ||
66 | sigout () | |
67 | { | |
68 | fcntl (fileno (stdin), F_SETFL, 0); | |
69 | exit (-1); | |
70 | } | |
71 | #endif | |
72 | ||
73 | main (argc, argv) | |
74 | int argc; | |
75 | char *argv[]; | |
76 | { | |
77 | struct hostent *host; | |
78 | struct sockaddr_in sockin, sockme; | |
79 | struct servent *serv; | |
80 | char *hostname = NULL; | |
81 | char *service = "nntp"; | |
82 | int port; | |
83 | int readfds; | |
84 | int writefds; | |
85 | int server; /* NNTP Server */ | |
86 | int emacsIn = fileno (stdin); /* Emacs intput */ | |
87 | int emacsOut = fileno (stdout); /* Emacs output */ | |
88 | char buffer[1024]; | |
89 | int nbuffer; /* Number of bytes in buffer */ | |
90 | int wret; | |
91 | char *retry; /* retry bufferp */ | |
92 | int false = 0; /* FALSE flag for setsockopt () */ | |
93 | ||
94 | if (argc < 2) | |
95 | { | |
96 | fprintf (stderr, "Usage: %s HOST [SERVICE]\n", argv[0]); | |
97 | exit (1); | |
98 | } | |
99 | if (argc >= 2) | |
100 | hostname = argv[1]; | |
101 | if (argc >= 3) | |
102 | service = argv[2]; | |
103 | ||
104 | if ((host = gethostbyname (hostname)) == NULL) | |
105 | { | |
106 | perror ("gethostbyname"); | |
107 | exit (1); | |
108 | } | |
109 | if (isdigit (service[0])) | |
110 | port = atoi (service); | |
111 | else | |
112 | { | |
113 | serv = getservbyname (service, "tcp"); | |
114 | if (serv == NULL) | |
115 | { | |
116 | perror ("getservbyname"); | |
117 | exit (1); | |
118 | } | |
119 | port = serv->s_port; | |
120 | } | |
121 | ||
122 | bzero (&sockin, sizeof (sockin)); | |
123 | sockin.sin_family = host->h_addrtype; | |
124 | bcopy (host->h_addr, &sockin.sin_addr, host->h_length); | |
125 | sockin.sin_port = port; | |
126 | if ((server = socket (AF_INET, SOCK_STREAM, 0)) < 0) | |
127 | { | |
128 | perror ("socket"); | |
129 | exit (1); | |
130 | } | |
131 | if (setsockopt (server, SOL_SOCKET, SO_REUSEADDR, &false, sizeof (false))) | |
132 | { | |
133 | perror ("setsockopt"); | |
134 | exit (1); | |
135 | } | |
136 | bzero (&sockme, sizeof (sockme)); | |
137 | sockme.sin_family = sockin.sin_family; | |
138 | sockme.sin_addr.s_addr = INADDR_ANY; | |
139 | if (bind (server, &sockme, sizeof (sockme)) < 0) | |
140 | { | |
141 | perror ("bind"); | |
142 | exit (1); | |
143 | } | |
144 | if (connect (server, &sockin, sizeof (sockin)) < 0) | |
145 | { | |
146 | perror ("connect"); | |
147 | close (server); | |
148 | exit (1); | |
149 | } | |
150 | ||
151 | #ifdef O_NDELAY | |
152 | fcntl (server, F_SETFL, O_NDELAY); | |
153 | ||
154 | #ifdef USG | |
155 | /* USG pipe cannot not select emacsIn */ | |
156 | { | |
157 | struct stat statbuf; | |
158 | fstat (emacsIn, &statbuf); | |
159 | if (statbuf.st_mode & 010000) | |
160 | selectable = 0; | |
161 | if (!selectable) | |
162 | { | |
163 | signal (SIGINT, sigout); | |
164 | fcntl (emacsIn, F_SETFL, O_NDELAY); | |
165 | } | |
166 | } | |
167 | #endif | |
168 | #endif | |
169 | ||
170 | /* Connection established. */ | |
171 | while (1) | |
172 | { | |
173 | readfds = (1 << server) | (1 << emacsIn); | |
174 | if (select (32, &readfds, NULL, NULL, (struct timeval *)NULL) == -1) | |
175 | { | |
176 | perror ("select"); | |
177 | exit (1); | |
178 | } | |
179 | if (readfds & (1 << emacsIn)) | |
180 | { | |
181 | /* From Emacs */ | |
182 | nbuffer = read (emacsIn, buffer, sizeof buffer -1); | |
183 | ||
184 | #ifdef USG | |
185 | if (selectable && nbuffer == 0) | |
186 | { | |
187 | goto finish; | |
188 | } | |
189 | else if (!(readfds & (1 << server)) && nbuffer == 0) | |
190 | { | |
191 | sleep (1); | |
192 | } | |
193 | else | |
194 | #else | |
195 | if (nbuffer == 0) | |
196 | goto finish; | |
197 | #endif | |
198 | for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret) | |
199 | { | |
200 | writefds = 1 << server; | |
201 | if (select (server+1, NULL, &writefds, NULL, (struct timeval*)NULL) == -1) | |
202 | { | |
203 | perror ("select"); | |
204 | exit (1); | |
205 | } | |
206 | wret = write (server, retry, nbuffer); | |
207 | if (wret < 0) goto finish; | |
208 | } | |
209 | } | |
210 | if (readfds & (1 << server)) | |
211 | { | |
212 | /* From NNTP server */ | |
213 | nbuffer = read (server, buffer, sizeof buffer -1); | |
214 | if (nbuffer == 0) | |
215 | goto finish; | |
216 | for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret) | |
217 | { | |
218 | writefds = 1 << emacsOut; | |
219 | #ifdef USG | |
220 | if (selectable) | |
221 | #endif | |
222 | if (select (emacsOut+1, NULL, &writefds, NULL, (struct timeval*)NULL) == -1) | |
223 | { | |
224 | perror ("select"); | |
225 | exit (1); | |
226 | } | |
227 | wret = write (emacsOut, retry, nbuffer); | |
228 | if (wret < 0) goto finish; | |
229 | } | |
230 | } | |
231 | } | |
232 | ||
233 | /* End of communication. */ | |
234 | finish: | |
235 | close (server); | |
236 | #ifdef USG | |
237 | if (!selectable) fcntl (emacsIn, F_SETFL, 0); | |
238 | #endif | |
239 | close (emacsIn); | |
240 | close (emacsOut); | |
241 | exit (0); | |
242 | } |