[Return to Library] [Contents] [Previous Chapter] [Next Chapter] [Index] [Help]


A    Sample STREAMS Module

The spass module is a simple STREAMS module that passes all messages put to it to the putnext() procedure. The spass module delays the call to putnext() for the service procedure to handle. It has flow control code built in, and both the read and write sides share a service procedure.

The following is the code for the spass module:

#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/sysconfig.h>

 
static int spass_close(); static int spass_open(); static int spass_rput(); static int spass_srv(); static int spass_wput();
 
static struct module_info minfo = { 0, "spass", 0, INFPSZ, 2048, 128 };
 
static struct qinit rinit = { spass_rput, spass_srv, spass_open, spass_close, NULL, &minfo };
 
static struct qinit winit = { spass_wput, spass_srv, NULL, NULL, NULL, &minfo };
 
struct streamtab spassinfo = { &rinit, &winit };
 
cfg_subsys_attr_t bufcall_attributes[] = { {, 0, 0, 0, 0, 0, 0} /* must be the last element */ };
 
int spass_configure(op, indata, indata_size, outdata, outdata_size) cfg_op_t op; caddr_t indata; ulong indata_size; caddr_t outdata; ulong outdata_size; { struct streamadm sa; dev_t devno = NODEV;
 
if (op != CFG_OP_CONFIGURE) return EINVAL;
 
sa.sa_version = OSF_STREAMS_10; sa.sa_flags = STR_IS_MODULE | STR_SYSV4_OPEN; sa.sa_ttys = 0; sa.sa_sync_level = SQLVL_QUEUE; sa.sa_sync_info = 0; strcpy(sa.sa_name, "spass"); if ( (devno = strmod_add(devno, &spassinfo, &sa)) == NODEV ) { return ENODEV; }
 
return 0; }
 
/* Called when module is popped or the Stream is closed */ static int spass_close (q, credp) queue_t * q; cred_t * credp; { return 0; }
 
/* Called when module is pushed */ static int spass_open (q, devp, flag, sflag, credp) queue_t * q; int * devp; int flag; int sflag; cred_t * credp; { return 0; }
 
/* * Called to process a message coming upstream. All messages * but flow control messages are put on the read side service * queue for later processing. */ static int spass_rput (q, mp) queue_t * q; mblk_t * mp; { switch (mp->b_datap->db_type) { case M_FLUSH: if (*mp->b_rptr & FLUSHR) flushq(q, 0); putnext(q, mp); break; default: putq(q, mp); break; } return 0; }
 
/* * Shared by both read and write sides to process messages put * on the read or write service queues. When called from the * write side, sends all messages on the write side queue * downstream until flow control kicks in or all messages are * processed. When called from the read side sends all messages * on its read side service queue upstreams until flow control * kicks in or all messages are processed. */ static int spass_srv (q) queue_t * q; { mblk_t * mp;
 
while (mp = getq(q)) { if (!canput(q->q_next)) return putbq(q, mp); putnext(q, mp); } return 0; }
 
/* * Called to process a message coming downstream. All messages but * flow control messages are put on the write side service queue for * later processing. */ static int spass_wput (q, mp) queue_t * q; mblk_t * mp; { switch (mp->b_datap->db_type) { case M_FLUSH: if (*mp->b_rptr & FLUSHW) flushq(q, 0); putnext(q, mp); break; default: putq(q, mp); break; } return 0; }