Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  3 * Licensed under the GPL
  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	char *title;
 22	int device;
 23	int raw;
 24	struct termios tt;
 25};
 26
 27static void *xterm_init(char *str, int device, const struct chan_opts *opts)
 28{
 29	struct xterm_chan *data;
 30
 31	data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
 32	if (data == NULL)
 33		return NULL;
 34	*data = ((struct xterm_chan) { .pid 		= -1,
 35				       .helper_pid 	= -1,
 36				       .device 		= device,
 37				       .title 		= opts->xterm_title,
 38				       .raw  		= opts->raw } );
 39	return data;
 40}
 41
 42/* Only changed by xterm_setup, which is a setup */
 43static char *terminal_emulator = "xterm";
 44static char *title_switch = "-T";
 45static char *exec_switch = "-e";
 46
 47static int __init xterm_setup(char *line, int *add)
 48{
 49	*add = 0;
 50	terminal_emulator = line;
 51
 52	line = strchr(line, ',');
 53	if (line == NULL)
 54		return 0;
 55
 56	*line++ = '\0';
 57	if (*line)
 58		title_switch = line;
 59
 60	line = strchr(line, ',');
 61	if (line == NULL)
 62		return 0;
 63
 64	*line++ = '\0';
 65	if (*line)
 66		exec_switch = line;
 67
 68	return 0;
 69}
 70
 71__uml_setup("xterm=", xterm_setup,
 72"xterm=<terminal emulator>,<title switch>,<exec switch>\n"
 73"    Specifies an alternate terminal emulator to use for the debugger,\n"
 74"    consoles, and serial lines when they are attached to the xterm channel.\n"
 75"    The values are the terminal emulator binary, the switch it uses to set\n"
 76"    its title, and the switch it uses to execute a subprocess,\n"
 77"    respectively.  The title switch must have the form '<switch> title',\n"
 78"    not '<switch>=title'.  Similarly, the exec switch must have the form\n"
 79"    '<switch> command arg1 arg2 ...'.\n"
 80"    The default values are 'xterm=xterm,-T,-e'.  Values for gnome-terminal\n"
 81"    are 'xterm=gnome-terminal,-t,-x'.\n\n"
 82);
 83
 84static int xterm_open(int input, int output, int primary, void *d,
 85		      char **dev_out)
 86{
 87	struct xterm_chan *data = d;
 88	int pid, fd, new, err;
 89	char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
 90	char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
 91			 OS_LIB_PATH "/uml/port-helper", "-uml-socket",
 92			 file, NULL };
 93
 94	if (access(argv[4], X_OK) < 0)
 95		argv[4] = "port-helper";
 96
 97	/*
 98	 * Check that DISPLAY is set, this doesn't guarantee the xterm
 99	 * will work but w/o it we can be pretty sure it won't.
100	 */
101	if (getenv("DISPLAY") == NULL) {
102		printk(UM_KERN_ERR "xterm_open: $DISPLAY not 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	new = xterm_fd(fd, &data->helper_pid);
153	if (new < 0) {
154		err = new;
155		printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
156		       -err);
157		goto out_kill;
158	}
159
160	err = os_set_fd_block(new, 0);
161	if (err) {
162		printk(UM_KERN_ERR "xterm_open : failed to set xterm "
163		       "descriptor non-blocking, err = %d\n", -err);
164		goto out_close2;
165	}
166
167	CATCH_EINTR(err = tcgetattr(new, &data->tt));
168	if (err) {
169		new = err;
170		goto out_close2;
171	}
172
173	if (data->raw) {
174		err = raw(new);
175		if (err) {
176			new = err;
177			goto out_close2;
178		}
179	}
180
181	unlink(file);
182	data->pid = pid;
183	*dev_out = NULL;
184
185	return new;
186
187 out_close2:
188	close(new);
189 out_kill:
190	os_kill_process(pid, 1);
191 out_close1:
192	close(fd);
193
194	return err;
195}
196
197static void xterm_close(int fd, void *d)
198{
199	struct xterm_chan *data = d;
200
201	if (data->pid != -1)
202		os_kill_process(data->pid, 1);
203	data->pid = -1;
204
205	if (data->helper_pid != -1)
206		os_kill_process(data->helper_pid, 0);
207	data->helper_pid = -1;
208
209	os_close_file(fd);
210}
211
212const struct chan_ops xterm_ops = {
213	.type		= "xterm",
214	.init		= xterm_init,
215	.open		= xterm_open,
216	.close		= xterm_close,
217	.read		= generic_read,
218	.write		= generic_write,
219	.console_write	= generic_console_write,
220	.window_size	= generic_window_size,
221	.free		= generic_free,
222	.winch		= 1,
223};
v3.1
  1/*
  2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  3 * Licensed under the GPL
  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 "kern_constants.h"
 15#include "os.h"
 16#include "um_malloc.h"
 17#include "user.h"
 18#include "xterm.h"
 19
 20struct xterm_chan {
 21	int pid;
 22	int helper_pid;
 23	char *title;
 24	int device;
 25	int raw;
 26	struct termios tt;
 27};
 28
 29static void *xterm_init(char *str, int device, const struct chan_opts *opts)
 30{
 31	struct xterm_chan *data;
 32
 33	data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
 34	if (data == NULL)
 35		return NULL;
 36	*data = ((struct xterm_chan) { .pid 		= -1,
 37				       .helper_pid 	= -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	new = xterm_fd(fd, &data->helper_pid);
155	if (new < 0) {
156		err = new;
157		printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
158		       -err);
159		goto out_kill;
160	}
161
162	err = os_set_fd_block(new, 0);
163	if (err) {
164		printk(UM_KERN_ERR "xterm_open : failed to set xterm "
165		       "descriptor non-blocking, err = %d\n", -err);
166		goto out_close2;
167	}
168
169	CATCH_EINTR(err = tcgetattr(new, &data->tt));
170	if (err) {
171		new = err;
172		goto out_close2;
173	}
174
175	if (data->raw) {
176		err = raw(new);
177		if (err) {
178			new = err;
179			goto out_close2;
180		}
181	}
182
183	unlink(file);
184	data->pid = pid;
185	*dev_out = NULL;
186
187	return new;
188
189 out_close2:
190	close(new);
191 out_kill:
192	os_kill_process(pid, 1);
193 out_close1:
194	close(fd);
195
196	return err;
197}
198
199static void xterm_close(int fd, void *d)
200{
201	struct xterm_chan *data = d;
202
203	if (data->pid != -1)
204		os_kill_process(data->pid, 1);
205	data->pid = -1;
206
207	if (data->helper_pid != -1)
208		os_kill_process(data->helper_pid, 0);
209	data->helper_pid = -1;
210
211	os_close_file(fd);
212}
213
214const struct chan_ops xterm_ops = {
215	.type		= "xterm",
216	.init		= xterm_init,
217	.open		= xterm_open,
218	.close		= xterm_close,
219	.read		= generic_read,
220	.write		= generic_write,
221	.console_write	= generic_console_write,
222	.window_size	= generic_window_size,
223	.free		= generic_free,
224	.winch		= 1,
225};