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