Import 2.3.9
[davej-history.git] / kernel / printk.c
blobc2cbd4a7882edd991237826cb9b2693450bb03a2
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 <linux/mm.h>
16 #include <linux/tty_driver.h>
17 #include <linux/smp_lock.h>
18 #include <linux/console.h>
19 #include <linux/init.h>
21 #include <asm/uaccess.h>
23 #define LOG_BUF_LEN (16384)
25 static char buf[1024];
27 /* printk's without a loglevel use this.. */
28 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
30 /* We show everything that is MORE important than this.. */
31 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
32 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
34 unsigned long log_size = 0;
35 DECLARE_WAIT_QUEUE_HEAD(log_wait);
37 /* Keep together for sysctl support */
38 int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
39 int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL;
40 int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
41 int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
43 struct console *console_drivers = NULL;
44 static char log_buf[LOG_BUF_LEN];
45 static unsigned long log_start = 0;
46 static unsigned long logged_chars = 0;
47 struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
48 static int preferred_console = -1;
51 * Setup a list of consoles. Called from init/main.c
53 void __init console_setup(char *str, int *ints)
55 struct console_cmdline *c;
56 char name[sizeof(c->name)];
57 char *s, *options;
58 int i, idx;
61 * Decode str into name, index, options.
63 if (str[0] >= '0' && str[0] <= '9') {
64 strcpy(name, "ttyS");
65 strncpy(name + 4, str, sizeof(name) - 5);
66 } else
67 strncpy(name, str, sizeof(name) - 1);
68 name[sizeof(name) - 1] = 0;
69 if ((options = strchr(str, ',')) != NULL)
70 *(options++) = 0;
71 #ifdef __sparc__
72 if (!strcmp(str, "ttya"))
73 strcpy(name, "ttyS0");
74 if (!strcmp(str, "ttyb"))
75 strcpy(name, "ttyS1");
76 #endif
77 for(s = name; *s; s++)
78 if (*s >= '0' && *s <= '9')
79 break;
80 idx = simple_strtoul(s, NULL, 10);
81 *s = 0;
84 * See if this tty is not yet registered, and
85 * if we have a slot free.
87 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
88 if (strcmp(console_cmdline[i].name, name) == 0 &&
89 console_cmdline[i].index == idx) {
90 preferred_console = i;
91 return;
93 if (i == MAX_CMDLINECONSOLES)
94 return;
95 preferred_console = i;
96 c = &console_cmdline[i];
97 memcpy(c->name, name, sizeof(c->name));
98 c->options = options;
99 c->index = idx;
104 * Commands to do_syslog:
106 * 0 -- Close the log. Currently a NOP.
107 * 1 -- Open the log. Currently a NOP.
108 * 2 -- Read from the log.
109 * 3 -- Read up to the last 4k of messages in the ring buffer.
110 * 4 -- Read and clear last 4k of messages in the ring buffer
111 * 5 -- Clear ring buffer.
112 * 6 -- Disable printk's to console
113 * 7 -- Enable printk's to console
114 * 8 -- Set level of messages printed to console
116 int do_syslog(int type, char * buf, int len)
118 unsigned long i, j, count, flags;
119 int do_clear = 0;
120 char c;
121 int error = -EPERM;
123 lock_kernel();
124 error = 0;
125 switch (type) {
126 case 0: /* Close log */
127 break;
128 case 1: /* Open log */
129 break;
130 case 2: /* Read from log */
131 error = -EINVAL;
132 if (!buf || len < 0)
133 goto out;
134 error = 0;
135 if (!len)
136 goto out;
137 error = verify_area(VERIFY_WRITE,buf,len);
138 if (error)
139 goto out;
140 error = wait_event_interruptible(log_wait, log_size);
141 if (error)
142 goto out;
143 i = 0;
144 while (log_size && i < len) {
145 c = *((char *) log_buf+log_start);
146 log_start++;
147 log_size--;
148 log_start &= LOG_BUF_LEN-1;
149 sti();
150 __put_user(c,buf);
151 buf++;
152 i++;
153 cli();
155 sti();
156 error = i;
157 break;
158 case 4: /* Read/clear last kernel messages */
159 do_clear = 1;
160 /* FALL THRU */
161 case 3: /* Read last kernel messages */
162 error = -EINVAL;
163 if (!buf || len < 0)
164 goto out;
165 error = 0;
166 if (!len)
167 goto out;
168 error = verify_area(VERIFY_WRITE,buf,len);
169 if (error)
170 goto out;
172 * The logged_chars, log_start, and log_size values may
173 * change from an interrupt, so we disable interrupts.
175 __save_flags(flags);
176 __cli();
177 count = len;
178 if (count > LOG_BUF_LEN)
179 count = LOG_BUF_LEN;
180 if (count > logged_chars)
181 count = logged_chars;
182 j = log_start + log_size - count;
183 __restore_flags(flags);
184 for (i = 0; i < count; i++) {
185 c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
186 __put_user(c, buf++);
188 if (do_clear)
189 logged_chars = 0;
190 error = i;
191 break;
192 case 5: /* Clear ring buffer */
193 logged_chars = 0;
194 break;
195 case 6: /* Disable logging to console */
196 console_loglevel = minimum_console_loglevel;
197 break;
198 case 7: /* Enable logging to console */
199 console_loglevel = default_console_loglevel;
200 break;
201 case 8:
202 error = -EINVAL;
203 if (len < 1 || len > 8)
204 goto out;
205 if (len < minimum_console_loglevel)
206 len = minimum_console_loglevel;
207 console_loglevel = len;
208 error = 0;
209 break;
210 default:
211 error = -EINVAL;
212 break;
214 out:
215 unlock_kernel();
216 return error;
219 asmlinkage int sys_syslog(int type, char * buf, int len)
221 if ((type != 3) && !capable(CAP_SYS_ADMIN))
222 return -EPERM;
223 return do_syslog(type, buf, len);
227 spinlock_t console_lock;
229 asmlinkage int printk(const char *fmt, ...)
231 va_list args;
232 int i;
233 char *msg, *p, *buf_end;
234 int line_feed;
235 static signed char msg_level = -1;
236 long flags;
238 spin_lock_irqsave(&console_lock, flags);
239 va_start(args, fmt);
240 i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
241 buf_end = buf + 3 + i;
242 va_end(args);
243 for (p = buf + 3; p < buf_end; p++) {
244 msg = p;
245 if (msg_level < 0) {
246 if (
247 p[0] != '<' ||
248 p[1] < '0' ||
249 p[1] > '7' ||
250 p[2] != '>'
252 p -= 3;
253 p[0] = '<';
254 p[1] = default_message_loglevel + '0';
255 p[2] = '>';
256 } else
257 msg += 3;
258 msg_level = p[1] - '0';
260 line_feed = 0;
261 for (; p < buf_end; p++) {
262 log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
263 if (log_size < LOG_BUF_LEN)
264 log_size++;
265 else {
266 log_start++;
267 log_start &= LOG_BUF_LEN-1;
269 logged_chars++;
270 if (*p == '\n') {
271 line_feed = 1;
272 break;
275 if (msg_level < console_loglevel && console_drivers) {
276 struct console *c = console_drivers;
277 while(c) {
278 if ((c->flags & CON_ENABLED) && c->write)
279 c->write(c, msg, p - msg + line_feed);
280 c = c->next;
283 if (line_feed)
284 msg_level = -1;
286 spin_unlock_irqrestore(&console_lock, flags);
287 wake_up_interruptible(&log_wait);
288 return i;
291 void console_print(const char *s)
293 struct console *c = console_drivers;
294 int len = strlen(s);
296 while(c) {
297 if ((c->flags & CON_ENABLED) && c->write)
298 c->write(c, s, len);
299 c = c->next;
303 void unblank_console(void)
305 struct console *c = console_drivers;
306 while(c) {
307 if ((c->flags & CON_ENABLED) && c->unblank)
308 c->unblank();
309 c = c->next;
314 * The console driver calls this routine during kernel initialization
315 * to register the console printing procedure with printk() and to
316 * print any messages that were printed by the kernel before the
317 * console driver was initialized.
319 void register_console(struct console * console)
321 int i,j,len;
322 int p = log_start;
323 char buf[16];
324 signed char msg_level = -1;
325 char *q;
328 * See if we want to use this console driver. If we
329 * didn't select a console we take the first one
330 * that registers here.
332 if (preferred_console < 0) {
333 if (console->index < 0)
334 console->index = 0;
335 if (console->setup == NULL ||
336 console->setup(console, NULL) == 0) {
337 console->flags |= CON_ENABLED | CON_CONSDEV;
338 preferred_console = 0;
343 * See if this console matches one we selected on
344 * the command line.
346 for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
347 if (strcmp(console_cmdline[i].name, console->name) != 0)
348 continue;
349 if (console->index >= 0 &&
350 console->index != console_cmdline[i].index)
351 continue;
352 if (console->index < 0)
353 console->index = console_cmdline[i].index;
354 if (console->setup &&
355 console->setup(console, console_cmdline[i].options) != 0)
356 break;
357 console->flags |= CON_ENABLED;
358 console->index = console_cmdline[i].index;
359 if (i == preferred_console)
360 console->flags |= CON_CONSDEV;
361 break;
364 if (!(console->flags & CON_ENABLED))
365 return;
368 * Put this console in the list - keep the
369 * preferred driver at the head of the list.
371 if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
372 console->next = console_drivers;
373 console_drivers = console;
374 } else {
375 console->next = console_drivers->next;
376 console_drivers->next = console;
378 if ((console->flags & CON_PRINTBUFFER) == 0) return;
381 * Print out buffered log messages.
383 for (i=0,j=0; i < log_size; i++) {
384 buf[j++] = log_buf[p];
385 p++; p &= LOG_BUF_LEN-1;
386 if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
387 continue;
388 buf[j] = 0;
389 q = buf;
390 len = j;
391 if (msg_level < 0) {
392 msg_level = buf[1] - '0';
393 q = buf + 3;
394 len -= 3;
396 if (msg_level < console_loglevel)
397 console->write(console, q, len);
398 if (buf[j-1] == '\n')
399 msg_level = -1;
400 j = 0;
405 int unregister_console(struct console * console)
407 struct console *a,*b;
409 if (console_drivers == console) {
410 console_drivers=console->next;
411 return (0);
413 for (a=console_drivers->next, b=console_drivers ;
414 a; b=a, a=b->next) {
415 if (a == console) {
416 b->next = a->next;
417 return 0;
421 return (1);
425 * Write a message to a certain tty, not just the console. This is used for
426 * messages that need to be redirected to a specific tty.
427 * We don't put it into the syslog queue right now maybe in the future if
428 * really needed.
430 void tty_write_message(struct tty_struct *tty, char *msg)
432 if (tty && tty->driver.write)
433 tty->driver.write(tty, 0, msg, strlen(msg));
434 return;