Import 2.1.118
[davej-history.git] / kernel / printk.c
blob0d8287fefaeeb1b5cac118f3e6429baa10a59032
1 /*
2 * linux/kernel/printk.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * Modified to make sys_syslog() more flexible: added commands to
7 * return the last 4k of kernel messages, regardless of whether
8 * they've been read or not. Added option to suppress kernel printk's
9 * to the console. Added hook for sending the console messages
10 * elsewhere, in preparation for a serial line console (someday).
11 * Ted Ts'o, 2/11/93.
12 * Modified for sysctl support, 1/8/97, Chris Horn.
15 #include <stdarg.h>
17 #include <linux/errno.h>
18 #include <linux/sched.h>
19 #include <linux/kernel.h>
20 #include <linux/mm.h>
21 #include <linux/tty.h>
22 #include <linux/tty_driver.h>
23 #include <linux/smp.h>
24 #include <linux/smp_lock.h>
25 #include <linux/console.h>
26 #include <linux/init.h>
28 #include <asm/system.h>
29 #include <asm/uaccess.h>
31 #define LOG_BUF_LEN (16384)
33 static char buf[1024];
35 /* printk's without a loglevel use this.. */
36 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
38 /* We show everything that is MORE important than this.. */
39 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
40 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
42 unsigned long log_size = 0;
43 struct wait_queue * log_wait = NULL;
45 /* Keep together for sysctl support */
46 int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
47 int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL;
48 int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
49 int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
51 struct console *console_drivers = NULL;
52 static char log_buf[LOG_BUF_LEN];
53 static unsigned long log_start = 0;
54 static unsigned long logged_chars = 0;
55 struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
56 static int preferred_console = -1;
59 * Setup a list of consoles. Called from init/main.c
61 void __init console_setup(char *str, int *ints)
63 struct console_cmdline *c;
64 char name[sizeof(c->name)];
65 char *s, *options;
66 int i, idx;
69 * Decode str into name, index, options.
71 if (str[0] >= '0' && str[0] <= '9') {
72 strcpy(name, "ttyS");
73 strncpy(name + 4, str, sizeof(name) - 5);
74 } else
75 strncpy(name, str, sizeof(name) - 1);
76 name[sizeof(name) - 1] = 0;
77 if ((options = strchr(str, ',')) != NULL)
78 *(options++) = 0;
79 #ifdef __sparc__
80 if (!strcmp(str, "ttya"))
81 strcpy(name, "ttyS0");
82 if (!strcmp(str, "ttyb"))
83 strcpy(name, "ttyS1");
84 #endif
85 for(s = name; *s; s++)
86 if (*s >= '0' && *s <= '9')
87 break;
88 idx = simple_strtoul(s, NULL, 10);
89 *s = 0;
92 * See if this tty is not yet registered, and
93 * if we have a slot free.
95 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
96 if (strcmp(console_cmdline[i].name, name) == 0 &&
97 console_cmdline[i].index == idx) {
98 preferred_console = i;
99 return;
101 if (i == MAX_CMDLINECONSOLES)
102 return;
103 preferred_console = i;
104 c = &console_cmdline[i];
105 memcpy(c->name, name, sizeof(c->name));
106 c->options = options;
107 c->index = idx;
112 * Commands to sys_syslog:
114 * 0 -- Close the log. Currently a NOP.
115 * 1 -- Open the log. Currently a NOP.
116 * 2 -- Read from the log.
117 * 3 -- Read up to the last 4k of messages in the ring buffer.
118 * 4 -- Read and clear last 4k of messages in the ring buffer
119 * 5 -- Clear ring buffer.
120 * 6 -- Disable printk's to console
121 * 7 -- Enable printk's to console
122 * 8 -- Set level of messages printed to console
124 asmlinkage int sys_syslog(int type, char * buf, int len)
126 unsigned long i, j, count, flags;
127 int do_clear = 0;
128 char c;
129 int error = -EPERM;
131 lock_kernel();
132 if ((type != 3) && !capable(CAP_SYS_ADMIN))
133 goto out;
134 error = 0;
135 switch (type) {
136 case 0: /* Close log */
137 break;
138 case 1: /* Open log */
139 break;
140 case 2: /* Read from log */
141 error = -EINVAL;
142 if (!buf || len < 0)
143 goto out;
144 error = 0;
145 if (!len)
146 goto out;
147 error = verify_area(VERIFY_WRITE,buf,len);
148 if (error)
149 goto out;
150 cli();
151 error = -ERESTARTSYS;
152 while (!log_size) {
153 if (signal_pending(current)) {
154 sti();
155 goto out;
157 interruptible_sleep_on(&log_wait);
159 i = 0;
160 while (log_size && i < len) {
161 c = *((char *) log_buf+log_start);
162 log_start++;
163 log_size--;
164 log_start &= LOG_BUF_LEN-1;
165 sti();
166 __put_user(c,buf);
167 buf++;
168 i++;
169 cli();
171 sti();
172 error = i;
173 break;
174 case 4: /* Read/clear last kernel messages */
175 do_clear = 1;
176 /* FALL THRU */
177 case 3: /* Read last kernel messages */
178 error = -EINVAL;
179 if (!buf || len < 0)
180 goto out;
181 error = 0;
182 if (!len)
183 goto out;
184 error = verify_area(VERIFY_WRITE,buf,len);
185 if (error)
186 goto out;
188 * The logged_chars, log_start, and log_size values may
189 * change from an interrupt, so we disable interrupts.
191 __save_flags(flags);
192 __cli();
193 count = len;
194 if (count > LOG_BUF_LEN)
195 count = LOG_BUF_LEN;
196 if (count > logged_chars)
197 count = logged_chars;
198 j = log_start + log_size - count;
199 __restore_flags(flags);
200 for (i = 0; i < count; i++) {
201 c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
202 __put_user(c, buf++);
204 if (do_clear)
205 logged_chars = 0;
206 error = i;
207 break;
208 case 5: /* Clear ring buffer */
209 logged_chars = 0;
210 break;
211 case 6: /* Disable logging to console */
212 console_loglevel = minimum_console_loglevel;
213 break;
214 case 7: /* Enable logging to console */
215 console_loglevel = default_console_loglevel;
216 break;
217 case 8:
218 error = -EINVAL;
219 if (len < 1 || len > 8)
220 goto out;
221 if (len < minimum_console_loglevel)
222 len = minimum_console_loglevel;
223 console_loglevel = len;
224 error = 0;
225 break;
226 default:
227 error = -EINVAL;
228 break;
230 out:
231 unlock_kernel();
232 return error;
235 spinlock_t console_lock;
237 asmlinkage int printk(const char *fmt, ...)
239 va_list args;
240 int i;
241 char *msg, *p, *buf_end;
242 int line_feed;
243 static signed char msg_level = -1;
244 long flags;
246 spin_lock_irqsave(&console_lock, flags);
247 va_start(args, fmt);
248 i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
249 buf_end = buf + 3 + i;
250 va_end(args);
251 for (p = buf + 3; p < buf_end; p++) {
252 msg = p;
253 if (msg_level < 0) {
254 if (
255 p[0] != '<' ||
256 p[1] < '0' ||
257 p[1] > '7' ||
258 p[2] != '>'
260 p -= 3;
261 p[0] = '<';
262 p[1] = default_message_loglevel + '0';
263 p[2] = '>';
264 } else
265 msg += 3;
266 msg_level = p[1] - '0';
268 line_feed = 0;
269 for (; p < buf_end; p++) {
270 log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
271 if (log_size < LOG_BUF_LEN)
272 log_size++;
273 else {
274 log_start++;
275 log_start &= LOG_BUF_LEN-1;
277 logged_chars++;
278 if (*p == '\n') {
279 line_feed = 1;
280 break;
283 if (msg_level < console_loglevel && console_drivers) {
284 struct console *c = console_drivers;
285 while(c) {
286 if ((c->flags & CON_ENABLED) && c->write)
287 c->write(c, msg, p - msg + line_feed);
288 c = c->next;
291 if (line_feed)
292 msg_level = -1;
294 spin_unlock_irqrestore(&console_lock, flags);
295 wake_up_interruptible(&log_wait);
296 return i;
299 void console_print(const char *s)
301 struct console *c = console_drivers;
302 int len = strlen(s);
304 while(c) {
305 if ((c->flags & CON_ENABLED) && c->write)
306 c->write(c, s, len);
307 c = c->next;
311 void unblank_console(void)
313 struct console *c = console_drivers;
314 while(c) {
315 if ((c->flags & CON_ENABLED) && c->unblank)
316 c->unblank();
317 c = c->next;
322 * The console driver calls this routine during kernel initialization
323 * to register the console printing procedure with printk() and to
324 * print any messages that were printed by the kernel before the
325 * console driver was initialized.
327 void register_console(struct console * console)
329 int i,j,len;
330 int p = log_start;
331 char buf[16];
332 signed char msg_level = -1;
333 char *q;
336 * See if we want to use this console driver. If we
337 * didn't select a console we take the first one
338 * that registers here.
340 if (preferred_console < 0) {
341 if (console->index < 0)
342 console->index = 0;
343 if (console->setup == NULL ||
344 console->setup(console, NULL) == 0) {
345 console->flags |= CON_ENABLED | CON_CONSDEV;
346 preferred_console = 0;
351 * See if this console matches one we selected on
352 * the command line.
354 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
355 if (strcmp(console_cmdline[i].name, console->name) != 0)
356 continue;
357 if (console->index >= 0 &&
358 console->index != console_cmdline[i].index)
359 continue;
360 if (console->index < 0)
361 console->index = console_cmdline[i].index;
362 if (console->setup &&
363 console->setup(console, console_cmdline[i].options) != 0)
364 break;
365 console->flags |= CON_ENABLED;
366 console->index = console_cmdline[i].index;
367 if (i == preferred_console)
368 console->flags |= CON_CONSDEV;
369 break;
372 if (!(console->flags & CON_ENABLED))
373 return;
376 * Put this console in the list - keep the
377 * preferred driver at the head of the list.
379 if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
380 console->next = console_drivers;
381 console_drivers = console;
382 } else {
383 console->next = console_drivers->next;
384 console_drivers->next = console;
386 if ((console->flags & CON_PRINTBUFFER) == 0) return;
389 * Print out buffered log messages.
391 for (i=0,j=0; i < log_size; i++) {
392 buf[j++] = log_buf[p];
393 p++; p &= LOG_BUF_LEN-1;
394 if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
395 continue;
396 buf[j] = 0;
397 q = buf;
398 len = j;
399 if (msg_level < 0) {
400 msg_level = buf[1] - '0';
401 q = buf + 3;
402 len -= 3;
404 if (msg_level < console_loglevel)
405 console->write(console, q, len);
406 if (buf[j-1] == '\n')
407 msg_level = -1;
408 j = 0;
413 int unregister_console(struct console * console)
415 struct console *a,*b;
417 if (console_drivers == console) {
418 console_drivers=console->next;
419 return (0);
421 for (a=console_drivers->next, b=console_drivers ;
422 a; b=a, a=b->next) {
423 if (a == console) {
424 b->next = a->next;
425 return 0;
429 return (1);
433 * Write a message to a certain tty, not just the console. This is used for
434 * messages that need to be redirected to a specific tty.
435 * We don't put it into the syslog queue right now maybe in the future if
436 * really needed.
438 void tty_write_message(struct tty_struct *tty, char *msg)
440 if (tty && tty->driver.write)
441 tty->driver.write(tty, 0, msg, strlen(msg));
442 return;