fd.c revision 4fef0c10fa174b57a10854b8b4b2b90d155706e0
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
16struct fd_chan {
17	int fd;
18	int raw;
19	struct termios tt;
20	char str[sizeof("1234567890\0")];
21};
22
23static void *fd_init(char *str, int device, 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
47static 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
66static 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
80struct 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