diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3a23c2c --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +RM=rm -f +CFLAGS= +LDFLAGS= +LIBS= +TARGET=wstationd +SRC= \ + src/wstationd.c +OBJ=$(SRC:.c=.o) + +.PHONY: clean all + +.c.o: + $(CC) -Wall -std=c99 $(CFLAGS) -c $< -o $@ + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ + +clean: + $(RM) $(OBJ) $(TARGET) diff --git a/src/wstationd.c b/src/wstationd.c new file mode 100644 index 0000000..1c05e00 --- /dev/null +++ b/src/wstationd.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wstationd.h" + + +static char *exec_name; + + +static void print_help() +{ + fprintf(stdout, "usage: %s\n", exec_name); + fprintf(stdout, " -p, --port Port to listen on (default: 10800)\n"); + fprintf(stdout, " -b, --bind
Address to bind to (default: 0.0.0.0)\n"); + fprintf(stdout, " -h, --help Print this message and exit\n"); + fprintf(stdout, " -v, --version Print version and exit\n"); +} + + +int main(int argc, char *argv[]) +{ + const struct option longopts[] = { + { "port", required_argument, NULL, 'p' }, + { "bind", required_argument, NULL, 'b' }, + { "version", no_argument, NULL, 'v' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } + }; + + exec_name = basename(argv[0]); + + int flag = 1; + int sockfd = 0, connfd = 0; + int port = 10800; + uint32_t addr = INADDR_ANY; + + for(int ch; (ch = getopt_long(argc, argv, "b:p:vh", longopts, NULL)) != -1;){ + switch(ch){ + case 'p': + port = (int)strtol(optarg, NULL, 10); + if(port < 1 || port > 65535){ + fprintf(stderr, "%s: invalid port number\n", exec_name); + print_help(); + goto shutdown_error; + } + break; + + case 'b': + if(inet_pton(AF_INET, optarg, &addr) == -1){ + fprintf(stderr, "%s: invalid bind address\n", exec_name); + print_help(); + goto shutdown_error; + } + break; + + case 'v': + fprintf(stdout, "wstationd v%s (%s %s)\n", VERSION,__DATE__, __TIME__); + goto shutdown_clean; + + case '?': + case 'h': + print_help(); + goto shutdown_clean; + } + } + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd == -1){ + fprintf(stderr, "%s: cannot open socket - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } + + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); + + struct sockaddr_in sockin; + memset(&sockin, 0, sizeof(sockin)); + sockin.sin_family = AF_INET; + sockin.sin_addr.s_addr = addr; + sockin.sin_port = htons(port); + + if(bind(sockfd, (struct sockaddr*)&sockin, sizeof(sockin)) < 0){ + fprintf(stderr, "%s: cannot bind to port - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } + + if(listen(sockfd, 10) != 0){ + fprintf(stderr, "%s: cannot listen - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } + + connfd = accept(sockfd, NULL, NULL); + if(connfd == -1){ + fprintf(stderr, "%s: connection failed - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } + + shutdown_clean: + if(connfd > 0) close(connfd); + if(sockfd > 0) close(sockfd); + return 0; + + shutdown_error: + if(connfd > 0) close(connfd); + if(sockfd > 0) close(sockfd); + return 1; +} diff --git a/src/wstationd.h b/src/wstationd.h new file mode 100644 index 0000000..563d1eb --- /dev/null +++ b/src/wstationd.h @@ -0,0 +1 @@ +#define VERSION "0.1.0"