home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / advise / part01 / advisedev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-23  |  10.2 KB  |  547 lines

  1. /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
  2.  
  3. This file is part of advise.
  4.  
  5. advise is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY.  No author or distributor
  7. accepts responsibility to anyone for the consequences of using it
  8. or for whether it serves any particular purpose or works at all,
  9. unless he says so in writing.  Refer to the advise General Public
  10. License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. advise, but only under the conditions described in the
  14. advise General Public License.   A copy of this license is
  15. supposed to have been given to you along with advise so you
  16. can know your rights and responsibilities.  It should be in a
  17. file named COPYING.  Among other things, the copyright notice
  18. and this notice must be preserved on all copies.  */
  19.  
  20. /*
  21. ** Author:    Keith Gabryelski    (ag@amix.commodore.com)
  22. */
  23.  
  24. #include <sys/types.h>
  25. #include <sys/param.h>
  26. #include <sys/sysmacros.h>
  27. #include <sys/signal.h>
  28. #include <sys/file.h>
  29. #if !defined(sun) && !defined(i386) /* AmigaUnix ? */
  30. #include <sys/user.h>
  31. #endif /* !sun && !i386 */
  32. #include <sys/proc.h>
  33. #include <sys/termios.h>
  34. #include <sys/ttold.h>
  35. #ifndef sun
  36. #include <sys/cmn_err.h>
  37. #endif /* !sun */
  38. #include <sys/stream.h>
  39. #include <sys/stropts.h>
  40. #include <sys/errno.h>
  41. #include <sys/debug.h>
  42. #include "advise.h"
  43. #ifndef sun
  44. #include <sys/inline.h>
  45. #else
  46. #include "advisemod.c"
  47.  
  48. #ifndef L_MAXMIN
  49. #define L_MAXMIN 0377
  50. #endif /* ! L_MAXMIN */
  51.  
  52. #ifndef EUNATCH
  53. #define EUNATCH ENOPROTOOPT
  54. #endif /* ! EUNATCH */
  55.  
  56. #endif /* ! sun */
  57.  
  58. #ifdef i386
  59. #include <sys/ddi.h>
  60.  
  61. int advisedevflag = 0;    /* Used by the Kernel */
  62. #endif /* i386 */
  63.  
  64. int adviseopen(), adviseclose(), adviserput(), advisewput();
  65. void advisesrvioc();
  66.  
  67. static struct module_info adviseiinfo =
  68. {
  69.     0, "advise", 0, INFPSZ, 2048, 128,
  70. };
  71.  
  72. static struct qinit adviserinit =
  73. {
  74.     adviserput, NULL, adviseopen, adviseclose, NULL, &adviseiinfo, NULL
  75. };
  76.  
  77. static struct module_info adviseoinfo =
  78. {
  79.     42, "advise", 0, INFPSZ, 300, 200,
  80. };
  81.  
  82. static struct qinit advisewinit =
  83. {
  84.     advisewput, NULL, NULL, NULL, NULL, &adviseoinfo, NULL
  85. };
  86.  
  87. #ifndef sun
  88. extern struct advise_state advise_table;
  89. #else
  90. static
  91. #endif /* sun */
  92. struct streamtab adviseinfo =
  93. {
  94.     &adviserinit, &advisewinit, NULL, NULL,
  95. };
  96.  
  97. static char minoralloc[((L_MAXMIN+1+7)&~7)/8];
  98.  
  99. /*ARGSUSED*/
  100. static int
  101. adviseopen(q, dev, flag, sflag
  102. #ifndef sun
  103.     , credp
  104. #endif /* !sun */
  105. )
  106. register queue_t *q;
  107. #ifdef sun
  108. #define openerr(x) return OPENFAIL
  109. #else
  110. #define openerr(x) return x
  111. dev_t *dev;
  112. cred_t *credp;
  113. #endif /* sun */
  114. {
  115.     register mblk_t *bp;
  116.     struct advise_queue_list *ql;
  117.     struct advise_state  *sp;
  118.     int i;
  119.     int s;
  120.  
  121.     if (sflag != CLONEOPEN)
  122.     openerr(EINVAL);
  123.  
  124.     s=spladvise();
  125.     for (i=0; i < L_MAXMIN && minoralloc[i/8]&(1<<(i%8)); ++i);
  126.  
  127.     if(i==L_MAXMIN) {
  128.     splx(s);
  129.     openerr(ENOMEM); /* no more resources */
  130.     }
  131.  
  132.     minoralloc[i/8] |= 1<<(i%8);
  133.     i++;
  134.     splx(s);
  135.  
  136. #ifndef sun
  137.     *dev = makedevice(getmajor(*dev), i);
  138. #endif /* sun */
  139.  
  140.     if ((bp = allocb((int)sizeof(struct advise_queue_list), BPRI_MED)) == NULL)
  141.     {
  142.     openerr(ENOMEM);
  143.     }
  144.  
  145.     bp->b_wptr += sizeof(struct advise_queue_list);
  146.     ql = (struct advise_queue_list *)bp->b_rptr;
  147.     ql->savbp = bp;
  148.     ql->next = NULL;
  149.     ql->q = q;
  150.     ql->minord = i;
  151.     ql->wdir = 0;
  152.     ql->state = NULL;
  153.  
  154.     q->q_ptr = (caddr_t)ql;
  155.     WR(q)->q_ptr = (caddr_t)ql;
  156.  
  157. #ifdef sun
  158.     return minor(i);
  159. #else
  160.     return 0;
  161. #endif /* sun */
  162. }
  163.  
  164. static struct advise_state *
  165. validstate(sp)
  166. struct advise_state *sp;
  167. {
  168.     struct advise_state *llist = &advise_table;
  169.  
  170.     if(sp != NULL) if (sp->q != NULL) {
  171.     while (llist != NULL && llist->next != sp)
  172.         llist = llist->next;
  173.  
  174.     return(llist);
  175.     }
  176.     return(NULL);
  177. }
  178.  
  179. static
  180. adviseclose(q)
  181. register queue_t *q;
  182. {
  183.     struct advise_state *llist = &advise_table;
  184.     struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
  185.     struct advise_queue_list *ql, *qlp;
  186.     int s;
  187.  
  188.     s=spladvise();
  189.  
  190.     /* Remove us from the advisor's list */
  191.     if (llist = validstate(qp->state))
  192.     {
  193.     if(ql = llist->next->q_wlist) {
  194.  
  195.     if (ql->q == q)
  196.       llist->next->q_wlist = ql->next;
  197.     else
  198.     {
  199.         while (ql->next != NULL && ql->next->q != q)
  200.         ql = ql->next;
  201.  
  202.         if (ql->next != NULL)
  203.         ql->next = ql->next->next;
  204.     }
  205.     }
  206.  
  207.     if(ql = llist->next->q_rlist) {
  208.  
  209.     if (ql->q == q)
  210.         llist->next->q_rlist = ql->next;
  211.     else
  212.     {
  213.         while (ql->next != NULL && ql->next->q != q)
  214.         ql = ql->next;
  215.  
  216.         if (ql->next != NULL)
  217.         ql->next = ql->next->next;
  218.     }
  219.     }
  220.     }
  221.  
  222.     /* mark minor device number as free in our allocation bitmap */
  223.     minoralloc[(qp->minord-1)/8] &= ~(1<<((qp->minord-1)%8));
  224.  
  225.     splx(s);
  226.  
  227.     qp->state = NULL;
  228.     freeb(qp->savbp);
  229.  
  230.     q->q_ptr = NULL;
  231.     WR(q)->q_ptr = NULL;
  232. }
  233.  
  234. static int
  235. adviserput(q, bp)
  236. struct queue *q;
  237. mblk_t *bp;
  238. {
  239.     putnext(q, bp);
  240. }
  241.  
  242. static int
  243. advisewput(q, mp)
  244. struct queue *q;
  245. mblk_t *mp;
  246. {
  247.     struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
  248.     struct advise_state *sp = qp->state;
  249.     int s;
  250.  
  251.     switch (mp->b_datap->db_type)
  252.     {
  253.     case M_PROTO:
  254.     {
  255.     struct advise_message *ms = (struct advise_message *)mp->b_rptr;
  256.     mblk_t *mp2 = unlinkb(mp);
  257.  
  258.     if (mp2)
  259.     {
  260.         s=spladvise();
  261.         if (validstate(sp))
  262.         {
  263.         if (ms->type == ADVISE_READDATA)
  264.         {
  265.             putnext(WR(sp->q), mp2);
  266.         }
  267.         else
  268.         {
  269.             putnext(sp->q, mp2);
  270.         }
  271.         }
  272.         else
  273.         freemsg(mp2);
  274.         splx(s);
  275.     }
  276.  
  277.     freemsg(mp);
  278.     break;
  279.     }
  280.  
  281.     case M_DATA:
  282.     /*
  283.     ** Write data to advisee.
  284.     */
  285.         s=spladvise();
  286.     if (validstate(sp))
  287.         putnext(qp->wdir?WR(sp->q):sp->q, mp);
  288.     else
  289.         freemsg(mp);
  290.     splx(s);
  291.     break;
  292.  
  293. #ifdef M_COPYOUT
  294.     case M_IOCDATA:
  295. #endif /* M_COPYOUT */
  296.     case M_IOCTL:
  297.     advisesrvioc(q, mp);
  298.     break;
  299.  
  300.     default:
  301.     freemsg(mp);
  302.     break;
  303.     }
  304. }
  305.  
  306.  
  307. static void
  308. advisesrvioc(q, mp)
  309. queue_t *q;
  310. mblk_t *mp;
  311. {
  312.     mblk_t *mp1;
  313.     struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
  314.     struct advise_queue_list *qp=(struct advise_queue_list *)q->q_ptr; 
  315.     int s;
  316.  
  317. #ifdef M_COPYOUT
  318.     if (mp->b_datap->db_type == M_IOCDATA)
  319.     {
  320.     /* For copyin/copyout failures, just free message. */
  321.     if (((struct copyresp *)mp->b_rptr)->cp_rval)
  322.     {
  323.         freemsg(mp);
  324.         return;
  325.     }
  326.  
  327.     if (!((struct copyresp *)mp->b_rptr)->cp_private)
  328.     {
  329.         mp->b_datap->db_type = M_IOCACK;
  330.         freemsg(unlinkb(mp));
  331.         iocbp->ioc_count = 0;
  332.         iocbp->ioc_rval = 0;
  333.         iocbp->ioc_error = 0;
  334.         putnext(RD(q), mp);
  335.         return;
  336.     }
  337.     }
  338. #endif /* M_COPYOUT */
  339.  
  340.     switch (iocbp->ioc_cmd)
  341.     {
  342.     case ADVISE_SETADVISEEWR:
  343.     case ADVISE_SETADVISEERD:
  344.     {
  345.         register dev_t p;
  346.         struct advise_queue_list *qlp, **qlist;
  347.         struct advise_state *llist;
  348.  
  349.         if (qp->state != NULL) /* already advising someone */
  350.         {
  351.         iocbp->ioc_error = EBUSY;
  352.         mp->b_datap->db_type = M_IOCNAK;
  353.         iocbp->ioc_count = 0;
  354.         putnext(RD(q), mp);
  355.         break;
  356.         }
  357.  
  358.         if (!mp->b_cont)
  359.         {
  360.         iocbp->ioc_error = EINVAL;
  361.         mp->b_datap->db_type = M_IOCNAK;
  362.         iocbp->ioc_count = 0;
  363.         putnext(RD(q), mp);
  364.         break;
  365.         }
  366.  
  367.         p = *(dev_t *)mp->b_cont->b_rptr;
  368.  
  369.         s = spladvise();
  370.  
  371. #ifdef sun
  372. consoletryagain:    /* ugly hack to allow advising of /dev/console */
  373. #endif /* sun */
  374.         llist = advise_table.next;
  375.  
  376.         while (llist != NULL && llist->dev != p)
  377.         {
  378.         llist = llist->next;
  379.         }
  380.  
  381.         if (llist == NULL)
  382.         {
  383. #ifdef sun
  384.         if(major(p)==0) {
  385.             p=makedev(1, minor(p));
  386.             goto consoletryagain;
  387.         }
  388. #endif /* sun */
  389.         splx(s);
  390.         iocbp->ioc_error = EUNATCH;
  391.         mp->b_datap->db_type = M_IOCNAK;
  392.         iocbp->ioc_count = 0;
  393.         putnext(RD(q), mp);
  394.         break;
  395.         }
  396.  
  397.         if ((llist->status & ALLOW_ADVICE) == 0 && (
  398. #ifdef sun
  399.         iocbp->ioc_uid
  400. #else
  401. #ifdef i386
  402.         drv_priv(iocbp->ioc_cr)
  403. #else
  404.         !suser(u.u_cred)
  405. #endif /* i386 */
  406. #endif /* sun */
  407.         ))
  408.         {
  409.         splx(s);
  410.         iocbp->ioc_error = EACCES;
  411.         mp->b_datap->db_type = M_IOCNAK;
  412.         iocbp->ioc_count = 0;
  413.         putnext(RD(q), mp);
  414.         break;
  415.         }
  416.  
  417.         /*
  418.         ** Add ourself to the list of advisors for this advisee.
  419.         */
  420.  
  421.         if(iocbp->ioc_cmd==ADVISE_SETADVISEERD) qlist=&llist->q_rlist;
  422.         else qlist=&llist->q_wlist;
  423.  
  424.         if (*qlist == NULL)
  425.         {
  426.         qlp = *qlist = qp;
  427.         }
  428.         else
  429.         {
  430.         qlp = *qlist;
  431.  
  432.         while (qlp->next != NULL)
  433.             qlp = qlp->next;
  434.  
  435.         qlp->next = qp;
  436.         qlp = qp;
  437.         }
  438.  
  439.         qlp->state = llist;
  440.  
  441.         if(iocbp->ioc_cmd==ADVISE_SETADVISEERD) qlp->wdir=1;
  442.         else qlp->wdir=0;
  443.  
  444.         splx(s);
  445.  
  446.         mp->b_datap->db_type = M_IOCACK;
  447.         mp1 = unlinkb(mp);
  448.         if (mp1)
  449.         freeb(mp1);
  450.         iocbp->ioc_count = 0;
  451.         putnext(RD(q), mp);
  452.         break;
  453.     }
  454.  
  455.     default:
  456.     /* Unrecognized ioctl command */
  457.     if (canput(RD(q)->q_next))
  458.     {
  459.         mp->b_datap->db_type = M_IOCNAK;
  460.         putnext(RD(q), mp);
  461.     }
  462.     else
  463.         putbq(q, mp);
  464.     break;
  465.     }
  466. }
  467.  
  468. #ifdef sun
  469.  
  470. /* autoload support for SunOS 4.1. 
  471.    Derived from example in section 5.7 of Sun manual "Writing Device Drivers",
  472.    and code of similar purpose in a streams logging module written by
  473.    Matthias Urlichs <urlichs@smurf.sub.org>.
  474. */
  475. #include <sys/conf.h>
  476. #include <sys/buf.h>
  477. #include <sundev/mbvar.h>
  478. #include <sun/autoconf.h>
  479. #include <sun/vddrv.h>
  480.  
  481. extern nodev();
  482.  
  483. static struct cdevsw advisecdev = {
  484.     nodev,          nodev,          nodev,          nodev,
  485.     nodev,          nodev,          nodev,          0,
  486.     &adviseinfo,    0
  487. };
  488.  
  489. static struct vdldrv vd = {
  490.     VDMAGIC_PSEUDO,
  491.     "advise",
  492.     NULL,
  493. #ifndef sun4c
  494.     NULL,NULL,0,1,
  495. #endif    /* sun4c */
  496.     NULL,&advisecdev,0,0
  497. };
  498.  
  499. static struct fmodsw *fmod_advmod=NULL;
  500.  
  501. xxxinit(fc,vdp,vdi,vds)
  502. unsigned int fc;
  503. struct vddrv *vdp;
  504. addr_t vdi;
  505. struct vdstat *vds;
  506. {
  507.     switch(fc) {
  508.         case VDLOAD:
  509.             if(fmod_advmod) return(EBUSY);
  510.         {
  511.             int dev,i;
  512.  
  513.             for(dev=0; dev < fmodcnt; dev++) {
  514.                 if(fmodsw[dev].f_str == NULL)
  515.                     break;
  516.             }
  517.             if(dev == fmodcnt) return(ENODEV);
  518.  
  519.             fmod_advmod = &fmodsw[dev];
  520.             for(i=0;i<=FMNAMESZ;i++)
  521.                 fmod_advmod->f_name[i] = advmodinfo.st_rdinit->qi_minfo->mi_idname[i];
  522.         }
  523.             fmod_advmod->f_str = &advmodinfo;
  524.             vdp->vdd_vdtab = (struct vdlinkage *)&vd;
  525.             return 0;
  526.  
  527.         case VDUNLOAD:
  528.             if(advise_table.next) return(EIO);
  529.             for(i=0; i<sizeof(minoralloc); i++)
  530.                 if(minoralloc[i]) return(EIO);
  531.  
  532.             if(fmod_advmod) {
  533.                 fmod_advmod->f_name[0] = '\0';
  534.                 fmod_advmod->f_str = NULL;
  535.                 fmod_advmod=NULL;
  536.             } else return(ENODEV);
  537.             return 0;
  538.  
  539.         case VDSTAT:
  540.             return 0;
  541.  
  542.         default:
  543.             return EIO;
  544.     }
  545. }
  546. #endif /* sun */
  547.