1 /* tty_clk_STREAMS.c,v 3.1 1993/07/06 01:07:34 jbj Exp
2 * Timestamp STREAMS module for SunOS 4.1
4 * Copyright 1991, Nick Sayer
6 * Special thanks to Greg Onufer for his debug assists.
8 * Should be PUSHed directly on top of a serial I/O channel.
9 * For any character in a user-designated set, adds a kernel
10 * timestamp to that character.
14 * Only so many characters can be timestamped. This number, however,
17 * The null character ($00) cannot be timestamped.
19 * The M_DATA messages passed upstream will not be the same
20 * size as when they arrive from downstream, even if no
21 * timestamp character is in the message. This, however,
22 * should not affect anything.
29 * How big should the messages we pass upstream be?
31 #define MESSAGE_SIZE 128
34 #include <sys/types.h>
35 #include <sys/stream.h>
36 #include <sys/param.h>
38 #include <sys/kernel.h>
40 #include <sys/errno.h>
41 #include <sys/syslog.h>
43 #include <sys/clkdefs.h>
45 static struct module_info rminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
46 static struct module_info wminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
47 static int clkopen(), clkrput(), clkwput(), clkclose();
49 static struct qinit rinit = { clkrput, NULL, clkopen, clkclose, NULL,
52 static struct qinit winit = { clkwput, NULL, NULL, NULL, NULL,
55 struct streamtab clkinfo = { &rinit, &winit, NULL, NULL };
60 char string[CLK_MAXSTRSIZE];
66 * God only knows why, but linking with strchr() fails
67 * on my system, so here's a renamed copy.
81 static int clkopen(q, dev, flag, sflag)
89 /* Damn it! We can't even have the global data struct properly
90 initialized! So we have a mark to tell us to init the global
91 data on the first open */
98 priv_data[i].in_use=0;
102 if(!priv_data[i].in_use)
104 priv_data[i].in_use++;
105 ((struct priv_data_type *) (q->q_ptr))=priv_data+i;
106 priv_data[i].string[0]=0;
114 static int clkclose(q, flag)
118 ((struct priv_data_type *) (q->q_ptr))->in_use=0;
124 * Now the crux of the biscuit.
126 * If it's an M_DATA package, we take each character and pass
132 static int clkrput(q, mp)
138 switch(mp->b_datap->db_type)
142 for(bp=mp; bp!=NULL; bp=bp->b_cont)
144 while(bp->b_rptr < bp->b_wptr)
145 clkchar( ((u_char)*(bp->b_rptr++)) , q , 0 );
158 * If it's a matching M_IOCTL, handle it.
161 static int clkwput(q, mp)
167 switch(mp->b_datap->db_type)
170 iocp=(struct iocblk*) mp->b_rptr;
171 if (iocp->ioc_cmd==CLK_SETSTR)
173 strncpy( ((struct priv_data_type *) (RD(q)->q_ptr))->string,
174 (char *) mp->b_cont->b_rptr,CLK_MAXSTRSIZE);
175 /* make sure it's null terminated */
176 ((struct priv_data_type *) (RD(q)->q_ptr))->string[CLK_MAXSTRSIZE-1]=0;
177 mp->b_datap->db_type = M_IOCACK;
190 * Now clkchar. It takes a character, a queue pointer and an action
191 * flag and depending on the flag either:
193 * 0 - adds the character to the current message. If there's a
194 * timestamp to be done, do that too. If the message is less than
195 * 8 chars from being full, link in a new one, and set it up for
198 * 1 - sends the whole mess to Valhala.
202 * Yeah, it's an ugly hack. Complaints may be filed with /dev/null.
212 static mblk_t *message,*mp;
215 /* Get a timestamp ASAP! */
225 mp=message= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
226 error=(message==NULL);
228 log(LOG_ERR,"clk: cannot allocate message - data lost");
231 if (error) /* If we had an error, forget it. */
234 *mp->b_wptr++=c; /* Put the char away first.
236 /* If it's in the special string, append a struct timeval */
238 if (str_chr( ((struct priv_data_type *) (q->q_ptr))->string ,
243 for (i=0;i<sizeof(struct timeval);i++)
244 *mp->b_wptr++= *( ((char*)&tv) + i );
247 /* If we don't have space for a complete struct timeval, and a
248 char, it's time for a new mp block */
250 if (((mp->b_wptr-mp->b_rptr)+sizeof(struct timeval)+2)>MESSAGE_SIZE)
252 mp->b_cont= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
253 error=(mp->b_cont==NULL);
256 log(LOG_ERR,"clk: cannot allocate message - data lost");