From: Kim Gunsoo Date: Thu, 23 Jul 2015 09:07:39 +0000 (+0900) Subject: Synchronize shell window size with remote shell. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cb1f8230dd5dcf404ba9b0055aad7c6d2d53b629;p=sdk%2Ftools%2Fsdb.git Synchronize shell window size with remote shell. Change-Id: I661cd1500ead0daacaaacb2bb4e3007f2b5665d8 Signed-off-by: Kim Gunsoo --- diff --git a/src/command_function.c b/src/command_function.c index aef04cc..0e19b6d 100644 --- a/src/command_function.c +++ b/src/command_function.c @@ -726,7 +726,6 @@ int uninstall(int argc, char **argv) { return 0; } -#define CAPBUF_SIZE 4096 int get_capability(int argc, char ** argv) { char full_cmd[16] = {0,}; char cap_buffer[CAPBUF_SIZE] = {0,}; diff --git a/src/command_function.h b/src/command_function.h index 866ecaf..60ea086 100644 --- a/src/command_function.h +++ b/src/command_function.h @@ -34,6 +34,8 @@ #define PATH_MAX 4096 #endif +#define CAPBUF_SIZE 4096 + int da(int argc, char ** argv); int oprofile(int argc, char ** argv); int profile(int argc, char ** argv); diff --git a/src/commandline.c b/src/commandline.c index 93ed88d..50ef644 100755 --- a/src/commandline.c +++ b/src/commandline.c @@ -52,6 +52,10 @@ static void create_opt_list(LIST_NODE** opt_list); static void create_cmd_list(LIST_NODE** cmd_list); static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); +static int ishell_fd = -1; +static int enable_sync_winsz = 0; +static void sync_winsz(void); + #ifdef HAVE_TERMIO_H static __inline__ void stdin_raw_init(int fd, struct termios* tio_save); @@ -98,7 +102,7 @@ static __inline__ void stdin_raw_init(void** args) { return; } - if(!SetConsoleMode(input_t_handle, 0)) { + if(!SetConsoleMode(input_t_handle, ENABLE_MOUSE_INPUT)) { fprintf(stdout, "error: fail to set console mode\n"); return; } @@ -251,6 +255,12 @@ static void *stdin_read_thread(void *x) } buf = NULL; } + } else if(i_record.EventType == MOUSE_EVENT) { + if (i_record.Event.MouseEvent.dwEventFlags == 0) { + if (enable_sync_winsz == 1) { + sync_winsz(); + } + } } } } @@ -288,6 +298,17 @@ static int get_screensize(int* lines, int* columns) return 0; } + +static void sig_winch_handler(int sig) { + if (sig != SIGWINCH) { + return; + } + + if (enable_sync_winsz == 1) { + sync_winsz(); + } +} + #else // for Windows static int get_screensize(int* lines, int* columns) { @@ -310,6 +331,110 @@ static int get_screensize(int* lines, int* columns) } #endif +static void sync_winsz() { + int lines, columns; + int fd = -1; + int remote_id = -1; + char full_cmd[64] = {0,}; + char *ret_str; + struct sockaddr_in addr; + int sockaddr_len = sizeof(addr); + + if (get_screensize(&lines, &columns) == 0) { + memset(&addr, 0, sizeof(addr)); + if (sdb_getsockname(ishell_fd, (struct sockaddr *)&addr, &sockaddr_len) < 0) { + D("failed to get sock name. errno=%d, %s\n", errno, strerror(errno)); + return; + } + + snprintf(full_cmd, sizeof(full_cmd), "host:get-remote-id:%d:%d", + addr.sin_port, addr.sin_addr.s_addr); + ret_str = sdb_query(full_cmd); + if(ret_str == NULL) { + D("failed to sdb query.\n"); + return; + } + + if (sscanf(ret_str, "remote-id:%d", &remote_id) != 1 || remote_id == -1) { + D("failed to get remote-id\n"); + return; + } + + memset(full_cmd, 0, sizeof(full_cmd)); + snprintf(full_cmd, sizeof(full_cmd), "shellconf:syncwinsz:%d:%d:%d", remote_id, lines, columns); + fd = sdb_connect(full_cmd); + if(fd < 0) { + enable_sync_winsz = 0; + D("failed to syncwinsz.\n"); + return; + } + + sdb_close(fd); + } +} + +static int match_capability_key_value(char* cap, char* key, char* value) { + char *p_str = NULL; + int offset = 0; + char *k = NULL; + char *v = NULL; + int matched = -1; + + if (cap == NULL || key == NULL || value == NULL) { + return -1; + } + + while ((p_str = strchr(cap+offset, ':')) != NULL) { + p_str[0] = 0; + k = cap+offset; + offset += strlen(cap+offset)+1; + + p_str = strchr(cap+offset, '\n'); + if (p_str != NULL) { + p_str[0] = 0; + v = cap+offset; + offset += strlen(cap+offset)+1; + } + + if (k == NULL || v == NULL) { + k = NULL; + v = NULL; + continue; + } + + if (!strcmp(k, key) && !strcmp(v, value)) { + matched = 1; + break; + } + + k = NULL; + v = NULL; + } + + return matched; +} + +static int check_syncwinsz_support() { + char full_cmd[16] = {0,}; + char cap_buffer[CAPBUF_SIZE] = {0,}; + uint16_t len = 0; + int supported = -1; + + snprintf(full_cmd, sizeof(full_cmd), "capability:"); + int fd = sdb_connect(full_cmd); + if (fd >= 0) { + readx(fd, &len, sizeof(uint16_t)); + if (len > CAPBUF_SIZE-1) { + len = CAPBUF_SIZE-1; + } + readx(fd, cap_buffer, len); + sdb_close(fd); + + supported = match_capability_key_value(cap_buffer, "syncwinsz_support", "enabled"); + } + return supported; +} + int interactive_shell() { sdb_thread_t thr; @@ -317,7 +442,7 @@ int interactive_shell() int lines, columns; int fd = -1; - if (get_screensize(&lines, &columns) == 0) { + if(get_screensize(&lines, &columns) == 0) { snprintf(eshell+7, sizeof(eshell)-7, "%d:%d", lines, columns); D("interactive shell : eshell command=%s\n", eshell); fd = sdb_connect(eshell); @@ -335,6 +460,11 @@ int interactive_shell() int* fd_p = malloc(sizeof(int)); *fd_p = fd; + ishell_fd = fd; + if(check_syncwinsz_support() == 1) { + D("Support sync window size with remote\n"); + enable_sync_winsz = 1; + } #ifdef HAVE_TERMIO_H void** args = (void**)malloc(sizeof(void*)*2); @@ -343,6 +473,15 @@ int interactive_shell() struct termios* tio_save_p = (struct termios*)malloc(sizeof(struct termios)); memcpy(tio_save_p, &tio_save, sizeof(struct termios)); args[1] = tio_save_p; + + // register SIGWINCH signal handler. + struct sigaction sa_winch; + sigemptyset(&sa_winch.sa_mask); + sa_winch.sa_flags = 0; + sa_winch.sa_handler = sig_winch_handler; + if (sigaction(SIGWINCH, &sa_winch, NULL) < -1) { + D("failed to register the SIGWINCH signal handler.\n"); + } #else void** args = (void**)malloc(sizeof(void*)*3); stdin_raw_init(args); diff --git a/src/sockets.c b/src/sockets.c index 361a286..b42d4eb 100755 --- a/src/sockets.c +++ b/src/sockets.c @@ -862,6 +862,33 @@ static void unregister_all_tcp_transports() sdb_mutex_unlock(&transport_lock, "transport unregister_all_tcp_transports"); } +static int find_remote_id(int port, int ip) +{ + int remote_id = -1; + struct sockaddr_in peer_addr; + int sockaddr_len = sizeof(peer_addr); + + LIST_NODE* curptr = local_socket_list; + while(curptr != NULL) { + SDB_SOCKET* s = curptr->data; + curptr = curptr->next_ptr; + + memset(&peer_addr, 0, sizeof(peer_addr)); + if (sdb_getpeername(s->fd, (struct sockaddr *)&peer_addr, &sockaddr_len) < 0) { + LOG_ERROR("Failed to get peer name. errno=%d, %s\n", errno, strerror(errno)); + return -1; + } + + if (port == peer_addr.sin_port && ip == peer_addr.sin_addr.s_addr) { + LOG_DEBUG("get-remote-id : remote_id=%d\n", s->remote_id); + remote_id = s->remote_id; + break; + } + } + + return remote_id; +} + static int handle_host_request(char *service, SDB_SOCKET* socket) { LOG_INFO("LS(%X)\n", socket->fd); @@ -907,6 +934,23 @@ static int handle_host_request(char *service, SDB_SOCKET* socket) return 0; } + // return a remote id + if (!strncmp(service, "get-remote-id:", 14)) { + int remote_id = -1; + int port = -1; + int ip = -1; + + if (sscanf(service+14, "%d:%d", &port, &ip) == 2) { + remote_id = find_remote_id(port, ip); + } else { + LOG_ERROR("Invalid argument\n"); + } + + snprintf(cmd_buf, cbuf_size, "remote-id:%d", remote_id); + sendokmsg(socket->fd, cmd_buf); + return 0; + } + // add a new TCP transport, device or emulator if (!strncmp(service, "connect:", 8)) { char* host = service + 8; diff --git a/src/utils.c b/src/utils.c index cddd915..bf26b09 100755 --- a/src/utils.c +++ b/src/utils.c @@ -295,6 +295,14 @@ void disable_tcp_nagle(int fd) { return utils_backend->disable_tcp_nagle(fd); } +int sdb_getsockname(int fd, struct sockaddr *addr, int *sockaddr_len) { + return utils_backend->sdb_getsockname(fd, addr, sockaddr_len); +} + +int sdb_getpeername(int fd, struct sockaddr *addr, int *sockaddr_len) { + return utils_backend->sdb_getpeername(fd, addr, sockaddr_len); +} + int sdb_thread_create(sdb_thread_t *pthread, sdb_thread_func_t start, void* arg) { return utils_backend->sdb_thread_create(pthread, start, arg); } diff --git a/src/utils.h b/src/utils.h index 2889f57..73b72c7 100755 --- a/src/utils.h +++ b/src/utils.h @@ -128,6 +128,8 @@ char* sdb_dirstart(const char* path); char* sdb_dirstop(const char* path); int sdb_socket_setbufsize(int fd, int bufsize); void disable_tcp_nagle(int fd); +int sdb_getsockname(int fd, struct sockaddr *addr, int *sockaddr_len); +int sdb_getpeername(int fd, struct sockaddr *addr, int *sockaddr_len); // sockets #define LISTEN_BACKLOG 4 diff --git a/src/utils_backend.h b/src/utils_backend.h index c0f9ef9..b7c8b17 100755 --- a/src/utils_backend.h +++ b/src/utils_backend.h @@ -75,6 +75,8 @@ struct utils_os_backend { char* (*sdb_dirstop)(const char* path); int (*sdb_socket_setbufsize)(int fd, int bufsize); void (*disable_tcp_nagle)(int fd); + int (*sdb_getsockname)(int fd, struct sockaddr *addr, int *sockaddr_len); + int (*sdb_getpeername)(int fd, struct sockaddr *addr, int *sockaddr_len); // simple implementation of pthread int (*sdb_thread_create)(sdb_thread_t *pthread, sdb_thread_func_t start, void* arg); int (*sdb_mutex_lock)(sdb_mutex_t *mutex); diff --git a/src/utils_unix.c b/src/utils_unix.c index f05441d..96dda83 100755 --- a/src/utils_unix.c +++ b/src/utils_unix.c @@ -259,6 +259,14 @@ static void _disable_tcp_nagle(int fd) LOG_ERROR("failed to set the file descriptor '%d': %s\n", fd, strerror(errno)); } +int _sdb_getsockname(int fd, struct sockaddr *addr, int *sockaddr_len) { + return getsockname(fd, addr, sockaddr_len); +} + +int _sdb_getpeername(int fd, struct sockaddr *addr, int *sockaddr_len) { + return getpeername(fd, addr, sockaddr_len); +} + static int _sdb_thread_create( sdb_thread_t *pthread, sdb_thread_func_t start, void* arg ) { pthread_attr_t attr; @@ -439,6 +447,8 @@ const struct utils_os_backend utils_unix_backend = { .sdb_dirstop = _sdb_dirstop, .sdb_socket_setbufsize = _sdb_socket_setbufsize, .disable_tcp_nagle = _disable_tcp_nagle, + .sdb_getsockname = _sdb_getsockname, + .sdb_getpeername = _sdb_getpeername, // simple pthread implementations .sdb_thread_create = _sdb_thread_create, .sdb_mutex_lock = _sdb_mutex_lock, diff --git a/src/utils_windows.c b/src/utils_windows.c index 4af013a..ef18f77 100755 --- a/src/utils_windows.c +++ b/src/utils_windows.c @@ -537,6 +537,18 @@ static int _sdb_socket_setbufsize(int fd, int bufsize) { return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*) &opt, sizeof(opt)); } +int _sdb_getsockname(int fd, struct sockaddr *addr, int *sockaddr_len) { + SDB_HANDLE* sdb_handle = sdb_handle_map_get(fd); + SOCKET s = sdb_handle->u.socket; + return getsockname(s, (SOCKADDR *)addr, sockaddr_len); +} + +int _sdb_getpeername(int fd, struct sockaddr *addr, int *sockaddr_len) { + SDB_HANDLE* sdb_handle = sdb_handle_map_get(fd); + SOCKET s = sdb_handle->u.socket; + return getpeername(s, (SOCKADDR *)addr, sockaddr_len); +} + static char* _sdb_dirstart(const char* path) { char* p = strchr(path, '/'); char* p2 = strchr(path, '\\'); @@ -1006,6 +1018,8 @@ const struct utils_os_backend utils_windows_backend = { .sdb_dirstop = _sdb_dirstop, .sdb_socket_setbufsize = _sdb_socket_setbufsize, .disable_tcp_nagle = _disable_tcp_nagle, + .sdb_getsockname = _sdb_getsockname, + .sdb_getpeername = _sdb_getpeername, // simple pthread implementations .sdb_thread_create = _sdb_thread_create, .sdb_mutex_lock = _pthread_mutex_lock,