2007-06-09 00:46:54 +04:00
/*
2008-02-05 09:31:14 +03:00
* Copyright ( C ) 2002 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-17 02:20:36 +04:00
* Licensed under the GPL
*/
2008-02-05 09:31:14 +03:00
# include <linux/ctype.h>
# include <linux/init.h>
# include <linux/kernel.h>
2009-12-15 05:00:11 +03:00
# include <linux/module.h>
2008-02-05 09:31:14 +03:00
# include <linux/proc_fs.h>
2009-12-15 05:00:11 +03:00
# include <linux/seq_file.h>
2008-02-05 09:31:14 +03:00
# include <linux/types.h>
# include <asm/uaccess.h>
2005-04-17 02:20:36 +04:00
2008-02-05 09:31:14 +03:00
/*
* If read and write race , the read will still atomically read a valid
2005-04-17 02:20:36 +04:00
* value .
*/
int uml_exitcode = 0 ;
2009-12-15 05:00:11 +03:00
static int exitcode_proc_show ( struct seq_file * m , void * v )
2005-04-17 02:20:36 +04:00
{
2009-12-15 05:00:11 +03:00
int val ;
2005-04-17 02:20:36 +04:00
2008-02-05 09:31:14 +03:00
/*
* Save uml_exitcode in a local so that we don ' t need to guarantee
2006-09-29 12:58:50 +04:00
* that sprintf accesses it atomically .
*/
val = uml_exitcode ;
2009-12-15 05:00:11 +03:00
seq_printf ( m , " %d \n " , val ) ;
return 0 ;
}
static int exitcode_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , exitcode_proc_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2009-12-15 05:00:11 +03:00
static ssize_t exitcode_proc_write ( struct file * file ,
const char __user * buffer , size_t count , loff_t * pos )
2005-04-17 02:20:36 +04:00
{
char * end , buf [ sizeof ( " nnnnn \0 " ) ] ;
2013-10-29 23:06:04 +04:00
size_t size ;
2005-04-17 02:20:36 +04:00
int tmp ;
2013-10-29 23:06:04 +04:00
size = min ( count , sizeof ( buf ) ) ;
if ( copy_from_user ( buf , buffer , size ) )
2007-06-09 00:46:54 +04:00
return - EFAULT ;
2005-04-17 02:20:36 +04:00
tmp = simple_strtol ( buf , & end , 0 ) ;
2008-02-05 09:31:14 +03:00
if ( ( * end ! = ' \0 ' ) & & ! isspace ( * end ) )
2007-06-09 00:46:54 +04:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
uml_exitcode = tmp ;
2007-06-09 00:46:54 +04:00
return count ;
2005-04-17 02:20:36 +04:00
}
2009-12-15 05:00:11 +03:00
static const struct file_operations exitcode_proc_fops = {
. owner = THIS_MODULE ,
. open = exitcode_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = exitcode_proc_write ,
} ;
2005-04-17 02:20:36 +04:00
static int make_proc_exitcode ( void )
{
struct proc_dir_entry * ent ;
2009-12-15 05:00:11 +03:00
ent = proc_create ( " exitcode " , 0600 , NULL , & exitcode_proc_fops ) ;
2008-02-05 09:31:14 +03:00
if ( ent = = NULL ) {
2005-07-29 08:16:12 +04:00
printk ( KERN_WARNING " make_proc_exitcode : Failed to register "
2005-04-17 02:20:36 +04:00
" /proc/exitcode \n " ) ;
2007-06-09 00:46:54 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-06-09 00:46:54 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
__initcall ( make_proc_exitcode ) ;