From eb996e5650cd697161cbbcdb35bc0e95012d824c Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 28 Jan 2021 09:57:06 +0900 Subject: [PATCH] netcat: Rewrite the i/o loop * Stop echoing back the input. It isn't the responsibility of this app, IMO. * Allow non-text data * Error checks and cleanups --- netutils/netcat/netcat_main.c | 149 ++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 60 deletions(-) diff --git a/netutils/netcat/netcat_main.c b/netutils/netcat/netcat_main.c index 116b2e8ae..797db2f51 100644 --- a/netutils/netcat/netcat_main.c +++ b/netutils/netcat/netcat_main.c @@ -24,8 +24,9 @@ ****************************************************************************/ #include -#include +#include +#include #include #include #include @@ -45,12 +46,44 @@ * Public Functions ****************************************************************************/ +int do_io(int infd, int outfd) +{ + size_t capacity = 256; + char buf[capacity]; + + while (true) + { + ssize_t avail = read(infd, buf, capacity); + if (avail == 0) + { + break; + } + + if (avail == -1) + { + perror("do_io: read error"); + return 5; + } + + ssize_t written = write(outfd, buf, avail); + if (written == -1) + { + perror("do_io: write error"); + return 6; + } + } + + return EXIT_SUCCESS; +} + int netcat_server(int argc, char * argv[]) { - FILE * fout = stdout; + int id = -1; + int outfd = STDOUT_FILENO; struct sockaddr_in server; struct sockaddr_in client; int port = NETCAT_PORT; + int result = EXIT_SUCCESS; if ((1 < argc) && (0 == strcmp("-l", argv[1]))) { @@ -61,21 +94,23 @@ int netcat_server(int argc, char * argv[]) if (3 < argc) { - fout = fopen(argv[3], "w"); - if (0 > fout) + outfd = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (outfd == -1) { perror("error: io: Failed to create file"); - return 1; + outfd = STDOUT_FILENO; + result = 1; + goto out; } } } - int id; id = socket(AF_INET , SOCK_STREAM , 0); if (0 > id) { perror("error: net: Failed to create socket"); - return 2; + result = 2; + goto out; } server.sin_family = AF_INET; @@ -84,49 +119,57 @@ int netcat_server(int argc, char * argv[]) if (0 > bind(id, (struct sockaddr *)&server , sizeof(server))) { perror("error: net: Failed to bind"); - return 3; + result = 3; + goto out; } fprintf(stderr, "log: net: listening on :%d\n", port); - listen(id , 3); - int capacity = 256; - char buf[capacity]; + if (listen(id , 3) == -1) + { + perror("error: net: Failed to listen"); + result = 7; + goto out; + } + socklen_t addrlen; int conn; - while ((conn = accept(id, (struct sockaddr *)&client, &addrlen))) + while ((conn = accept(id, (struct sockaddr *)&client, &addrlen)) != -1) { - int avail = 1; - while (0 < avail) + result = do_io(conn, outfd); + if (result != 0) { - avail = recv(conn, buf, capacity, 0); - fwrite(buf, avail, 1, fout); - int status = fflush(fout); - if (0 != status) - { - perror("error: io: Failed to flush"); - } + break; } } if (0 > conn) { perror("accept failed"); - return 4; + result = 4; + goto out; } - if (stdout != fout) +out: + if (id != -1) { - fclose(fout); + close(id); } - return EXIT_SUCCESS; + if (outfd != STDOUT_FILENO) + { + close(outfd); + } + + return result; } int netcat_client(int argc, char * argv[]) { - FILE *fin = stdin; + int id = -1; + int infd = STDIN_FILENO; char *host = "127.0.0.1"; int port = NETCAT_PORT; + int result = EXIT_SUCCESS; if (argc > 1) { @@ -140,20 +183,22 @@ int netcat_client(int argc, char * argv[]) if (argc > 3) { - fin = fopen(argv[3], "r"); - if (0 > fin) + infd = open(argv[3], O_RDONLY); + if (infd == -1) { - perror("error: io: Failed to create file"); - return 1; + perror("error: io: Failed to open file"); + infd = STDIN_FILENO; + result = 1; + goto out; } } - int id; id = socket(AF_INET , SOCK_STREAM , 0); if (0 > id) { perror("error: net: Failed to create socket"); - return 2; + result = 2; + goto out; } struct sockaddr_in server; @@ -162,47 +207,31 @@ int netcat_client(int argc, char * argv[]) if (1 != inet_pton(AF_INET, host, &server.sin_addr)) { perror("error: net: Invalid host"); - return 3; + result = 3; + goto out; } if (connect(id, (struct sockaddr *) &server, sizeof(server)) < 0) { perror("error: net: Failed to connect"); - return 4; + result = 4; + goto out; } - int capacity = 256; - char buf[capacity]; - int avail; - while (true) + result = do_io(infd, id); + +out: + if (id != -1) { - avail = -1; - if (fgets(buf, capacity, fin)) - { - avail = strnlen(buf, capacity); - } - - if (avail < 0) - { - exit(EXIT_SUCCESS); - } - - buf[avail] = 0; - avail = write(id, buf, avail); - printf("%s", buf); - if (avail < 0) - { - perror("error: net: writing to socket"); - exit(1); - } + close(id); } - if (stdout != fin) + if (infd != STDIN_FILENO) { - fclose(fin); + close(infd); } - return EXIT_SUCCESS; + return result; } /****************************************************************************