uml: DEBUG_SHIRQ fixes
[linux-2.6-block.git] / arch / um / drivers / xterm.c
CommitLineData
1da177e4
LT
1/*
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"
1da177e4
LT
17#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 */
5e7672ec 33void *xterm_init(char *str, int device, const struct chan_opts *opts)
1da177e4
LT
34{
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){
b4fd310e 111 err = -errno;
1da177e4 112 printk("xterm_open : mkstemp failed, errno = %d\n", errno);
b4fd310e 113 return err;
1da177e4
LT
114 }
115
116 if(unlink(file)){
b4fd310e 117 err = -errno;
1da177e4 118 printk("xterm_open : unlink failed, errno = %d\n", errno);
b4fd310e 119 return err;
1da177e4
LT
120 }
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
1da177e4
LT
138 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
89df6bfc
EGM
154 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
1da177e4
LT
161 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
5e7672ec 201const struct chan_ops xterm_ops = {
1da177e4
LT
202 .type = "xterm",
203 .init = xterm_init,
204 .open = xterm_open,
205 .close = xterm_close,
206 .read = generic_read,
207 .write = generic_write,
fd9bc53b 208 .console_write = generic_console_write,
1da177e4
LT
209 .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 */