root/kernel/printk.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_syslog
  2. printk
  3. register_console

   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 
  23 #define LOG_BUF_LEN     4096
  24 
  25 static char buf[1024];
  26 
  27 extern void console_print(const char *);
  28 
  29 #define DEFAULT_MESSAGE_LOGLEVEL 7 /* KERN_DEBUG */
  30 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything more serious than KERN_DEBUG */
  31 
  32 unsigned long log_size = 0;
  33 struct wait_queue * log_wait = NULL;
  34 int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
  35 
  36 static void (*console_print_proc)(const char *) = 0;
  37 static char log_buf[LOG_BUF_LEN];
  38 static unsigned long log_start = 0;
  39 static unsigned long logged_chars = 0;
  40 
  41 /*
  42  * Commands to sys_syslog:
  43  *
  44  *      0 -- Close the log.  Currently a NOP.
  45  *      1 -- Open the log. Currently a NOP.
  46  *      2 -- Read from the log.
  47  *      3 -- Read up to the last 4k of messages in the ring buffer.
  48  *      4 -- Read and clear last 4k of messages in the ring buffer
  49  *      5 -- Clear ring buffer.
  50  *      6 -- Disable printk's to console
  51  *      7 -- Enable printk's to console
  52  *      8 -- Set level of messages printed to console
  53  */
  54 asmlinkage int sys_syslog(int type, char * buf, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56         unsigned long i, j, count;
  57         int do_clear = 0;
  58         char c;
  59         int error;
  60 
  61         if ((type != 3) && !suser())
  62                 return -EPERM;
  63         switch (type) {
  64                 case 0:         /* Close log */
  65                         return 0;
  66                 case 1:         /* Open log */
  67                         return 0;
  68                 case 2:         /* Read from log */
  69                         if (!buf || len < 0)
  70                                 return -EINVAL;
  71                         if (!len)
  72                                 return 0;
  73                         error = verify_area(VERIFY_WRITE,buf,len);
  74                         if (error)
  75                                 return error;
  76                         cli();
  77                         while (!log_size) {
  78                                 if (current->signal & ~current->blocked) {
  79                                         sti();
  80                                         return -ERESTARTSYS;
  81                                 }
  82                                 interruptible_sleep_on(&log_wait);
  83                         }
  84                         i = 0;
  85                         while (log_size && i < len) {
  86                                 c = *((char *) log_buf+log_start);
  87                                 log_start++;
  88                                 log_size--;
  89                                 log_start &= LOG_BUF_LEN-1;
  90                                 sti();
  91                                 put_fs_byte(c,buf);
  92                                 buf++;
  93                                 i++;
  94                                 cli();
  95                         }
  96                         sti();
  97                         return i;
  98                 case 4:         /* Read/clear last kernel messages */
  99                         do_clear = 1; 
 100                         /* FALL THRU */
 101                 case 3:         /* Read last kernel messages */
 102                         if (!buf || len < 0)
 103                                 return -EINVAL;
 104                         if (!len)
 105                                 return 0;
 106                         error = verify_area(VERIFY_WRITE,buf,len);
 107                         if (error)
 108                                 return error;
 109                         count = len;
 110                         if (count > LOG_BUF_LEN)
 111                                 count = LOG_BUF_LEN;
 112                         if (count > logged_chars)
 113                                 count = logged_chars;
 114                         j = log_start + log_size - count;
 115                         for (i = 0; i < count; i++) {
 116                                 c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
 117                                 put_fs_byte(c, buf++);
 118                         }
 119                         if (do_clear)
 120                                 logged_chars = 0;
 121                         return i;
 122                 case 5:         /* Clear ring buffer */
 123                         logged_chars = 0;
 124                         return 0;
 125                 case 6:         /* Disable logging to console */
 126                         console_loglevel = 1; /* only panic messages shown */
 127                         return 0;
 128                 case 7:         /* Enable logging to console */
 129                         console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
 130                         return 0;
 131                 case 8:
 132                         if (len < 0 || len > 8)
 133                                 return -EINVAL;
 134                         console_loglevel = len;
 135                         return 0;
 136         }
 137         return -EINVAL;
 138 }
 139 
 140 
 141 asmlinkage int printk(const char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         va_list args;
 144         int i;
 145         char *msg, *p, *buf_end;
 146         static char msg_level = -1;
 147         long flags;
 148 
 149         save_flags(flags);
 150         cli();
 151         va_start(args, fmt);
 152         i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
 153         buf_end = buf + 3 + i;
 154         va_end(args);
 155         for (p = buf + 3; p < buf_end; p++) {
 156                 msg = p;
 157                 if (msg_level < 0) {
 158                         if (
 159                                 p[0] != '<' ||
 160                                 p[1] < '0' || 
 161                                 p[1] > '7' ||
 162                                 p[2] != '>'
 163                         ) {
 164                                 p -= 3;
 165                                 p[0] = '<';
 166                                 p[1] = DEFAULT_MESSAGE_LOGLEVEL - 1 + '0';
 167                                 p[2] = '>';
 168                         } else
 169                                 msg += 3;
 170                         msg_level = p[1] - '0';
 171                 }
 172                 for (; p < buf_end; p++) {
 173                         log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
 174                         if (log_size < LOG_BUF_LEN)
 175                                 log_size++;
 176                         else {
 177                                 log_start++;
 178                                 log_start &= LOG_BUF_LEN-1;
 179                         }
 180                         logged_chars++;
 181                         if (*p == '\n')
 182                                 break;
 183                 }
 184                 if (msg_level < console_loglevel && console_print_proc) {
 185                         char tmp = p[1];
 186                         p[1] = '\0';
 187                         (*console_print_proc)(msg);
 188                         p[1] = tmp;
 189                 }
 190                 if (*p == '\n')
 191                         msg_level = -1;
 192         }
 193         restore_flags(flags);
 194         wake_up_interruptible(&log_wait);
 195         return i;
 196 }
 197 
 198 /*
 199  * The console driver calls this routine during kernel initialization
 200  * to register the console printing procedure with printk() and to
 201  * print any messages that were printed by the kernel before the
 202  * console driver was initialized.
 203  */
 204 void register_console(void (*proc)(const char *))
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206         int     i,j;
 207         int     p = log_start;
 208         char    buf[16];
 209         char    msg_level = -1;
 210         char    *q;
 211 
 212         console_print_proc = proc;
 213 
 214         for (i=0,j=0; i < log_size; i++) {
 215                 buf[j++] = log_buf[p];
 216                 p++; p &= LOG_BUF_LEN-1;
 217                 if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
 218                         continue;
 219                 buf[j] = 0;
 220                 q = buf;
 221                 if (msg_level < 0) {
 222                         msg_level = buf[1] - '0';
 223                         q = buf + 3;
 224                 }
 225                 if (msg_level < console_loglevel)
 226                         (*proc)(q);
 227                 if (buf[j-1] == '\n')
 228                         msg_level = -1;
 229                 j = 0;
 230         }
 231 }

/* [previous][next][first][last][top][bottom][index][help] */