1 /* tcp.c - TCP/IP stream emulation for GNU Emacs.
2 * Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
3 * Copyright (C) 1998-2003 Daiki Ueno
5 * This file is part of Riece.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 /* This program is based on `tcp' comming from old GNUS distribution
22 written by Masanobu Umeda <umerin@mse.kyutech.ac.jp>. */
24 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/ioctl.h>
35 #include <netinet/in.h>
48 # define basename(path) (rindex((path), '/') + 1)
52 # define NI_MAXHOST 1025
55 static char *progname;
60 "Copyright (C) 1998-2003 Daiki Ueno\n"
61 "This is free software; see the source for copying conditions. There is NO\n"
62 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
63 progname, PACKAGE, VERSION);
67 fprintf(stderr, "Usage: %s [options] host [service]\n", progname);
75 struct protoent *proto;
77 struct sockaddr *addr;
79 #ifdef HAVE_GETADDRINFO
80 struct addrinfo *in, hints;
84 struct sockaddr_in sin;
86 char *hostname = NULL, *service = "ircd";
88 fd_set *readfds, *writefds;
89 int server, emacsIn = fileno (stdin), emacsOut = fileno (stdout);
90 char buffer[1024], *retry;
91 int nbuffer, wret, false = 0;
94 progname = (char *) basename (argv[0]);
98 int this_option_optind = optind ? optind : 1;
100 static struct option long_options[] =
102 {"version", 0, 0, 'v'},
107 c = getopt_long (argc, argv, "vh", long_options, &option_index);
136 proto = getprotobyname ("tcp");
139 perror ("getprotobyname");
143 #ifdef HAVE_GETADDRINFO
144 memset (&hints, 0, sizeof (hints));
145 hints.ai_family = AF_UNSPEC;
146 hints.ai_socktype = SOCK_STREAM;
147 hints.ai_protocol = proto->p_proto;
148 if (getaddrinfo (hostname, service, &hints, &in) < 0)
150 perror ("getaddrinfo");
153 family = in->ai_family;
154 socktype = in->ai_socktype;
156 addrlen = in->ai_addrlen;
159 memset (&sin, 0, sizeof (sin));
160 host = gethostbyname (hostname);
163 memcpy (&sin.sin_addr, host->h_addr, host->h_length);
164 serv = getservbyname (service, proto->p_name);
166 sin.sin_port = htons (serv->s_port);
167 else if (isdigit (service[0]))
168 sin.sin_port = htons (atoi (service));
169 family = sin.sin_family = AF_INET;
170 socktype = SOCK_STREAM;
171 addr = (struct sockaddr *)&sin;
172 addrlen = sizeof (sin);
175 server = socket (family, socktype, 0);
182 setsockopt (server, SOL_SOCKET, SO_REUSEADDR,
183 (const char *) &false, sizeof (false));
185 if (connect (server, addr, addrlen) < 0)
193 fcntl (server, F_SETFL, O_NDELAY);
194 #endif /* O_NDELAY */
196 /* Connection established. */
198 readfds = (fd_set *) calloc(server + 1, sizeof (fd_mask));
199 writefds = (fd_set *) calloc(server + 1, sizeof (fd_mask));
203 FD_SET (server, readfds);
204 FD_SET (emacsIn, readfds);
205 if (select (server+1, readfds, NULL, NULL, NULL) == -1)
210 if (FD_ISSET (emacsIn, readfds))
213 nbuffer = read (emacsIn, buffer, sizeof buffer -1);
217 for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
219 FD_SET (server, writefds);
220 if (select (server+1, NULL, writefds, NULL, NULL) == -1)
225 wret = write (server, retry, nbuffer);
226 if (wret < 0) goto finish;
229 if (FD_ISSET (server, readfds))
231 /* From NNTP server */
232 nbuffer = read (server, buffer, sizeof buffer -1);
235 for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
237 FD_SET (emacsOut, writefds);
238 if (select (emacsOut+1, NULL, writefds, NULL, NULL) == -1)
243 wret = write (emacsOut, retry, nbuffer);
244 if (wret < 0) goto finish;
249 /* End of communication. */