blob: 850221d9b4c953306d87817bfd455551dc4aee67 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <unistd.h>
9#include <string.h>
10#include <errno.h>
11#include <termios.h>
12#include <signal.h>
13#include <sched.h>
14#include <sys/socket.h>
15#include "kern_util.h"
16#include "chan_user.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include "user_util.h"
18#include "user.h"
19#include "os.h"
20#include "xterm.h"
21
22struct xterm_chan {
23 int pid;
24 int helper_pid;
25 char *title;
26 int device;
27 int raw;
28 struct termios tt;
29 unsigned long stack;
30 int direct_rcv;
31};
32
33/* Not static because it's called directly by the tt mode gdb code */
Jeff Dike5e7672e2006-09-27 01:50:33 -070034void *xterm_init(char *str, int device, const struct chan_opts *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035{
36 struct xterm_chan *data;
37
38 data = malloc(sizeof(*data));
39 if(data == NULL) return(NULL);
40 *data = ((struct xterm_chan) { .pid = -1,
41 .helper_pid = -1,
42 .device = device,
43 .title = opts->xterm_title,
44 .raw = opts->raw,
45 .stack = opts->tramp_stack,
46 .direct_rcv = !opts->in_kernel } );
47 return(data);
48}
49
50/* Only changed by xterm_setup, which is a setup */
51static char *terminal_emulator = "xterm";
52static char *title_switch = "-T";
53static char *exec_switch = "-e";
54
55static int __init xterm_setup(char *line, int *add)
56{
57 *add = 0;
58 terminal_emulator = line;
59
60 line = strchr(line, ',');
61 if(line == NULL) return(0);
62 *line++ = '\0';
63 if(*line) title_switch = line;
64
65 line = strchr(line, ',');
66 if(line == NULL) return(0);
67 *line++ = '\0';
68 if(*line) 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
86/* XXX This badly needs some cleaning up in the error paths
87 * Not static because it's called directly by the tt mode gdb code
88 */
89int xterm_open(int input, int output, int primary, void *d,
90 char **dev_out)
91{
92 struct xterm_chan *data = d;
93 unsigned long stack;
94 int pid, fd, new, err;
95 char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
96 char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
97 "/usr/lib/uml/port-helper", "-uml-socket",
98 file, NULL };
99
100 if(os_access(argv[4], OS_ACC_X_OK) < 0)
101 argv[4] = "port-helper";
102
103 /* Check that DISPLAY is set, this doesn't guarantee the xterm
104 * will work but w/o it we can be pretty sure it won't. */
105 if (!getenv("DISPLAY")) {
106 printk("xterm_open: $DISPLAY not set.\n");
107 return -ENODEV;
108 }
109
110 fd = mkstemp(file);
111 if(fd < 0){
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700112 err = -errno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 printk("xterm_open : mkstemp failed, errno = %d\n", errno);
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700114 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 }
116
117 if(unlink(file)){
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700118 err = -errno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 printk("xterm_open : unlink failed, errno = %d\n", errno);
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700120 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 }
122 os_close_file(fd);
123
124 fd = os_create_unix_socket(file, sizeof(file), 1);
125 if(fd < 0){
126 printk("xterm_open : create_unix_socket failed, errno = %d\n",
127 -fd);
128 return(fd);
129 }
130
131 sprintf(title, data->title, data->device);
132 stack = data->stack;
133 pid = run_helper(NULL, NULL, argv, &stack);
134 if(pid < 0){
135 printk("xterm_open : run_helper failed, errno = %d\n", -pid);
136 return(pid);
137 }
138
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 if (data->direct_rcv) {
140 new = os_rcv_fd(fd, &data->helper_pid);
141 } else {
142 err = os_set_fd_block(fd, 0);
143 if(err < 0){
144 printk("xterm_open : failed to set descriptor "
145 "non-blocking, err = %d\n", -err);
146 return(err);
147 }
148 new = xterm_fd(fd, &data->helper_pid);
149 }
150 if(new < 0){
151 printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
152 goto out;
153 }
154
155 CATCH_EINTR(err = tcgetattr(new, &data->tt));
156 if(err){
157 new = err;
158 goto out;
159 }
160
161 if(data->raw){
162 err = raw(new);
163 if(err){
164 new = err;
165 goto out;
166 }
167 }
168
169 data->pid = pid;
170 *dev_out = NULL;
171 out:
172 unlink(file);
173 return(new);
174}
175
176/* Not static because it's called directly by the tt mode gdb code */
177void xterm_close(int fd, void *d)
178{
179 struct xterm_chan *data = d;
180
181 if(data->pid != -1)
182 os_kill_process(data->pid, 1);
183 data->pid = -1;
184 if(data->helper_pid != -1)
185 os_kill_process(data->helper_pid, 0);
186 data->helper_pid = -1;
187 os_close_file(fd);
188}
189
190static void xterm_free(void *d)
191{
192 free(d);
193}
194
Jeff Dike5e7672e2006-09-27 01:50:33 -0700195const struct chan_ops xterm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 .type = "xterm",
197 .init = xterm_init,
198 .open = xterm_open,
199 .close = xterm_close,
200 .read = generic_read,
201 .write = generic_write,
Paolo 'Blaisorblade' Giarrussofd9bc532005-11-13 16:07:10 -0800202 .console_write = generic_console_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 .window_size = generic_window_size,
204 .free = xterm_free,
205 .winch = 1,
206};
207
208/*
209 * Overrides for Emacs so that we follow Linus's tabbing style.
210 * Emacs will notice this stuff at the end of the file and automatically
211 * adjust the settings for this buffer only. This must remain at the end
212 * of the file.
213 * ---------------------------------------------------------------------------
214 * Local variables:
215 * c-file-style: "linux"
216 * End:
217 */