Add address and port command line parameters

This commit is contained in:
Camden Dixie O'Brien 2022-10-14 21:08:45 +01:00
parent e7dc81cfad
commit 726acba679
2 changed files with 65 additions and 15 deletions

View File

@ -3,5 +3,3 @@
A small gopher server for POSIX systems, written in C99.
To build: `make`
At the moment it only serves on `::1` at port 7070.

78
main.c
View File

@ -18,12 +18,14 @@
#define _POSIX_SOURCE
#include <arpa/inet.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -36,8 +38,8 @@ int pledge(const char *, const char *);
int unveil(const char *, const char *);
#endif
#define HOST "::1"
#define PORT 7070
#define DEFAULT_ADDRSTR "::1"
#define DEFAULT_PORT 70
#define RESP_TERM ".\r\n"
#define RESP_TERM_LEN 3 /* strlen(".\r\n") */
@ -83,6 +85,12 @@ static int append_selector_part(const char *part, size_t partlen, char *buf,
return partlen + 1;
}
static void usage(const char *name)
{
fprintf(stderr, "Usage: %s [-a ipv6addr] [-p portnum] srvroot\n", name);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
(void)argc;
@ -100,24 +108,68 @@ int main(int argc, char *argv[])
#endif
/*
* Get srvroot path from arguments and copy into pbuf.
* Extract arguments.
*/
const char *srvroot = NULL, *addrstr = NULL, *portstr = NULL;
if (argc < 2)
usage(argv[0]);
for (int i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
if (i + 1 >= argc || strlen(argv[i]) != 2)
usage(argv[0]);
switch (argv[i][1]) {
case 'a':
addrstr = argv[++i];
break;
case 'p':
portstr = argv[++i];
break;
default:
usage(argv[0]);
break;
}
} else {
srvroot = argv[i];
}
}
if (!srvroot)
usage(argv[0]);
if (!addrstr)
addrstr = DEFAULT_ADDRSTR;
/*
* Parse address and port.
*/
struct in6_addr addr;
if (inet_pton(AF_INET6, addrstr, &addr) != 1)
usage(argv[0]);
if (portstr[0] == '-')
usage(argv[0]);
uint16_t port;
{
char *end;
unsigned long res = strtoul(portstr, &end, 10);
if (*end != '\0' || res > UINT16_MAX)
usage(argv[0]);
else
port = res;
}
/*
* Copy srvroot into pbuf.
*
* The srvroot being at the start of pbuf should be maintained
* through the whole application. Any trailing '/' is removed if
* present.
*/
if (argc < 2) {
fprintf(stderr, "Usage: %s srvroot\n", argv[0]);
return EXIT_FAILURE;
}
size_t srvroot_len = strlen(argv[1]);
if (argv[1][srvroot_len - 1] == '/')
size_t srvroot_len = strlen(srvroot);
if (srvroot[srvroot_len - 1] == '/')
--srvroot_len;
if (srvroot_len > PBUF_SIZE) {
fprintf(stderr, "srvroot path is too long\n");
return EXIT_FAILURE;
}
memcpy(pbuf, argv[1], srvroot_len);
memcpy(pbuf, srvroot, srvroot_len);
#ifdef __OpenBSD__
/*
@ -169,8 +221,8 @@ int main(int argc, char *argv[])
}
const struct sockaddr_in6 haddr = {
.sin6_family = AF_INET6,
.sin6_port = htons(PORT),
.sin6_addr = in6addr_loopback,
.sin6_port = htons(port),
.sin6_addr = addr,
};
if (bind(sfd, (const struct sockaddr *)&haddr, sizeof(haddr)) == -1) {
fprintf(stderr, "Error binding socket to address\n");
@ -407,7 +459,7 @@ int main(int argc, char *argv[])
*/
n = snprintf(&rbuf[rlen], RBUF_SIZE - rlen,
"%1u%s\t%s\t%s\t%u\r\n", type, ent->d_name,
&pbuf[srvroot_len], HOST, PORT);
&pbuf[srvroot_len], addrstr, port);
if (n >= RBUF_SIZE - rlen) {
fprintf(stderr, "Response buffer was too small\n");
goto send_response;