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 */ 104