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).
12 * Modified for sysctl support, 1/8/97, Chris Horn.
17 #include <asm/system.h>
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
23 #include <linux/tty.h>
24 #include <linux/tty_driver.h>
25 #include <linux/smp.h>
26 #include <linux/smp_lock.h>
27 #include <linux/console.h>
28 #include <linux/init.h>
30 #include <asm/uaccess.h>
32 #define LOG_BUF_LEN 8192
34 static char buf
[1024];
36 /* printk's without a loglevel use this.. */
37 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
39 /* We show everything that is MORE important than this.. */
40 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
41 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
43 unsigned long log_size
= 0;
44 struct wait_queue
* log_wait
= NULL
;
46 /* Keep together for sysctl support */
47 int console_loglevel
= DEFAULT_CONSOLE_LOGLEVEL
;
48 int default_message_loglevel
= DEFAULT_MESSAGE_LOGLEVEL
;
49 int minimum_console_loglevel
= MINIMUM_CONSOLE_LOGLEVEL
;
50 int default_console_loglevel
= DEFAULT_CONSOLE_LOGLEVEL
;
52 struct console
*console_drivers
= NULL
;
53 static char log_buf
[LOG_BUF_LEN
];
54 static unsigned long log_start
= 0;
55 static unsigned long logged_chars
= 0;
56 struct console_cmdline console_cmdline
[MAX_CMDLINECONSOLES
];
57 static int selected_console
= 0;
60 * Setup a list of consoles. Called from init/main.c
62 __initfunc(void console_setup(char *str
, int *ints
))
66 struct console_cmdline
*c
;
68 for(i
= 0; i
< MAX_CMDLINECONSOLES
&& console_cmdline
[i
].name
[0]; i
++)
70 if (i
== MAX_CMDLINECONSOLES
)
72 c
= &console_cmdline
[i
];
75 if (str
[0] >= '0' && str
[0] <= '9') {
76 strcpy(c
->name
, "ttyS");
77 strncpy(c
->name
+ 4, str
, sizeof(c
->name
) - 5);
79 strncpy(c
->name
, str
, sizeof(c
->name
) - 1);
80 if ((c
->options
= strchr(str
, ',')) != NULL
)
83 if (!strcmp(str
, "ttya"))
84 strcpy(c
->name
, "ttyS0");
85 if (!strcmp(str
, "ttyb"))
86 strcpy(c
->name
, "ttyS1");
89 for(s
= c
->name
; *s
; s
++)
90 if (*s
>= '0' && *s
<= '9')
92 c
->index
= simple_strtoul(s
, NULL
, 10);
98 * Commands to sys_syslog:
100 * 0 -- Close the log. Currently a NOP.
101 * 1 -- Open the log. Currently a NOP.
102 * 2 -- Read from the log.
103 * 3 -- Read up to the last 4k of messages in the ring buffer.
104 * 4 -- Read and clear last 4k of messages in the ring buffer
105 * 5 -- Clear ring buffer.
106 * 6 -- Disable printk's to console
107 * 7 -- Enable printk's to console
108 * 8 -- Set level of messages printed to console
110 asmlinkage
int sys_syslog(int type
, char * buf
, int len
)
112 unsigned long i
, j
, count
, flags
;
118 if ((type
!= 3) && !suser())
122 case 0: /* Close log */
124 case 1: /* Open log */
126 case 2: /* Read from log */
133 error
= verify_area(VERIFY_WRITE
,buf
,len
);
137 error
= -ERESTARTSYS
;
139 if (signal_pending(current
)) {
143 interruptible_sleep_on(&log_wait
);
146 while (log_size
&& i
< len
) {
147 c
= *((char *) log_buf
+log_start
);
150 log_start
&= LOG_BUF_LEN
-1;
160 case 4: /* Read/clear last kernel messages */
163 case 3: /* Read last kernel messages */
170 error
= verify_area(VERIFY_WRITE
,buf
,len
);
174 * The logged_chars, log_start, and log_size values may
175 * change from an interrupt, so we disable interrupts.
180 if (count
> LOG_BUF_LEN
)
182 if (count
> logged_chars
)
183 count
= logged_chars
;
184 j
= log_start
+ log_size
- count
;
185 __restore_flags(flags
);
186 for (i
= 0; i
< count
; i
++) {
187 c
= *((char *) log_buf
+(j
++ & (LOG_BUF_LEN
-1)));
188 __put_user(c
, buf
++);
194 case 5: /* Clear ring buffer */
197 case 6: /* Disable logging to console */
198 console_loglevel
= minimum_console_loglevel
;
200 case 7: /* Enable logging to console */
201 console_loglevel
= default_console_loglevel
;
205 if (len
< 1 || len
> 8)
207 if (len
< minimum_console_loglevel
)
208 len
= minimum_console_loglevel
;
209 console_loglevel
= len
;
221 spinlock_t console_lock
;
223 asmlinkage
int printk(const char *fmt
, ...)
227 char *msg
, *p
, *buf_end
;
229 static signed char msg_level
= -1;
232 spin_lock_irqsave(&console_lock
, flags
);
234 i
= vsprintf(buf
+ 3, fmt
, args
); /* hopefully i < sizeof(buf)-4 */
235 buf_end
= buf
+ 3 + i
;
237 for (p
= buf
+ 3; p
< buf_end
; p
++) {
248 p
[1] = default_message_loglevel
+ '0';
252 msg_level
= p
[1] - '0';
255 for (; p
< buf_end
; p
++) {
256 log_buf
[(log_start
+log_size
) & (LOG_BUF_LEN
-1)] = *p
;
257 if (log_size
< LOG_BUF_LEN
)
261 log_start
&= LOG_BUF_LEN
-1;
269 if (msg_level
< console_loglevel
&& console_drivers
) {
270 struct console
*c
= console_drivers
;
272 if ((c
->flags
& CON_ENABLED
) && c
->write
)
273 c
->write(c
, msg
, p
- msg
+ line_feed
);
280 spin_unlock_irqrestore(&console_lock
, flags
);
281 wake_up_interruptible(&log_wait
);
285 void console_print(const char *s
)
287 struct console
*c
= console_drivers
;
291 if ((c
->flags
& CON_ENABLED
) && c
->write
)
297 void unblank_console(void)
299 struct console
*c
= console_drivers
;
301 if ((c
->flags
& CON_ENABLED
) && c
->unblank
)
308 * The console driver calls this routine during kernel initialization
309 * to register the console printing procedure with printk() and to
310 * print any messages that were printed by the kernel before the
311 * console driver was initialized.
313 void register_console(struct console
* console
)
318 signed char msg_level
= -1;
322 * See if we want to use this console driver. If we
323 * didn't select a console we take the first one
324 * that registers here.
326 if (selected_console
== 0) {
327 if (console
->index
< 0)
329 if (console
->setup
== NULL
||
330 console
->setup(console
, NULL
) == 0) {
331 console
->flags
|= CON_ENABLED
| CON_FIRST
;
332 selected_console
= 1;
337 * See if this console matches one we selected on
340 for(i
= 0; i
< MAX_CMDLINECONSOLES
&& console_cmdline
[i
].name
[0]; i
++) {
341 if (strcmp(console_cmdline
[i
].name
, console
->name
) != 0)
343 if (console
->index
>= 0 &&
344 console
->index
!= console_cmdline
[i
].index
)
346 if (console
->index
< 0) console
->index
= 0;
347 if (console
->setup
&&
348 console
->setup(console
, console_cmdline
[i
].options
) != 0)
350 console
->flags
|= CON_ENABLED
;
351 console
->index
= console_cmdline
[i
].index
;
353 console
->flags
|= CON_FIRST
;
357 if (!(console
->flags
& CON_ENABLED
))
361 * Put this console in the list - keep the
362 * preferred driver at the head of the list.
364 if ((console
->flags
& CON_FIRST
) || console_drivers
== NULL
) {
365 console
->next
= console_drivers
;
366 console_drivers
= console
;
368 console
->next
= console_drivers
->next
;
369 console_drivers
->next
= console
;
371 if ((console
->flags
& CON_PRINTBUFFER
) == 0) return;
374 * Print out buffered log messages.
376 for (i
=0,j
=0; i
< log_size
; i
++) {
377 buf
[j
++] = log_buf
[p
];
378 p
++; p
&= LOG_BUF_LEN
-1;
379 if (buf
[j
-1] != '\n' && i
< log_size
- 1 && j
< sizeof(buf
)-1)
385 msg_level
= buf
[1] - '0';
389 if (msg_level
< console_loglevel
)
390 console
->write(console
, q
, len
);
391 if (buf
[j
-1] == '\n')
398 int unregister_console(struct console
* console
)
400 struct console
*a
,*b
;
402 if (console_drivers
== console
) {
403 console_drivers
=console
->next
;
406 for (a
=console_drivers
->next
, b
=console_drivers
;
418 * Write a message to a certain tty, not just the console. This is used for
419 * messages that need to be redirected to a specific tty.
420 * We don't put it into the syslog queue right now maybe in the future if
423 void tty_write_message(struct tty_struct
*tty
, char *msg
)
425 if (tty
&& tty
->driver
.write
)
426 tty
->driver
.write(tty
, 0, msg
, strlen(msg
));