2019-08-25 12:49:16 +03:00
// SPDX-License-Identifier: GPL-2.0
2007-10-16 12:27:34 +04:00
/*
2007-10-16 12:26:41 +04:00
* Copyright ( C ) 2001 - 2007 Jeff Dike ( jdike @ { linux . intel , addtoit } . com )
2005-04-17 02:20:36 +04:00
*/
2007-10-16 12:26:41 +04:00
# include <stdio.h>
2007-10-16 12:27:34 +04:00
# include <stdlib.h>
# include <unistd.h>
2005-04-17 02:20:36 +04:00
# include <errno.h>
2007-10-16 12:26:41 +04:00
# include <termios.h>
2005-04-17 02:20:36 +04:00
# include "chan_user.h"
2012-10-08 06:27:32 +04:00
# include <os.h>
# include <um_malloc.h>
2005-04-17 02:20:36 +04:00
struct fd_chan {
int fd ;
int raw ;
struct termios tt ;
char str [ sizeof ( " 1234567890 \0 " ) ] ;
} ;
2006-09-27 12:50:33 +04:00
static void * fd_init ( char * str , int device , const struct chan_opts * opts )
2005-04-17 02:20:36 +04:00
{
struct fd_chan * data ;
char * end ;
int n ;
2007-10-16 12:26:41 +04:00
if ( * str ! = ' : ' ) {
printk ( UM_KERN_ERR " fd_init : channel type 'fd' must specify a "
" file descriptor \n " ) ;
return NULL ;
2005-04-17 02:20:36 +04:00
}
str + + ;
n = strtoul ( str , & end , 0 ) ;
2007-10-16 12:26:41 +04:00
if ( ( * end ! = ' \0 ' ) | | ( end = = str ) ) {
printk ( UM_KERN_ERR " fd_init : couldn't parse file descriptor "
" '%s' \n " , str ) ;
return NULL ;
2005-04-17 02:20:36 +04:00
}
2007-10-16 12:26:41 +04:00
2008-05-13 01:01:52 +04:00
data = uml_kmalloc ( sizeof ( * data ) , UM_GFP_KERNEL ) ;
2007-10-16 12:27:34 +04:00
if ( data = = NULL )
2007-10-16 12:26:41 +04:00
return NULL ;
2005-04-17 02:20:36 +04:00
* data = ( ( struct fd_chan ) { . fd = n ,
. raw = opts - > raw } ) ;
2007-10-16 12:26:41 +04:00
return data ;
2005-04-17 02:20:36 +04:00
}
static int fd_open ( int input , int output , int primary , void * d , char * * dev_out )
{
struct fd_chan * data = d ;
int err ;
2007-10-16 12:26:41 +04:00
if ( data - > raw & & isatty ( data - > fd ) ) {
2005-04-17 02:20:36 +04:00
CATCH_EINTR ( err = tcgetattr ( data - > fd , & data - > tt ) ) ;
2007-10-16 12:26:41 +04:00
if ( err )
return err ;
2005-04-17 02:20:36 +04:00
err = raw ( data - > fd ) ;
2007-10-16 12:26:41 +04:00
if ( err )
return err ;
2005-04-17 02:20:36 +04:00
}
sprintf ( data - > str , " %d " , data - > fd ) ;
* dev_out = data - > str ;
2007-10-16 12:26:41 +04:00
return data - > fd ;
2005-04-17 02:20:36 +04:00
}
static void fd_close ( int fd , void * d )
{
struct fd_chan * data = d ;
int err ;
2007-10-16 12:26:41 +04:00
if ( ! data - > raw | | ! isatty ( fd ) )
return ;
CATCH_EINTR ( err = tcsetattr ( fd , TCSAFLUSH , & data - > tt ) ) ;
if ( err )
printk ( UM_KERN_ERR " Failed to restore terminal state - "
" errno = %d \n " , - err ) ;
data - > raw = 0 ;
2005-04-17 02:20:36 +04:00
}
2006-09-27 12:50:33 +04:00
const struct chan_ops fd_ops = {
2005-04-17 02:20:36 +04:00
. type = " fd " ,
. init = fd_init ,
. open = fd_open ,
. close = fd_close ,
. read = generic_read ,
. write = generic_write ,
2005-11-14 03:07:10 +03:00
. console_write = generic_console_write ,
2005-04-17 02:20:36 +04:00
. window_size = generic_window_size ,
. free = generic_free ,
. winch = 1 ,
} ;