Blame


1 d23d2886 2023-07-30 op /* $Id: icbirc.c,v 1.3 2016/04/25 08:17:01 dhartmei Exp $ */
2 d23d2886 2023-07-30 op
3 d23d2886 2023-07-30 op /*
4 a29564dd 2023-08-20 op * Copyright (c) 2023 Omar Polo <op@openbsd.org>
5 d23d2886 2023-07-30 op * Copyright (c) 2003-2004 Daniel Hartmeier
6 d23d2886 2023-07-30 op * All rights reserved.
7 d23d2886 2023-07-30 op *
8 d23d2886 2023-07-30 op * Redistribution and use in source and binary forms, with or without
9 d23d2886 2023-07-30 op * modification, are permitted provided that the following conditions
10 d23d2886 2023-07-30 op * are met:
11 d23d2886 2023-07-30 op *
12 d23d2886 2023-07-30 op * - Redistributions of source code must retain the above copyright
13 d23d2886 2023-07-30 op * notice, this list of conditions and the following disclaimer.
14 d23d2886 2023-07-30 op * - Redistributions in binary form must reproduce the above
15 d23d2886 2023-07-30 op * copyright notice, this list of conditions and the following
16 d23d2886 2023-07-30 op * disclaimer in the documentation and/or other materials provided
17 d23d2886 2023-07-30 op * with the distribution.
18 d23d2886 2023-07-30 op *
19 d23d2886 2023-07-30 op * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 d23d2886 2023-07-30 op * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 d23d2886 2023-07-30 op * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 d23d2886 2023-07-30 op * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 d23d2886 2023-07-30 op * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 d23d2886 2023-07-30 op * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 d23d2886 2023-07-30 op * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 d23d2886 2023-07-30 op * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 d23d2886 2023-07-30 op * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 d23d2886 2023-07-30 op * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 d23d2886 2023-07-30 op * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 d23d2886 2023-07-30 op * POSSIBILITY OF SUCH DAMAGE.
31 d23d2886 2023-07-30 op *
32 d23d2886 2023-07-30 op */
33 d23d2886 2023-07-30 op
34 d23d2886 2023-07-30 op #include <sys/types.h>
35 d23d2886 2023-07-30 op #include <sys/socket.h>
36 d23d2886 2023-07-30 op #include <sys/stat.h>
37 fe009782 2023-08-01 op
38 d23d2886 2023-07-30 op #include <netinet/in.h>
39 d23d2886 2023-07-30 op #include <arpa/inet.h>
40 fe009782 2023-08-01 op
41 d23d2886 2023-07-30 op #include <ctype.h>
42 3e0dfc16 2023-08-01 op #include <err.h>
43 d23d2886 2023-07-30 op #include <errno.h>
44 d23d2886 2023-07-30 op #include <fcntl.h>
45 d23d2886 2023-07-30 op #include <netdb.h>
46 4070540c 2023-08-01 op #include <poll.h>
47 d23d2886 2023-07-30 op #include <signal.h>
48 d23d2886 2023-07-30 op #include <stdarg.h>
49 d23d2886 2023-07-30 op #include <stdio.h>
50 d23d2886 2023-07-30 op #include <stdlib.h>
51 d23d2886 2023-07-30 op #include <string.h>
52 d23d2886 2023-07-30 op #include <time.h>
53 d23d2886 2023-07-30 op #include <unistd.h>
54 fe009782 2023-08-01 op
55 d23d2886 2023-07-30 op #include "icb.h"
56 d23d2886 2023-07-30 op #include "irc.h"
57 d23d2886 2023-07-30 op
58 c8394ca1 2023-08-01 op void icbirc_quit(void);
59 d23d2886 2023-07-30 op int sync_write(int, const char *, int);
60 d23d2886 2023-07-30 op static void usage(void);
61 d23d2886 2023-07-30 op
62 c8394ca1 2023-08-01 op time_t t;
63 c8394ca1 2023-08-01 op unsigned long bytes_in, bytes_out;
64 c8394ca1 2023-08-01 op
65 d23d2886 2023-07-30 op static void
66 d23d2886 2023-07-30 op usage(void)
67 d23d2886 2023-07-30 op {
68 d23d2886 2023-07-30 op extern char *__progname;
69 d23d2886 2023-07-30 op
70 2e004277 2023-08-01 op fprintf(stderr, "usage: %s host[:port][/room]\n",
71 25d0780c 2023-08-01 op getprogname());
72 d23d2886 2023-07-30 op exit(1);
73 d23d2886 2023-07-30 op }
74 d23d2886 2023-07-30 op
75 d23d2886 2023-07-30 op int
76 d23d2886 2023-07-30 op main(int argc, char *argv[])
77 d23d2886 2023-07-30 op {
78 4070540c 2023-08-01 op struct pollfd pfds[2], *pirc, *picb;
79 7d9bde6e 2023-08-01 op struct addrinfo hints, *res, *res0;
80 7d9bde6e 2023-08-01 op const char *host, *cause = NULL;
81 2e004277 2023-08-01 op char *port, *room;
82 7d9bde6e 2023-08-01 op int ch, error, save_errno;
83 3e0dfc16 2023-08-01 op int listen_fd = -1, server_fd = -1;
84 d23d2886 2023-07-30 op
85 3e0dfc16 2023-08-01 op #ifdef __OpenBSD__
86 3e0dfc16 2023-08-01 op if (pledge("stdio inet dns", NULL) == -1)
87 3e0dfc16 2023-08-01 op err(1, "pledge");
88 3e0dfc16 2023-08-01 op #endif /* __OpenBSD__ */
89 3e0dfc16 2023-08-01 op
90 2e004277 2023-08-01 op while ((ch = getopt(argc, argv, "")) != -1) {
91 d23d2886 2023-07-30 op switch (ch) {
92 d23d2886 2023-07-30 op default:
93 d23d2886 2023-07-30 op usage();
94 d23d2886 2023-07-30 op }
95 d23d2886 2023-07-30 op }
96 d23d2886 2023-07-30 op argc -= optind;
97 2e004277 2023-08-01 op argv += optind;
98 2e004277 2023-08-01 op
99 2e004277 2023-08-01 op if (argc != 1)
100 d23d2886 2023-07-30 op usage();
101 d23d2886 2023-07-30 op
102 7d9bde6e 2023-08-01 op signal(SIGPIPE, SIG_IGN);
103 7d9bde6e 2023-08-01 op if (fcntl(0, F_SETFL, fcntl(listen_fd, F_GETFL) | O_NONBLOCK))
104 7d9bde6e 2023-08-01 op err(1, "fcntl");
105 7d9bde6e 2023-08-01 op
106 2e004277 2023-08-01 op if ((port = strchr(argv[0], ':')) != NULL) {
107 2e004277 2023-08-01 op *port++ = '\0';
108 2e004277 2023-08-01 op if ((room = strchr(port, '/')) != NULL) {
109 2e004277 2023-08-01 op *room++ = '\0';
110 2e004277 2023-08-01 op strlcpy(irc_pass, room, sizeof(irc_pass));
111 2e004277 2023-08-01 op }
112 2e004277 2023-08-01 op } else if ((room = strchr(argv[0], '/')) != NULL) {
113 2e004277 2023-08-01 op *room++ = '\0';
114 2e004277 2023-08-01 op strlcpy(irc_pass, room, sizeof(irc_pass));
115 2e004277 2023-08-01 op }
116 7d9bde6e 2023-08-01 op host = argv[0];
117 7d9bde6e 2023-08-01 op if (port == NULL)
118 7d9bde6e 2023-08-01 op port = "7326";
119 2e004277 2023-08-01 op
120 7d9bde6e 2023-08-01 op t = time(NULL);
121 d23d2886 2023-07-30 op
122 7d9bde6e 2023-08-01 op irc_send_notice(1, "*** Connecting to server %s:%s", host, port);
123 d23d2886 2023-07-30 op
124 7d9bde6e 2023-08-01 op memset(&hints, 0, sizeof(hints));
125 7d9bde6e 2023-08-01 op hints.ai_family = AF_UNSPEC;
126 7d9bde6e 2023-08-01 op hints.ai_socktype = SOCK_STREAM;
127 7d9bde6e 2023-08-01 op error = getaddrinfo(host, port, &hints, &res0);
128 7d9bde6e 2023-08-01 op if (error)
129 7d9bde6e 2023-08-01 op errx(1, "can't resolve %s: %s", host, gai_strerror(error));
130 d23d2886 2023-07-30 op
131 7d9bde6e 2023-08-01 op for (res = res0; res; res = res->ai_next) {
132 7d9bde6e 2023-08-01 op server_fd = socket(res->ai_family, res->ai_socktype,
133 7d9bde6e 2023-08-01 op res->ai_protocol);
134 7d9bde6e 2023-08-01 op if (server_fd == -1) {
135 7d9bde6e 2023-08-01 op cause = "socket";
136 7d9bde6e 2023-08-01 op continue;
137 7d9bde6e 2023-08-01 op }
138 7d9bde6e 2023-08-01 op
139 7d9bde6e 2023-08-01 op if (connect(server_fd, res->ai_addr, res->ai_addrlen) == -1) {
140 7d9bde6e 2023-08-01 op cause = "connect";
141 7d9bde6e 2023-08-01 op save_errno = errno;
142 7d9bde6e 2023-08-01 op close(server_fd);
143 7d9bde6e 2023-08-01 op errno = save_errno;
144 7d9bde6e 2023-08-01 op server_fd = -1;
145 7d9bde6e 2023-08-01 op continue;
146 7d9bde6e 2023-08-01 op }
147 7d9bde6e 2023-08-01 op
148 7d9bde6e 2023-08-01 op break;
149 d23d2886 2023-07-30 op }
150 7d9bde6e 2023-08-01 op freeaddrinfo(res0);
151 7d9bde6e 2023-08-01 op if (server_fd == -1)
152 7d9bde6e 2023-08-01 op err(1, "%s", cause);
153 d23d2886 2023-07-30 op
154 3e0dfc16 2023-08-01 op if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_NONBLOCK))
155 3e0dfc16 2023-08-01 op err(1, "fcntl");
156 d23d2886 2023-07-30 op
157 3e0dfc16 2023-08-01 op #ifdef __OpenBSD__
158 3e0dfc16 2023-08-01 op /* drop inet dns */
159 3e0dfc16 2023-08-01 op if (pledge("stdio", NULL) == -1)
160 3e0dfc16 2023-08-01 op err(1, "pledge");
161 3e0dfc16 2023-08-01 op #endif /* __OpenBSD__ */
162 d23d2886 2023-07-30 op
163 3e0dfc16 2023-08-01 op irc_send_notice(1, "*** Connected");
164 d23d2886 2023-07-30 op icb_init();
165 3e0dfc16 2023-08-01 op
166 4070540c 2023-08-01 op memset(&pfds, 0, sizeof(pfds));
167 4070540c 2023-08-01 op pirc = &pfds[0];
168 4070540c 2023-08-01 op picb = &pfds[1];
169 4070540c 2023-08-01 op
170 4070540c 2023-08-01 op pirc->fd = 0;
171 4070540c 2023-08-01 op pirc->events = POLLIN;
172 4070540c 2023-08-01 op
173 4070540c 2023-08-01 op picb->fd = server_fd;
174 4070540c 2023-08-01 op picb->events = POLLIN;
175 4070540c 2023-08-01 op
176 3e0dfc16 2023-08-01 op for (;;) {
177 4070540c 2023-08-01 op char buf[65535];
178 4070540c 2023-08-01 op int len;
179 d23d2886 2023-07-30 op
180 0b102eb4 2023-08-01 op if (poll(pfds, 2, 10000) == -1) {
181 4070540c 2023-08-01 op if (errno == EINTR)
182 4070540c 2023-08-01 op continue;
183 4070540c 2023-08-01 op err(1, "poll");
184 d23d2886 2023-07-30 op }
185 d23d2886 2023-07-30 op
186 4070540c 2023-08-01 op if (picb->revents & (POLLIN|POLLNVAL|POLLHUP)) {
187 4070540c 2023-08-01 op len = read(server_fd, buf, sizeof(buf));
188 4070540c 2023-08-01 op if (len < 0) {
189 4070540c 2023-08-01 op if (errno == EINTR)
190 4070540c 2023-08-01 op continue;
191 4070540c 2023-08-01 op warnx("read");
192 4070540c 2023-08-01 op len = 0;
193 d23d2886 2023-07-30 op }
194 4070540c 2023-08-01 op if (len == 0) {
195 4070540c 2023-08-01 op warnx("connection closed by server");
196 4070540c 2023-08-01 op irc_send_notice(1, "*** Connection "
197 4070540c 2023-08-01 op "closed by server");
198 4070540c 2023-08-01 op break;
199 d23d2886 2023-07-30 op }
200 84fbe5aa 2023-08-01 op icb_recv(buf, len, 1, server_fd);
201 4070540c 2023-08-01 op bytes_in += len;
202 d23d2886 2023-07-30 op }
203 4070540c 2023-08-01 op
204 4070540c 2023-08-01 op if (pirc->revents & (POLLIN|POLLNVAL|POLLHUP)) {
205 4070540c 2023-08-01 op len = read(0, buf, sizeof(buf));
206 4070540c 2023-08-01 op if (len < 0) {
207 4070540c 2023-08-01 op if (errno == EINTR)
208 4070540c 2023-08-01 op continue;
209 4070540c 2023-08-01 op warnx("read");
210 4070540c 2023-08-01 op len = 0;
211 4070540c 2023-08-01 op }
212 4070540c 2023-08-01 op if (len == 0) {
213 4070540c 2023-08-01 op warnx("connection closed by client");
214 4070540c 2023-08-01 op break;
215 4070540c 2023-08-01 op }
216 4070540c 2023-08-01 op irc_recv(buf, len, 1, server_fd);
217 4070540c 2023-08-01 op bytes_out += len;
218 4070540c 2023-08-01 op }
219 d23d2886 2023-07-30 op }
220 d23d2886 2023-07-30 op
221 c8394ca1 2023-08-01 op icbirc_quit();
222 c8394ca1 2023-08-01 op }
223 c8394ca1 2023-08-01 op
224 c8394ca1 2023-08-01 op void
225 c8394ca1 2023-08-01 op icbirc_quit(void)
226 c8394ca1 2023-08-01 op {
227 3e0dfc16 2023-08-01 op irc_send_notice(1, "*** Closing connection "
228 3e0dfc16 2023-08-01 op "(%u seconds, %lu:%lu bytes)",
229 3e0dfc16 2023-08-01 op time(NULL) - t, bytes_out, bytes_in);
230 c8394ca1 2023-08-01 op exit(0);
231 d23d2886 2023-07-30 op }
232 d23d2886 2023-07-30 op
233 d23d2886 2023-07-30 op int
234 d23d2886 2023-07-30 op sync_write(int fd, const char *buf, int len)
235 d23d2886 2023-07-30 op {
236 d23d2886 2023-07-30 op int off = 0;
237 d23d2886 2023-07-30 op
238 d23d2886 2023-07-30 op while (len > off) {
239 d23d2886 2023-07-30 op fd_set writefds;
240 d23d2886 2023-07-30 op struct timeval tv;
241 d23d2886 2023-07-30 op int r;
242 d23d2886 2023-07-30 op
243 d23d2886 2023-07-30 op FD_ZERO(&writefds);
244 d23d2886 2023-07-30 op FD_SET(fd, &writefds);
245 d23d2886 2023-07-30 op memset(&tv, 0, sizeof(tv));
246 d23d2886 2023-07-30 op tv.tv_sec = 10;
247 d23d2886 2023-07-30 op r = select(fd + 1, NULL, &writefds, NULL, &tv);
248 d23d2886 2023-07-30 op if (r < 0) {
249 d23d2886 2023-07-30 op if (errno != EINTR) {
250 d23d2886 2023-07-30 op perror("select");
251 d23d2886 2023-07-30 op return (1);
252 d23d2886 2023-07-30 op }
253 d23d2886 2023-07-30 op continue;
254 d23d2886 2023-07-30 op }
255 d23d2886 2023-07-30 op if (r > 0 && FD_ISSET(fd, &writefds)) {
256 d23d2886 2023-07-30 op r = write(fd, buf + off, len - off);
257 d23d2886 2023-07-30 op if (r < 0) {
258 d23d2886 2023-07-30 op perror("write");
259 d23d2886 2023-07-30 op return (1);
260 d23d2886 2023-07-30 op }
261 d23d2886 2023-07-30 op off += r;
262 d23d2886 2023-07-30 op }
263 d23d2886 2023-07-30 op }
264 d23d2886 2023-07-30 op return (0);
265 d23d2886 2023-07-30 op }