1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)subr_log.c 7.14 (Berkeley) 05/20/92 8 */ 9 10 /* 11 * Error log buffer for kernel printf's. 12 */ 13 14 #include "param.h" 15 #include "proc.h" 16 #include "vnode.h" 17 #include "ioctl.h" 18 #include "msgbuf.h" 19 #include "file.h" 20 21 #define LOG_RDPRI (PZERO + 1) 22 23 #define LOG_ASYNC 0x04 24 #define LOG_RDWAIT 0x08 25 26 struct logsoftc { 27 int sc_state; /* see above for possibilities */ 28 struct selinfo sc_selp; /* process waiting on select call */ 29 int sc_pgid; /* process/group for async I/O */ 30 } logsoftc; 31 32 int log_open; /* also used in log() */ 33 34 /*ARGSUSED*/ 35 logopen(dev, flags, mode, p) 36 dev_t dev; 37 int flags, mode; 38 struct proc *p; 39 { 40 register struct msgbuf *mbp = msgbufp; 41 42 if (log_open) 43 return (EBUSY); 44 log_open = 1; 45 logsoftc.sc_pgid = p->p_pid; /* signal process only */ 46 /* 47 * Potential race here with putchar() but since putchar should be 48 * called by autoconf, msg_magic should be initialized by the time 49 * we get here. 50 */ 51 if (mbp->msg_magic != MSG_MAGIC) { 52 register int i; 53 54 mbp->msg_magic = MSG_MAGIC; 55 mbp->msg_bufx = mbp->msg_bufr = 0; 56 for (i=0; i < MSG_BSIZE; i++) 57 mbp->msg_bufc[i] = 0; 58 } 59 return (0); 60 } 61 62 /*ARGSUSED*/ 63 logclose(dev, flag, mode, p) 64 dev_t dev; 65 int flag, mode; 66 struct proc *p; 67 { 68 69 log_open = 0; 70 logsoftc.sc_state = 0; 71 return (0); 72 } 73 74 /*ARGSUSED*/ 75 logread(dev, uio, flag) 76 dev_t dev; 77 struct uio *uio; 78 int flag; 79 { 80 register struct msgbuf *mbp = msgbufp; 81 register long l; 82 register int s; 83 int error = 0; 84 85 s = splhigh(); 86 while (mbp->msg_bufr == mbp->msg_bufx) { 87 if (flag & IO_NDELAY) { 88 splx(s); 89 return (EWOULDBLOCK); 90 } 91 logsoftc.sc_state |= LOG_RDWAIT; 92 if (error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 93 "klog", 0)) { 94 splx(s); 95 return (error); 96 } 97 } 98 splx(s); 99 logsoftc.sc_state &= ~LOG_RDWAIT; 100 101 while (uio->uio_resid > 0) { 102 l = mbp->msg_bufx - mbp->msg_bufr; 103 if (l < 0) 104 l = MSG_BSIZE - mbp->msg_bufr; 105 l = MIN(l, uio->uio_resid); 106 if (l == 0) 107 break; 108 error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr], 109 (int)l, uio); 110 if (error) 111 break; 112 mbp->msg_bufr += l; 113 if (mbp->msg_bufr < 0 || mbp->msg_bufr >= MSG_BSIZE) 114 mbp->msg_bufr = 0; 115 } 116 return (error); 117 } 118 119 /*ARGSUSED*/ 120 logselect(dev, rw, p) 121 dev_t dev; 122 int rw; 123 struct proc *p; 124 { 125 int s = splhigh(); 126 127 switch (rw) { 128 129 case FREAD: 130 if (msgbufp->msg_bufr != msgbufp->msg_bufx) { 131 splx(s); 132 return (1); 133 } 134 selrecord(p, &logsoftc.sc_selp); 135 break; 136 } 137 splx(s); 138 return (0); 139 } 140 141 logwakeup() 142 { 143 struct proc *p; 144 145 if (!log_open) 146 return; 147 selwakeup(&logsoftc.sc_selp); 148 if (logsoftc.sc_state & LOG_ASYNC) { 149 if (logsoftc.sc_pgid < 0) 150 gsignal(-logsoftc.sc_pgid, SIGIO); 151 else if (p = pfind(logsoftc.sc_pgid)) 152 psignal(p, SIGIO); 153 } 154 if (logsoftc.sc_state & LOG_RDWAIT) { 155 wakeup((caddr_t)msgbufp); 156 logsoftc.sc_state &= ~LOG_RDWAIT; 157 } 158 } 159 160 /*ARGSUSED*/ 161 logioctl(dev, com, data, flag, p) 162 dev_t dev; 163 int com; 164 caddr_t data; 165 int flag; 166 struct proc *p; 167 { 168 long l; 169 int s; 170 171 switch (com) { 172 173 /* return number of characters immediately available */ 174 case FIONREAD: 175 s = splhigh(); 176 l = msgbufp->msg_bufx - msgbufp->msg_bufr; 177 splx(s); 178 if (l < 0) 179 l += MSG_BSIZE; 180 *(off_t *)data = l; 181 break; 182 183 case FIONBIO: 184 break; 185 186 case FIOASYNC: 187 if (*(int *)data) 188 logsoftc.sc_state |= LOG_ASYNC; 189 else 190 logsoftc.sc_state &= ~LOG_ASYNC; 191 break; 192 193 case TIOCSPGRP: 194 logsoftc.sc_pgid = *(int *)data; 195 break; 196 197 case TIOCGPGRP: 198 *(int *)data = logsoftc.sc_pgid; 199 break; 200 201 default: 202 return (-1); 203 } 204 return (0); 205 } 206