#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