2 oops.c - Dummy loadable module for testing klogd.
3 Copyright (c) 2007 Martin Schulze <joey@infodrom.org>
5 This file is part of the sysklogd package, a kernel and system log daemon.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Helpful documentation: http://www.tldp.org/LDP/lkmpg/2.6/html/
25 echo TEXT > /proc/oops Emits TEXT via printk at log level
26 [<address+delta>] triggers klogd address decoding
27 echo level: info > /proc/oops Sets the log level to 'info'
28 echo oops > /proc/oops Creates a real oops, kills executing shell
29 cat /proc/oops Display current log level and last oops time
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/init.h>
35 #include <linux/proc_fs.h>
36 #include <linux/poll.h>
37 #include <linux/time.h>
39 #define MODNAME "oops"
40 #define PROCNAME "oops"
42 MODULE_AUTHOR("Martin Schulze <joey@infodrom.org>");
43 MODULE_DESCRIPTION("Oops module from klogd");
44 MODULE_LICENSE("GPL");
46 static DEFINE_MUTEX(oops_lock);
49 unsigned long lastoops;
52 static struct oops_t oops_data;
54 static int procflag = 0;
61 struct code priorities[] = {
63 {"panic", 0}, /* DEPRECATED */
67 {"error", 3}, /* DEPRECATED */
69 {"warn", 4}, /* DEPRECATED */
76 void oops_decode_level (char *line)
81 if (strncmp(line, "level:", 6))
84 for (p = (char *)(line) + 6;*p == ' ' || *p == '\t';p++);
86 for (prio = priorities; prio->name; prio++)
87 if (!strcmp(p, prio->name)) {
88 oops_data.loglevel = prio->level;
94 * This routine will create a real and ugly oops
96 static void oops(void)
98 auto unsigned long *p = (unsigned long *) 828282828;
103 static int oops_proc_open (struct inode *inode, struct file *file)
106 printk (KERN_DEBUG "oops_proc_open().\n");
112 oops_proc_read (struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
121 printk (KERN_DEBUG "oops_proc_read(%d).\n",nbytes);
129 for (prio = priorities;
130 prio->name && prio->level != oops_data.loglevel;
134 if (oops_data.lastoops == 0)
135 size = sprintf (s, "Log level: %s\nLast oops: none\n", level);
137 unsigned long now = get_seconds();
138 unsigned long delta = now - oops_data.lastoops;
139 size = sprintf (s, "Log level: %s\nLast oops: %lu (%lu second%s ago)\n",
140 level, oops_data.lastoops,
141 delta, delta == 1 ? "" : "s");
147 if (copy_to_user(buf, s, nbytes))
158 oops_proc_release(struct inode *inode, struct file *filp)
161 printk (KERN_DEBUG "oops_proc_release().\n");
167 oops_proc_write(struct file *file, const char __user *buf,
168 size_t nbytes, loff_t *ppos)
174 printk (KERN_DEBUG "oops_proc_write(%d).\n", nbytes);
177 len = nbytes >= sizeof(input) ? sizeof(input)-1 : nbytes;
179 if (copy_from_user(input, buf, len))
183 if (input[len-1] == '\n')
186 if (!strncmp(input, "level:", 6))
187 oops_decode_level(input);
188 else if (!strcmp(input, "oops")) {
189 oops_data.lastoops = get_seconds();
192 printk ("<%d>%s\n", oops_data.loglevel, input);
197 static const struct file_operations oops_proc_operations = {
198 .read = oops_proc_read,
199 .release = oops_proc_release,
200 .write = oops_proc_write,
201 .open = oops_proc_open,
204 void oops_proc_add (void)
206 struct proc_dir_entry *entry;
208 mutex_lock (&oops_lock);
210 entry = create_proc_entry (PROCNAME, 0, NULL);
213 entry->proc_fops = &oops_proc_operations;
216 mutex_unlock (&oops_lock);
219 void oops_proc_remove (void)
221 mutex_lock (&oops_lock);
223 remove_proc_entry(PROCNAME, NULL);
225 mutex_unlock(&oops_lock);
230 printk (KERN_INFO "Loading module " MODNAME ".\n");
232 oops_data.lastoops = 0;
233 oops_data.loglevel = 5;
240 void oops_cleanup (void)
244 printk (KERN_INFO "Removing module " MODNAME ".\n");
248 module_init(oops_init);
249 module_exit(oops_cleanup);