Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.11-rc3 228 lines 5.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6#include <stddef.h> 7#include <stdio.h> 8#include <stdlib.h> 9#include <unistd.h> 10#include <errno.h> 11#include <string.h> 12#include <termios.h> 13#include "chan_user.h" 14#include <os.h> 15#include <um_malloc.h> 16#include "xterm.h" 17 18struct xterm_chan { 19 int pid; 20 int helper_pid; 21 int chan_fd; 22 char *title; 23 int device; 24 int raw; 25 struct termios tt; 26}; 27 28static void *xterm_init(char *str, int device, const struct chan_opts *opts) 29{ 30 struct xterm_chan *data; 31 32 data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); 33 if (data == NULL) 34 return NULL; 35 *data = ((struct xterm_chan) { .pid = -1, 36 .helper_pid = -1, 37 .chan_fd = -1, 38 .device = device, 39 .title = opts->xterm_title, 40 .raw = opts->raw } ); 41 return data; 42} 43 44/* Only changed by xterm_setup, which is a setup */ 45static char *terminal_emulator = "xterm"; 46static char *title_switch = "-T"; 47static char *exec_switch = "-e"; 48 49static int __init xterm_setup(char *line, int *add) 50{ 51 *add = 0; 52 terminal_emulator = line; 53 54 line = strchr(line, ','); 55 if (line == NULL) 56 return 0; 57 58 *line++ = '\0'; 59 if (*line) 60 title_switch = line; 61 62 line = strchr(line, ','); 63 if (line == NULL) 64 return 0; 65 66 *line++ = '\0'; 67 if (*line) 68 exec_switch = line; 69 70 return 0; 71} 72 73__uml_setup("xterm=", xterm_setup, 74"xterm=<terminal emulator>,<title switch>,<exec switch>\n" 75" Specifies an alternate terminal emulator to use for the debugger,\n" 76" consoles, and serial lines when they are attached to the xterm channel.\n" 77" The values are the terminal emulator binary, the switch it uses to set\n" 78" its title, and the switch it uses to execute a subprocess,\n" 79" respectively. The title switch must have the form '<switch> title',\n" 80" not '<switch>=title'. Similarly, the exec switch must have the form\n" 81" '<switch> command arg1 arg2 ...'.\n" 82" The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n" 83" are 'xterm=gnome-terminal,-t,-x'.\n\n" 84); 85 86static int xterm_open(int input, int output, int primary, void *d, 87 char **dev_out) 88{ 89 struct xterm_chan *data = d; 90 int pid, fd, new, err; 91 char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; 92 char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 93 OS_LIB_PATH "/uml/port-helper", "-uml-socket", 94 file, NULL }; 95 96 if (access(argv[4], X_OK) < 0) 97 argv[4] = "port-helper"; 98 99 /* 100 * Check that DISPLAY is set, this doesn't guarantee the xterm 101 * will work but w/o it we can be pretty sure it won't. 102 */ 103 if (getenv("DISPLAY") == NULL) { 104 printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n"); 105 return -ENODEV; 106 } 107 108 /* 109 * This business of getting a descriptor to a temp file, 110 * deleting the file and closing the descriptor is just to get 111 * a known-unused name for the Unix socket that we really 112 * want. 113 */ 114 fd = mkstemp(file); 115 if (fd < 0) { 116 err = -errno; 117 printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n", 118 errno); 119 return err; 120 } 121 122 if (unlink(file)) { 123 err = -errno; 124 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n", 125 errno); 126 close(fd); 127 return err; 128 } 129 close(fd); 130 131 fd = os_create_unix_socket(file, sizeof(file), 1); 132 if (fd < 0) { 133 printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, " 134 "errno = %d\n", -fd); 135 return fd; 136 } 137 138 sprintf(title, data->title, data->device); 139 pid = run_helper(NULL, NULL, argv); 140 if (pid < 0) { 141 err = pid; 142 printk(UM_KERN_ERR "xterm_open : run_helper failed, " 143 "errno = %d\n", -err); 144 goto out_close1; 145 } 146 147 err = os_set_fd_block(fd, 0); 148 if (err < 0) { 149 printk(UM_KERN_ERR "xterm_open : failed to set descriptor " 150 "non-blocking, err = %d\n", -err); 151 goto out_kill; 152 } 153 154 data->chan_fd = fd; 155 new = xterm_fd(fd, &data->helper_pid); 156 if (new < 0) { 157 err = new; 158 printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n", 159 -err); 160 goto out_kill; 161 } 162 163 err = os_set_fd_block(new, 0); 164 if (err) { 165 printk(UM_KERN_ERR "xterm_open : failed to set xterm " 166 "descriptor non-blocking, err = %d\n", -err); 167 goto out_close2; 168 } 169 170 CATCH_EINTR(err = tcgetattr(new, &data->tt)); 171 if (err) { 172 new = err; 173 goto out_close2; 174 } 175 176 if (data->raw) { 177 err = raw(new); 178 if (err) { 179 new = err; 180 goto out_close2; 181 } 182 } 183 184 unlink(file); 185 data->pid = pid; 186 *dev_out = NULL; 187 188 return new; 189 190 out_close2: 191 close(new); 192 out_kill: 193 os_kill_process(pid, 1); 194 out_close1: 195 close(fd); 196 197 return err; 198} 199 200static void xterm_close(int fd, void *d) 201{ 202 struct xterm_chan *data = d; 203 204 if (data->pid != -1) 205 os_kill_process(data->pid, 1); 206 data->pid = -1; 207 208 if (data->helper_pid != -1) 209 os_kill_process(data->helper_pid, 0); 210 data->helper_pid = -1; 211 212 if (data->chan_fd != -1) 213 os_close_file(data->chan_fd); 214 os_close_file(fd); 215} 216 217const struct chan_ops xterm_ops = { 218 .type = "xterm", 219 .init = xterm_init, 220 .open = xterm_open, 221 .close = xterm_close, 222 .read = generic_read, 223 .write = generic_write, 224 .console_write = generic_console_write, 225 .window_size = generic_window_size, 226 .free = generic_free, 227 .winch = 1, 228};