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