1cb8fa61c2b8b29d422d7310f064d60022f18f89bJeff Dike/* 2e99525f9706900417f37721e601d2b414d41bfeeJeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6e99525f9706900417f37721e601d2b414d41bfeeJeff Dike#include <stdio.h> 7cb8fa61c2b8b29d422d7310f064d60022f18f89bJeff Dike#include <stdlib.h> 8cb8fa61c2b8b29d422d7310f064d60022f18f89bJeff Dike#include <unistd.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 10e99525f9706900417f37721e601d2b414d41bfeeJeff Dike#include <termios.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "chan_user.h" 1237185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <os.h> 1337185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <um_malloc.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct fd_chan { 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fd; 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int raw; 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct termios tt; 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char str[sizeof("1234567890\0")]; 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 225e7672ec3f059f764fcc5c78216e24bb16c44dbaJeff Dikestatic void *fd_init(char *str, int device, const struct chan_opts *opts) 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fd_chan *data; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *end; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if (*str != ':') { 29e99525f9706900417f37721e601d2b414d41bfeeJeff Dike printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a " 30e99525f9706900417f37721e601d2b414d41bfeeJeff Dike "file descriptor\n"); 31e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return NULL; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str++; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = strtoul(str, &end, 0); 35e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if ((*end != '\0') || (end == str)) { 36e99525f9706900417f37721e601d2b414d41bfeeJeff Dike printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor " 37e99525f9706900417f37721e601d2b414d41bfeeJeff Dike "'%s'\n", str); 38e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return NULL; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40e99525f9706900417f37721e601d2b414d41bfeeJeff Dike 4143f5b3085fdd27c4edf535d938b2cb0ccead4f75Jeff Dike data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); 42cb8fa61c2b8b29d422d7310f064d60022f18f89bJeff Dike if (data == NULL) 43e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return NULL; 44e99525f9706900417f37721e601d2b414d41bfeeJeff Dike 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *data = ((struct fd_chan) { .fd = n, 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .raw = opts->raw }); 47e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return data; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_open(int input, int output, int primary, void *d, char **dev_out) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fd_chan *data = d; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 55e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if (data->raw && isatty(data->fd)) { 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); 57e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if (err) 58e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return err; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = raw(data->fd); 61e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if (err) 62e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return err; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(data->str, "%d", data->fd); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *dev_out = data->str; 66e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return data->fd; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fd_close(int fd, void *d) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fd_chan *data = d; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if (!data->raw || !isatty(fd)) 75e99525f9706900417f37721e601d2b414d41bfeeJeff Dike return; 76e99525f9706900417f37721e601d2b414d41bfeeJeff Dike 77e99525f9706900417f37721e601d2b414d41bfeeJeff Dike CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); 78e99525f9706900417f37721e601d2b414d41bfeeJeff Dike if (err) 79e99525f9706900417f37721e601d2b414d41bfeeJeff Dike printk(UM_KERN_ERR "Failed to restore terminal state - " 80e99525f9706900417f37721e601d2b414d41bfeeJeff Dike "errno = %d\n", -err); 81e99525f9706900417f37721e601d2b414d41bfeeJeff Dike data->raw = 0; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 845e7672ec3f059f764fcc5c78216e24bb16c44dbaJeff Dikeconst struct chan_ops fd_ops = { 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .type = "fd", 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init = fd_init, 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = fd_open, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .close = fd_close, 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = generic_read, 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = generic_write, 91fd9bc53b99a77aefe89d810d889aa6385565959bPaolo 'Blaisorblade' Giarrusso .console_write = generic_console_write, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .window_size = generic_window_size, 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .free = generic_free, 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .winch = 1, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 96