2 * TCP/IP stream emulation for GNU Emacs.
3 * Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
5 * Author: Masanobu Umeda <umerin@mse.kyutech.ac.jp>
6 * Daiki Ueno <daiki@kiss.kake.info.waseda.ac.jp>
8 This file is part of GNU Emacs.
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)
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.
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 Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.
26 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <sys/ioctl.h>
37 #include <netinet/in.h>
45 #ifndef HAVE_GETADDRINFO
46 #include "getaddrinfo.h"
47 #endif /* !HAVE_GETADDRINFO */
58 # define basename(path) (rindex((path), '/') + 1)
62 # define NI_MAXHOST 1025
65 static char *progname;
68 printf("%s (Liece) 1.4.0\n"
69 "Copyright (C) 1998, 1999 Daiki Ueno\n"
70 "This is free software; see the source for copying conditions. There is NO\n"
71 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
76 printf("Usage: %s [options] host [service]\n", progname);
84 struct protoent *proto;
86 struct addrinfo *in, hints;
88 char *hostname = NULL, *service = "ircd";
90 fd_set *readfds, *writefds;
91 int server, emacsIn = fileno (stdin), emacsOut = fileno (stdout);
92 char buffer[1024], *retry;
93 int nbuffer, wret, false = 0;
96 progname = (char *) basename (argv[0]);
99 int this_option_optind = optind ? optind : 1;
100 int option_index = 0;
101 static struct option long_options[] = {
102 {"version", 0, 0, 'v'},
107 c = getopt_long (argc, argv, "vh", long_options, &option_index);
135 if ((proto = getprotobyname ("tcp")) == NULL) {
136 perror ("getprotobyname");
140 memset (&hints, 0, sizeof (hints));
141 hints.ai_family = AF_UNSPEC;
142 hints.ai_socktype = SOCK_STREAM;
143 hints.ai_protocol = proto->p_proto;
144 if (getaddrinfo (hostname, service, &hints, &in) < 0) {
145 perror ("getaddrinfo");
149 if ((server = socket (in->ai_family, in->ai_socktype, 0)) < 0) {
154 if (setsockopt (server, SOL_SOCKET, SO_REUSEADDR,
155 (const char *) &false, sizeof (false))) {
156 perror ("setsockopt");
160 if (connect (server, in->ai_addr, in->ai_addrlen) < 0) {
167 fcntl (server, F_SETFL, O_NDELAY);
168 #endif /* O_NDELAY */
170 /* Connection established. */
172 readfds = (fd_set *) calloc(server + 1, sizeof (fd_mask));
173 writefds = (fd_set *) calloc(server + 1, sizeof (fd_mask));
177 FD_SET (server, readfds);
178 FD_SET (emacsIn, readfds);
179 if (select (server+1, readfds, NULL, NULL, NULL) == -1)
184 if (FD_ISSET (emacsIn, readfds))
187 nbuffer = read (emacsIn, buffer, sizeof buffer -1);
191 for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
193 FD_SET (server, writefds);
194 if (select (server+1, NULL, writefds, NULL, NULL) == -1)
199 wret = write (server, retry, nbuffer);
200 if (wret < 0) goto finish;
203 if (FD_ISSET (server, readfds))
205 /* From NNTP server */
206 nbuffer = read (server, buffer, sizeof buffer -1);
209 for (retry = buffer; nbuffer > 0; nbuffer -= wret, retry += wret)
211 FD_SET (emacsOut, writefds);
212 if (select (emacsOut+1, NULL, writefds, NULL, NULL) == -1)
217 wret = write (emacsOut, retry, nbuffer);
218 if (wret < 0) goto finish;
223 /* End of communication. */