Merge tag 'boards-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[linux-2.6-block.git] / arch / um / drivers / xterm.c
CommitLineData
cb8fa61c 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>
63920f47 7#include <stdio.h>
cb8fa61c 8#include <stdlib.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"
37185b33
AV
14#include <os.h>
15#include <um_malloc.h>
1da177e4
LT
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;
1da177e4
LT
25};
26
63920f47 27static void *xterm_init(char *str, int device, const struct chan_opts *opts)
1da177e4
LT
28{
29 struct xterm_chan *data;
30
43f5b308 31 data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
63920f47
JD
32 if (data == NULL)
33 return NULL;
34 *data = ((struct xterm_chan) { .pid = -1,
1da177e4 35 .helper_pid = -1,
63920f47 36 .device = device,
1da177e4 37 .title = opts->xterm_title,
63920f47
JD
38 .raw = opts->raw } );
39 return data;
1da177e4
LT
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, ',');
63920f47
JD
53 if (line == NULL)
54 return 0;
55
1da177e4 56 *line++ = '\0';
63920f47
JD
57 if (*line)
58 title_switch = line;
1da177e4
LT
59
60 line = strchr(line, ',');
63920f47
JD
61 if (line == NULL)
62 return 0;
63
1da177e4 64 *line++ = '\0';
63920f47
JD
65 if (*line)
66 exec_switch = line;
1da177e4 67
63920f47 68 return 0;
1da177e4
LT
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
63920f47 84static int xterm_open(int input, int output, int primary, void *d,
1da177e4
LT
85 char **dev_out)
86{
87 struct xterm_chan *data = d;
1da177e4
LT
88 int pid, fd, new, err;
89 char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
63920f47 90 char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
0ce451ac 91 OS_LIB_PATH "/uml/port-helper", "-uml-socket",
1da177e4
LT
92 file, NULL };
93
63920f47 94 if (access(argv[4], X_OK) < 0)
1da177e4
LT
95 argv[4] = "port-helper";
96
cb8fa61c
JD
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 */
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);
b40997b8 124 close(fd);
b4fd310e 125 return err;
1da177e4 126 }
63920f47 127 close(fd);
1da177e4
LT
128
129 fd = os_create_unix_socket(file, sizeof(file), 1);
63920f47
JD
130 if (fd < 0) {
131 printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
132 "errno = %d\n", -fd);
133 return fd;
1da177e4
LT
134 }
135
136 sprintf(title, data->title, data->device);
c4399016 137 pid = run_helper(NULL, NULL, argv);
63920f47
JD
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;
1da177e4
LT
143 }
144
63920f47
JD
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;
1da177e4 150 }
63920f47
JD
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;
1da177e4
LT
158 }
159
89df6bfc
EGM
160 err = os_set_fd_block(new, 0);
161 if (err) {
63920f47
JD
162 printk(UM_KERN_ERR "xterm_open : failed to set xterm "
163 "descriptor non-blocking, err = %d\n", -err);
164 goto out_close2;
89df6bfc
EGM
165 }
166
1da177e4 167 CATCH_EINTR(err = tcgetattr(new, &data->tt));
63920f47 168 if (err) {
1da177e4 169 new = err;
63920f47 170 goto out_close2;
1da177e4
LT
171 }
172
63920f47 173 if (data->raw) {
1da177e4 174 err = raw(new);
63920f47 175 if (err) {
1da177e4 176 new = err;
63920f47 177 goto out_close2;
1da177e4
LT
178 }
179 }
180
63920f47 181 unlink(file);
1da177e4
LT
182 data->pid = pid;
183 *dev_out = NULL;
63920f47
JD
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;
1da177e4
LT
195}
196
63920f47 197static void xterm_close(int fd, void *d)
1da177e4
LT
198{
199 struct xterm_chan *data = d;
cb8fa61c 200
63920f47 201 if (data->pid != -1)
1da177e4
LT
202 os_kill_process(data->pid, 1);
203 data->pid = -1;
63920f47
JD
204
205 if (data->helper_pid != -1)
1da177e4
LT
206 os_kill_process(data->helper_pid, 0);
207 data->helper_pid = -1;
63920f47 208
1da177e4
LT
209 os_close_file(fd);
210}
211
5e7672ec 212const struct chan_ops xterm_ops = {
1da177e4
LT
213 .type = "xterm",
214 .init = xterm_init,
215 .open = xterm_open,
216 .close = xterm_close,
217 .read = generic_read,
218 .write = generic_write,
fd9bc53b 219 .console_write = generic_console_write,
1da177e4 220 .window_size = generic_window_size,
e99525f9 221 .free = generic_free,
1da177e4
LT
222 .winch = 1,
223};