|
|
1.1 root 1: /*
2: * linux/kernel/printk.c
3: *
4: * Copyright (C) 1991, 1992 Linus Torvalds
5: *
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: */
13:
14: #include <stdarg.h>
15:
16: #include <asm/segment.h>
17: #include <asm/system.h>
18:
19: #include <linux/errno.h>
20: #include <linux/sched.h>
21: #include <linux/kernel.h>
22: #include <linux/mm.h>
23: #include <linux/tty.h>
24: #include <linux/tty_driver.h>
25:
26: #define LOG_BUF_LEN 8192
27:
28: static char buf[1024];
29:
30: extern void console_print(const char *);
31:
32: /* printk's without a loglevel use this.. */
33: #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
34:
35: /* We show everything that is MORE important than this.. */
36: #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
37: #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
38:
39: unsigned long log_size = 0;
40: struct wait_queue * log_wait = NULL;
41: int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
42:
43: static void (*console_print_proc)(const char *) = 0;
44: static char log_buf[LOG_BUF_LEN];
45: static unsigned long log_start = 0;
46: static unsigned long logged_chars = 0;
47:
48: /*
49: * Commands to sys_syslog:
50: *
51: * 0 -- Close the log. Currently a NOP.
52: * 1 -- Open the log. Currently a NOP.
53: * 2 -- Read from the log.
54: * 3 -- Read up to the last 4k of messages in the ring buffer.
55: * 4 -- Read and clear last 4k of messages in the ring buffer
56: * 5 -- Clear ring buffer.
57: * 6 -- Disable printk's to console
58: * 7 -- Enable printk's to console
59: * 8 -- Set level of messages printed to console
60: */
61: asmlinkage int sys_syslog(int type, char * buf, int len)
62: {
63: unsigned long i, j, count;
64: int do_clear = 0;
65: char c;
66: int error;
67:
68: if ((type != 3) && !suser())
69: return -EPERM;
70: switch (type) {
71: case 0: /* Close log */
72: return 0;
73: case 1: /* Open log */
74: return 0;
75: case 2: /* Read from log */
76: if (!buf || len < 0)
77: return -EINVAL;
78: if (!len)
79: return 0;
80: error = verify_area(VERIFY_WRITE,buf,len);
81: if (error)
82: return error;
83: cli();
84: while (!log_size) {
85: if (current->signal & ~current->blocked) {
86: sti();
87: return -ERESTARTSYS;
88: }
89: interruptible_sleep_on(&log_wait);
90: }
91: i = 0;
92: while (log_size && i < len) {
93: c = *((char *) log_buf+log_start);
94: log_start++;
95: log_size--;
96: log_start &= LOG_BUF_LEN-1;
97: sti();
98: put_user(c,buf);
99: buf++;
100: i++;
101: cli();
102: }
103: sti();
104: return i;
105: case 4: /* Read/clear last kernel messages */
106: do_clear = 1;
107: /* FALL THRU */
108: case 3: /* Read last kernel messages */
109: if (!buf || len < 0)
110: return -EINVAL;
111: if (!len)
112: return 0;
113: error = verify_area(VERIFY_WRITE,buf,len);
114: if (error)
115: return error;
116: count = len;
117: if (count > LOG_BUF_LEN)
118: count = LOG_BUF_LEN;
119: if (count > logged_chars)
120: count = logged_chars;
121: j = log_start + log_size - count;
122: for (i = 0; i < count; i++) {
123: c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
124: put_user(c, buf++);
125: }
126: if (do_clear)
127: logged_chars = 0;
128: return i;
129: case 5: /* Clear ring buffer */
130: logged_chars = 0;
131: return 0;
132: case 6: /* Disable logging to console */
133: console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
134: return 0;
135: case 7: /* Enable logging to console */
136: console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
137: return 0;
138: case 8:
139: if (len < 1 || len > 8)
140: return -EINVAL;
141: if (len < MINIMUM_CONSOLE_LOGLEVEL)
142: len = MINIMUM_CONSOLE_LOGLEVEL;
143: console_loglevel = len;
144: return 0;
145: }
146: return -EINVAL;
147: }
148:
149:
150: asmlinkage int printk(const char *fmt, ...)
151: {
152: va_list args;
153: int i;
154: char *msg, *p, *buf_end;
155: static char msg_level = -1;
156: long flags;
157:
158: save_flags(flags);
159: cli();
160: va_start(args, fmt);
161: i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
162: buf_end = buf + 3 + i;
163: va_end(args);
164: for (p = buf + 3; p < buf_end; p++) {
165: msg = p;
166: if (msg_level < 0) {
167: if (
168: p[0] != '<' ||
169: p[1] < '0' ||
170: p[1] > '7' ||
171: p[2] != '>'
172: ) {
173: p -= 3;
174: p[0] = '<';
175: p[1] = DEFAULT_MESSAGE_LOGLEVEL + '0';
176: p[2] = '>';
177: } else
178: msg += 3;
179: msg_level = p[1] - '0';
180: }
181: for (; p < buf_end; p++) {
182: log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
183: if (log_size < LOG_BUF_LEN)
184: log_size++;
185: else {
186: log_start++;
187: log_start &= LOG_BUF_LEN-1;
188: }
189: logged_chars++;
190: if (*p == '\n')
191: break;
192: }
193: if (msg_level < console_loglevel && console_print_proc) {
194: char tmp = p[1];
195: p[1] = '\0';
196: (*console_print_proc)(msg);
197: p[1] = tmp;
198: }
199: if (*p == '\n')
200: msg_level = -1;
201: }
202: restore_flags(flags);
203: wake_up_interruptible(&log_wait);
204: return i;
205: }
206:
207: /*
208: * The console driver calls this routine during kernel initialization
209: * to register the console printing procedure with printk() and to
210: * print any messages that were printed by the kernel before the
211: * console driver was initialized.
212: */
213: void register_console(void (*proc)(const char *))
214: {
215: int i,j;
216: int p = log_start;
217: char buf[16];
218: char msg_level = -1;
219: char *q;
220:
221: console_print_proc = proc;
222:
223: for (i=0,j=0; i < log_size; i++) {
224: buf[j++] = log_buf[p];
225: p++; p &= LOG_BUF_LEN-1;
226: if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
227: continue;
228: buf[j] = 0;
229: q = buf;
230: if (msg_level < 0) {
231: msg_level = buf[1] - '0';
232: q = buf + 3;
233: }
234: if (msg_level < console_loglevel)
235: (*proc)(q);
236: if (buf[j-1] == '\n')
237: msg_level = -1;
238: j = 0;
239: }
240: }
241:
242: /*
243: * Write a message to a certain tty, not just the console. This is used for
244: * messages that need to be redirected to a specific tty.
245: * We don't put it into the syslog queue right now maybe in the future if
246: * really needed.
247: */
248: void tty_write_message(struct tty_struct *tty, char *msg)
249: {
250: if (tty && tty->driver.write)
251: tty->driver.write(tty, 0, msg, strlen(msg));
252: return;
253: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.