commit a8f3425f16aa4dc1ce56b45b5ad5e8bdde8fc866
parent fffd975b08d08b6e98a0cd262310fdb2009f1623
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date: Wed, 6 Jan 2021 23:17:31 -0800
Move networking functions to net.c
Diffstat:
M | Makefile | | | 2 | +- |
M | command.c | | | 1 | + |
M | config.def.h | | | 2 | +- |
M | gawk.h | | | 3 | ++- |
M | main.c | | | 153 | ++----------------------------------------------------------------------------- |
A | net.c | | | 157 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | net.h | | | 7 | +++++++ |
7 files changed, 171 insertions(+), 154 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,5 +1,5 @@
TARGET = gawk
-OBJS = main.o util.o command.o strtonum.o
+OBJS = main.o util.o command.o strtonum.o net.o
# paths
PREFIX = /usr/local
diff --git a/command.c b/command.c
@@ -22,6 +22,7 @@
#include <unistd.h>
#include "gawk.h"
+#include "net.h"
#include "util.h"
/*
diff --git a/config.def.h b/config.def.h
@@ -1,7 +1,7 @@
/* gawk configuration */
/* how long to wait for response in ms */
-static int const timeout = 5 * 1000;
+int const timeout = 5000;
/* character used to negate commands */
static char const negate = '!';
diff --git a/gawk.h b/gawk.h
@@ -37,7 +37,8 @@ struct bind {
command *f;
};
-int gopher(char **, char const *, int);
int gawk(char **);
+extern int const timeout;
+
#endif /* _gawk_h */
diff --git a/main.c b/main.c
@@ -15,19 +15,17 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include <sys/socket.h>
#include <dirent.h>
#include <errno.h>
-#include <netdb.h>
-#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
+#include <string.h>
#include "command.h"
#include "gawk.h"
+#include "net.h"
#include "util.h"
#include "config.h" /* must be included last */
@@ -51,41 +49,6 @@ argsplit(char **argv, int size, char *s, char const *sep, int cat)
return argc;
}
-int
-resolve(char const *host, char const *port)
-{
- int error, s;
- struct addrinfo hints;
- struct addrinfo *ai, *ai0;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
-
- error = getaddrinfo(host, port, &hints, &ai0);
- if (error) {
- warn(0, "unable to resolve '%s' (%s): %s",
- host, port, gai_strerror(error));
- return -1;
- }
-
- s = -1;
- for (ai = ai0; ai && s == -1; ai = ai->ai_next) {
- s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (s != -1 && connect(s, ai->ai_addr, ai->ai_addrlen) == -1) {
- close(s);
- s = -1;
- }
- }
- freeaddrinfo(ai0);
-
- if (s == -1) {
- warn(0, "unable to connect to '%s' at '%s'", host, port);
- return -1;
- }
- return s;
-}
-
void
putprompt(char const *prompt)
{
@@ -131,118 +94,6 @@ too_big:
}
int
-gph_send(int sock, char const *message)
-{
- char tmp[MY_PATH_MAX];
- int n;
-
- n = strcspn(message, "?");
- if (message[n] == '\0')
- n = send(sock, message, n, 0);
- else {
- strlcpy(tmp, message, n + 1);
- tr(tmp + n, message + n, '?', ' ');
- tmp[n] = '\t';
- n = send(sock, tmp, strlen(tmp), 0);
- }
-
- if (n == -1) {
- warn(errno, "unable to send message");
- return 1;
- }
- if (shutdown(sock, SHUT_WR)) {
- warn(errno, "shutdown");
- return 1;
- }
- return 0;
-}
-
-ssize_t
-recvtxt(int s, FILE *output)
-{
- FILE *input;
- char *bufp;
- char buf[MY_LINE_MAX];
-
- input = fdopen(s, "r");
- if (input == NULL) {
- warn(errno, "fdopen");
- return 1;
- }
-
- /*
- * While the specification says strip leading periods if
- * there are multiple I think it must mean only one (see
- * RFC 1436 Appendix).
- */
- while ((bufp = fgets(buf, sizeof(buf), input)) != NULL) {
- if (*bufp == '.')
- if (strcmp(++bufp, "\r\n") == 0)
- break;
- if (fputs(bufp, output) == EOF)
- return 1;
- }
-
- return 0;
-}
-
-int
-recvbin(int s, FILE *output)
-{
- char buf[MY_CHUNK_MAX];
- ssize_t bytes;
-
- while ((bytes = recv(s, buf, sizeof(buf), 0)) > 0)
- /* NOTE: cast is safe, bytes _is_ >0 */
- if (fwrite(buf, 1, bytes, output) != (size_t)bytes)
- return 1;
- return 0;
-}
-
-int
-gph_recvto(int sock, char const *path, int bin)
-{
- FILE *fp;
- int status;
- struct pollfd pfd;
-
- pfd.fd = sock;
- pfd.events = POLLRDNORM;
- if (poll(&pfd, 1, timeout) < 1) {
- warn(errno, "Unable to recieve response");
- return 1;
- }
-
- fp = wfopen(path, "w+");
- if (fp == NULL)
- return 1;
-
- if (bin)
- status = recvbin(sock, fp);
- else status = recvtxt(sock, fp);
- if (wfclose(fp) || status)
- return 1;
- return 0;
-}
-
-int
-gopher(char **addr, char const *path, int bin)
-{
- int sock;
-
- sock = resolve(addr[AR_HOST], addr[AR_PORT]);
- if (sock == -1)
- return 1;
-
- if (gph_send(sock, addr[AR_PATH]) != 0 ||
- gph_recvto(sock, path, bin) != 0) {
- close(sock);
- return 1;
- }
- return close(sock);
-}
-
-int
gphsplit(char **item, int size, char *buf)
{
int n;
diff --git a/net.c b/net.c
@@ -0,0 +1,157 @@
+#include <sys/socket.h>
+#include <errno.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "gawk.h"
+#include "util.h"
+
+int
+resolve(char const *host, char const *port)
+{
+ int error, s;
+ struct addrinfo hints;
+ struct addrinfo *ai, *ai0;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo(host, port, &hints, &ai0);
+ if (error) {
+ warn(0, "unable to resolve '%s' (%s): %s",
+ host, port, gai_strerror(error));
+ return -1;
+ }
+
+ s = -1;
+ for (ai = ai0; ai && s == -1; ai = ai->ai_next) {
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s != -1 && connect(s, ai->ai_addr, ai->ai_addrlen) == -1) {
+ close(s);
+ s = -1;
+ }
+ }
+ freeaddrinfo(ai0);
+
+ if (s == -1) {
+ warn(0, "unable to connect to '%s' at '%s'", host, port);
+ return -1;
+ }
+ return s;
+}
+
+int
+gph_send(int sock, char const *message)
+{
+ char tmp[MY_PATH_MAX];
+ int n;
+
+ n = strcspn(message, "?");
+ if (message[n] == '\0')
+ n = send(sock, message, n, 0);
+ else {
+ strlcpy(tmp, message, n + 1);
+ tr(tmp + n, message + n, '?', ' ');
+ tmp[n] = '\t';
+ n = send(sock, tmp, strlen(tmp), 0);
+ }
+
+ if (n == -1) {
+ warn(errno, "unable to send message");
+ return 1;
+ }
+ if (shutdown(sock, SHUT_WR)) {
+ warn(errno, "shutdown");
+ return 1;
+ }
+ return 0;
+}
+
+ssize_t
+recvtxt(int s, FILE *output)
+{
+ FILE *input;
+ char *bufp;
+ char buf[MY_LINE_MAX];
+
+ input = fdopen(s, "r");
+ if (input == NULL) {
+ warn(errno, "fdopen");
+ return 1;
+ }
+
+ /*
+ * While the specification says strip leading periods if
+ * there are multiple I think it must mean only one (see
+ * RFC 1436 Appendix).
+ */
+ while ((bufp = fgets(buf, sizeof(buf), input)) != NULL) {
+ if (*bufp == '.')
+ if (strcmp(++bufp, "\r\n") == 0)
+ break;
+ if (fputs(bufp, output) == EOF)
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+recvbin(int s, FILE *output)
+{
+ char buf[MY_CHUNK_MAX];
+ ssize_t bytes;
+
+ while ((bytes = recv(s, buf, sizeof(buf), 0)) > 0)
+ /* NOTE: cast is safe, bytes _is_ >0 */
+ if (fwrite(buf, 1, bytes, output) != (size_t)bytes)
+ return 1;
+ return 0;
+}
+
+int
+gph_recvto(int sock, char const *path, int bin)
+{
+ FILE *fp;
+ int status;
+ struct pollfd pfd;
+
+ pfd.fd = sock;
+ pfd.events = POLLRDNORM;
+ if (poll(&pfd, 1, timeout) < 1) {
+ warn(errno, "Unable to recieve response");
+ return 1;
+ }
+
+ fp = wfopen(path, "w+");
+ if (fp == NULL)
+ return 1;
+
+ if (bin)
+ status = recvbin(sock, fp);
+ else status = recvtxt(sock, fp);
+ if (wfclose(fp) || status)
+ return 1;
+ return 0;
+}
+
+int
+gopher(char **addr, char const *path, int bin)
+{
+ int sock;
+
+ sock = resolve(addr[AR_HOST], addr[AR_PORT]);
+ if (sock == -1)
+ return 1;
+
+ if (gph_send(sock, addr[AR_PATH]) != 0 ||
+ gph_recvto(sock, path, bin) != 0) {
+ close(sock);
+ return 1;
+ }
+ return close(sock);
+}
diff --git a/net.h b/net.h
@@ -0,0 +1,7 @@
+#ifndef _net_h
+#define _net_h
+
+int gopher(char **, char const *, int);
+int resolve(char const *, char const *, int);
+
+#endif /* _net_h */