#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
/* TODO
* - should check for close() errors, theoretically
*/
int make_server_socket(const struct sockaddr_in *sa, int backlog) {
const int one = 1;
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == -1) {
perror("socket");
exit(1);
}
if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != 0) {
perror("setsockopt SO_REUSEADDR");
exit(1);
}
if (bind(server_socket, (struct sockaddr *) sa, sizeof(*sa)) != 0) {
perror("bind");
exit(1);
}
if (listen(server_socket, backlog) != 0) {
perror("listen");
exit(1);
}
return server_socket;
}
int main(int argc, char *const argv[]) {
int server_socket;
struct sockaddr_in sa;
int port;
char *const *new_argv;
int option;
int listen_backlog = 20;
while ((option = getopt(argc, argv, "b:")) != -1) {
switch (option) {
case 'b':
listen_backlog = atoi(optarg);
break;
}
}
if (optind + 2 >= argc) {
fprintf(stderr,
"Usage: %s [-b listen_backlog] host port command...\n", argv[0]);
exit(1);
}
sa.sin_family = AF_INET;
if (inet_aton(argv[optind], &sa.sin_addr) == 0) {
fprintf(stderr, "Bad IP address: %s\n", argv[optind]);
exit(1);
}
port = atoi(argv[optind + 1]);
if (port <= 0) {
fputs("Bad port number", stderr);
exit(1);
}
sa.sin_port = htons(port);
server_socket = make_server_socket(&sa, listen_backlog);
if (dup2(server_socket, STDIN_FILENO) == -1) {
perror("dup2");
exit(1);
}
close(server_socket);
new_argv = argv + optind + 2;
execvp(*new_argv, new_argv);
perror("execvp");
exit(1);
}
syntax highlighted by Code2HTML, v. 0.9.1