Annotation of Gnu-Mach/linux/src/kernel/printk.c, revision 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.