1 /* $Id: icbirc.c,v 1.3 2016/04/25 08:17:01 dhartmei Exp $ */
4 * Copyright (c) 2003-2004 Daniel Hartmeier
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/types.h>
34 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
54 void icbirc_quit(void);
55 int sync_write(int, const char *, int);
56 static void usage(void);
59 unsigned long bytes_in, bytes_out;
64 extern char *__progname;
66 fprintf(stderr, "usage: %s host[:port][/room]\n",
72 main(int argc, char *argv[])
74 struct pollfd pfds[2], *pirc, *picb;
75 struct addrinfo hints, *res, *res0;
76 const char *host, *cause = NULL;
78 int ch, error, save_errno;
79 int listen_fd = -1, server_fd = -1;
82 if (pledge("stdio inet dns", NULL) == -1)
84 #endif /* __OpenBSD__ */
86 while ((ch = getopt(argc, argv, "")) != -1) {
98 signal(SIGPIPE, SIG_IGN);
99 if (fcntl(0, F_SETFL, fcntl(listen_fd, F_GETFL) | O_NONBLOCK))
102 if ((port = strchr(argv[0], ':')) != NULL) {
104 if ((room = strchr(port, '/')) != NULL) {
106 strlcpy(irc_pass, room, sizeof(irc_pass));
108 } else if ((room = strchr(argv[0], '/')) != NULL) {
110 strlcpy(irc_pass, room, sizeof(irc_pass));
118 irc_send_notice(1, "*** Connecting to server %s:%s", host, port);
120 memset(&hints, 0, sizeof(hints));
121 hints.ai_family = AF_UNSPEC;
122 hints.ai_socktype = SOCK_STREAM;
123 error = getaddrinfo(host, port, &hints, &res0);
125 errx(1, "can't resolve %s: %s", host, gai_strerror(error));
127 for (res = res0; res; res = res->ai_next) {
128 server_fd = socket(res->ai_family, res->ai_socktype,
130 if (server_fd == -1) {
135 if (connect(server_fd, res->ai_addr, res->ai_addrlen) == -1) {
150 if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_NONBLOCK))
155 if (pledge("stdio", NULL) == -1)
157 #endif /* __OpenBSD__ */
159 irc_send_notice(1, "*** Connected");
162 memset(&pfds, 0, sizeof(pfds));
167 pirc->events = POLLIN;
169 picb->fd = server_fd;
170 picb->events = POLLIN;
176 if (poll(pfds, 2, 10) == -1) {
182 if (picb->revents & (POLLIN|POLLNVAL|POLLHUP)) {
183 len = read(server_fd, buf, sizeof(buf));
191 warnx("connection closed by server");
192 irc_send_notice(1, "*** Connection "
196 icb_recv(buf, len, 0, server_fd);
200 if (pirc->revents & (POLLIN|POLLNVAL|POLLHUP)) {
201 len = read(0, buf, sizeof(buf));
209 warnx("connection closed by client");
212 irc_recv(buf, len, 1, server_fd);
223 irc_send_notice(1, "*** Closing connection "
224 "(%u seconds, %lu:%lu bytes)",
225 time(NULL) - t, bytes_out, bytes_in);
230 sync_write(int fd, const char *buf, int len)
240 FD_SET(fd, &writefds);
241 memset(&tv, 0, sizeof(tv));
243 r = select(fd + 1, NULL, &writefds, NULL, &tv);
245 if (errno != EINTR) {
251 if (r > 0 && FD_ISSET(fd, &writefds)) {
252 r = write(fd, buf + off, len - off);