subr_log.c revision 41087
16562Sphk/*
237421Scharnier * Copyright (c) 1982, 1986, 1993
36562Sphk *	The Regents of the University of California.  All rights reserved.
46562Sphk *
53995Spst * Redistribution and use in source and binary forms, with or without
63995Spst * modification, are permitted provided that the following conditions
76562Sphk * are met:
86562Sphk * 1. Redistributions of source code must retain the above copyright
96562Sphk *    notice, this list of conditions and the following disclaimer.
106562Sphk * 2. Redistributions in binary form must reproduce the above copyright
116562Sphk *    notice, this list of conditions and the following disclaimer in the
126562Sphk *    documentation and/or other materials provided with the distribution.
136562Sphk * 3. All advertising materials mentioning features or use of this software
146562Sphk *    must display the following acknowledgement:
156562Sphk *	This product includes software developed by the University of
166562Sphk *	California, Berkeley and its contributors.
176562Sphk * 4. Neither the name of the University nor the names of its contributors
183995Spst *    may be used to endorse or promote products derived from this software
193995Spst *    without specific prior written permission.
2037421Scharnier *
2137421Scharnier * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2250476Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2337421Scharnier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2437421Scharnier * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2519168Sbde * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2637421Scharnier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2719168Sbde * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
283995Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2978949Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3078949Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313995Spst * SUCH DAMAGE.
3232074Ssteve *
3319168Sbde *	@(#)subr_log.c	8.1 (Berkeley) 6/10/93
346562Sphk * $Id: subr_log.c,v 1.31 1998/11/11 10:03:55 truckman Exp $
356562Sphk */
363995Spst
3746226Skris/*
3846226Skris * Error log buffer for kernel printf's.
393995Spst */
4054109Sobrien
4152949Sobrien#include "opt_devfs.h"
4288226Sphk
4352949Sobrien#include <sys/param.h>
4476988Sru#include <sys/systm.h>
4576988Sru#include <sys/conf.h>
4676988Sru#include <sys/proc.h>
4776988Sru#include <sys/vnode.h>
4876988Sru#include <sys/filio.h>
493995Spst#include <sys/ttycom.h>
503995Spst#include <sys/msgbuf.h>
513995Spst#include <sys/signalvar.h>
523995Spst#include <sys/kernel.h>
533995Spst#include <sys/poll.h>
543995Spst#include <sys/filedesc.h>
553995Spst#ifdef DEVFS
563995Spst#include <sys/devfsext.h>
573995Spst#endif /*DEVFS*/
583995Spst
596562Sphk#define LOG_RDPRI	(PZERO + 1)
6076988Sru
613995Spst#define LOG_ASYNC	0x04
6232086Ssteve#define LOG_RDWAIT	0x08
636562Sphk
649489Sphkstatic	d_open_t	logopen;
653995Spststatic	d_close_t	logclose;
6678756Srustatic	d_read_t	logread;
6776988Srustatic	d_ioctl_t	logioctl;
6876988Srustatic	d_poll_t	logpoll;
6976988Sru
7076988Sru#define CDEV_MAJOR 7
7176988Srustatic struct cdevsw log_cdevsw =
7276988Sru	{ logopen,	logclose,	logread,	nowrite,	/*7*/
7376988Sru	  logioctl,	nostop,		nullreset,	nodevtotty,/* klog */
7476988Sru	  logpoll,	nommap,		NULL,	"log",	NULL,	-1 };
7576988Sru
7676988Srustatic struct logsoftc {
7776988Sru	int	sc_state;		/* see above for possibilities */
7888226Sphk	struct	selinfo sc_selp;	/* process waiting on select call */
7976988Sru	struct  sigio *sc_sigio;	/* information for async I/O */
8076988Sru} logsoftc;
8176988Sru
8276988Sruint	log_open;			/* also used in log() */
8376988Sru
8476988Sru/*ARGSUSED*/
8576988Srustatic	int
8676988Srulogopen(dev, flags, mode, p)
8776988Sru	dev_t dev;
8876988Sru	int flags, mode;
8932074Ssteve	struct proc *p;
9076988Sru{
9176988Sru	if (log_open)
9276988Sru		return (EBUSY);
9376988Sru	log_open = 1;
9476988Sru	fsetown(p->p_pid, &logsoftc.sc_sigio);	/* signal process only */
9576988Sru	return (0);
9632074Ssteve}
9776988Sru
9832074Ssteve/*ARGSUSED*/
9954109Sobrienstatic	int
10054109Sobrienlogclose(dev, flag, mode, p)
10154109Sobrien	dev_t dev;
10276988Sru	int flag, mode;
10352949Sobrien	struct proc *p;
10476988Sru{
10576988Sru
10688226Sphk	log_open = 0;
1076725Sphk	logsoftc.sc_state = 0;
1083995Spst	funsetown(logsoftc.sc_sigio);
1096562Sphk	return (0);
1103995Spst}
1116562Sphk
1126562Sphk/*ARGSUSED*/
1133995Spststatic	int
1146562Sphklogread(dev, uio, flag)
11576988Sru	dev_t dev;
1163995Spst	struct uio *uio;
11748953Sbillf	int flag;
1189489Sphk{
1193995Spst	register struct msgbuf *mbp = msgbufp;
12054109Sobrien	register long l;
12154109Sobrien	register int s;
12254109Sobrien	int error = 0;
12353092Sobrien
12452949Sobrien	s = splhigh();
12552949Sobrien	while (mbp->msg_bufr == mbp->msg_bufx) {
1263995Spst		if (flag & IO_NDELAY) {
1276562Sphk			splx(s);
1286562Sphk			return (EWOULDBLOCK);
1293995Spst		}
1306562Sphk		logsoftc.sc_state |= LOG_RDWAIT;
13176988Sru		if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH,
1323995Spst		    "klog", 0))) {
1336562Sphk			splx(s);
1346562Sphk			return (error);
1356725Sphk		}
1366562Sphk	}
1379489Sphk	splx(s);
1383995Spst	logsoftc.sc_state &= ~LOG_RDWAIT;
1396562Sphk
1406562Sphk	while (uio->uio_resid > 0) {
14121763Sphk		l = mbp->msg_bufx - mbp->msg_bufr;
14246226Skris		if (l < 0)
1433995Spst			l = mbp->msg_size - mbp->msg_bufr;
1446562Sphk		l = min(l, uio->uio_resid);
1456562Sphk		if (l == 0)
1466562Sphk			break;
1473995Spst		error = uiomove((caddr_t)msgbufp->msg_ptr + mbp->msg_bufr,
1486562Sphk		    (int)l, uio);
1496562Sphk		if (error)
1503995Spst			break;
1516562Sphk		mbp->msg_bufr += l;
1526562Sphk		if (mbp->msg_bufr >= mbp->msg_size)
1536562Sphk			mbp->msg_bufr = 0;
1546562Sphk	}
1559489Sphk	return (error);
1563995Spst}
1576562Sphk
1586562Sphk/*ARGSUSED*/
1593995Spststatic	int
1606562Sphklogpoll(dev, events, p)
1616562Sphk	dev_t dev;
1626562Sphk	int events;
1636562Sphk	struct proc *p;
1646562Sphk{
1656562Sphk	int s;
1666562Sphk	int revents = 0;
16785611Sdillon
1683995Spst	s = splhigh();
1696562Sphk
1706562Sphk	if (events & (POLLIN | POLLRDNORM))
1713995Spst		if (msgbufp->msg_bufr != msgbufp->msg_bufx)
172109870Ssilby			revents |= events & (POLLIN | POLLRDNORM);
173109870Ssilby		else
174109870Ssilby			selrecord(p, &logsoftc.sc_selp);
175109870Ssilby
176109870Ssilby	splx(s);
177109870Ssilby	return (revents);
178109870Ssilby}
179109870Ssilby
180109870Ssilbyvoid
181109870Ssilbylogwakeup()
182109870Ssilby{
183109870Ssilby	struct proc *p;
184109870Ssilby
185109870Ssilby	if (!log_open)
186109870Ssilby		return;
187109870Ssilby	selwakeup(&logsoftc.sc_selp);
188109870Ssilby	if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL)
189109870Ssilby		pgsigio(logsoftc.sc_sigio, SIGIO, 0);
190109870Ssilby	if (logsoftc.sc_state & LOG_RDWAIT) {
191109870Ssilby		wakeup((caddr_t)msgbufp);
192109870Ssilby		logsoftc.sc_state &= ~LOG_RDWAIT;
193109870Ssilby	}
194109870Ssilby}
195109870Ssilby
196109870Ssilby/*ARGSUSED*/
1976562Sphkstatic	int
19876988Srulogioctl(dev, com, data, flag, p)
1993995Spst	dev_t dev;
200109870Ssilby	u_long com;
201109870Ssilby	caddr_t data;
20232086Ssteve	int flag;
2036562Sphk	struct proc *p;
204109870Ssilby{
205109870Ssilby	long l;
206109870Ssilby	int s;
207109870Ssilby
208109870Ssilby	switch (com) {
209109870Ssilby
210109870Ssilby	/* return number of characters immediately available */
211109870Ssilby	case FIONREAD:
2123995Spst		s = splhigh();
2133995Spst		l = msgbufp->msg_bufx - msgbufp->msg_bufr;
2146562Sphk		splx(s);
2156562Sphk		if (l < 0)
2163995Spst			l += msgbufp->msg_size;
2176562Sphk		*(int *)data = l;
21876988Sru		break;
2193995Spst
2206562Sphk	case FIONBIO:
22176988Sru		break;
22232074Ssteve
2239489Sphk	case FIOASYNC:
2243995Spst		if (*(int *)data)
2256562Sphk			logsoftc.sc_state |= LOG_ASYNC;
22632074Ssteve		else
22776988Sru			logsoftc.sc_state &= ~LOG_ASYNC;
22837421Scharnier		break;
2296562Sphk
2306725Sphk	case FIOSETOWN:
2319489Sphk		return (fsetown(*(int *)data, &logsoftc.sc_sigio));
2323995Spst
23332074Ssteve	case FIOGETOWN:
23432074Ssteve		*(int *)data = fgetown(logsoftc.sc_sigio);
23576988Sru		break;
23632074Ssteve
23732086Ssteve	/* This is deprecated, FIOSETOWN should be used instead. */
23868503Sobrien	case TIOCSPGRP:
23932074Ssteve		return (fsetown(-(*(int *)data), &logsoftc.sc_sigio));
24032074Ssteve
241	/* This is deprecated, FIOGETOWN should be used instead */
242	case TIOCGPGRP:
243		*(int *)data = -fgetown(logsoftc.sc_sigio);
244		break;
245
246	default:
247		return (ENOTTY);
248	}
249	return (0);
250}
251
252static	int	log_devsw_installed;
253#ifdef DEVFS
254static	void	*log_devfs_token;
255#endif
256
257static void log_drvinit __P((void *unused));
258static void
259log_drvinit(unused)
260	void *unused;
261{
262	dev_t dev;
263
264	if( ! log_devsw_installed ) {
265		dev = makedev(CDEV_MAJOR,0);
266		cdevsw_add(&dev,&log_cdevsw,NULL);
267		log_devsw_installed = 1;
268#ifdef DEVFS
269		log_devfs_token = devfs_add_devswf(&log_cdevsw, 0, DV_CHR,
270						   UID_ROOT, GID_WHEEL, 0600,
271						   "klog");
272#endif
273    	}
274}
275
276SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL)
277