1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
4 | */ |
5 | |
6 | #include <linux/ctype.h> |
7 | #include <linux/init.h> |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> |
10 | #include <linux/proc_fs.h> |
11 | #include <linux/seq_file.h> |
12 | #include <linux/types.h> |
13 | #include <linux/uaccess.h> |
14 | |
15 | /* |
16 | * If read and write race, the read will still atomically read a valid |
17 | * value. |
18 | */ |
19 | int uml_exitcode = 0; |
20 | |
21 | static int exitcode_proc_show(struct seq_file *m, void *v) |
22 | { |
23 | int val; |
24 | |
25 | /* |
26 | * Save uml_exitcode in a local so that we don't need to guarantee |
27 | * that sprintf accesses it atomically. |
28 | */ |
29 | val = uml_exitcode; |
30 | seq_printf(m, fmt: "%d\n" , val); |
31 | return 0; |
32 | } |
33 | |
34 | static int exitcode_proc_open(struct inode *inode, struct file *file) |
35 | { |
36 | return single_open(file, exitcode_proc_show, NULL); |
37 | } |
38 | |
39 | static ssize_t exitcode_proc_write(struct file *file, |
40 | const char __user *buffer, size_t count, loff_t *pos) |
41 | { |
42 | char *end, buf[sizeof("nnnnn\0" )]; |
43 | size_t size; |
44 | int tmp; |
45 | |
46 | size = min(count, sizeof(buf)); |
47 | if (copy_from_user(to: buf, from: buffer, n: size)) |
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 const struct proc_ops exitcode_proc_ops = { |
59 | .proc_open = exitcode_proc_open, |
60 | .proc_read = seq_read, |
61 | .proc_lseek = seq_lseek, |
62 | .proc_release = single_release, |
63 | .proc_write = exitcode_proc_write, |
64 | }; |
65 | |
66 | static int make_proc_exitcode(void) |
67 | { |
68 | struct proc_dir_entry *ent; |
69 | |
70 | ent = proc_create(name: "exitcode" , mode: 0600, NULL, proc_ops: &exitcode_proc_ops); |
71 | if (ent == NULL) { |
72 | printk(KERN_WARNING "make_proc_exitcode : Failed to register " |
73 | "/proc/exitcode\n" ); |
74 | return 0; |
75 | } |
76 | return 0; |
77 | } |
78 | |
79 | __initcall(make_proc_exitcode); |
80 | |