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>
# include <linux/proc_fs.h>
# 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 ;
static int read_proc_exitcode ( char * page , char * * start , off_t off ,
int count , int * eof , void * data )
{
2006-09-29 12:58:50 +04:00
int len , 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 ;
len = sprintf ( page , " %d \n " , val ) ;
2005-04-17 02:20:36 +04:00
len - = off ;
2008-02-05 09:31:14 +03:00
if ( len < = off + count )
2007-06-09 00:46:54 +04:00
* eof = 1 ;
2005-04-17 02:20:36 +04:00
* start = page + off ;
2008-02-05 09:31:14 +03:00
if ( len > count )
2007-06-09 00:46:54 +04:00
len = count ;
2008-02-05 09:31:14 +03:00
if ( len < 0 )
2007-06-09 00:46:54 +04:00
len = 0 ;
return len ;
2005-04-17 02:20:36 +04:00
}
static int write_proc_exitcode ( struct file * file , const char __user * buffer ,
unsigned long count , void * data )
{
char * end , buf [ sizeof ( " nnnnn \0 " ) ] ;
int tmp ;
2008-02-05 09:31:14 +03:00
if ( copy_from_user ( buf , buffer , count ) )
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
}
static int make_proc_exitcode ( void )
{
struct proc_dir_entry * ent ;
2008-04-29 12:01:44 +04:00
ent = create_proc_entry ( " exitcode " , 0600 , NULL ) ;
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
}
ent - > read_proc = read_proc_exitcode ;
ent - > write_proc = write_proc_exitcode ;
2007-06-09 00:46:54 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
__initcall ( make_proc_exitcode ) ;