home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / unix / internal / 1630 < prev    next >
Encoding:
Text File  |  1992-07-29  |  9.3 KB  |  408 lines

  1. Xref: sparky comp.unix.internals:1630 comp.unix.programmer:4010
  2. Path: sparky!uunet!zephyr.ens.tek.com!psgrain!hippo!ucthpx!aim1!aim1!gram
  3. From: gram@aim1.aztec.co.za (Graham Wheeler)
  4. Newsgroups: comp.unix.internals,comp.unix.programmer
  5. Subject: STREAMS debug module
  6. Message-ID: <gram.712486053@aim1>
  7. Date: 30 Jul 92 08:47:33 GMT
  8. Organization: Aztec Information Management
  9. Lines: 397
  10.  
  11. For those who are developing STREAMS applications and want to use the dump
  12. module for debugging, here it is. My STREAMS manual is riddled with typos,
  13. so I have fixed it up to the best of my ability. Also, I have the 3B2 manual
  14. but I'm using a 386, so I've changed a couple of things (added dumpdevflag,
  15. and made the extern declarations explicit; there is no /etc/master.d/dump
  16. file).
  17.  
  18. Unfortunately, having created this module, I can't get autopush to accept
  19. it, so I don't know how much use it is going to be to me or anyone. But
  20. at least I may save some other people some time.
  21.  
  22. autpush comes up with the message: `Invalid major device number or invalid
  23. module name or too many modules'. I have only the one module, my device
  24. number is valid (I am just replacing ldterm with dump over the same driver,
  25. and I never had problems with autopushing ldterm). If I do an ls -l on /dev,
  26. there I see:
  27.  
  28. crw-rw-rw- 1 root root 77, 55 Jul 29 18:48 /dev/dump
  29.  
  30. BTW, does anyone know why I am getting a minor dev number of 55, when my
  31. Node file is:
  32.  
  33. dump dump c 0
  34.  
  35. I have found this with other modules as well - the last entry always seems
  36. to bomb out. If, for example, I had:
  37.  
  38. dump dump c 0
  39. dump dump c 1
  40. dump dump c 2
  41.  
  42. I would get minor devs 0, 1 and 55.
  43.  
  44. Why isn't anything in life simple? I've found it easier to implement a couple
  45. of OSI protocols in STREAMS than to get the configuration working properly, the
  46. dump module working, or a TCGETA ioctl to work (believe it or not).
  47.  
  48. Here is the code. Sorry, I don't have shar, you'll have to cut it up yourselves.
  49.  
  50. === dump.h ==================================================================
  51.  
  52. /*
  53.  * dump.h - header for DUMP module
  54.  */
  55.  
  56. #define DUMPIOC        ('Q'<<8)
  57.  
  58. #define DUMP_VERB    (DUMPIOC | 1)
  59. #define DUMP_TERSE    (DUMPIOC | 2)
  60.  
  61. #define D_FREE        0
  62. #define D_USED        1
  63.  
  64. #define D_OUT        1
  65. #define D_IN        2
  66.  
  67. #define D_VERB        0x01
  68.  
  69. struct dm_str {
  70.     char dm_use;
  71.     char dm_state;
  72.     char dm_flags;
  73. };
  74.  
  75. === dump.c ==========================================================
  76.  
  77. #include "sys/types.h"
  78. #include "sys/stream.h"
  79. #include "sys/param.h"
  80. #include "sys/fcntl.h"
  81. #include "sys/cmn_err.h"
  82. #include "dump.h"
  83. #include "sys/termio.h"
  84.  
  85. static struct module_info dumprinfo = { 0x6475, "dump", 0, INFPSZ, 0, 0 };
  86. static struct module_info dumpwinfo = { 0x6475, "dump", 0, INFPSZ, 0, 0 };
  87.  
  88. static int dumpopen(), dumprput(), dumpwput(), dumpclose();
  89.  
  90. static struct qinit rinit = {
  91.     dumprput, NULL, dumpopen, dumpclose, NULL, &dumprinfo, NULL };
  92.  
  93. static struct qinit winit = {
  94.     dumpwput, NULL, NULL, NULL, NULL, &dumpwinfo, NULL };
  95.  
  96. struct streamtab dumpinfo = { &rinit, &winit, NULL, NULL };
  97.  
  98. int dm_ucnt=NUM_DUMP;
  99.  
  100. struct dm_str dm_users[NUM_DUMP];
  101.  
  102. int dumpdevflag = 0;
  103.  
  104. /*
  105.  * dumpopen
  106.  */
  107.  
  108. static int dumpopen(queue_t *q, dev_t *dev, int flag, int sflag) {
  109.     register int i;
  110.  
  111.     if (q->q_ptr != NULL) {
  112.         cmn_err(CE_CONT, "^DUMP: re-open slot %d\n",
  113.             ((struct dm_str *)q->q_ptr - dm_users));
  114.         if (flag & O_NDELAY)
  115.             cmn_err(CE_CONT, "^DUMP: re-open: O_NDELAY set\n");
  116.         return 0;
  117.     }
  118.     for (i=0; i<dm_ucnt; i++) {
  119.         if (dm_users[i].dm_use == D_FREE) {
  120.             dm_users[i].dm_use = D_USED;
  121.             dm_users[i].dm_state = 0;
  122.             dm_users[i].dm_flags = D_VERB;
  123.             q->q_ptr = (caddr_t)&dm_users[i];
  124.             if (flag & O_NDELAY)
  125.                 cmn_err(CE_CONT,"^DUMP: open: O_NDELAY set\n");
  126.             return 0;
  127.         }
  128.     }
  129.     return OPENFAIL;
  130. }
  131.  
  132. /*
  133.  * dumpclose
  134.  */
  135.  
  136. static int dumpclose(queue_t *q, int flag) {
  137.     struct dm_str *d;
  138.     d = (struct dm_str *)q->q_ptr;
  139.     d->dm_use = D_FREE;
  140.     d->dm_flags = 0;
  141.     q->q_ptr = 0;
  142.     WR(q)->q_ptr = 0;
  143.     return 0;
  144. }
  145.  
  146. static int dumpwput(queue_t *q, mblk_t *mp) {
  147.     struct iocblk *iocp;
  148.     struct dm_str *d;
  149.  
  150.     d = (struct dm_str *)q->q_ptr;
  151.     if (mp->b_datap->db_type == M_IOCTL) {
  152.         iocp = (struct iocblk *)mp->b_rptr;
  153.         if ((iocp->ioc_cmd & DUMPIOC)==DUMPIOC) {
  154.             dumpioc(q,mp);
  155.             return 0;
  156.         } else {
  157.             cmn_err(CE_CONT,"^o: M_IOCTL %x, cnt %d ",
  158.                 iocp->ioc_cmd, iocp->ioc_count);
  159.             if ((d->dm_flags & D_VERB) && mp->b_cont)
  160.                 dumpshow(mp->b_cont, iocp->ioc_cmd);
  161.             d->dm_state = 0;
  162.             putnext(q,mp);
  163.         }
  164.     } else if (mp->b_datap->db_type == M_DATA) {
  165.         dumpgather(q,mp,D_OUT);
  166.         putnext(q,mp);
  167.     } else    {
  168.         dumpctl(q,mp,d,D_OUT);
  169.         d->dm_state = 0;
  170.         putnext(q,mp);
  171.     }
  172. }
  173.  
  174. /*
  175.  * dumprput
  176.  */
  177.  
  178. static int dumprput(queue_t *q, mblk_t *mp) {
  179.     struct dm_str *d;
  180.  
  181.     d = (struct dm_str *)q->q_ptr;
  182.     if (mp->b_datap->db_type == M_DATA) {
  183.         dumpgather(q,mp,D_IN);
  184.     } else    {
  185.         dumpctl(q,mp,d,D_IN);
  186.         d->dm_state = 0;
  187.     }
  188.     putnext(q,mp);
  189. }
  190.  
  191. /*
  192.  * dumpgather
  193.  */
  194.  
  195. dumpgather(queue_t *q, mblk_t *mp, int dir) {
  196.     register struct dm_str *d;
  197.     register int sx;
  198.     register unsigned char *readp;
  199.     register mblk_t *tmp;
  200.     int counter;
  201.     char junk[2];
  202.  
  203.     d = (struct dm_str *)q->q_ptr;
  204.     if (d->dm_state != dir) {
  205.         d->dm_state = dir;
  206.         cmn_err(CE_CONT,"^%s",((dir==D_IN) ? "I" : "O" ));
  207.     }
  208.     if ((!mp->b_datap) || 
  209.         ((mp->b_rptr == mp->b_wptr) && (mp->b_cont == NULL))) {
  210.             cmn_err(CE_CONT,"^DUMP: 0 len data msg %s\n",
  211.                 (dir==D_OUT) ? "OUT":"IN");
  212.             return;
  213.     }
  214.     cmn_err(CE_CONT,"^ {{");
  215.     tmp = mp;
  216.     counter = 0;
  217.     sx = splstr();
  218.     junk[1] = ' ';
  219. more:
  220.     readp = tmp->b_rptr;
  221.     while (readp < tmp->b_wptr) {
  222.         if (d->dm_flags & D_VERB) {
  223.             if ((*readp >= ' ') && (*readp <= '~') && !(*readp & 0x80)) {
  224.                 junk[0] = *readp;
  225.                 cmn_err(CE_CONT, "^ %s",junk);
  226.             } else cmn_err(CE_CONT,"^ 0x%x", *readp);
  227.         } else {
  228.             ++counter;
  229.         }
  230.         ++readp;
  231.     }
  232.     if ((tmp->b_cont) && (tmp->b_datap->db_type == M_DATA)) {
  233.         tmp = tmp->b_cont;
  234.         goto more;
  235.     }
  236.     if (!(d->dm_flags & D_VERB))
  237.         cmn_err(CE_CONT,"^%d ",counter);
  238.     cmn_err(CE_CONT,"^}} ");
  239.     if (tmp->b_cont && (tmp->b_datap->db_type != M_DATA))
  240.         cmn_err(CE_CONT,"^DUMP: non-data b_cont\n");
  241.     splx(sx);
  242. }
  243.  
  244. /*
  245.  * dumpioc
  246.  */
  247.  
  248. dumpioc(queue_t *q, mblk_t *mp) {
  249.     register struct iocblk *iocp;
  250.     register struct dm_str *d, *rst;
  251.     d = (struct dm_str *)q->q_ptr;
  252.     iocp = (struct iocblk *)mp->b_datap->db_base;
  253.     cmn_err(CE_CONT,"^DUMP: own ioctl is ");
  254.     switch (iocp->ioc_cmd) {
  255.     case DUMP_VERB:
  256.         d->dm_flags |= D_VERB;
  257.         cmn_err(CE_CONT, "^DUMP_VERB\n");
  258.         break;
  259.     case DUMP_TERSE:
  260.         d->dm_flags &= ~D_VERB;
  261.         cmn_err(CE_CONT, "^DUMP_TERSE\n");
  262.         break;
  263.     default:
  264.         mp->b_datap->db_type = M_IOCNAK;
  265.         cmn_err(CE_CONT,"^UNKNOWN DUMP IOCTL x%x\n",iocp->ioc_cmd);
  266.         qreply(q,mp);
  267.         return;
  268.     }
  269.     mp->b_datap->db_type = M_IOCACK;
  270.     iocp->ioc_count = 0;
  271.     qreply(q,mp);
  272. }
  273.  
  274. /*
  275.  * dumpctl
  276.  */
  277.  
  278. dumpctl(queue_t *q, mblk_t *mp, struct dm_str *d, int dir) {
  279.     cmn_err(CE_CONT,"^%s: M_",((dir==D_IN) ? "i":"o"));
  280.     switch(mp->b_datap->db_type) {
  281.     case M_DATA:
  282.         cmn_err(CE_CONT,"^DATA");
  283.         break;
  284.     case M_READ:
  285.         cmn_err(CE_CONT,"^READ");
  286.         break;
  287.     case M_IOCTL:
  288.         cmn_err(CE_CONT,"^IOCTL");
  289.         break;
  290.     case M_IOCACK:
  291.         cmn_err(CE_CONT,"^IOCACK");
  292.         break;
  293.     case M_IOCNAK:
  294.         cmn_err(CE_CONT,"^IOCNAK");
  295.         break;
  296.     case M_IOCDATA:
  297.         cmn_err(CE_CONT,"^IOCDATA");
  298.         break;
  299.     case M_CTL:
  300.         cmn_err(CE_CONT,"^CTL");
  301.         break;
  302.     case M_PROTO:
  303.         cmn_err(CE_CONT,"^PROTO");
  304.         break;
  305.     case M_PCPROTO:
  306.         cmn_err(CE_CONT,"^PCPROTO");
  307.         break;
  308.     case M_BREAK:
  309.         cmn_err(CE_CONT,"^BREAK");
  310.         break;
  311.     case M_DELAY:
  312.         cmn_err(CE_CONT,"^DELAY");
  313.         break;
  314.     case M_PASSFP:
  315.         cmn_err(CE_CONT,"^PASSFP");
  316.         break;
  317.     case M_SETOPTS:
  318.         cmn_err(CE_CONT,"^SETOPTS");
  319.         break;
  320.     case M_SIG:
  321.         cmn_err(CE_CONT,"^SIG (%d) ",(int)*mp->b_rptr);
  322.         break;
  323.     case M_ERROR:
  324.         cmn_err(CE_CONT,"^ERROR");
  325.         break;
  326.     case M_HANGUP:
  327.         cmn_err(CE_CONT,"^HANGUP");
  328.         break;
  329.     case M_FLUSH:
  330.         cmn_err(CE_CONT,"^FLUSH");
  331.         break;
  332.     case M_PCSIG:
  333.         cmn_err(CE_CONT,"^PCSIG (%d) ",(int)*mp->b_rptr);
  334.         break;
  335.     case M_COPYOUT:
  336.         cmn_err(CE_CONT,"^COPYOUT");
  337.         break;
  338.     case M_COPYIN:
  339.         cmn_err(CE_CONT,"^COPYIN");
  340.         break;
  341.     case M_START:
  342.         cmn_err(CE_CONT,"^START");
  343.         break;
  344.     case M_STOP:
  345.         cmn_err(CE_CONT,"^STOP");
  346.         break;
  347.     case M_STARTI:
  348.         cmn_err(CE_CONT,"^STARTI");
  349.         break;
  350.     case M_STOPI:
  351.         cmn_err(CE_CONT,"^STOPI");
  352.         break;
  353.     default:
  354.         cmn_err(CE_CONT,"^Unknown!");
  355.     }
  356. }
  357.  
  358. /*
  359.  * dumpshow
  360.  */
  361.  
  362. dumpshow(mblk_t *mp, int cmd) {
  363.     int i;
  364.     struct termio *t;
  365.  
  366.     switch (cmd) {
  367.     case TCSETAF:
  368.         cmn_err(CE_CONT,"^TCSETAF "); goto prtall;
  369.     case TCSETA:
  370.         cmn_err(CE_CONT,"^TCSETA "); goto prtall;
  371.     case TCSETAW:
  372.         cmn_err(CE_CONT,"^TCSETAW "); goto prtall;
  373.     case TCGETA:
  374.         cmn_err(CE_CONT,"^TCGETA "); goto prtall;
  375. prtall:
  376.         t = (struct termio *) mp->b_rptr;
  377.         cmn_err(CE_CONT,"^if = %x; of = %x; cf=%x; lf=%x\ncc=",
  378.             t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag);
  379.         for (i=0;i<NCC;i++) 
  380.             cmn_err(CE_CONT,"^0x%x ",(int)t->c_cc[i]);
  381.         cmn_err(CE_CONT,"^\n");
  382.         break;
  383.     default:
  384.         return;
  385.     }
  386. }
  387.  
  388. ===  Node  ==================================================================
  389.  
  390. dump dump c 0
  391.  
  392. === sdevice =================================================================
  393.  
  394. dump Y 1 0 0 0 0 0 0 0 
  395.  
  396. === Master ==================================================================
  397.  
  398. dump - ifSoc dump 0 0 1 1 -1
  399.  
  400. =============================================================================
  401.  
  402.  
  403. -- 
  404. Graham Wheeler                     | "That which is weak conquers the strong,
  405. Software Systems Engineer/Student  | that which is soft conquers the hard."
  406. Aztec Information Management/UCT   |         Lao Tzu - Tao Te Ching Ch. 78
  407. gram@aim1.aztec.co.za / gram@cs.uct.ac.za 
  408.