Linux Audio

Check our new training course

Loading...
v6.2
  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,-x'.\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	/*
101	 * Check that DISPLAY is set, this doesn't guarantee the xterm
102	 * will work but w/o it we can be pretty sure it won't.
103	 */
104	if (getenv("DISPLAY") == NULL) {
105		printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
106		return -ENODEV;
107	}
108
109	/*
110	 * This business of getting a descriptor to a temp file,
111	 * deleting the file and closing the descriptor is just to get
112	 * a known-unused name for the Unix socket that we really
113	 * want.
114	 */
115	fd = mkstemp(file);
116	if (fd < 0) {
117		err = -errno;
118		printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
119		       errno);
120		return err;
121	}
122
123	if (unlink(file)) {
124		err = -errno;
125		printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
126		       errno);
127		close(fd);
128		return err;
129	}
130	close(fd);
131
132	fd = os_create_unix_socket(file, sizeof(file), 1);
133	if (fd < 0) {
134		printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
135		       "errno = %d\n", -fd);
136		return fd;
137	}
138
139	sprintf(title, data->title, data->device);
140	pid = run_helper(NULL, NULL, argv);
141	if (pid < 0) {
142		err = pid;
143		printk(UM_KERN_ERR "xterm_open : run_helper failed, "
144		       "errno = %d\n", -err);
145		goto out_close1;
146	}
147
148	err = os_set_fd_block(fd, 0);
149	if (err < 0) {
150		printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
151		       "non-blocking, err = %d\n", -err);
152		goto out_kill;
153	}
154
155	data->chan_fd = fd;
156	new = xterm_fd(fd, &data->helper_pid);
157	if (new < 0) {
158		err = new;
159		printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
160		       -err);
161		goto out_kill;
162	}
163
164	err = os_set_fd_block(new, 0);
165	if (err) {
166		printk(UM_KERN_ERR "xterm_open : failed to set xterm "
167		       "descriptor non-blocking, err = %d\n", -err);
168		goto out_close2;
169	}
170
171	CATCH_EINTR(err = tcgetattr(new, &data->tt));
172	if (err) {
173		new = err;
174		goto out_close2;
175	}
176
177	if (data->raw) {
178		err = raw(new);
179		if (err) {
180			new = err;
181			goto out_close2;
182		}
183	}
184
185	unlink(file);
186	data->pid = pid;
187	*dev_out = NULL;
188
189	return new;
190
191 out_close2:
192	close(new);
193 out_kill:
194	os_kill_process(pid, 1);
195 out_close1:
196	close(fd);
197
198	return err;
199}
200
201static void xterm_close(int fd, void *d)
202{
203	struct xterm_chan *data = d;
204
205	if (data->pid != -1)
206		os_kill_process(data->pid, 1);
207	data->pid = -1;
208
209	if (data->helper_pid != -1)
210		os_kill_process(data->helper_pid, 0);
211	data->helper_pid = -1;
212
213	if (data->chan_fd != -1)
214		os_close_file(data->chan_fd);
215	os_close_file(fd);
216}
217
218const struct chan_ops xterm_ops = {
219	.type		= "xterm",
220	.init		= xterm_init,
221	.open		= xterm_open,
222	.close		= xterm_close,
223	.read		= generic_read,
224	.write		= generic_write,
225	.console_write	= generic_console_write,
226	.window_size	= generic_window_size,
227	.free		= generic_free,
228	.winch		= 1,
229};
v5.14.15
  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};