Import 2.1.129pre6
[davej-history.git] / kernel / printk.c
blob3c8cda649b6b153e434205bfd2c8d2a573f7f7be
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/mm.h>
20 #include <linux/tty_driver.h>
21 #include <linux/smp_lock.h>
22 #include <linux/console.h>
23 #include <linux/init.h>
25 #include <asm/uaccess.h>
27 #define LOG_BUF_LEN (16384)
29 static char buf[1024];
31 /* printk's without a loglevel use this.. */
32 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
34 /* We show everything that is MORE important than this.. */
35 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
36 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
38 unsigned long log_size = 0;
39 struct wait_queue * log_wait = NULL;
41 /* Keep together for sysctl support */
42 int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
43 int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL;
44 int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
45 int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
47 struct console *console_drivers = NULL;
48 static char log_buf[LOG_BUF_LEN];
49 static unsigned long log_start = 0;
50 static unsigned long logged_chars = 0;
51 struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
52 static int preferred_console = -1;
55 * Setup a list of consoles. Called from init/main.c
57 void __init console_setup(char *str, int *ints)
59 struct console_cmdline *c;
60 char name[sizeof(c->name)];
61 char *s, *options;
62 int i, idx;
65 * Decode str into name, index, options.
67 if (str[0] >= '0' && str[0] <= '9') {
68 strcpy(name, "ttyS");
69 strncpy(name + 4, str, sizeof(name) - 5);
70 } else
71 strncpy(name, str, sizeof(name) - 1);
72 name[sizeof(name) - 1] = 0;
73 if ((options = strchr(str, ',')) != NULL)
74 *(options++) = 0;
75 #ifdef __sparc__
76 if (!strcmp(str, "ttya"))
77 strcpy(name, "ttyS0");
78 if (!strcmp(str, "ttyb"))
79 strcpy(name, "ttyS1");
80 #endif
81 for(s = name; *s; s++)
82 if (*s >= '0' && *s <= '9')
83 break;
84 idx = simple_strtoul(s, NULL, 10);
85 *s = 0;
88 * See if this tty is not yet registered, and
89 * if we have a slot free.
91 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
92 if (strcmp(console_cmdline[i].name, name) == 0 &&
93 console_cmdline[i].index == idx) {
94 preferred_console = i;
95 return;
97 if (i == MAX_CMDLINECONSOLES)
98 return;
99 preferred_console = i;
100 c = &console_cmdline[i];
101 memcpy(c->name, name, sizeof(c->name));
102 c->options = options;
103 c->index = idx;
108 * Commands to do_syslog:
110 * 0 -- Close the log. Currently a NOP.
111 * 1 -- Open the log. Currently a NOP.
112 * 2 -- Read from the log.
113 * 3 -- Read up to the last 4k of messages in the ring buffer.
114 * 4 -- Read and clear last 4k of messages in the ring buffer
115 * 5 -- Clear ring buffer.
116 * 6 -- Disable printk's to console
117 * 7 -- Enable printk's to console
118 * 8 -- Set level of messages printed to console
120 int do_syslog(int type, char * buf, int len)
122 unsigned long i, j, count, flags;
123 int do_clear = 0;
124 char c;
125 int error = -EPERM;
127 lock_kernel();
128 error = 0;
129 switch (type) {
130 case 0: /* Close log */
131 break;
132 case 1: /* Open log */
133 break;
134 case 2: /* Read from log */
135 error = -EINVAL;
136 if (!buf || len < 0)
137 goto out;
138 error = 0;
139 if (!len)
140 goto out;
141 error = verify_area(VERIFY_WRITE,buf,len);
142 if (error)
143 goto out;
144 cli();
145 error = -ERESTARTSYS;
146 while (!log_size) {
147 if (signal_pending(current)) {
148 sti();
149 goto out;
151 interruptible_sleep_on(&log_wait);
153 i = 0;
154 while (log_size && i < len) {
155 c = *((char *) log_buf+log_start);
156 log_start++;
157 log_size--;
158 log_start &= LOG_BUF_LEN-1;
159 sti();
160 __put_user(c,buf);
161 buf++;
162 i++;
163 cli();
165 sti();
166 error = i;
167 break;
168 case 4: /* Read/clear last kernel messages */
169 do_clear = 1;
170 /* FALL THRU */
171 case 3: /* Read last kernel messages */
172 error = -EINVAL;
173 if (!buf || len < 0)
174 goto out;
175 error = 0;
176 if (!len)
177 goto out;
178 error = verify_area(VERIFY_WRITE,buf,len);
179 if (error)
180 goto out;
182 * The logged_chars, log_start, and log_size values may
183 * change from an interrupt, so we disable interrupts.
185 __save_flags(flags);
186 __cli();
187 count = len;
188 if (count > LOG_BUF_LEN)
189 count = LOG_BUF_LEN;
190 if (count > logged_chars)
191 count = logged_chars;
192 j = log_start + log_size - count;
193 __restore_flags(flags);
194 for (i = 0; i < count; i++) {
195 c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
196 __put_user(c, buf++);
198 if (do_clear)
199 logged_chars = 0;
200 error = i;
201 break;
202 case 5: /* Clear ring buffer */
203 logged_chars = 0;
204 break;
205 case 6: /* Disable logging to console */
206 console_loglevel = minimum_console_loglevel;
207 break;
208 case 7: /* Enable logging to console */
209 console_loglevel = default_console_loglevel;
210 break;
211 case 8:
212 error = -EINVAL;
213 if (len < 1 || len > 8)
214 goto out;
215 if (len < minimum_console_loglevel)
216 len = minimum_console_loglevel;
217 console_loglevel = len;
218 error = 0;
219 break;
220 default:
221 error = -EINVAL;
222 break;
224 out:
225 unlock_kernel();
226 return error;
229 asmlinkage int sys_syslog(int type, char * buf, int len)
231 if ((type != 3) && !capable(CAP_SYS_ADMIN))
232 return -EPERM;
233 return do_syslog(type, buf, len);
237 spinlock_t console_lock;
239 asmlinkage int printk(const char *fmt, ...)
241 va_list args;
242 int i;
243 char *msg, *p, *buf_end;
244 int line_feed;
245 static signed char msg_level = -1;
246 long flags;
248 spin_lock_irqsave(&console_lock, flags);
249 va_start(args, fmt);
250 i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
251 buf_end = buf + 3 + i;
252 va_end(args);
253 for (p = buf + 3; p < buf_end; p++) {
254 msg = p;
255 if (msg_level < 0) {
256 if (
257 p[0] != '<' ||
258 p[1] < '0' ||
259 p[1] > '7' ||
260 p[2] != '>'
262 p -= 3;
263 p[0] = '<';
264 p[1] = default_message_loglevel + '0';
265 p[2] = '>';
266 } else
267 msg += 3;
268 msg_level = p[1] - '0';
270 line_feed = 0;
271 for (; p < buf_end; p++) {
272 log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
273 if (log_size < LOG_BUF_LEN)
274 log_size++;
275 else {
276 log_start++;
277 log_start &= LOG_BUF_LEN-1;
279 logged_chars++;
280 if (*p == '\n') {
281 line_feed = 1;
282 break;
285 if (msg_level < console_loglevel && console_drivers) {
286 struct console *c = console_drivers;
287 while(c) {
288 if ((c->flags & CON_ENABLED) && c->write)
289 c->write(c, msg, p - msg + line_feed);
290 c = c->next;
293 if (line_feed)
294 msg_level = -1;
296 spin_unlock_irqrestore(&console_lock, flags);
297 wake_up_interruptible(&log_wait);
298 return i;
301 void console_print(const char *s)
303 struct console *c = console_drivers;
304 int len = strlen(s);
306 while(c) {
307 if ((c->flags & CON_ENABLED) && c->write)
308 c->write(c, s, len);
309 c = c->next;
313 void unblank_console(void)
315 struct console *c = console_drivers;
316 while(c) {
317 if ((c->flags & CON_ENABLED) && c->unblank)
318 c->unblank();
319 c = c->next;
324 * The console driver calls this routine during kernel initialization
325 * to register the console printing procedure with printk() and to
326 * print any messages that were printed by the kernel before the
327 * console driver was initialized.
329 void register_console(struct console * console)
331 int i,j,len;
332 int p = log_start;
333 char buf[16];
334 signed char msg_level = -1;
335 char *q;
338 * See if we want to use this console driver. If we
339 * didn't select a console we take the first one
340 * that registers here.
342 if (preferred_console < 0) {
343 if (console->index < 0)
344 console->index = 0;
345 if (console->setup == NULL ||
346 console->setup(console, NULL) == 0) {
347 console->flags |= CON_ENABLED | CON_CONSDEV;
348 preferred_console = 0;
353 * See if this console matches one we selected on
354 * the command line.
356 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
357 if (strcmp(console_cmdline[i].name, console->name) != 0)
358 continue;
359 if (console->index >= 0 &&
360 console->index != console_cmdline[i].index)
361 continue;
362 if (console->index < 0)
363 console->index = console_cmdline[i].index;
364 if (console->setup &&
365 console->setup(console, console_cmdline[i].options) != 0)
366 break;
367 console->flags |= CON_ENABLED;
368 console->index = console_cmdline[i].index;
369 if (i == preferred_console)
370 console->flags |= CON_CONSDEV;
371 break;
374 if (!(console->flags & CON_ENABLED))
375 return;
378 * Put this console in the list - keep the
379 * preferred driver at the head of the list.
381 if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
382 console->next = console_drivers;
383 console_drivers = console;
384 } else {
385 console->next = console_drivers->next;
386 console_drivers->next = console;
388 if ((console->flags & CON_PRINTBUFFER) == 0) return;
391 * Print out buffered log messages.
393 for (i=0,j=0; i < log_size; i++) {
394 buf[j++] = log_buf[p];
395 p++; p &= LOG_BUF_LEN-1;
396 if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
397 continue;
398 buf[j] = 0;
399 q = buf;
400 len = j;
401 if (msg_level < 0) {
402 msg_level = buf[1] - '0';
403 q = buf + 3;
404 len -= 3;
406 if (msg_level < console_loglevel)
407 console->write(console, q, len);
408 if (buf[j-1] == '\n')
409 msg_level = -1;
410 j = 0;
415 int unregister_console(struct console * console)
417 struct console *a,*b;
419 if (console_drivers == console) {
420 console_drivers=console->next;
421 return (0);
423 for (a=console_drivers->next, b=console_drivers ;
424 a; b=a, a=b->next) {
425 if (a == console) {
426 b->next = a->next;
427 return 0;
431 return (1);
435 * Write a message to a certain tty, not just the console. This is used for
436 * messages that need to be redirected to a specific tty.
437 * We don't put it into the syslog queue right now maybe in the future if
438 * really needed.
440 void tty_write_message(struct tty_struct *tty, char *msg)
442 if (tty && tty->driver.write)
443 tty->driver.write(tty, 0, msg, strlen(msg));
444 return;