/* 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 "main.h" #include "handlers.h" extern char *optarg; extern int optind, opterr, optopt; /* From main.h given external */ int app_stdin; int app_stdout; int app_stderr; struct Command_line command_line; static const char version[] = "0.4"; static int showhelp(const char *pname) { printf("tm v%s - terminal mixer, Copyright (C) 2007 " "Lluis Batlle i Rossell\n", version); printf("usage: %s [opts] [appcommand] [param1] [param2] ...\n", pname); printf(" If you give _appcommand_, it starts the application and\n"); printf(" serves it through a Unix socket on $TM_SOCKET or " "/tmp/tm-socket.UID,\n"); printf(" unless '-p' is used.\n"); printf(" Without _appcomand_, starts a the Unix socket client.\n"); printf("options: \n"); printf(" -h Show help.\n"); printf(" -P Run the child as connected to a pipe (default).\n"); printf(" -t Run the child as connected to a terminal (raw mode in " "client).\n"); printf(" -n Unlink the program from the terminal (as 'nohup').\n"); printf(" -N MAX Serve at most MAX sockets for each transport (1 default)." "\n"); printf(" -w The remote clients can write to the application.\n"); printf(" -C The remote clients end will close app's stdin.\n"); printf(" -p NUM Listen to tcp port NUM for 'telnet', and not listen to " "any\n" " Unix socket.\n"); printf(" -E Echo remote input to the server terminal.\n"); #ifdef linux printf(" -e dev Also serve/connect using raw ethernet, device 'dev'.\n"); printf(" -c adr Connect to address (MAC if eth).\n"); #endif /* linux */ printf(" -x Send xterm's resize control string to clients.\n"); return 0; } static int my_getopt(int argc, char * argv[], const char *optstring) { char *old_getopt_env; static char getopt_env[100] = "POSIXLY_CORRECT=YES"; int res; old_getopt_env = getenv("POSIXLY_CORRECT"); putenv(getopt_env); res = getopt(argc, argv, optstring); if (old_getopt_env == 0) { putenv("POSIXLY_CORRECT"); } else snprintf(getopt_env, sizeof getopt_env, "POSIXLY_CORRECT=%s", old_getopt_env); return res; } static void default_command_line() { command_line.is_server = 0; command_line.s_param.use_blocking_sockets = 1; command_line.s_param.run_in_subterminal = 0; command_line.s_param.max_served = 1; command_line.s_param.serve_unix = 1; command_line.s_param.serve_tcp = 0; command_line.s_param.send_xterm_resize = 1; command_line.s_param.client_may_close_app_stdin = 0; command_line.s_param.nohup = 0; command_line.s_param.client_can_write = 0; command_line.s_param.echo_in_local_terminal = 0; command_line.s_param.send_xterm_resize = 0; command_line.s_param.serve_eth = 0; command_line.tcp_port = 40000; /* Arbitrary */ command_line.buffer_size = 4096; /* Arbitrary */ command_line.eth_device = 0; get_unix_path(); /* for command_line.unix_path */ command_line.c_param.transport = UNIX; command_line.c_param.wait_until_char = -1; command_line.c_param.raw_mode = 0; command_line.c_param.server_address = 0; /* TODO: free it */ } static int parse_opts(int argc, char * argv[]) { int c; extern char *optarg; extern int optind, opterr, optopt; while(1) { c = my_getopt(argc, argv, "tp:nBxdPN:hwCED" #ifdef linux "c:e:" #endif /* linux */ ); if (c == -1) break; switch(c) { case 't': command_line.s_param.run_in_subterminal = 1; command_line.c_param.raw_mode = 1; break; case 'P': command_line.s_param.run_in_subterminal = 0; break; case 'B': command_line.s_param.use_blocking_sockets = 0; break; case 'n': command_line.s_param.nohup = 1; break; case 'p': command_line.tcp_port = atoi(optarg); command_line.s_param.serve_tcp = 1; command_line.s_param.serve_unix = 0; break; case 'N': command_line.s_param.max_served = atoi(optarg); break; case 'c': command_line.c_param.server_address = strdup(optarg); break; case 'h': showhelp(argv[0]); exit(0); break; case 'w': command_line.s_param.client_can_write = 1; break; case 'C': command_line.s_param.client_may_close_app_stdin = 1; break; case 'x': command_line.s_param.send_xterm_resize = 1; break; case 'E': command_line.s_param.echo_in_local_terminal = 1; break; case 'D': should_dump = 1; break; case 'e': command_line.s_param.serve_eth = 1; command_line.eth_device = strdup(optarg); command_line.c_param.transport = ETHERNET; break; case '?': error("Wrong option %c.\n", optopt); } } if (command_line.s_param.use_blocking_sockets == 0) not_implemented("Not using blocking sockets."); if (optind < argc) { command_line.is_server = 1; command_line.s_param.command = &argv[optind]; } return 0; } int main(int argc, char * argv[]) { int res; default_command_line(); parse_opts(argc, argv); init_stream_buffers(); if (command_line.is_server) res = server(); else res = client(); return res; }