/*
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 <signal.h>
#include <string.h>
#include "main.h"
#include "handlers.h"
static void loop()
{
fd_set read_set;
sigset_t sigold,signoalarm;
int maxfd;
int stdin_opened;
int res;
if (command_line.s_param.nohup)
stdin_opened = 0;
else
stdin_opened = 1;
/* Prepare the sigset for blocking alarm */
sigemptyset(&signoalarm);
sigaddset(&signoalarm, SIGALRM);
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 */
/* Prepare checking for timeout */
sigprocmask(SIG_BLOCK, &signoalarm, &sigold);
#ifdef linux
if (command_line.s_param.serve_eth)
/* This will check if the timeout occurred,
* and will not do anything otherwise. */
eth_proto_process_timeouts();
#endif
/* Will block */
res = pselect(maxfd + 1, &read_set, 0, 0, 0, &sigold);
#ifdef linux
if (command_line.s_param.serve_eth)
eth_proto_process_timeouts();
#endif
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)
{
ignore_sighup();
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;
}
syntax highlighted by Code2HTML, v. 0.9.1