PageRenderTime 41ms CodeModel.GetById 2ms app.highlight 33ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/um/drivers/xterm.c

https://bitbucket.org/evzijst/gittest
C | 225 lines | 174 code | 29 blank | 22 comment | 27 complexity | f48093ebcad1df53798e345758ec2fb4 MD5 | raw file
  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
 23struct 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 */
 35void *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 */
 52static char *terminal_emulator = "xterm";
 53static char *title_switch = "-T";
 54static char *exec_switch = "-e";
 55
 56static 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 */
 90int 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 */
178void 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
191static void xterm_free(void *d)
192{
193	free(d);
194}
195
196static 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
203struct 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 */