11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 31da177e4SLinus Torvalds * Licensed under the GPL 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include <stdio.h> 71da177e4SLinus Torvalds #include <stdlib.h> 81da177e4SLinus Torvalds #include <unistd.h> 91da177e4SLinus Torvalds #include <string.h> 101da177e4SLinus Torvalds #include <errno.h> 111da177e4SLinus Torvalds #include <termios.h> 121da177e4SLinus Torvalds #include <signal.h> 131da177e4SLinus Torvalds #include <sched.h> 141da177e4SLinus Torvalds #include <sys/socket.h> 151da177e4SLinus Torvalds #include "kern_util.h" 161da177e4SLinus Torvalds #include "chan_user.h" 171da177e4SLinus Torvalds #include "user_util.h" 181da177e4SLinus Torvalds #include "user.h" 191da177e4SLinus Torvalds #include "os.h" 201da177e4SLinus Torvalds #include "xterm.h" 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds struct xterm_chan { 231da177e4SLinus Torvalds int pid; 241da177e4SLinus Torvalds int helper_pid; 251da177e4SLinus Torvalds char *title; 261da177e4SLinus Torvalds int device; 271da177e4SLinus Torvalds int raw; 281da177e4SLinus Torvalds struct termios tt; 291da177e4SLinus Torvalds unsigned long stack; 301da177e4SLinus Torvalds int direct_rcv; 311da177e4SLinus Torvalds }; 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds /* Not static because it's called directly by the tt mode gdb code */ 34*5e7672ecSJeff Dike void *xterm_init(char *str, int device, const struct chan_opts *opts) 351da177e4SLinus Torvalds { 361da177e4SLinus Torvalds struct xterm_chan *data; 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds data = malloc(sizeof(*data)); 391da177e4SLinus Torvalds if(data == NULL) return(NULL); 401da177e4SLinus Torvalds *data = ((struct xterm_chan) { .pid = -1, 411da177e4SLinus Torvalds .helper_pid = -1, 421da177e4SLinus Torvalds .device = device, 431da177e4SLinus Torvalds .title = opts->xterm_title, 441da177e4SLinus Torvalds .raw = opts->raw, 451da177e4SLinus Torvalds .stack = opts->tramp_stack, 461da177e4SLinus Torvalds .direct_rcv = !opts->in_kernel } ); 471da177e4SLinus Torvalds return(data); 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* Only changed by xterm_setup, which is a setup */ 511da177e4SLinus Torvalds static char *terminal_emulator = "xterm"; 521da177e4SLinus Torvalds static char *title_switch = "-T"; 531da177e4SLinus Torvalds static char *exec_switch = "-e"; 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds static int __init xterm_setup(char *line, int *add) 561da177e4SLinus Torvalds { 571da177e4SLinus Torvalds *add = 0; 581da177e4SLinus Torvalds terminal_emulator = line; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds line = strchr(line, ','); 611da177e4SLinus Torvalds if(line == NULL) return(0); 621da177e4SLinus Torvalds *line++ = '\0'; 631da177e4SLinus Torvalds if(*line) title_switch = line; 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds line = strchr(line, ','); 661da177e4SLinus Torvalds if(line == NULL) return(0); 671da177e4SLinus Torvalds *line++ = '\0'; 681da177e4SLinus Torvalds if(*line) exec_switch = line; 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds return(0); 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds __uml_setup("xterm=", xterm_setup, 741da177e4SLinus Torvalds "xterm=<terminal emulator>,<title switch>,<exec switch>\n" 751da177e4SLinus Torvalds " Specifies an alternate terminal emulator to use for the debugger,\n" 761da177e4SLinus Torvalds " consoles, and serial lines when they are attached to the xterm channel.\n" 771da177e4SLinus Torvalds " The values are the terminal emulator binary, the switch it uses to set\n" 781da177e4SLinus Torvalds " its title, and the switch it uses to execute a subprocess,\n" 791da177e4SLinus Torvalds " respectively. The title switch must have the form '<switch> title',\n" 801da177e4SLinus Torvalds " not '<switch>=title'. Similarly, the exec switch must have the form\n" 811da177e4SLinus Torvalds " '<switch> command arg1 arg2 ...'.\n" 821da177e4SLinus Torvalds " The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n" 831da177e4SLinus Torvalds " are 'xterm=gnome-terminal,-t,-x'.\n\n" 841da177e4SLinus Torvalds ); 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds /* XXX This badly needs some cleaning up in the error paths 871da177e4SLinus Torvalds * Not static because it's called directly by the tt mode gdb code 881da177e4SLinus Torvalds */ 891da177e4SLinus Torvalds int xterm_open(int input, int output, int primary, void *d, 901da177e4SLinus Torvalds char **dev_out) 911da177e4SLinus Torvalds { 921da177e4SLinus Torvalds struct xterm_chan *data = d; 931da177e4SLinus Torvalds unsigned long stack; 941da177e4SLinus Torvalds int pid, fd, new, err; 951da177e4SLinus Torvalds char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; 961da177e4SLinus Torvalds char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 971da177e4SLinus Torvalds "/usr/lib/uml/port-helper", "-uml-socket", 981da177e4SLinus Torvalds file, NULL }; 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds if(os_access(argv[4], OS_ACC_X_OK) < 0) 1011da177e4SLinus Torvalds argv[4] = "port-helper"; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds /* Check that DISPLAY is set, this doesn't guarantee the xterm 1041da177e4SLinus Torvalds * will work but w/o it we can be pretty sure it won't. */ 1051da177e4SLinus Torvalds if (!getenv("DISPLAY")) { 1061da177e4SLinus Torvalds printk("xterm_open: $DISPLAY not set.\n"); 1071da177e4SLinus Torvalds return -ENODEV; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds fd = mkstemp(file); 1111da177e4SLinus Torvalds if(fd < 0){ 112b4fd310eSJeff Dike err = -errno; 1131da177e4SLinus Torvalds printk("xterm_open : mkstemp failed, errno = %d\n", errno); 114b4fd310eSJeff Dike return err; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds if(unlink(file)){ 118b4fd310eSJeff Dike err = -errno; 1191da177e4SLinus Torvalds printk("xterm_open : unlink failed, errno = %d\n", errno); 120b4fd310eSJeff Dike return err; 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds os_close_file(fd); 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds fd = os_create_unix_socket(file, sizeof(file), 1); 1251da177e4SLinus Torvalds if(fd < 0){ 1261da177e4SLinus Torvalds printk("xterm_open : create_unix_socket failed, errno = %d\n", 1271da177e4SLinus Torvalds -fd); 1281da177e4SLinus Torvalds return(fd); 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds sprintf(title, data->title, data->device); 1321da177e4SLinus Torvalds stack = data->stack; 1331da177e4SLinus Torvalds pid = run_helper(NULL, NULL, argv, &stack); 1341da177e4SLinus Torvalds if(pid < 0){ 1351da177e4SLinus Torvalds printk("xterm_open : run_helper failed, errno = %d\n", -pid); 1361da177e4SLinus Torvalds return(pid); 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds if(data->stack == 0) free_stack(stack, 0); 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds if (data->direct_rcv) { 1421da177e4SLinus Torvalds new = os_rcv_fd(fd, &data->helper_pid); 1431da177e4SLinus Torvalds } else { 1441da177e4SLinus Torvalds err = os_set_fd_block(fd, 0); 1451da177e4SLinus Torvalds if(err < 0){ 1461da177e4SLinus Torvalds printk("xterm_open : failed to set descriptor " 1471da177e4SLinus Torvalds "non-blocking, err = %d\n", -err); 1481da177e4SLinus Torvalds return(err); 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds new = xterm_fd(fd, &data->helper_pid); 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds if(new < 0){ 1531da177e4SLinus Torvalds printk("xterm_open : os_rcv_fd failed, err = %d\n", -new); 1541da177e4SLinus Torvalds goto out; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds CATCH_EINTR(err = tcgetattr(new, &data->tt)); 1581da177e4SLinus Torvalds if(err){ 1591da177e4SLinus Torvalds new = err; 1601da177e4SLinus Torvalds goto out; 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds if(data->raw){ 1641da177e4SLinus Torvalds err = raw(new); 1651da177e4SLinus Torvalds if(err){ 1661da177e4SLinus Torvalds new = err; 1671da177e4SLinus Torvalds goto out; 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds } 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds data->pid = pid; 1721da177e4SLinus Torvalds *dev_out = NULL; 1731da177e4SLinus Torvalds out: 1741da177e4SLinus Torvalds unlink(file); 1751da177e4SLinus Torvalds return(new); 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds /* Not static because it's called directly by the tt mode gdb code */ 1791da177e4SLinus Torvalds void xterm_close(int fd, void *d) 1801da177e4SLinus Torvalds { 1811da177e4SLinus Torvalds struct xterm_chan *data = d; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds if(data->pid != -1) 1841da177e4SLinus Torvalds os_kill_process(data->pid, 1); 1851da177e4SLinus Torvalds data->pid = -1; 1861da177e4SLinus Torvalds if(data->helper_pid != -1) 1871da177e4SLinus Torvalds os_kill_process(data->helper_pid, 0); 1881da177e4SLinus Torvalds data->helper_pid = -1; 1891da177e4SLinus Torvalds os_close_file(fd); 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds static void xterm_free(void *d) 1931da177e4SLinus Torvalds { 1941da177e4SLinus Torvalds free(d); 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 197*5e7672ecSJeff Dike const struct chan_ops xterm_ops = { 1981da177e4SLinus Torvalds .type = "xterm", 1991da177e4SLinus Torvalds .init = xterm_init, 2001da177e4SLinus Torvalds .open = xterm_open, 2011da177e4SLinus Torvalds .close = xterm_close, 2021da177e4SLinus Torvalds .read = generic_read, 2031da177e4SLinus Torvalds .write = generic_write, 204fd9bc53bSPaolo 'Blaisorblade' Giarrusso .console_write = generic_console_write, 2051da177e4SLinus Torvalds .window_size = generic_window_size, 2061da177e4SLinus Torvalds .free = xterm_free, 2071da177e4SLinus Torvalds .winch = 1, 2081da177e4SLinus Torvalds }; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds /* 2111da177e4SLinus Torvalds * Overrides for Emacs so that we follow Linus's tabbing style. 2121da177e4SLinus Torvalds * Emacs will notice this stuff at the end of the file and automatically 2131da177e4SLinus Torvalds * adjust the settings for this buffer only. This must remain at the end 2141da177e4SLinus Torvalds * of the file. 2151da177e4SLinus Torvalds * --------------------------------------------------------------------------- 2161da177e4SLinus Torvalds * Local variables: 2171da177e4SLinus Torvalds * c-file-style: "linux" 2181da177e4SLinus Torvalds * End: 2191da177e4SLinus Torvalds */ 220