Annotation of Gnu-Mach/linux/src/kernel/printk.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.