uml: fix stub address calculations
[linux-2.6-block.git] / arch / um / drivers / xterm.c
CommitLineData
1da177e4 1/*
63920f47 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
1da177e4
LT
3 * Licensed under the GPL
4 */
5
e99525f9 6#include <stddef.h>
1da177e4 7#include <stdlib.h>
63920f47 8#include <stdio.h>
1da177e4 9#include <unistd.h>
1da177e4 10#include <errno.h>
e99525f9 11#include <string.h>
1da177e4 12#include <termios.h>
1da177e4 13#include "chan_user.h"
e99525f9 14#include "kern_constants.h"
1da177e4 15#include "os.h"
e99525f9 16#include "um_malloc.h"
63920f47 17#include "user.h"
1da177e4
LT
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;
1da177e4
LT
27};
28
63920f47 29static void *xterm_init(char *str, int device, const struct chan_opts *opts)
1da177e4
LT
30{
31 struct xterm_chan *data;
32
e99525f9 33 data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
63920f47
JD
34 if (data == NULL)
35 return NULL;
36 *data = ((struct xterm_chan) { .pid = -1,
1da177e4 37 .helper_pid = -1,
63920f47 38 .device = device,
1da177e4 39 .title = opts->xterm_title,
63920f47
JD
40 .raw = opts->raw } );
41 return data;
1da177e4
LT
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, ',');
63920f47
JD
55 if (line == NULL)
56 return 0;
57
1da177e4 58 *line++ = '\0';
63920f47
JD
59 if (*line)
60 title_switch = line;
1da177e4
LT
61
62 line = strchr(line, ',');
63920f47
JD
63 if (line == NULL)
64 return 0;
65
1da177e4 66 *line++ = '\0';
63920f47
JD
67 if (*line)
68 exec_switch = line;
1da177e4 69
63920f47 70 return 0;
1da177e4
LT
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
63920f47 86static int xterm_open(int input, int output, int primary, void *d,
1da177e4
LT
87 char **dev_out)
88{
89 struct xterm_chan *data = d;
1da177e4
LT
90 int pid, fd, new, err;
91 char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
63920f47 92 char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
1da177e4
LT
93 "/usr/lib/uml/port-helper", "-uml-socket",
94 file, NULL };
95
63920f47 96 if (access(argv[4], X_OK) < 0)
1da177e4
LT
97 argv[4] = "port-helper";
98
99 /* Check that DISPLAY is set, this doesn't guarantee the xterm
100 * will work but w/o it we can be pretty sure it won't. */
63920f47
JD
101 if (getenv("DISPLAY") == NULL) {
102 printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
1da177e4
LT
103 return -ENODEV;
104 }
105
63920f47
JD
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 */
1da177e4 112 fd = mkstemp(file);
63920f47 113 if (fd < 0) {
b4fd310e 114 err = -errno;
63920f47
JD
115 printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
116 errno);
b4fd310e 117 return err;
1da177e4
LT
118 }
119
63920f47 120 if (unlink(file)) {
b4fd310e 121 err = -errno;
63920f47
JD
122 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
123 errno);
b4fd310e 124 return err;
1da177e4 125 }
63920f47 126 close(fd);
1da177e4
LT
127
128 fd = os_create_unix_socket(file, sizeof(file), 1);
63920f47
JD
129 if (fd < 0) {
130 printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
131 "errno = %d\n", -fd);
132 return fd;
1da177e4
LT
133 }
134
135 sprintf(title, data->title, data->device);
c4399016 136 pid = run_helper(NULL, NULL, argv);
63920f47
JD
137 if (pid < 0) {
138 err = pid;
139 printk(UM_KERN_ERR "xterm_open : run_helper failed, "
140 "errno = %d\n", -err);
141 goto out_close1;
1da177e4
LT
142 }
143
63920f47
JD
144 err = os_set_fd_block(fd, 0);
145 if (err < 0) {
146 printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
147 "non-blocking, err = %d\n", -err);
148 goto out_kill;
1da177e4 149 }
63920f47
JD
150
151 new = xterm_fd(fd, &data->helper_pid);
152 if (new < 0) {
153 err = new;
154 printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
155 -err);
156 goto out_kill;
1da177e4
LT
157 }
158
89df6bfc
EGM
159 err = os_set_fd_block(new, 0);
160 if (err) {
63920f47
JD
161 printk(UM_KERN_ERR "xterm_open : failed to set xterm "
162 "descriptor non-blocking, err = %d\n", -err);
163 goto out_close2;
89df6bfc
EGM
164 }
165
1da177e4 166 CATCH_EINTR(err = tcgetattr(new, &data->tt));
63920f47 167 if (err) {
1da177e4 168 new = err;
63920f47 169 goto out_close2;
1da177e4
LT
170 }
171
63920f47 172 if (data->raw) {
1da177e4 173 err = raw(new);
63920f47 174 if (err) {
1da177e4 175 new = err;
63920f47 176 goto out_close2;
1da177e4
LT
177 }
178 }
179
63920f47 180 unlink(file);
1da177e4
LT
181 data->pid = pid;
182 *dev_out = NULL;
63920f47
JD
183
184 return new;
185
186 out_close2:
187 close(new);
188 out_kill:
189 os_kill_process(pid, 1);
190 out_close1:
191 close(fd);
192
193 return err;
1da177e4
LT
194}
195
63920f47 196static void xterm_close(int fd, void *d)
1da177e4
LT
197{
198 struct xterm_chan *data = d;
199
63920f47 200 if (data->pid != -1)
1da177e4
LT
201 os_kill_process(data->pid, 1);
202 data->pid = -1;
63920f47
JD
203
204 if (data->helper_pid != -1)
1da177e4
LT
205 os_kill_process(data->helper_pid, 0);
206 data->helper_pid = -1;
63920f47 207
1da177e4
LT
208 os_close_file(fd);
209}
210
5e7672ec 211const struct chan_ops xterm_ops = {
1da177e4
LT
212 .type = "xterm",
213 .init = xterm_init,
214 .open = xterm_open,
215 .close = xterm_close,
216 .read = generic_read,
217 .write = generic_write,
fd9bc53b 218 .console_write = generic_console_write,
1da177e4 219 .window_size = generic_window_size,
e99525f9 220 .free = generic_free,
1da177e4
LT
221 .winch = 1,
222};