/* 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" static int served_sockets = 0; static int listen_socket = -1; /* not listening */ static int connected_sockets = 0; static int *conn_sockets = 0; static char *socket_path = 0; static char default_path_prefix[] = "/tmp/tm-socket."; void get_unix_path() { char *new; new = getenv("TM_SOCKET"); if (new == 0) /* Compose the path from the default values */ { char num[20]; /* enough for an int */ int len; sprintf(num, "%i", (int) getuid()); len = strlen(default_path_prefix) + strlen(num) + 1; command_line.unix_path = malloc(len); sprintf(command_line.unix_path, "%s%s", default_path_prefix, num); } else { command_line.unix_path = malloc(strlen(new) + 1); strcpy(command_line.unix_path, new); } } static void start_listening(int new) { int ls; struct sockaddr_un addr; int res; assert(new > 0); assert(command_line.unix_path != 0); socket_path = command_line.unix_path; ls = socket(AF_UNIX, SOCK_STREAM, 0); if (ls == -1) error("Cannot create the unix listen socket in the server"); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)); res = bind(ls, (struct sockaddr *) & addr, sizeof(addr)); if (res == -1) error("Error binding to %s", socket_path); /* NUANCE: 0 backlog. Why should we assure future connections? */ res = listen(ls, 0); if (res == -1) error("Error listening on the binded unix socket"); listen_socket = ls; } void s_unix_update_served(int new) { if (new > served_sockets && new > 0 ) { conn_sockets = realloc(conn_sockets, sizeof(*conn_sockets) * new); if (listen_socket == -1) /* not listening */ { start_listening(new); } served_sockets = new; } else if (new < served_sockets) { not_implemented("new < served_sockets at unix_update_served"); } } void s_unix_shutdown() { int i; if (listen_socket != -1) { close(listen_socket); unlink(socket_path); } for (i=0; i < connected_sockets; ++i) { close(conn_sockets[i]); } connected_sockets = 0; served_sockets = 0; } void s_unix_prepare_read_fdset(fd_set *read_set, int *maxfd) { int i; FD_SET(listen_socket, read_set); *maxfd = max(*maxfd, listen_socket); for (i=0; i < connected_sockets; ++i) { /* We only accept if we don't have any * connetion opened. */ FD_SET(conn_sockets[i], read_set); *maxfd = max(*maxfd, conn_sockets[i]); } } static void remove_conn_socket(int n) { int i; assert(n >= 0); for(i=n+1; i connected_sockets) { int s; s = accept_connection(listen_socket); conn_sockets[connected_sockets++] = s; welcome_new_client_socket(s); } else { int s; s = accept_connection(listen_socket); close(s); } } } void s_unix_send_to_connected(const char *buffer, size_t size) { int i; for (i=0; i < connected_sockets; ++i) { write(conn_sockets[i], buffer, size); } }