FILE
xterm.c
File preview with syntax highlighting.
linux-6.19.14/arch/um/drivers/xterm.c
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 = CONFIG_XTERM_CHAN_DEFAULT_EMULATOR; 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=" CONFIG_XTERM_CHAN_DEFAULT_EMULATOR 83 ",-T,-e'.\n" 84" Values for gnome-terminal are 'xterm=gnome-terminal,-t,--'.\n\n" 85); 86 87static int xterm_open(int input, int output, int primary, void *d, 88 char **dev_out) 89{ 90 struct xterm_chan *data = d; 91 int pid, fd, new, err; 92 char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; 93 char *argv[] = { terminal_emulator, title_switch, title, exec_switch, 94 OS_LIB_PATH "/uml/port-helper", "-uml-socket", 95 file, NULL }; 96 97 if (access(argv[4], X_OK) < 0) 98 argv[4] = "port-helper"; 99 100 /* Ensure we are running on Xorg or Wayland. */ 101 if (!getenv("DISPLAY") && !getenv("WAYLAND_DISPLAY")) { 102 printk(UM_KERN_ERR "xterm_open : neither $DISPLAY nor $WAYLAND_DISPLAY is set.\n"); 103 return -ENODEV; 104 } 105 106 /* 107 * This business of getting a descriptor to a temp file, 108 * deleting the file and closing the descriptor is just to get 109 * a known-unused name for the Unix socket that we really 110 * want. 111 */ 112 fd = mkstemp(file); 113 if (fd < 0) { 114 err = -errno; 115 printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n", 116 errno); 117 return err; 118 } 119 120 if (unlink(file)) { 121 err = -errno; 122 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n", 123 errno); 124 close(fd); 125 return err; 126 } 127 close(fd); 128 129 fd = os_create_unix_socket(file, sizeof(file), 1); 130 if (fd < 0) { 131 printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, " 132 "errno = %d\n", -fd); 133 return fd; 134 } 135 136 sprintf(title, data->title, data->device); 137 pid = run_helper(NULL, NULL, argv); 138 if (pid < 0) { 139 err = pid; 140 printk(UM_KERN_ERR "xterm_open : run_helper failed, " 141 "errno = %d\n", -err); 142 goto out_close1; 143 } 144 145 err = os_set_fd_block(fd, 0); 146 if (err < 0) { 147 printk(UM_KERN_ERR "xterm_open : failed to set descriptor " 148 "non-blocking, err = %d\n", -err); 149 goto out_kill; 150 } 151 152 data->chan_fd = fd; 153 new = xterm_fd(fd, &data->helper_pid); 154 if (new < 0) { 155 err = new; 156 printk(UM_KERN_ERR "xterm_open : xterm_fd failed, err = %d\n", 157 -err); 158 goto out_kill; 159 } 160 161 err = os_set_fd_block(new, 0); 162 if (err) { 163 printk(UM_KERN_ERR "xterm_open : failed to set xterm " 164 "descriptor non-blocking, err = %d\n", -err); 165 goto out_close2; 166 } 167 168 CATCH_EINTR(err = tcgetattr(new, &data->tt)); 169 if (err) { 170 new = err; 171 goto out_close2; 172 } 173 174 if (data->raw) { 175 err = raw(new); 176 if (err) { 177 new = err; 178 goto out_close2; 179 } 180 } 181 182 unlink(file); 183 data->pid = pid; 184 *dev_out = NULL; 185 186 return new; 187 188 out_close2: 189 close(new); 190 out_kill: 191 os_kill_process(pid, 1); 192 out_close1: 193 close(fd); 194 195 return err; 196} 197 198static void xterm_close(int fd, void *d) 199{ 200 struct xterm_chan *data = d; 201 202 if (data->pid != -1) 203 os_kill_process(data->pid, 1); 204 data->pid = -1; 205 206 if (data->helper_pid != -1) 207 os_kill_process(data->helper_pid, 0); 208 data->helper_pid = -1; 209 210 if (data->chan_fd != -1) 211 os_close_file(data->chan_fd); 212 os_close_file(fd); 213} 214 215const struct chan_ops xterm_ops = { 216 .type = "xterm", 217 .init = xterm_init, 218 .open = xterm_open, 219 .close = xterm_close, 220 .read = generic_read, 221 .write = generic_write, 222 .console_write = generic_console_write, 223 .window_size = generic_window_size, 224 .free = generic_free, 225 .winch = 1, 226};
~/
Read-only file preview.