File Index
Files and directories
Sign in
FILE

xterm.c

File preview with syntax highlighting.

linux-6.19.14/arch/um/drivers/xterm.c 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.