1: /*
   2:  * Copyright (c) 1982, 1986 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	2.1 (2.11BSD) 1999/4/29
   7:  */
   8: 
   9: /*
  10:  * logioctl() had the wrong number of arguments.  Argh!  Apparently this
  11:  * driver was overlooked when 'dev' was added to ioctl entry points.
  12:  *
  13:  * logclose() returned garbage.  this went unnoticed because most programs
  14:  * don't check status when doing a close.
  15: 
  16:  * Remove vax ifdefs - this driver is never going back to vaxland.
  17:  *
  18:  * Add support for multiple log devices.  Minor device 0 is the traditional
  19:  * kernel logger (/dev/klog), minor device 1 is reserved for the future device
  20:  * error logging daemon.  Minor device 2 is used by the 'accounting' daemon
  21:  * 'acctd'.
  22:  */
  23: 
  24: #define NLOG    3
  25:     int nlog = NLOG;
  26: 
  27: #include "param.h"
  28: #include "user.h"
  29: #include "proc.h"
  30: #include "ioctl.h"
  31: #include "msgbuf.h"
  32: #include "file.h"
  33: #include "inode.h"
  34: #include "errno.h"
  35: #include "uio.h"
  36: #include "machine/seg.h"
  37: #include "map.h"
  38: 
  39: #define LOG_RDPRI   (PZERO + 1)
  40: 
  41: #define LOG_OPEN    0x01
  42: #define LOG_ASYNC   0x04
  43: #define LOG_RDWAIT  0x08
  44: 
  45: /*
  46:  * This is an efficiency hack.  This global is provided for exit() to
  47:  * test and avoid the overhead of function calls when accounting is
  48:  * turned off.
  49: */
  50:     int Acctopen;
  51: 
  52:     struct  msgbuf  msgbuf[NLOG];
  53:     static  struct logsoftc
  54:         {
  55:         int sc_state;   /* see above for possibilities */
  56:         struct  proc *sc_selp;  /* process waiting on select call */
  57:         int sc_pgid;    /* process/group for async I/O */
  58:         int sc_overrun; /* full buffer count */
  59:         } logsoftc[NLOG];
  60: 
  61: /*ARGSUSED*/
  62: logopen(dev, mode)
  63:     dev_t dev;
  64:     int mode;
  65:     {
  66:     register int    unit = minor(dev);
  67: 
  68:     if  (unit >= NLOG)
  69:         return(ENODEV);
  70:     if  (logisopen(unit))
  71:         return(EBUSY);
  72:     if  (msgbuf[unit].msg_click == 0)   /* no buffer allocated */
  73:         return(ENOMEM);
  74:     logsoftc[unit].sc_state |= LOG_OPEN;
  75:     if  (unit == logACCT)
  76:         Acctopen = 1;
  77:     logsoftc[unit].sc_pgid = u.u_procp->p_pid;  /* signal process only */
  78:     logsoftc[unit].sc_overrun = 0;
  79:     return(0);
  80:     }
  81: 
  82: /*ARGSUSED*/
  83: logclose(dev, flag)
  84:     dev_t   dev;
  85:     int flag;
  86:     {
  87:     register int unit = minor(dev);
  88: 
  89:     logsoftc[unit].sc_state = 0;
  90:     if  (unit == logACCT)
  91:         Acctopen = 0;
  92:     return(0);
  93:     }
  94: 
  95: /*
  96:  * This is a helper function to keep knowledge of this driver's data
  97:  * structures away from the rest of the kernel.
  98: */
  99: logisopen(unit)
 100:     int unit;
 101:     {
 102: 
 103:     if  (logsoftc[unit].sc_state & LOG_OPEN)
 104:         return(1);
 105:     return(0);
 106:     }
 107: 
 108: /*ARGSUSED*/
 109: logread(dev, uio, flag)
 110:     dev_t dev;
 111:     struct uio *uio;
 112:     int flag;
 113:     {
 114:     register int l;
 115:     register struct logsoftc *lp;
 116:     register struct msgbuf *mp;
 117:     int s, error = 0;
 118:     char    buf[ctob(2)];
 119: 
 120:     l = minor(dev);
 121:     lp = &logsoftc[l];
 122:     mp = &msgbuf[l];
 123:     s = splhigh();
 124:     while   (mp->msg_bufr == mp->msg_bufx)
 125:         {
 126:         if  (flag & IO_NDELAY)
 127:             {
 128:             splx(s);
 129:             return(EWOULDBLOCK);
 130:             }
 131:         lp->sc_state |= LOG_RDWAIT;
 132:         sleep((caddr_t)mp, LOG_RDPRI);
 133:         }
 134:     lp->sc_state &= ~LOG_RDWAIT;
 135: 
 136:     while   (uio->uio_resid)
 137:         {
 138:         l = mp->msg_bufx - mp->msg_bufr;
 139: /*
 140:  * If the reader and writer are equal then we have caught up and there
 141:  * is nothing more to transfer.
 142: */
 143:         if  (l == 0)
 144:             break;
 145: /*
 146:  * If the write pointer is behind the reader then only consider as
 147:  * available for now the bytes from the read pointer thru the end of
 148:  * the buffer.
 149: */
 150:         if  (l < 0)
 151:             {
 152:             l = MSG_BSIZE - mp->msg_bufr;
 153: /*
 154:  * If the reader is exactly at the end of the buffer it is
 155:  * time to wrap it around to the beginning and recalculate the
 156:  * amount of data to transfer.
 157: */
 158:             if  (l == 0)
 159:                 {
 160:                 mp->msg_bufr = 0;
 161:                 continue;
 162:                 }
 163:             }
 164:         l = MIN(l, uio->uio_resid);
 165:         l = MIN(l, sizeof buf);
 166:         mapseg5(mp->msg_click, (btoc(MSG_BSIZE) << 8) | RW);
 167:         bcopy(&mp->msg_bufc[mp->msg_bufr], buf, l);
 168:         normalseg5();
 169:         error = uiomove(buf, l, uio);
 170:         if  (error)
 171:             break;
 172:         mp->msg_bufr += l;
 173:         }
 174:     splx(s);
 175:     return(error);
 176:     }
 177: 
 178: /*ARGSUSED*/
 179: logselect(dev, rw)
 180:     dev_t dev;
 181:     int rw;
 182:     {
 183:     register int s = splhigh();
 184:     int unit = minor(dev);
 185: 
 186:     switch  (rw)
 187:         {
 188:         case    FREAD:
 189:             if  (msgbuf[unit].msg_bufr != msgbuf[unit].msg_bufx)
 190:                 {
 191:                 splx(s);
 192:                 return(1);
 193:                 }
 194:             logsoftc[unit].sc_selp = u.u_procp;
 195:             break;
 196:         }
 197:     splx(s);
 198:     return(0);
 199:     }
 200: 
 201: logwakeup(unit)
 202:     int unit;
 203:     {
 204:     register struct proc *p;
 205:     register struct logsoftc *lp;
 206:     register struct msgbuf *mp;
 207: 
 208:     if  (!logisopen(unit))
 209:         return;
 210:     lp = &logsoftc[unit];
 211:     mp = &msgbuf[unit];
 212:     if  (lp->sc_selp)
 213:         {
 214:         selwakeup(lp->sc_selp, (long) 0);
 215:         lp->sc_selp = 0;
 216:         }
 217:     if  (lp->sc_state & LOG_ASYNC && (mp->msg_bufx != mp->msg_bufr))
 218:         {
 219:         if  (lp->sc_pgid < 0)
 220:             gsignal(-lp->sc_pgid, SIGIO);
 221:         else if (p = pfind(lp->sc_pgid))
 222:             psignal(p, SIGIO);
 223:         }
 224:     if  (lp->sc_state & LOG_RDWAIT)
 225:         {
 226:         wakeup((caddr_t)mp);
 227:         lp->sc_state &= ~LOG_RDWAIT;
 228:         }
 229: }
 230: 
 231: /*ARGSUSED*/
 232: logioctl(dev, com, data, flag)
 233:     dev_t   dev;
 234:     u_int   com;
 235:     caddr_t data;
 236:     int flag;
 237:     {
 238:     long l;
 239:     register int s;
 240:     int unit;
 241:     register struct logsoftc *lp;
 242:     register struct msgbuf *mp;
 243: 
 244:     unit = minor(dev);
 245:     lp = &logsoftc[unit];
 246:     mp = &msgbuf[unit];
 247: 
 248:     switch  (com)
 249:         {
 250:         case    FIONREAD:
 251:             s = splhigh();
 252:             l = mp->msg_bufx - mp->msg_bufr;
 253:             splx(s);
 254:             if  (l < 0)
 255:                 l += MSG_BSIZE;
 256:             *(off_t *)data = l;
 257:             break;
 258:         case    FIONBIO:
 259:             break;
 260:         case    FIOASYNC:
 261:             if (*(int *)data)
 262:                 lp->sc_state |= LOG_ASYNC;
 263:             else
 264:                 lp->sc_state &= ~LOG_ASYNC;
 265:             break;
 266:         case    TIOCSPGRP:
 267:             lp->sc_pgid = *(int *)data;
 268:             break;
 269:         case    TIOCGPGRP:
 270:             *(int *)data = lp->sc_pgid;
 271:             break;
 272:         default:
 273:             return(-1);
 274:         }
 275:     return(0);
 276:     }
 277: 
 278: /*
 279:  * This is inefficient for single character writes.  Alas, changing this
 280:  * to be buffered would affect the networking code's use of printf.
 281: */
 282: 
 283: logwrt(buf,len,log)
 284:     char    *buf;
 285:     int len;
 286:     int log;
 287:     {
 288:     segm    s5;
 289:     register struct msgbuf *mp = &msgbuf[log];
 290:     struct  logsoftc *lp = &logsoftc[log];
 291:     register int    infront;
 292:     int  s, n, writer, err = 0;
 293: 
 294:     if  (mp->msg_magic != MSG_MAGIC || (len > MSG_BSIZE))
 295:         return(-1);
 296:     saveseg5(s5);
 297: /*
 298:  * Hate to do this but since this can be called from anywhere in the kernel
 299:  * we have to hold off any interrupt service routines so they don't change
 300:  * things.  This looks like a lot of code but it isn't really.
 301: */
 302:     s = splhigh();
 303:     while   (len)
 304:         {
 305: again:      infront = MSG_BSIZE - mp->msg_bufx;
 306:         if  (infront <= 0)
 307:             {
 308:             mp->msg_bufx = 0;
 309:             infront = MSG_BSIZE - mp->msg_bufr;
 310:             }
 311:         n = mp->msg_bufr - mp->msg_bufx;
 312:         if  (n < 0)     /* bufr < bufx */
 313:             writer = (MSG_BSIZE - mp->msg_bufx) + mp->msg_bufr;
 314:         else if (n == 0)
 315:             writer = MSG_BSIZE;
 316:         else
 317:             {
 318:             writer = n;
 319:             infront = n;
 320:             }
 321:         if  (len > writer)
 322:             {
 323: /*
 324:  * won't fit.  the total number of bytes to be written is
 325:  * greater than the number available.  the buffer is full.
 326:  * throw away the old data and keep the current data by resetting
 327:  * the 'writer' pointer to the current 'reader' position.  Bump the
 328:  * overrun counter in case anyone wants to look at it for debugging.
 329: */
 330:             lp->sc_overrun++;
 331:             mp->msg_bufx = mp->msg_bufr;
 332:             goto    again;
 333:             }
 334:         if  (infront > len)
 335:             infront = len;
 336:         mapseg5(mp->msg_click, (btoc(MSG_BSIZE) << 8) | RW);  /* XXX */
 337:         bcopy(buf, &mp->msg_bufc[mp->msg_bufx], infront);
 338:         restorseg5(s5);
 339:         mp->msg_bufx += infront;
 340:         len -= infront;
 341:         buf += infront;
 342:         }
 343: out:    splx(s);
 344:     return(err);
 345:     }
 346: 
 347: /*
 348:  * Initialize the log driver.  Called from the system startup code (machdep2.c).
 349:  * All buffers are the same (MSG_BSIZE) size.
 350: */
 351: 
 352: loginit()
 353:     {
 354: register struct msgbuf *mp;
 355: 
 356:     for (mp = &msgbuf[0]; mp < &msgbuf[NLOG]; mp++)
 357:         {
 358:         mp->msg_click = malloc(coremap,btoc(MSG_BSIZE));
 359:         if  (!mp->msg_click)
 360:             return(-1);
 361:         mp->msg_magic = MSG_MAGIC;
 362:         mp->msg_bufc = SEG5;
 363:         mp->msg_bufx = mp->msg_bufr = 0;
 364:         }
 365:     return(0);
 366:     }

Defined functions

logclose defined in line 83; used 2 times
loginit defined in line 352; used 1 times
logioctl defined in line 232; used 2 times
logisopen defined in line 99; used 3 times
logopen defined in line 62; used 2 times
logread defined in line 109; used 2 times
logselect defined in line 179; used 2 times
logwakeup defined in line 201; used 3 times
logwrt defined in line 283; used 2 times

Defined variables

Acctopen defined in line 50; used 3 times
logsoftc defined in line 59; used 10 times
msgbuf defined in line 52; used 9 times
nlog defined in line 25; never used

Defined struct's

logsoftc defined in line 53; used 8 times

Defined macros

LOG_ASYNC defined in line 42; used 3 times
LOG_OPEN defined in line 41; used 2 times
LOG_RDPRI defined in line 39; used 1 times
LOG_RDWAIT defined in line 43; used 4 times
NLOG defined in line 24; used 5 times
Last modified: 1999-04-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3920
Valid CSS Valid XHTML 1.0 Strict