This source file includes following definitions.
- sys_syslog
- printk
- register_console
- tty_write_message
1
2
3
4
5
6
7
8
9
10
11
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 4096
27
28 static char buf[1024];
29
30 extern void console_print(const char *);
31
32
33 #define DEFAULT_MESSAGE_LOGLEVEL 5
34
35
36 #define MINIMUM_CONSOLE_LOGLEVEL 6
37 #define DEFAULT_CONSOLE_LOGLEVEL 6
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
50
51
52
53
54
55
56
57
58
59
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:
72 return 0;
73 case 1:
74 return 0;
75 case 2:
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:
106 do_clear = 1;
107
108 case 3:
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:
130 logged_chars = 0;
131 return 0;
132 case 6:
133 console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
134 return 0;
135 case 7:
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);
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
209
210
211
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
244
245
246
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 }