Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[linux-2.6] / arch / um / drivers / fd.c
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  */