xref: /linux/arch/um/drivers/fd.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
1 /*
2  * Copyright (C) 2001 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 <termios.h>
10 #include <errno.h>
11 #include "user.h"
12 #include "user_util.h"
13 #include "chan_user.h"
14 #include "os.h"
15 #include "um_malloc.h"
16 
17 struct fd_chan {
18 	int fd;
19 	int raw;
20 	struct termios tt;
21 	char str[sizeof("1234567890\0")];
22 };
23 
24 static void *fd_init(char *str, int device, const struct chan_opts *opts)
25 {
26 	struct fd_chan *data;
27 	char *end;
28 	int n;
29 
30 	if(*str != ':'){
31 		printk("fd_init : channel type 'fd' must specify a file "
32 		       "descriptor\n");
33 		return(NULL);
34 	}
35 	str++;
36 	n = strtoul(str, &end, 0);
37 	if((*end != '\0') || (end == str)){
38 		printk("fd_init : couldn't parse file descriptor '%s'\n", str);
39 		return(NULL);
40 	}
41 	data = um_kmalloc(sizeof(*data));
42 	if(data == NULL) return(NULL);
43 	*data = ((struct fd_chan) { .fd  	= n,
44 				    .raw  	= opts->raw });
45 	return(data);
46 }
47 
48 static int fd_open(int input, int output, int primary, void *d, char **dev_out)
49 {
50 	struct fd_chan *data = d;
51 	int err;
52 
53 	if(data->raw && isatty(data->fd)){
54 		CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
55 		if(err)
56 			return(err);
57 
58 		err = raw(data->fd);
59 		if(err)
60 			return(err);
61 	}
62 	sprintf(data->str, "%d", data->fd);
63 	*dev_out = data->str;
64 	return(data->fd);
65 }
66 
67 static void fd_close(int fd, void *d)
68 {
69 	struct fd_chan *data = d;
70 	int err;
71 
72 	if(data->raw && isatty(fd)){
73 		CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
74 		if(err)
75 			printk("Failed to restore terminal state - "
76 			       "errno = %d\n", -err);
77 		data->raw = 0;
78 	}
79 }
80 
81 const struct chan_ops fd_ops = {
82 	.type		= "fd",
83 	.init		= fd_init,
84 	.open		= fd_open,
85 	.close		= fd_close,
86 	.read		= generic_read,
87 	.write		= generic_write,
88 	.console_write	= generic_console_write,
89 	.window_size	= generic_window_size,
90 	.free		= generic_free,
91 	.winch		= 1,
92 };
93 
94 /*
95  * Overrides for Emacs so that we follow Linus's tabbing style.
96  * Emacs will notice this stuff at the end of the file and automatically
97  * adjust the settings for this buffer only.  This must remain at the end
98  * of the file.
99  * ---------------------------------------------------------------------------
100  * Local variables:
101  * c-file-style: "linux"
102  * End:
103  */
104