Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[GitHub/mt8127/android_kernel_alcatel_ttab.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"
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
43f5b308 33 data = uml_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
cb8fa61c
JD
99 /*
100 * Check that DISPLAY is set, this doesn't guarantee the xterm
101 * will work but w/o it we can be pretty sure it won't.
102 */
63920f47
JD
103 if (getenv("DISPLAY") == NULL) {
104 printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n");
1da177e4
LT
105 return -ENODEV;
106 }
107
63920f47
JD
108 /*
109 * This business of getting a descriptor to a temp file,
110 * deleting the file and closing the descriptor is just to get
111 * a known-unused name for the Unix socket that we really
112 * want.
113 */
1da177e4 114 fd = mkstemp(file);
63920f47 115 if (fd < 0) {
b4fd310e 116 err = -errno;
63920f47
JD
117 printk(UM_KERN_ERR "xterm_open : mkstemp failed, errno = %d\n",
118 errno);
b4fd310e 119 return err;
1da177e4
LT
120 }
121
63920f47 122 if (unlink(file)) {
b4fd310e 123 err = -errno;
63920f47
JD
124 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
125 errno);
b4fd310e 126 return err;
1da177e4 127 }
63920f47 128 close(fd);
1da177e4
LT
129
130 fd = os_create_unix_socket(file, sizeof(file), 1);
63920f47
JD
131 if (fd < 0) {
132 printk(UM_KERN_ERR "xterm_open : create_unix_socket failed, "
133 "errno = %d\n", -fd);
134 return fd;
1da177e4
LT
135 }
136
137 sprintf(title, data->title, data->device);
c4399016 138 pid = run_helper(NULL, NULL, argv);
63920f47
JD
139 if (pid < 0) {
140 err = pid;
141 printk(UM_KERN_ERR "xterm_open : run_helper failed, "
142 "errno = %d\n", -err);
143 goto out_close1;
1da177e4
LT
144 }
145
63920f47
JD
146 err = os_set_fd_block(fd, 0);
147 if (err < 0) {
148 printk(UM_KERN_ERR "xterm_open : failed to set descriptor "
149 "non-blocking, err = %d\n", -err);
150 goto out_kill;
1da177e4 151 }
63920f47
JD
152
153 new = xterm_fd(fd, &data->helper_pid);
154 if (new < 0) {
155 err = new;
156 printk(UM_KERN_ERR "xterm_open : os_rcv_fd failed, err = %d\n",
157 -err);
158 goto out_kill;
1da177e4
LT
159 }
160
89df6bfc
EGM
161 err = os_set_fd_block(new, 0);
162 if (err) {
63920f47
JD
163 printk(UM_KERN_ERR "xterm_open : failed to set xterm "
164 "descriptor non-blocking, err = %d\n", -err);
165 goto out_close2;
89df6bfc
EGM
166 }
167
1da177e4 168 CATCH_EINTR(err = tcgetattr(new, &data->tt));
63920f47 169 if (err) {
1da177e4 170 new = err;
63920f47 171 goto out_close2;
1da177e4
LT
172 }
173
63920f47 174 if (data->raw) {
1da177e4 175 err = raw(new);
63920f47 176 if (err) {
1da177e4 177 new = err;
63920f47 178 goto out_close2;
1da177e4
LT
179 }
180 }
181
63920f47 182 unlink(file);
1da177e4
LT
183 data->pid = pid;
184 *dev_out = NULL;
63920f47
JD
185
186 return new;
187
188 out_close2:
189 close(new);
190 out_kill:
191 os_kill_process(pid, 1);
192 out_close1:
193 close(fd);
194
195 return err;
1da177e4
LT
196}
197
63920f47 198static void xterm_close(int fd, void *d)
1da177e4
LT
199{
200 struct xterm_chan *data = d;
cb8fa61c 201
63920f47 202 if (data->pid != -1)
1da177e4
LT
203 os_kill_process(data->pid, 1);
204 data->pid = -1;
63920f47
JD
205
206 if (data->helper_pid != -1)
1da177e4
LT
207 os_kill_process(data->helper_pid, 0);
208 data->helper_pid = -1;
63920f47 209
1da177e4
LT
210 os_close_file(fd);
211}
212
5e7672ec 213const struct chan_ops xterm_ops = {
1da177e4
LT
214 .type = "xterm",
215 .init = xterm_init,
216 .open = xterm_open,
217 .close = xterm_close,
218 .read = generic_read,
219 .write = generic_write,
fd9bc53b 220 .console_write = generic_console_write,
1da177e4 221 .window_size = generic_window_size,
e99525f9 222 .free = generic_free,
1da177e4
LT
223 .winch = 1,
224};