/* 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 #include #include #include #include #include #include #include #include "main.h" #include "filter.h" #include "handlers.h" struct FilterRules *client_recv_fr = 0; struct FilterRules *client_termin_fr = 0; static void loop(Net_c_prepare_read_fdset net_prepare, Net_c_process_read_fdset net_process, Net_c_send net_send) { fd_set read_set; sigset_t sigold,signoalarm; int maxfd; int res; /* Prepare the sigset for blocking alarm */ sigemptyset(&signoalarm); sigaddset(&signoalarm, SIGALRM); do { FD_ZERO(&read_set); FD_SET(0, &read_set); /* stdin */ maxfd = 0; net_prepare(&read_set, &maxfd); /* 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 res = pselect(maxfd + 1, &read_set, 0, 0, 0, &sigold); #ifdef linux if (command_line.c_param.transport == ETHERNET) /* If there isn't a good result, we quit */ if (!eth_proto_process_timeouts()) { error("Connection lost (no ACK received).\n"); break; } #endif if (res == -1) { if (errno == EINTR) continue; else error("Error in select()"); } res = net_process(&read_set); if (res == -1) /* EOF */ break; if (FD_ISSET(0, &read_set)) { res = read(0, stream_buffer, stream_buffer_size); if (client_termin_fr) { int olen; /* We use ostream_buffer2 for data from the * keyboard to the tm client, because * *_client.c use the ostream_buffer for data * from the server to us (tm client). */ hex_dump("Client prefilter", stream_buffer, res); filter_stream(client_termin_fr, ostream_buffer2, &olen, stream_buffer, res); if (olen > 0) net_send(ostream_buffer2, olen); } else net_send(stream_buffer, res); if (res == 0) /* EOF */ break; } } while (1); } void filtercb_tildes(struct FilterRules *fr, const struct FFilter *ff, char *obuf, int *olen, const char *ibuf, int pos) { dump_line("filtercb_tildes: '%c'\n", ibuf[pos+3]); if (ibuf[pos+3] == '.') kill(getpid(), SIGINT); else { obuf[(*olen)++] = '~'; obuf[(*olen)++] = '~'; obuf[(*olen)++] = '~'; } } int client() { Net_c_prepare_read_fdset net_prepare_read_fdset; Net_c_process_read_fdset net_process_read_fdset; Net_c_send net_send; /* Prepare the filter */ { struct FFilter *ff; client_recv_fr = new_filter_rules(); ff = new_ftelnet(); add_ffilter(client_recv_fr, ff); if (command_line.c_param.raw_mode) { client_termin_fr = new_filter_rules(); ff = new_ftildes(); ff->callback = filtercb_tildes; add_ffilter(client_termin_fr, ff); } } if (command_line.c_param.transport == UNIX) /* Will be 'tcp', 'ether', ... */ { c_unix_connect_socket(); net_prepare_read_fdset = c_unix_prepare_read_fdset; net_process_read_fdset = c_unix_process_read_fdset; net_send = c_unix_send; } #ifdef linux else if (command_line.c_param.transport == ETHERNET) { c_eth_init(); net_prepare_read_fdset = c_eth_prepare_read_fdset; net_process_read_fdset = c_eth_process_read_fdset; net_send = c_eth_send_to_connected; } #endif /* linux */ if (command_line.c_param.raw_mode) prepare_user_terminal(); loop(net_prepare_read_fdset, net_process_read_fdset, net_send); if (command_line.c_param.raw_mode) restore_user_terminal(); return 0; }