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 | + |
M | Makefile | | | 12 | ++++++++---- |
A | nc.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;
+}