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 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, struct chan_opts *opts) 23 { 24 struct fd_chan *data; 25 char *end; 26 int n; 27 28 if(*str != ':'){ 29 printk("fd_init : channel type 'fd' must specify a file " 30 "descriptor\n"); 31 return(NULL); 32 } 33 str++; 34 n = strtoul(str, &end, 0); 35 if((*end != '\0') || (end == str)){ 36 printk("fd_init : couldn't parse file descriptor '%s'\n", str); 37 return(NULL); 38 } 39 data = um_kmalloc(sizeof(*data)); 40 if(data == NULL) return(NULL); 41 *data = ((struct fd_chan) { .fd = n, 42 .raw = opts->raw }); 43 return(data); 44 } 45 46 static int fd_open(int input, int output, int primary, void *d, char **dev_out) 47 { 48 struct fd_chan *data = d; 49 int err; 50 51 if(data->raw && isatty(data->fd)){ 52 CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); 53 if(err) 54 return(err); 55 56 err = raw(data->fd); 57 if(err) 58 return(err); 59 } 60 sprintf(data->str, "%d", data->fd); 61 *dev_out = data->str; 62 return(data->fd); 63 } 64 65 static void fd_close(int fd, void *d) 66 { 67 struct fd_chan *data = d; 68 int err; 69 70 if(data->raw && isatty(fd)){ 71 CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); 72 if(err) 73 printk("Failed to restore terminal state - " 74 "errno = %d\n", -err); 75 data->raw = 0; 76 } 77 } 78 79 struct chan_ops fd_ops = { 80 .type = "fd", 81 .init = fd_init, 82 .open = fd_open, 83 .close = fd_close, 84 .read = generic_read, 85 .write = generic_write, 86 .console_write = generic_console_write, 87 .window_size = generic_window_size, 88 .free = generic_free, 89 .winch = 1, 90 }; 91 92 /* 93 * Overrides for Emacs so that we follow Linus's tabbing style. 94 * Emacs will notice this stuff at the end of the file and automatically 95 * adjust the settings for this buffer only. This must remain at the end 96 * of the file. 97 * --------------------------------------------------------------------------- 98 * Local variables: 99 * c-file-style: "linux" 100 * End: 101 */ 102