1 /* 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 3 * Licensed under the GPL 4 */ 5 6 #include <stddef.h> 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <errno.h> 10 #include <termios.h> 11 #include <unistd.h> 12 #include "chan_user.h" 13 #include "um_malloc.h" 14 #include "user.h" 15 #include "os.h" 16 #include "kern_constants.h" 17 18 struct fd_chan { 19 int fd; 20 int raw; 21 struct termios tt; 22 char str[sizeof("1234567890\0")]; 23 }; 24 25 static void *fd_init(char *str, int device, const struct chan_opts *opts) 26 { 27 struct fd_chan *data; 28 char *end; 29 int n; 30 31 if (*str != ':') { 32 printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a " 33 "file descriptor\n"); 34 return NULL; 35 } 36 str++; 37 n = strtoul(str, &end, 0); 38 if ((*end != '\0') || (end == str)) { 39 printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor " 40 "'%s'\n", str); 41 return NULL; 42 } 43 44 data = kmalloc(sizeof(*data), UM_GFP_KERNEL); 45 if(data == NULL) 46 return NULL; 47 48 *data = ((struct fd_chan) { .fd = n, 49 .raw = opts->raw }); 50 return data; 51 } 52 53 static int fd_open(int input, int output, int primary, void *d, char **dev_out) 54 { 55 struct fd_chan *data = d; 56 int err; 57 58 if (data->raw && isatty(data->fd)) { 59 CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); 60 if (err) 61 return err; 62 63 err = raw(data->fd); 64 if (err) 65 return err; 66 } 67 sprintf(data->str, "%d", data->fd); 68 *dev_out = data->str; 69 return data->fd; 70 } 71 72 static void fd_close(int fd, void *d) 73 { 74 struct fd_chan *data = d; 75 int err; 76 77 if (!data->raw || !isatty(fd)) 78 return; 79 80 CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); 81 if (err) 82 printk(UM_KERN_ERR "Failed to restore terminal state - " 83 "errno = %d\n", -err); 84 data->raw = 0; 85 } 86 87 const struct chan_ops fd_ops = { 88 .type = "fd", 89 .init = fd_init, 90 .open = fd_open, 91 .close = fd_close, 92 .read = generic_read, 93 .write = generic_write, 94 .console_write = generic_console_write, 95 .window_size = generic_window_size, 96 .free = generic_free, 97 .winch = 1, 98 }; 99