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