server.c
author viric@llimona
Thu, 27 Sep 2007 00:25:54 +0200
changeset 58 2cf8c513d18f
parent 53 07500c5c53cb
child 66 b2469563a1dc
permissions -rw-r--r--
added authors.

/*
    Terminal Mixer - multi-point multi-user access to terminal applications
    Copyright (C) 2007  LluĂ­s Batlle i Rossell

    Please find the license in the provided COPYING file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include "main.h"
#include "handlers.h"

static void loop()
{
    fd_set read_set;
    int maxfd;
    int stdin_opened;
    int res;

    if (command_line.s_param.nohup)
        stdin_opened = 0;
    else
        stdin_opened = 1;

    do
    {
        FD_ZERO(&read_set);

        if (stdin_opened)
            FD_SET(0, &read_set);
        maxfd = 0;

        app_control_prepare_read_fdset(&read_set, &maxfd);
        if (command_line.s_param.serve_unix)
            s_unix_prepare_read_fdset(&read_set, &maxfd);
        if (command_line.s_param.serve_tcp)
            s_tcp_prepare_read_fdset(&read_set, &maxfd);
#ifdef linux
        if (command_line.s_param.serve_eth)
            s_eth_prepare_read_fdset(&read_set, &maxfd);
#endif /* linux */

        /* Will block */
        res = select(maxfd + 1, &read_set, 0, 0, 0);
        if (res == -1)
        {
            if (errno == EINTR)
                continue;
            else
                error("Error in select()");
        }

        res = app_control_process_read_fdset(&read_set);
        if (res == -1) /* app_stdout and app_stderr closed */
            break;

        if (stdin_opened && FD_ISSET(0, &read_set))
        {
            res = read(0, stream_buffer, stream_buffer_size);
            /* if res is 0, the fcall will close app_stdin */
            app_control_local_send_to_stdin(stream_buffer, res);
            if (res == 0)
                stdin_opened = 0;
        }

        if (command_line.s_param.serve_unix)
            s_unix_process_read_fdset(&read_set);
        if (command_line.s_param.serve_tcp)
            s_tcp_process_read_fdset(&read_set);
#ifdef linux
        if (command_line.s_param.serve_eth)
            s_eth_process_read_fdset(&read_set);
#endif /* linux */
    } while(1);
}

int server()
{
    int child;

    command_line.is_server = 1;

    app_control_start();

    /* in raw mode, the signals for Control-C, ... will be generated by the
     * slave pty. The master will receive the key codes. */
    if (command_line.s_param.serve_unix)
        s_unix_update_served(command_line.s_param.max_served);

    if (command_line.s_param.serve_tcp)
        s_tcp_update_served(command_line.s_param.max_served);

#ifdef linux
    if (command_line.s_param.serve_eth)
        s_eth_init();
#endif /* linux */

    child = fork_app(command_line.s_param.command);

    if (command_line.s_param.nohup)
    {
        close(0);
        close(1);
        close(2);
    } else
        if (command_line.s_param.run_in_subterminal)
            prepare_user_terminal();

    install_signal_forwarders(child);

    loop();

    if (command_line.s_param.serve_unix)
        s_unix_shutdown();

    if (command_line.s_param.serve_tcp)
        s_tcp_shutdown();

#ifdef linux
    if (command_line.s_param.serve_eth)
        s_eth_shutdown();
#endif /* linux */

    if (!command_line.s_param.nohup &&
            command_line.s_param.run_in_subterminal)
        restore_user_terminal();

    return 0;
}