blob: fe238e03a300dcaaccc22f1e94c35dbb27988448 [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.h"
18#include "os.h"
19#include "xterm.h"
20
21struct xterm_chan {
22 int pid;
23 int helper_pid;
24 char *title;
25 int device;
26 int raw;
27 struct termios tt;
28 unsigned long stack;
29 int direct_rcv;
30};
31
32/* Not static because it's called directly by the tt mode gdb code */
Jeff Dike5e7672e2006-09-27 01:50:33 -070033void *xterm_init(char *str, int device, const struct chan_opts *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -070034{
35 struct xterm_chan *data;
36
37 data = malloc(sizeof(*data));
38 if(data == NULL) return(NULL);
39 *data = ((struct xterm_chan) { .pid = -1,
40 .helper_pid = -1,
41 .device = device,
42 .title = opts->xterm_title,
43 .raw = opts->raw,
44 .stack = opts->tramp_stack,
45 .direct_rcv = !opts->in_kernel } );
46 return(data);
47}
48
49/* Only changed by xterm_setup, which is a setup */
50static char *terminal_emulator = "xterm";
51static char *title_switch = "-T";
52static char *exec_switch = "-e";
53
54static int __init xterm_setup(char *line, int *add)
55{
56 *add = 0;
57 terminal_emulator = line;
58
59 line = strchr(line, ',');
60 if(line == NULL) return(0);
61 *line++ = '\0';
62 if(*line) title_switch = line;
63
64 line = strchr(line, ',');
65 if(line == NULL) return(0);
66 *line++ = '\0';
67 if(*line) exec_switch = line;
68
69 return(0);
70}
71
72__uml_setup("xterm=", xterm_setup,
73"xterm=<terminal emulator>,<title switch>,<exec switch>\n"
74" Specifies an alternate terminal emulator to use for the debugger,\n"
75" consoles, and serial lines when they are attached to the xterm channel.\n"
76" The values are the terminal emulator binary, the switch it uses to set\n"
77" its title, and the switch it uses to execute a subprocess,\n"
78" respectively. The title switch must have the form '<switch> title',\n"
79" not '<switch>=title'. Similarly, the exec switch must have the form\n"
80" '<switch> command arg1 arg2 ...'.\n"
81" The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n"
82" are 'xterm=gnome-terminal,-t,-x'.\n\n"
83);
84
85/* XXX This badly needs some cleaning up in the error paths
86 * Not static because it's called directly by the tt mode gdb code
87 */
88int xterm_open(int input, int output, int primary, void *d,
89 char **dev_out)
90{
91 struct xterm_chan *data = d;
92 unsigned long stack;
93 int pid, fd, new, err;
94 char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
95 char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
96 "/usr/lib/uml/port-helper", "-uml-socket",
97 file, NULL };
98
99 if(os_access(argv[4], OS_ACC_X_OK) < 0)
100 argv[4] = "port-helper";
101
102 /* Check that DISPLAY is set, this doesn't guarantee the xterm
103 * will work but w/o it we can be pretty sure it won't. */
104 if (!getenv("DISPLAY")) {
105 printk("xterm_open: $DISPLAY not set.\n");
106 return -ENODEV;
107 }
108
109 fd = mkstemp(file);
110 if(fd < 0){
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700111 err = -errno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 printk("xterm_open : mkstemp failed, errno = %d\n", errno);
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700113 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 }
115
116 if(unlink(file)){
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700117 err = -errno;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 printk("xterm_open : unlink failed, errno = %d\n", errno);
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700119 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 }
121 os_close_file(fd);
122
123 fd = os_create_unix_socket(file, sizeof(file), 1);
124 if(fd < 0){
125 printk("xterm_open : create_unix_socket failed, errno = %d\n",
126 -fd);
127 return(fd);
128 }
129
130 sprintf(title, data->title, data->device);
131 stack = data->stack;
132 pid = run_helper(NULL, NULL, argv, &stack);
133 if(pid < 0){
134 printk("xterm_open : run_helper failed, errno = %d\n", -pid);
135 return(pid);
136 }
137
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 if (data->direct_rcv) {
139 new = os_rcv_fd(fd, &data->helper_pid);
140 } else {
141 err = os_set_fd_block(fd, 0);
142 if(err < 0){
143 printk("xterm_open : failed to set descriptor "
144 "non-blocking, err = %d\n", -err);
145 return(err);
146 }
147 new = xterm_fd(fd, &data->helper_pid);
148 }
149 if(new < 0){
150 printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
151 goto out;
152 }
153
Eduard-Gabriel Munteanu89df6bf2007-07-15 23:38:51 -0700154 err = os_set_fd_block(new, 0);
155 if (err) {
156 printk("xterm_open : failed to set xterm descriptor "
157 "non-blocking, err = %d\n", -err);
158 goto out;
159 }
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 CATCH_EINTR(err = tcgetattr(new, &data->tt));
162 if(err){
163 new = err;
164 goto out;
165 }
166
167 if(data->raw){
168 err = raw(new);
169 if(err){
170 new = err;
171 goto out;
172 }
173 }
174
175 data->pid = pid;
176 *dev_out = NULL;
177 out:
178 unlink(file);
179 return(new);
180}
181
182/* Not static because it's called directly by the tt mode gdb code */
183void xterm_close(int fd, void *d)
184{
185 struct xterm_chan *data = d;
186
187 if(data->pid != -1)
188 os_kill_process(data->pid, 1);
189 data->pid = -1;
190 if(data->helper_pid != -1)
191 os_kill_process(data->helper_pid, 0);
192 data->helper_pid = -1;
193 os_close_file(fd);
194}
195
196static void xterm_free(void *d)
197{
198 free(d);
199}
200
Jeff Dike5e7672e2006-09-27 01:50:33 -0700201const struct chan_ops xterm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 .type = "xterm",
203 .init = xterm_init,
204 .open = xterm_open,
205 .close = xterm_close,
206 .read = generic_read,
207 .write = generic_write,
Paolo 'Blaisorblade' Giarrussofd9bc532005-11-13 16:07:10 -0800208 .console_write = generic_console_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 .window_size = generic_window_size,
210 .free = xterm_free,
211 .winch = 1,
212};
213
214/*
215 * Overrides for Emacs so that we follow Linus's tabbing style.
216 * Emacs will notice this stuff at the end of the file and automatically
217 * adjust the settings for this buffer only. This must remain at the end
218 * of the file.
219 * ---------------------------------------------------------------------------
220 * Local variables:
221 * c-file-style: "linux"
222 * End:
223 */