Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / 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
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  */