1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)subr_log.c 6.6 (Berkeley) 09/04/85 7 */ 8 9 /* 10 * Error log buffer for kernel printf's. 11 */ 12 13 #include "param.h" 14 #include "dir.h" 15 #include "user.h" 16 #include "proc.h" 17 #include "ioctl.h" 18 #include "msgbuf.h" 19 #include "file.h" 20 #include "errno.h" 21 22 #define LOG_RDPRI (PZERO + 1) 23 24 #define LOG_NBIO 0x02 25 #define LOG_ASYNC 0x04 26 #define LOG_RDWAIT 0x08 27 28 struct logsoftc { 29 int sc_state; /* see above for possibilities */ 30 struct proc *sc_selp; /* process waiting on select call */ 31 int sc_pgrp; /* process group for async I/O */ 32 } logsoftc; 33 34 int log_open; /* also used in log() */ 35 36 #ifdef LOGDEBUG 37 /*VARARGS1*/ 38 xprintf(fmt, x1) 39 char *fmt; 40 unsigned x1; 41 { 42 43 prf(fmt, &x1, 1, (struct tty *)0); 44 } 45 #endif 46 47 /*ARGSUSED*/ 48 logopen(dev) 49 dev_t dev; 50 { 51 52 #ifdef LOGDEBUG 53 xprintf("logopen: dev=0x%x\n", dev); 54 #endif 55 if (log_open) 56 return (EBUSY); 57 log_open = 1; 58 logsoftc.sc_selp = 0; 59 logsoftc.sc_pgrp = u.u_procp->p_pgrp; 60 /* 61 * Potential race here with putchar() but since putchar should be 62 * called by autoconf, msg_magic should be initialized by the time 63 * we get here. 64 */ 65 if (msgbuf.msg_magic != MSG_MAGIC) { 66 register int i; 67 68 msgbuf.msg_magic = MSG_MAGIC; 69 msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 70 for (i=0; i < MSG_BSIZE; i++) 71 msgbuf.msg_bufc[i] = 0; 72 } 73 #ifdef LOGDEBUG 74 xprintf("logopen: bufx=%d, bufr=%d\n", msgbuf.msg_bufx, msgbuf.msg_bufr); 75 #endif 76 return (0); 77 } 78 79 /*ARGSUSED*/ 80 logclose(dev, flag) 81 dev_t dev; 82 { 83 log_open = 0; 84 logsoftc.sc_state = 0; 85 logsoftc.sc_selp = 0; 86 logsoftc.sc_pgrp = 0; 87 #ifdef LOGDEBUG 88 xprintf("logclose: dev=0x%x\n", dev); 89 #endif 90 } 91 92 /*ARGSUSED*/ 93 logread(dev, uio) 94 dev_t dev; 95 struct uio *uio; 96 { 97 register long l; 98 register u_int c; 99 register int s; 100 int error = 0; 101 102 #ifdef LOGDEBUG 103 xprintf("logread: dev=0x%x\n", dev); 104 #endif 105 106 s = splhigh(); 107 while (msgbuf.msg_bufr == msgbuf.msg_bufx) { 108 if (logsoftc.sc_state & LOG_NBIO) { 109 splx(s); 110 return (EWOULDBLOCK); 111 } 112 logsoftc.sc_state |= LOG_RDWAIT; 113 sleep((caddr_t)&msgbuf, LOG_RDPRI); 114 } 115 splx(s); 116 logsoftc.sc_state &= ~LOG_RDWAIT; 117 118 while (uio->uio_resid > 0) { 119 l = msgbuf.msg_bufx - msgbuf.msg_bufr; 120 if (l < 0) 121 l = MSG_BSIZE - msgbuf.msg_bufr; 122 c = min((u_int) l, (u_int)uio->uio_resid); 123 #ifdef LOGDEBUG 124 xprintf("logread: bufx=%d, bufr=%d, l=%d, c=%d\n", 125 msgbuf.msg_bufx, msgbuf.msg_bufr, l, c); 126 #endif 127 if (c <= 0) 128 break; 129 error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr], 130 (int)c, UIO_READ, uio); 131 if (error) 132 break; 133 msgbuf.msg_bufr += c; 134 if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE) 135 msgbuf.msg_bufr = 0; 136 } 137 return (error); 138 } 139 140 /*ARGSUSED*/ 141 logselect(dev, rw) 142 dev_t dev; 143 int rw; 144 { 145 int s = splhigh(); 146 147 switch (rw) { 148 149 case FREAD: 150 if (msgbuf.msg_bufr != msgbuf.msg_bufx) 151 goto win; 152 #ifdef LOGDEBUG 153 if (logsoftc.sc_selp) 154 xprintf("logselect: collision\n"); 155 #endif 156 logsoftc.sc_selp = u.u_procp; 157 break; 158 159 case FWRITE: 160 #ifdef LOGDEBUG 161 xprintf("logselect: FWRITE\n"); 162 #endif 163 break; 164 } 165 splx(s); 166 return (0); 167 win: 168 splx(s); 169 return (1); 170 } 171 172 logwakeup() 173 { 174 175 if (!log_open) 176 return; 177 if (logsoftc.sc_selp) { 178 selwakeup(logsoftc.sc_selp, 0); 179 logsoftc.sc_selp = 0; 180 } 181 if (logsoftc.sc_state & LOG_ASYNC) 182 gsignal(logsoftc.sc_pgrp, SIGIO); 183 if (logsoftc.sc_state & LOG_RDWAIT) { 184 wakeup((caddr_t)&msgbuf); 185 logsoftc.sc_state &= ~LOG_RDWAIT; 186 } 187 } 188 189 /*ARGSUSED*/ 190 logioctl(com, data, flag) 191 caddr_t data; 192 { 193 long l; 194 int s; 195 196 switch (com) { 197 198 /* return number of characters immediately available */ 199 case FIONREAD: 200 s = splhigh(); 201 l = msgbuf.msg_bufx - msgbuf.msg_bufr; 202 splx(s); 203 if (l < 0) 204 l += MSG_BSIZE; 205 *(off_t *)data = l; 206 break; 207 208 case FIONBIO: 209 if (*(int *)data) 210 logsoftc.sc_state |= LOG_NBIO; 211 else 212 logsoftc.sc_state &= ~LOG_NBIO; 213 break; 214 215 case FIOASYNC: 216 if (*(int *)data) 217 logsoftc.sc_state |= LOG_ASYNC; 218 else 219 logsoftc.sc_state &= ~LOG_ASYNC; 220 break; 221 222 case TIOCSPGRP: 223 logsoftc.sc_pgrp = *(int *)data; 224 break; 225 226 case TIOCGPGRP: 227 *(int *)data = logsoftc.sc_pgrp; 228 break; 229 230 default: 231 return (-1); 232 } 233 return (0); 234 } 235