home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
-
- This file is part of advise.
-
- advise is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the advise General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- advise, but only under the conditions described in the
- advise General Public License. A copy of this license is
- supposed to have been given to you along with advise so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
-
- /*
- ** Author: Keith Gabryelski (ag@amix.commodore.com)
- */
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/sysmacros.h>
- #include <sys/signal.h>
- #include <sys/file.h>
- #if !defined(sun) && !defined(i386) /* AmigaUnix ? */
- #include <sys/user.h>
- #endif /* !sun && !i386 */
- #include <sys/proc.h>
- #include <sys/termios.h>
- #include <sys/ttold.h>
- #ifndef sun
- #include <sys/cmn_err.h>
- #endif /* !sun */
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/errno.h>
- #include <sys/debug.h>
- #include "advise.h"
- #ifndef sun
- #include <sys/inline.h>
- #else
- #include "advisemod.c"
-
- #ifndef L_MAXMIN
- #define L_MAXMIN 0377
- #endif /* ! L_MAXMIN */
-
- #ifndef EUNATCH
- #define EUNATCH ENOPROTOOPT
- #endif /* ! EUNATCH */
-
- #endif /* ! sun */
-
- #ifdef i386
- #include <sys/ddi.h>
-
- int advisedevflag = 0; /* Used by the Kernel */
- #endif /* i386 */
-
- int adviseopen(), adviseclose(), adviserput(), advisewput();
- void advisesrvioc();
-
- static struct module_info adviseiinfo =
- {
- 0, "advise", 0, INFPSZ, 2048, 128,
- };
-
- static struct qinit adviserinit =
- {
- adviserput, NULL, adviseopen, adviseclose, NULL, &adviseiinfo, NULL
- };
-
- static struct module_info adviseoinfo =
- {
- 42, "advise", 0, INFPSZ, 300, 200,
- };
-
- static struct qinit advisewinit =
- {
- advisewput, NULL, NULL, NULL, NULL, &adviseoinfo, NULL
- };
-
- #ifndef sun
- extern struct advise_state advise_table;
- #else
- static
- #endif /* sun */
- struct streamtab adviseinfo =
- {
- &adviserinit, &advisewinit, NULL, NULL,
- };
-
- static char minoralloc[((L_MAXMIN+1+7)&~7)/8];
-
- /*ARGSUSED*/
- static int
- adviseopen(q, dev, flag, sflag
- #ifndef sun
- , credp
- #endif /* !sun */
- )
- register queue_t *q;
- #ifdef sun
- #define openerr(x) return OPENFAIL
- #else
- #define openerr(x) return x
- dev_t *dev;
- cred_t *credp;
- #endif /* sun */
- {
- register mblk_t *bp;
- struct advise_queue_list *ql;
- struct advise_state *sp;
- int i;
- int s;
-
- if (sflag != CLONEOPEN)
- openerr(EINVAL);
-
- s=spladvise();
- for (i=0; i < L_MAXMIN && minoralloc[i/8]&(1<<(i%8)); ++i);
-
- if(i==L_MAXMIN) {
- splx(s);
- openerr(ENOMEM); /* no more resources */
- }
-
- minoralloc[i/8] |= 1<<(i%8);
- i++;
- splx(s);
-
- #ifndef sun
- *dev = makedevice(getmajor(*dev), i);
- #endif /* sun */
-
- if ((bp = allocb((int)sizeof(struct advise_queue_list), BPRI_MED)) == NULL)
- {
- openerr(ENOMEM);
- }
-
- bp->b_wptr += sizeof(struct advise_queue_list);
- ql = (struct advise_queue_list *)bp->b_rptr;
- ql->savbp = bp;
- ql->next = NULL;
- ql->q = q;
- ql->minord = i;
- ql->wdir = 0;
- ql->state = NULL;
-
- q->q_ptr = (caddr_t)ql;
- WR(q)->q_ptr = (caddr_t)ql;
-
- #ifdef sun
- return minor(i);
- #else
- return 0;
- #endif /* sun */
- }
-
- static struct advise_state *
- validstate(sp)
- struct advise_state *sp;
- {
- struct advise_state *llist = &advise_table;
-
- if(sp != NULL) if (sp->q != NULL) {
- while (llist != NULL && llist->next != sp)
- llist = llist->next;
-
- return(llist);
- }
- return(NULL);
- }
-
- static
- adviseclose(q)
- register queue_t *q;
- {
- struct advise_state *llist = &advise_table;
- struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
- struct advise_queue_list *ql, *qlp;
- int s;
-
- s=spladvise();
-
- /* Remove us from the advisor's list */
- if (llist = validstate(qp->state))
- {
- if(ql = llist->next->q_wlist) {
-
- if (ql->q == q)
- llist->next->q_wlist = ql->next;
- else
- {
- while (ql->next != NULL && ql->next->q != q)
- ql = ql->next;
-
- if (ql->next != NULL)
- ql->next = ql->next->next;
- }
- }
-
- if(ql = llist->next->q_rlist) {
-
- if (ql->q == q)
- llist->next->q_rlist = ql->next;
- else
- {
- while (ql->next != NULL && ql->next->q != q)
- ql = ql->next;
-
- if (ql->next != NULL)
- ql->next = ql->next->next;
- }
- }
- }
-
- /* mark minor device number as free in our allocation bitmap */
- minoralloc[(qp->minord-1)/8] &= ~(1<<((qp->minord-1)%8));
-
- splx(s);
-
- qp->state = NULL;
- freeb(qp->savbp);
-
- q->q_ptr = NULL;
- WR(q)->q_ptr = NULL;
- }
-
- static int
- adviserput(q, bp)
- struct queue *q;
- mblk_t *bp;
- {
- putnext(q, bp);
- }
-
- static int
- advisewput(q, mp)
- struct queue *q;
- mblk_t *mp;
- {
- struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
- struct advise_state *sp = qp->state;
- int s;
-
- switch (mp->b_datap->db_type)
- {
- case M_PROTO:
- {
- struct advise_message *ms = (struct advise_message *)mp->b_rptr;
- mblk_t *mp2 = unlinkb(mp);
-
- if (mp2)
- {
- s=spladvise();
- if (validstate(sp))
- {
- if (ms->type == ADVISE_READDATA)
- {
- putnext(WR(sp->q), mp2);
- }
- else
- {
- putnext(sp->q, mp2);
- }
- }
- else
- freemsg(mp2);
- splx(s);
- }
-
- freemsg(mp);
- break;
- }
-
- case M_DATA:
- /*
- ** Write data to advisee.
- */
- s=spladvise();
- if (validstate(sp))
- putnext(qp->wdir?WR(sp->q):sp->q, mp);
- else
- freemsg(mp);
- splx(s);
- break;
-
- #ifdef M_COPYOUT
- case M_IOCDATA:
- #endif /* M_COPYOUT */
- case M_IOCTL:
- advisesrvioc(q, mp);
- break;
-
- default:
- freemsg(mp);
- break;
- }
- }
-
-
- static void
- advisesrvioc(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- mblk_t *mp1;
- struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
- struct advise_queue_list *qp=(struct advise_queue_list *)q->q_ptr;
- int s;
-
- #ifdef M_COPYOUT
- if (mp->b_datap->db_type == M_IOCDATA)
- {
- /* For copyin/copyout failures, just free message. */
- if (((struct copyresp *)mp->b_rptr)->cp_rval)
- {
- freemsg(mp);
- return;
- }
-
- if (!((struct copyresp *)mp->b_rptr)->cp_private)
- {
- mp->b_datap->db_type = M_IOCACK;
- freemsg(unlinkb(mp));
- iocbp->ioc_count = 0;
- iocbp->ioc_rval = 0;
- iocbp->ioc_error = 0;
- putnext(RD(q), mp);
- return;
- }
- }
- #endif /* M_COPYOUT */
-
- switch (iocbp->ioc_cmd)
- {
- case ADVISE_SETADVISEEWR:
- case ADVISE_SETADVISEERD:
- {
- register dev_t p;
- struct advise_queue_list *qlp, **qlist;
- struct advise_state *llist;
-
- if (qp->state != NULL) /* already advising someone */
- {
- iocbp->ioc_error = EBUSY;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- if (!mp->b_cont)
- {
- iocbp->ioc_error = EINVAL;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- p = *(dev_t *)mp->b_cont->b_rptr;
-
- s = spladvise();
-
- #ifdef sun
- consoletryagain: /* ugly hack to allow advising of /dev/console */
- #endif /* sun */
- llist = advise_table.next;
-
- while (llist != NULL && llist->dev != p)
- {
- llist = llist->next;
- }
-
- if (llist == NULL)
- {
- #ifdef sun
- if(major(p)==0) {
- p=makedev(1, minor(p));
- goto consoletryagain;
- }
- #endif /* sun */
- splx(s);
- iocbp->ioc_error = EUNATCH;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- if ((llist->status & ALLOW_ADVICE) == 0 && (
- #ifdef sun
- iocbp->ioc_uid
- #else
- #ifdef i386
- drv_priv(iocbp->ioc_cr)
- #else
- !suser(u.u_cred)
- #endif /* i386 */
- #endif /* sun */
- ))
- {
- splx(s);
- iocbp->ioc_error = EACCES;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- /*
- ** Add ourself to the list of advisors for this advisee.
- */
-
- if(iocbp->ioc_cmd==ADVISE_SETADVISEERD) qlist=&llist->q_rlist;
- else qlist=&llist->q_wlist;
-
- if (*qlist == NULL)
- {
- qlp = *qlist = qp;
- }
- else
- {
- qlp = *qlist;
-
- while (qlp->next != NULL)
- qlp = qlp->next;
-
- qlp->next = qp;
- qlp = qp;
- }
-
- qlp->state = llist;
-
- if(iocbp->ioc_cmd==ADVISE_SETADVISEERD) qlp->wdir=1;
- else qlp->wdir=0;
-
- splx(s);
-
- mp->b_datap->db_type = M_IOCACK;
- mp1 = unlinkb(mp);
- if (mp1)
- freeb(mp1);
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- default:
- /* Unrecognized ioctl command */
- if (canput(RD(q)->q_next))
- {
- mp->b_datap->db_type = M_IOCNAK;
- putnext(RD(q), mp);
- }
- else
- putbq(q, mp);
- break;
- }
- }
-
- #ifdef sun
-
- /* autoload support for SunOS 4.1.
- Derived from example in section 5.7 of Sun manual "Writing Device Drivers",
- and code of similar purpose in a streams logging module written by
- Matthias Urlichs <urlichs@smurf.sub.org>.
- */
- #include <sys/conf.h>
- #include <sys/buf.h>
- #include <sundev/mbvar.h>
- #include <sun/autoconf.h>
- #include <sun/vddrv.h>
-
- extern nodev();
-
- static struct cdevsw advisecdev = {
- nodev, nodev, nodev, nodev,
- nodev, nodev, nodev, 0,
- &adviseinfo, 0
- };
-
- static struct vdldrv vd = {
- VDMAGIC_PSEUDO,
- "advise",
- NULL,
- #ifndef sun4c
- NULL,NULL,0,1,
- #endif /* sun4c */
- NULL,&advisecdev,0,0
- };
-
- static struct fmodsw *fmod_advmod=NULL;
-
- xxxinit(fc,vdp,vdi,vds)
- unsigned int fc;
- struct vddrv *vdp;
- addr_t vdi;
- struct vdstat *vds;
- {
- switch(fc) {
- case VDLOAD:
- if(fmod_advmod) return(EBUSY);
- {
- int dev,i;
-
- for(dev=0; dev < fmodcnt; dev++) {
- if(fmodsw[dev].f_str == NULL)
- break;
- }
- if(dev == fmodcnt) return(ENODEV);
-
- fmod_advmod = &fmodsw[dev];
- for(i=0;i<=FMNAMESZ;i++)
- fmod_advmod->f_name[i] = advmodinfo.st_rdinit->qi_minfo->mi_idname[i];
- }
- fmod_advmod->f_str = &advmodinfo;
- vdp->vdd_vdtab = (struct vdlinkage *)&vd;
- return 0;
-
- case VDUNLOAD:
- if(advise_table.next) return(EIO);
- for(i=0; i<sizeof(minoralloc); i++)
- if(minoralloc[i]) return(EIO);
-
- if(fmod_advmod) {
- fmod_advmod->f_name[0] = '\0';
- fmod_advmod->f_str = NULL;
- fmod_advmod=NULL;
- } else return(ENODEV);
- return 0;
-
- case VDSTAT:
- return 0;
-
- default:
- return EIO;
- }
- }
- #endif /* sun */
-