1 /* 2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL 4 */ 5 6 #include <linux/ctype.h> 7 #include <linux/init.h> 8 #include <linux/kernel.h> 9 #include <linux/proc_fs.h> 10 #include <linux/types.h> 11 #include <asm/uaccess.h> 12 13 /* 14 * If read and write race, the read will still atomically read a valid 15 * value. 16 */ 17 int uml_exitcode = 0; 18 19 static int read_proc_exitcode(char *page, char **start, off_t off, 20 int count, int *eof, void *data) 21 { 22 int len, val; 23 24 /* 25 * Save uml_exitcode in a local so that we don't need to guarantee 26 * that sprintf accesses it atomically. 27 */ 28 val = uml_exitcode; 29 len = sprintf(page, "%d\n", val); 30 len -= off; 31 if (len <= off+count) 32 *eof = 1; 33 *start = page + off; 34 if (len > count) 35 len = count; 36 if (len < 0) 37 len = 0; 38 return len; 39 } 40 41 static int write_proc_exitcode(struct file *file, const char __user *buffer, 42 unsigned long count, void *data) 43 { 44 char *end, buf[sizeof("nnnnn\0")]; 45 int tmp; 46 47 if (copy_from_user(buf, buffer, count)) 48 return -EFAULT; 49 50 tmp = simple_strtol(buf, &end, 0); 51 if ((*end != '\0') && !isspace(*end)) 52 return -EINVAL; 53 54 uml_exitcode = tmp; 55 return count; 56 } 57 58 static int make_proc_exitcode(void) 59 { 60 struct proc_dir_entry *ent; 61 62 ent = create_proc_entry("exitcode", 0600, NULL); 63 if (ent == NULL) { 64 printk(KERN_WARNING "make_proc_exitcode : Failed to register " 65 "/proc/exitcode\n"); 66 return 0; 67 } 68 69 ent->read_proc = read_proc_exitcode; 70 ent->write_proc = write_proc_exitcode; 71 72 return 0; 73 } 74 75 __initcall(make_proc_exitcode); 76