Platon Technologies
neprihlásený Prihlásiť Registrácia
SlovakEnglish
open source software development oslavujeme 10 rokov vývoja otvoreného softvéru! Piatok, 29. marec 2024

Súbor: [Platon] / libplaton / utils / server-backend / server-backend.c (stiahnutie)

Revízia 1.3, Wed Oct 16 21:04:54 2002 UTC (21 years, 5 months ago) by nepto


Zmeny od 1.2: +30 -90 [lines]

Interactive communication implemented. Use -i switch.
Code split into several parts and redunand added into utils.c file.
server-backend2.[ch] removed, server-backed-fast.c added, they both use
  the same header server-backend.h file.
README added with description and compilation notes.

/*
 * server_backend.c - network server socketing backend
 *
 * (c) 2001 Ondrej Jombik <nepto@pobox.sk>
 *
 * History
 * - 19/9/2001 - initial release
 * - 20/9/2001 - minor bugfixes
 *             - waitpid() used as substitute of wait()
 *
 * TODO
 * - write debug infomations to STDERR
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/* wait() */
#include <sys/wait.h>

/* struct timeval */
#include <sys/time.h>

/* signal() */
#include <signal.h>

#include "utils.h"
#include "server-backend.h"

int main(int argc, char *argv[])
{
    int port;
    int listen_sock;
    fd_set fds;
    struct client *client_first = NULL;
    char **process;

    if (argc < 3) {
        fprintf(stderr, "Usage: %s <port> <process> <arg1> ... <argn>\n",
                PROG_NAME);
        return 1;
    }

    port = get_port(argv[1]);

    if ((process = create_process_array(argc, argv, 2)) == NULL) {
        perror(PROG_NAME);
        return 32;
    }

    fake_command_line(argc, argv);

    if ((listen_sock = bind_to_port(port)) == -1) {
        perror(PROG_NAME);
        return 16;
    }

    if (0) {
        (void) setpgrp();
        signal(SIGHUP, SIG_IGN);
    }

    if (1)
        fcntl(listen_sock,F_SETFL,O_NDELAY);

    switch (fork()) {
        case -1:
            perror(PROG_NAME);
            return errno;
            break;
        case 0:
            break;
        default:
            fprintf(stderr, "%s: accepting connections on port %d\n",
                    PROG_NAME, port);
            return 0;
            break;
    }

    while (1) {
        int pid;
        struct client *client;
        struct timeval tv;

        /*
           for (pid = 0, client = client_first; client != NULL;
           client = client->next)
           pid++;

           fprintf(stderr, "debug: %d active clients\n", pid);
           */

        FD_ZERO(&fds);
        FD_SET(listen_sock, &fds);

        tv.tv_sec = 1;
        tv.tv_usec = 0;

        if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) == -1)
            continue;

        if (FD_ISSET(listen_sock, &fds)) {
            struct client *client_new;
            struct sockaddr_in acc_addr;
            unsigned int size;
            int accept_sock;
            struct hostent *host;

            size        = sizeof(struct sockaddr_in);
            accept_sock = accept(listen_sock,
                    (struct sockaddr*) &acc_addr, &size);

            if (accept_sock > 0 &&
                    (client_new = (struct client*)
                     malloc(sizeof(struct client))) != NULL) {

                client_new->fd = accept_sock;

                /* Geting client IP address. */
                strncpy(client_new->ip,
                        (char*)inet_ntoa(acc_addr.sin_addr),
                        IP_SIZE);
                client_new->ip[IP_SIZE] = '\0';

                /* Geting host name. */
                host = gethostbyaddr((char *)&acc_addr.sin_addr, 4, AF_INET);
                if (host == NULL)
                    strncpy(client_new->host, client_new->ip, HOST_SIZE);
                else
                    strncpy(client_new->host, host->h_name, HOST_SIZE);

                client_new->host[HOST_SIZE] = '\0';

                client_new->port = ntohs(acc_addr.sin_port);
                client_new->next = NULL;

                if (client_first == NULL) {
                    client_first = client_new;
                }
                else {
                    for (client = client_first;
                            client->next != NULL;
                            client = client->next)
                        ;

                    client->next = client_new;
                }

                switch (pid = fork()) {
                    case -1:
                        perror(PROG_NAME);
                        return errno;
                        break;
                    case 0: /* child */
                        close(0);
                        dup(client_new->fd);

                        close(1);
                        dup(client_new->fd);

                        close(2);
                        dup(client_new->fd);

                        close(listen_sock);

                        /* write(client_new->fd, "----------------\n\r", 18); */
                        /* execvp(argv[2], argv + 2); */

                        execvp(process[0], process);
                        write(client_new->fd, "execlp() failure\n\r", 18);

                        break;
                    default: /* parent */
                        client_new->pid = pid;
                        close(client_new->fd);
                        break;
                }
            }
        }

        /*
         * Terminated childs remove stuff.
         */

        while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {

            for (client = client_first; client != NULL; ) {

                /*
                   fprintf(stderr, "debug: trying to removing pid %d, comparing with %d\n", pid, client->pid);
                   */

                if (client->pid == pid) {

                    /*
                       fprintf(stderr, "debug: removing pid %d\n", pid);
                       */

                    shutdown(client->fd, 2);
                    close(client->fd);

                    if (client_first != client) {
                        struct client* prev;
                        for (prev = client_first;
                                prev->next != client;
                                prev = prev->next )
                            ;

                        prev->next = client->next;
                        free(client);
                        client = prev->next;
                    }
                    else {
                        client_first = client->next;
                        free(client);
                        client = client_first;
                    }
                }
                else {
                    client = client->next;
                }
            }
        }

    } /* while (1) */

    return 0;
}


Platon Group <platon@platon.sk> http://platon.sk/
Copyright © 2002-2006 Platon Group
Stránka používa redakčný systém Metafox
Na začiatok