diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/drivers/xterm.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/um/drivers/xterm.c')
-rw-r--r-- | arch/um/drivers/xterm.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c new file mode 100644 index 000000000000..93dc1911363f --- /dev/null +++ b/arch/um/drivers/xterm.c | |||
@@ -0,0 +1,225 @@ | |||
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" | ||
17 | #include "helper.h" | ||
18 | #include "user_util.h" | ||
19 | #include "user.h" | ||
20 | #include "os.h" | ||
21 | #include "xterm.h" | ||
22 | |||
23 | struct xterm_chan { | ||
24 | int pid; | ||
25 | int helper_pid; | ||
26 | char *title; | ||
27 | int device; | ||
28 | int raw; | ||
29 | struct termios tt; | ||
30 | unsigned long stack; | ||
31 | int direct_rcv; | ||
32 | }; | ||
33 | |||
34 | /* Not static because it's called directly by the tt mode gdb code */ | ||
35 | void *xterm_init(char *str, int device, struct chan_opts *opts) | ||
36 | { | ||
37 | struct xterm_chan *data; | ||
38 | |||
39 | data = malloc(sizeof(*data)); | ||
40 | if(data == NULL) return(NULL); | ||
41 | *data = ((struct xterm_chan) { .pid = -1, | ||
42 | .helper_pid = -1, | ||
43 | .device = device, | ||
44 | .title = opts->xterm_title, | ||
45 | .raw = opts->raw, | ||
46 | .stack = opts->tramp_stack, | ||
47 | .direct_rcv = !opts->in_kernel } ); | ||
48 | return(data); | ||
49 | } | ||
50 | |||
51 | /* Only changed by xterm_setup, which is a setup */ | ||
52 | static char *terminal_emulator = "xterm"; | ||
53 | static char *title_switch = "-T"; | ||
54 | static char *exec_switch = "-e"; | ||
55 | |||
56 | static int __init xterm_setup(char *line, int *add) | ||
57 | { | ||
58 | *add = 0; | ||
59 | terminal_emulator = line; | ||
60 | |||
61 | line = strchr(line, ','); | ||
62 | if(line == NULL) return(0); | ||
63 | *line++ = '\0'; | ||
64 | if(*line) title_switch = line; | ||
65 | |||
66 | line = strchr(line, ','); | ||
67 | if(line == NULL) return(0); | ||
68 | *line++ = '\0'; | ||
69 | if(*line) exec_switch = line; | ||
70 | |||
71 | return(0); | ||
72 | } | ||
73 | |||
74 | __uml_setup("xterm=", xterm_setup, | ||
75 | "xterm=<terminal emulator>,<title switch>,<exec switch>\n" | ||
76 | " Specifies an alternate terminal emulator to use for the debugger,\n" | ||
77 | " consoles, and serial lines when they are attached to the xterm channel.\n" | ||
78 | " The values are the terminal emulator binary, the switch it uses to set\n" | ||
79 | " its title, and the switch it uses to execute a subprocess,\n" | ||
80 | " respectively. The title switch must have the form '<switch> title',\n" | ||
81 | " not '<switch>=title'. Similarly, the exec switch must have the form\n" | ||
82 | " '<switch> command arg1 arg2 ...'.\n" | ||
83 | " The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n" | ||
84 | " are 'xterm=gnome-terminal,-t,-x'.\n\n" | ||
85 | ); | ||
86 | |||
87 | /* XXX This badly needs some cleaning up in the error paths | ||
88 | * Not static because it's called directly by the tt mode gdb code | ||
89 | */ | ||
90 | int xterm_open(int input, int output, int primary, void *d, | ||
91 | char **dev_out) | ||
92 | { | ||
93 | struct xterm_chan *data = d; | ||
94 | unsigned long stack; | ||
95 | int pid, fd, new, err; | ||
96 | char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; | ||
97 | char *argv[] = { terminal_emulator, title_switch, title, exec_switch, | ||
98 | "/usr/lib/uml/port-helper", "-uml-socket", | ||
99 | file, NULL }; | ||
100 | |||
101 | if(os_access(argv[4], OS_ACC_X_OK) < 0) | ||
102 | argv[4] = "port-helper"; | ||
103 | |||
104 | /* Check that DISPLAY is set, this doesn't guarantee the xterm | ||
105 | * will work but w/o it we can be pretty sure it won't. */ | ||
106 | if (!getenv("DISPLAY")) { | ||
107 | printk("xterm_open: $DISPLAY not set.\n"); | ||
108 | return -ENODEV; | ||
109 | } | ||
110 | |||
111 | fd = mkstemp(file); | ||
112 | if(fd < 0){ | ||
113 | printk("xterm_open : mkstemp failed, errno = %d\n", errno); | ||
114 | return(-errno); | ||
115 | } | ||
116 | |||
117 | if(unlink(file)){ | ||
118 | printk("xterm_open : unlink failed, errno = %d\n", errno); | ||
119 | return(-errno); | ||
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 | |||
138 | if(data->stack == 0) free_stack(stack, 0); | ||
139 | |||
140 | if (data->direct_rcv) { | ||
141 | new = os_rcv_fd(fd, &data->helper_pid); | ||
142 | } else { | ||
143 | err = os_set_fd_block(fd, 0); | ||
144 | if(err < 0){ | ||
145 | printk("xterm_open : failed to set descriptor " | ||
146 | "non-blocking, err = %d\n", -err); | ||
147 | return(err); | ||
148 | } | ||
149 | new = xterm_fd(fd, &data->helper_pid); | ||
150 | } | ||
151 | if(new < 0){ | ||
152 | printk("xterm_open : os_rcv_fd failed, err = %d\n", -new); | ||
153 | goto out; | ||
154 | } | ||
155 | |||
156 | CATCH_EINTR(err = tcgetattr(new, &data->tt)); | ||
157 | if(err){ | ||
158 | new = err; | ||
159 | goto out; | ||
160 | } | ||
161 | |||
162 | if(data->raw){ | ||
163 | err = raw(new); | ||
164 | if(err){ | ||
165 | new = err; | ||
166 | goto out; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | data->pid = pid; | ||
171 | *dev_out = NULL; | ||
172 | out: | ||
173 | unlink(file); | ||
174 | return(new); | ||
175 | } | ||
176 | |||
177 | /* Not static because it's called directly by the tt mode gdb code */ | ||
178 | void xterm_close(int fd, void *d) | ||
179 | { | ||
180 | struct xterm_chan *data = d; | ||
181 | |||
182 | if(data->pid != -1) | ||
183 | os_kill_process(data->pid, 1); | ||
184 | data->pid = -1; | ||
185 | if(data->helper_pid != -1) | ||
186 | os_kill_process(data->helper_pid, 0); | ||
187 | data->helper_pid = -1; | ||
188 | os_close_file(fd); | ||
189 | } | ||
190 | |||
191 | static void xterm_free(void *d) | ||
192 | { | ||
193 | free(d); | ||
194 | } | ||
195 | |||
196 | static int xterm_console_write(int fd, const char *buf, int n, void *d) | ||
197 | { | ||
198 | struct xterm_chan *data = d; | ||
199 | |||
200 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
201 | } | ||
202 | |||
203 | struct chan_ops xterm_ops = { | ||
204 | .type = "xterm", | ||
205 | .init = xterm_init, | ||
206 | .open = xterm_open, | ||
207 | .close = xterm_close, | ||
208 | .read = generic_read, | ||
209 | .write = generic_write, | ||
210 | .console_write = xterm_console_write, | ||
211 | .window_size = generic_window_size, | ||
212 | .free = xterm_free, | ||
213 | .winch = 1, | ||
214 | }; | ||
215 | |||
216 | /* | ||
217 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
218 | * Emacs will notice this stuff at the end of the file and automatically | ||
219 | * adjust the settings for this buffer only. This must remain at the end | ||
220 | * of the file. | ||
221 | * --------------------------------------------------------------------------- | ||
222 | * Local variables: | ||
223 | * c-file-style: "linux" | ||
224 | * End: | ||
225 | */ | ||