irC

an attempt at writing an irc "client"
git clone git://bvnf.space/irC.git
Log | Files | Refs | README

commit 1c58927f7c75430f54b660733fc7d10a01b592cc
parent eefee86b3c900f92f6ab090b7f494c04b6b99f90
Author: aabacchus <ben@bvnf.space>
Date:   Tue,  5 Oct 2021 11:04:16 +0100

make nc utility

Diffstat:
M.gitignore | 1+
MMakefile | 12++++++++----
Anc.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 146 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,2 +1,3 @@ irC *.o +nc diff --git a/Makefile b/Makefile @@ -1,7 +1,11 @@ -CFLAGS += -Wall -Wextra -Wpedantic -LDFLAGS += -static +.POSIX: + +XCFLAGS = $(CFLAGS) -Wall -Wextra -Wpedantic -g -Og -D_XOPEN_SOURCE=700 + irC: main.c - $(CC) -g $(CFLAGS) $(LDFLAGS) main.c -o $@ + $(CC) $(XCFLAGS) $(LDFLAGS) main.c -o $@ +nc: nc.c + $(CC) $(XCFLAGS) $(LDFLAGS) nc.c -o $@ clean: - rm irC + rm -f irC nc diff --git a/nc.c b/nc.c @@ -0,0 +1,137 @@ +/* + * This file is in the public domain. + * Author: Ben Fuller + * + * Basic netcat-like utility to create a connection on the specified + * address and port, using stdin and stdout. + * + */ +#include <stdio.h> +#include <errno.h> +#include <poll.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> + +#define BUF_LEN 1024 + +void usage(const char *); +int sock_write(int, char *); +int sock_read(int); + +int main(int argc, char *argv[]) { + int s, sfd; + struct addrinfo hints, *result, *rp; + if (argc < 3) { + usage(argv[0]); + } + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = 0; + + + s = getaddrinfo(argv[1], argv[2], &hints, &result); + if (s != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return 1; + } + + sfd = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + for (rp = result; rp != NULL; rp = rp->ai_next) { + sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sfd == -1) + continue; + + if (connect(sfd, rp->ai_addr, rp->ai_addrlen) == 0) + break; + + if (close(sfd) == -1) { + perror("close"); + return 1; + } + } + + freeaddrinfo(result); + + if (rp == NULL) + return 1; + + size_t linelen = 0; + + int pollret; + struct pollfd fds[2]; + fds[0].fd = 0; + fds[0].events = POLLIN; + fds[1].fd = sfd; + fds[1].events = POLLIN | POLLWRBAND; + + while (1) { + pollret = poll(fds, 2, -1); + if (pollret <= 0) { + if (pollret == 0 || errno == EAGAIN) + continue; + perror("poll"); + return 1; + } + if (fds[1].revents & POLLIN) + if (sock_read(sfd) != 0) + return 1; + if (fds[0].revents & POLLIN) { + char *line = NULL; + if (getline(&line, &linelen, stdin) == -1) { + free(line); + break; + } + if (sock_write(sfd, line) != 0) { + free(line); + return 1; + } + free(line); + } + fds[0].revents = 0; + fds[1].revents = 0; + } + + if (close(sfd) == -1) { + perror("close"); + return 1; + } + return 0; +} + +void usage(const char *argv0){ + fprintf(stderr, "usage: %s host port\n", argv0); + exit(1); +} + +int sock_write(int sfd, char *msg){ + ssize_t ret; + int len = strlen(msg); + ret = send(sfd, msg, len, 0); + if (ret != (ssize_t) len) { + perror("sock_write"); + return 1; + } + return 0; +} + +int sock_read(int sfd){ + char buff[BUF_LEN]; + memset(&buff, 0, sizeof buff); + ssize_t ret; + + ret = recv(sfd, buff, BUF_LEN, 0); + + if (ret < 0) { + perror("sock_read"); + return 1; + } + printf("%s", buff); + return 0; +}