/* * linux/kernel/printk.c * * (C) 1991 Linus Torvalds */ #include <stdarg.h> #include <stddef.h> #include <errno.h> #include <asm/segment.h> #include <asm/system.h> #include <linux/sched.h> #include <linux/kernel.h> static char buf[1024]; extern int vsprintf(char * buf, const char * fmt, va_list args); extern void console_print(const char *); static unsigned long log_page = 0; static unsigned long log_start = 0; static unsigned long log_size = 0; static struct task_struct * log_wait = NULL; int sys_syslog(int type, char * buf, int len) { unsigned long i; char c; if (!suser()) return -EPERM; switch (type) { case 0: i = log_page; log_page = 0; free_page(i); wake_up(&log_wait); return 0; case 1: i = get_free_page(); if (log_page) { free_page(i); return 0; } else if (log_page = i) { log_start = log_size = 0; return 0; } return -ENOMEM; case 2: if (!buf || len < 0) return -EINVAL; if (!len) return 0; verify_area(buf,len); while (!log_size) { if (!log_page) return -EIO; if (current->signal & ~current->blocked) return -ERESTARTSYS; cli(); if (!log_size) interruptible_sleep_on(&log_wait); sti(); } i = 0; while (log_size && len) { c = *((char *) log_page+log_start); log_start++; log_size--; log_start &= 4095; put_fs_byte(c,buf); buf++; i++; } return i; } return -EINVAL; } int printk(const char *fmt, ...) { va_list args; int i,j; char * p; va_start(args, fmt); i=vsprintf(buf,fmt,args); va_end(args); for (j = 0; j < i && log_page ; j++) { p = (char *) log_page + (4095 & (log_start+log_size)); *p = buf[j]; if (log_size < 4096) log_size++; else log_start++; } if (log_page) wake_up(&log_wait); console_print(buf); return i; }