commit - fbe4e593edbbed17c1d7b84d42312cd749b3f79e
commit + 3e0dfc1698580979b40e0c5604db07e59b63b0e3
blob - 2e689513d7490efa18d0e5e5a78d6f4a23c0cdf6
blob + 9cdf01853cb5fe6445274adef51b199a311c4223
--- icbirc.c
+++ icbirc.c
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
+#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
int sync_write(int, const char *, int);
static void usage(void);
-static void handle_client(int);
int terminate_client;
static struct sockaddr_in sa_connect;
main(int argc, char *argv[])
{
int debug = 0;
- const char *addr_listen = NULL, *addr_connect = NULL;
- unsigned port_listen = 6667, port_connect = 7326;
+ const char *addr_connect = NULL;
+ unsigned port_connect = 7326;
int ch;
- int listen_fd = -1;
- struct sockaddr_in sa;
- socklen_t len;
- int val;
+ int listen_fd = -1, server_fd = -1;
+ time_t t;
+ unsigned long bytes_in, bytes_out;
- while ((ch = getopt(argc, argv, "dl:p:s:P:")) != -1) {
+#ifdef __OpenBSD__
+ if (pledge("stdio inet dns", NULL) == -1)
+ err(1, "pledge");
+#endif /* __OpenBSD__ */
+
+ while ((ch = getopt(argc, argv, "dp:s:P:")) != -1) {
switch (ch) {
case 'd':
debug++;
break;
- case 'l':
- addr_listen = optarg;
- break;
- case 'p':
- port_listen = atoi(optarg);
- break;
case 's':
addr_connect = optarg;
break;
if (sa_connect.sin_addr.s_addr == INADDR_NONE) {
struct hostent *h;
- if ((h = gethostbyname(addr_connect)) == NULL) {
- fprintf(stderr, "gethostbyname: %s: %s\n",
+ if ((h = gethostbyname(addr_connect)) == NULL)
+ errx(1, "gethostbyname: %s: %s\n",
addr_connect, hstrerror(h_errno));
- goto error;
- }
memcpy(&sa_connect.sin_addr.s_addr, h->h_addr,
sizeof(in_addr_t));
}
sa_connect.sin_port = htons(port_connect);
- if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- goto error;
- }
+ if (fcntl(0, F_SETFL, fcntl(listen_fd, F_GETFL) | O_NONBLOCK))
+ err(1, "fcntl");
- if (fcntl(listen_fd, F_SETFL, fcntl(listen_fd, F_GETFL) |
- O_NONBLOCK)) {
- perror("fcntl");
- goto error;
- }
-
- val = 1;
- if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
- (const char *)&val, sizeof(val))) {
- perror("setsockopt");
- goto error;
- }
-
- memset(&sa, 0, sizeof(sa));
- sa.sin_family = AF_INET;
- if (addr_listen != NULL)
- sa.sin_addr.s_addr = inet_addr(addr_listen);
- else
- sa.sin_addr.s_addr = INADDR_ANY;
- sa.sin_port = htons(port_listen);
- if (bind(listen_fd, (const struct sockaddr *)&sa, sizeof(sa))) {
- fprintf(stderr, "bind %s:%u: %s\n", inet_ntoa(sa.sin_addr),
- ntohs(sa.sin_port), strerror(errno));
- goto error;
- }
-
- if (listen(listen_fd, 1)) {
- perror("listen");
- goto error;
- }
-
- if (!debug && daemon(0, 0)) {
- perror("daemon");
- goto error;
- }
signal(SIGPIPE, SIG_IGN);
-
-#ifdef __OpenBSD__
- if (pledge("stdio inet dns", NULL) == -1) {
- perror("pledge");
- goto error;
- }
-#endif /* __OpenBSD__ */
-
- /* handle incoming client connections */
- while (1) {
- fd_set readfds;
- struct timeval tv;
- int r;
-
- FD_ZERO(&readfds);
- FD_SET(listen_fd, &readfds);
- memset(&tv, 0, sizeof(tv));
- tv.tv_sec = 10;
- r = select(listen_fd + 1, &readfds, NULL, NULL, &tv);
- if (r < 0) {
- if (errno != EINTR) {
- perror("select");
- break;
- }
- continue;
- }
- if (r > 0 && FD_ISSET(listen_fd, &readfds)) {
- int client_fd;
-
- memset(&sa, 0, sizeof(sa));
- len = sizeof(sa);
- client_fd = accept(listen_fd,
- (struct sockaddr *)&sa, &len);
- if (client_fd < 0) {
- if (errno != ECONNABORTED) {
- perror("accept");
- break;
- }
- continue;
- }
- printf("client connection from %s:%i\n",
- inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
- handle_client(client_fd);
- close(client_fd);
- }
- }
- close(listen_fd);
- return (0);
-
-error:
- if (listen_fd)
- close(listen_fd);
-
- return (1);
-}
-
-static void
-handle_client(int client_fd)
-{
- int server_fd;
- int max_fd;
- time_t t;
- unsigned long bytes_in, bytes_out;
-
t = time(NULL);
bytes_in = bytes_out = 0;
- irc_pass[0] = irc_nick[0] = irc_ident[0] = irc_channel[0] = 0;
- icb_logged_in = 0;
- terminate_client = 1;
- printf("connecting to server %s:%u\n",
+ fprintf(stderr, "connecting to server %s:%u\n",
inet_ntoa(sa_connect.sin_addr), ntohs(sa_connect.sin_port));
- irc_send_notice(client_fd, "*** Connecting to server %s:%u",
+ irc_send_notice(1, "*** Connecting to server %s:%u",
inet_ntoa(sa_connect.sin_addr), ntohs(sa_connect.sin_port));
- if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- goto done;
- }
+ if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ err(1, "socket");
if (connect(server_fd, (struct sockaddr *)&sa_connect,
sizeof(sa_connect))) {
- perror("connect");
- irc_send_notice(client_fd, "*** Error: connect: %s",
+ warn("connect");
+ irc_send_notice(1, "*** Error: connect: %s",
strerror(errno));
close(server_fd);
- goto done;
+ exit(1);
}
- if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_NONBLOCK) ||
- fcntl(client_fd, F_SETFL, fcntl(client_fd, F_GETFL) | O_NONBLOCK)) {
- perror("fcntl");
- goto done;
- }
+ if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_NONBLOCK))
+ err(1, "fcntl");
- if (client_fd > server_fd)
- max_fd = client_fd;
- else
- max_fd = server_fd;
+#ifdef __OpenBSD__
+ /* drop inet dns */
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+#endif /* __OpenBSD__ */
- irc_send_notice(client_fd, "*** Connected");
- terminate_client = 0;
+ irc_send_notice(1, "*** Connected");
icb_init();
- while (!terminate_client) {
+
+ for (;;) {
fd_set readfds;
struct timeval tv;
int r;
FD_ZERO(&readfds);
FD_SET(server_fd, &readfds);
- FD_SET(client_fd, &readfds);
+ FD_SET(0, &readfds);
memset(&tv, 0, sizeof(tv));
tv.tv_sec = 10;
- r = select(max_fd + 1, &readfds, NULL, NULL, &tv);
+ r = select(server_fd + 1, &readfds, NULL, NULL, &tv);
if (r < 0) {
- if (errno != EINTR) {
- perror("select");
- break;
- }
+ if (errno != EINTR)
+ err(1, "select");
continue;
}
if (r > 0) {
if (len < 0) {
if (errno == EINTR)
continue;
- perror("read");
+ warnx("read");
len = 0;
}
if (len == 0) {
- printf("connection closed by server\n");
- irc_send_notice(client_fd,
- "*** Connection closed by server");
+ warnx("connection closed by server");
+ irc_send_notice(1, "*** Connection "
+ "closed by server");
break;
}
- icb_recv(buf, len, client_fd, server_fd);
+ icb_recv(buf, len, 0, server_fd);
bytes_in += len;
}
- if (FD_ISSET(client_fd, &readfds)) {
- len = read(client_fd, buf, sizeof(buf));
+ if (FD_ISSET(0, &readfds)) {
+ len = read(0, buf, sizeof(buf));
if (len < 0) {
if (errno == EINTR)
continue;
- perror("read");
+ warnx("read");
len = 0;
}
if (len == 0) {
- printf("connection closed by client\n");
+ warnx("connection closed by client\n");
break;
}
- irc_recv(buf, len, client_fd, server_fd);
+ irc_recv(buf, len, 1, server_fd);
bytes_out += len;
}
}
}
-done:
- if (server_fd >= 0)
- close(server_fd);
- printf("(%lu seconds, %lu:%lu bytes)\n",
- (unsigned long)(time(NULL) - t), bytes_out, bytes_in);
- if (terminate_client)
- irc_send_notice(client_fd, "*** Closing connection "
- "(%u seconds, %lu:%lu bytes)",
- time(NULL) - t, bytes_out, bytes_in);
+ irc_send_notice(1, "*** Closing connection "
+ "(%u seconds, %lu:%lu bytes)",
+ time(NULL) - t, bytes_out, bytes_in);
}
int