123379Smckusick /* 229099Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323379Smckusick * All rights reserved. The Berkeley software License Agreement 423379Smckusick * specifies the terms and conditions for redistribution. 523379Smckusick * 6*35810Smarc * @(#)subr_log.c 7.2 (Berkeley) 10/18/88 723379Smckusick */ 816723Sralph 916723Sralph /* 1016723Sralph * Error log buffer for kernel printf's. 1116723Sralph */ 1216723Sralph 1317093Sbloom #include "param.h" 1417093Sbloom #include "dir.h" 1517093Sbloom #include "user.h" 1617093Sbloom #include "proc.h" 1717093Sbloom #include "ioctl.h" 1817093Sbloom #include "msgbuf.h" 1917093Sbloom #include "file.h" 2017093Sbloom #include "errno.h" 2116723Sralph 2216723Sralph #define LOG_RDPRI (PZERO + 1) 2316723Sralph 2416723Sralph #define LOG_NBIO 0x02 2516723Sralph #define LOG_ASYNC 0x04 2616723Sralph #define LOG_RDWAIT 0x08 2716723Sralph 2816723Sralph struct logsoftc { 2916723Sralph int sc_state; /* see above for possibilities */ 3016723Sralph struct proc *sc_selp; /* process waiting on select call */ 31*35810Smarc pid_t sc_pgid; /* process group id for async I/O */ 3216723Sralph } logsoftc; 3316723Sralph 3418365Skarels int log_open; /* also used in log() */ 3518365Skarels 3624524Sbloom /*ARGSUSED*/ 3716723Sralph logopen(dev) 3816723Sralph dev_t dev; 3916723Sralph { 4016723Sralph 4118365Skarels if (log_open) 4216725Sralph return (EBUSY); 4318365Skarels log_open = 1; 4416723Sralph logsoftc.sc_selp = 0; 45*35810Smarc logsoftc.sc_pgid = u.u_procp->p_pgrp->pg_id; 4616723Sralph /* 4716723Sralph * Potential race here with putchar() but since putchar should be 4816723Sralph * called by autoconf, msg_magic should be initialized by the time 4916723Sralph * we get here. 5016723Sralph */ 5116723Sralph if (msgbuf.msg_magic != MSG_MAGIC) { 5216723Sralph register int i; 5316723Sralph 5416723Sralph msgbuf.msg_magic = MSG_MAGIC; 5516723Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 5616723Sralph for (i=0; i < MSG_BSIZE; i++) 5716723Sralph msgbuf.msg_bufc[i] = 0; 5816723Sralph } 5916725Sralph return (0); 6016723Sralph } 6116723Sralph 6224524Sbloom /*ARGSUSED*/ 6316723Sralph logclose(dev, flag) 6416723Sralph dev_t dev; 6516723Sralph { 6618365Skarels log_open = 0; 6716723Sralph logsoftc.sc_state = 0; 6816723Sralph logsoftc.sc_selp = 0; 69*35810Smarc logsoftc.sc_pgid = 0; 7016723Sralph } 7116723Sralph 7224524Sbloom /*ARGSUSED*/ 7316723Sralph logread(dev, uio) 7416723Sralph dev_t dev; 7516723Sralph struct uio *uio; 7616723Sralph { 7716723Sralph register long l; 7816723Sralph register int s; 7916723Sralph int error = 0; 8016723Sralph 8116723Sralph s = splhigh(); 8216723Sralph while (msgbuf.msg_bufr == msgbuf.msg_bufx) { 8316723Sralph if (logsoftc.sc_state & LOG_NBIO) { 8416723Sralph splx(s); 8516725Sralph return (EWOULDBLOCK); 8616723Sralph } 8716723Sralph logsoftc.sc_state |= LOG_RDWAIT; 8816723Sralph sleep((caddr_t)&msgbuf, LOG_RDPRI); 8916723Sralph } 9016723Sralph splx(s); 9116723Sralph logsoftc.sc_state &= ~LOG_RDWAIT; 9216723Sralph 9316723Sralph while (uio->uio_resid > 0) { 9416723Sralph l = msgbuf.msg_bufx - msgbuf.msg_bufr; 9516723Sralph if (l < 0) 9616723Sralph l = MSG_BSIZE - msgbuf.msg_bufr; 9726356Skarels l = MIN(l, uio->uio_resid); 9826249Skarels if (l == 0) 9916725Sralph break; 10016723Sralph error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr], 10126249Skarels (int)l, UIO_READ, uio); 10216723Sralph if (error) 10316723Sralph break; 10426249Skarels msgbuf.msg_bufr += l; 10516723Sralph if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE) 10616723Sralph msgbuf.msg_bufr = 0; 10716723Sralph } 10816725Sralph return (error); 10916723Sralph } 11016723Sralph 11124524Sbloom /*ARGSUSED*/ 11216723Sralph logselect(dev, rw) 11316723Sralph dev_t dev; 11416723Sralph int rw; 11516723Sralph { 11616723Sralph int s = splhigh(); 11716723Sralph 11816723Sralph switch (rw) { 11916723Sralph 12016723Sralph case FREAD: 12126249Skarels if (msgbuf.msg_bufr != msgbuf.msg_bufx) { 12226249Skarels splx(s); 12326249Skarels return (1); 12426249Skarels } 12516723Sralph logsoftc.sc_selp = u.u_procp; 12616723Sralph break; 12716723Sralph } 12816723Sralph splx(s); 12916725Sralph return (0); 13016723Sralph } 13116723Sralph 13216723Sralph logwakeup() 13316723Sralph { 13416723Sralph 13518365Skarels if (!log_open) 13618365Skarels return; 13716723Sralph if (logsoftc.sc_selp) { 13816723Sralph selwakeup(logsoftc.sc_selp, 0); 13916723Sralph logsoftc.sc_selp = 0; 14016723Sralph } 14116723Sralph if (logsoftc.sc_state & LOG_ASYNC) 142*35810Smarc gsignal(logsoftc.sc_pgid, SIGIO); 14316723Sralph if (logsoftc.sc_state & LOG_RDWAIT) { 14416723Sralph wakeup((caddr_t)&msgbuf); 14516723Sralph logsoftc.sc_state &= ~LOG_RDWAIT; 14616723Sralph } 14716723Sralph } 14816723Sralph 14916723Sralph /*ARGSUSED*/ 15016723Sralph logioctl(com, data, flag) 15116723Sralph caddr_t data; 15216723Sralph { 15316723Sralph long l; 15416723Sralph int s; 15516723Sralph 15616723Sralph switch (com) { 15716723Sralph 15816723Sralph /* return number of characters immediately available */ 15916723Sralph case FIONREAD: 16016723Sralph s = splhigh(); 16116723Sralph l = msgbuf.msg_bufx - msgbuf.msg_bufr; 16216723Sralph splx(s); 16316723Sralph if (l < 0) 16416723Sralph l += MSG_BSIZE; 16516723Sralph *(off_t *)data = l; 16616723Sralph break; 16716723Sralph 16816723Sralph case FIONBIO: 16916723Sralph if (*(int *)data) 17016723Sralph logsoftc.sc_state |= LOG_NBIO; 17116723Sralph else 17216723Sralph logsoftc.sc_state &= ~LOG_NBIO; 17316723Sralph break; 17416723Sralph 17516723Sralph case FIOASYNC: 17616723Sralph if (*(int *)data) 17716723Sralph logsoftc.sc_state |= LOG_ASYNC; 17816723Sralph else 17916723Sralph logsoftc.sc_state &= ~LOG_ASYNC; 18016723Sralph break; 18116723Sralph 182*35810Smarc case TIOCSPGRP: { 183*35810Smarc logsoftc.sc_pgid = *(int *)data; 18416723Sralph break; 185*35810Smarc } 18616723Sralph 18716723Sralph case TIOCGPGRP: 188*35810Smarc *(int *)data = logsoftc.sc_pgid; 18916723Sralph break; 19016723Sralph 19116723Sralph default: 19216725Sralph return (-1); 19316723Sralph } 19416725Sralph return (0); 19516723Sralph } 196