3 /* tty_clk_STREAMS.c,v 3.1 1993/07/06 01:07:34 jbj Exp
4 * Timestamp STREAMS module for SunOS 4.1
6 * Copyright 1991, Nick Sayer
8 * Special thanks to Greg Onufer for his debug assists.
10 * Should be PUSHed directly on top of a serial I/O channel.
11 * For any character in a user-designated set, adds a kernel
12 * timestamp to that character.
16 * Only so many characters can be timestamped. This number, however,
19 * The null character ($00) cannot be timestamped.
21 * The M_DATA messages passed upstream will not be the same
22 * size as when they arrive from downstream, even if no
23 * timestamp character is in the message. This, however,
24 * should not affect anything.
31 * How big should the messages we pass upstream be?
33 #define MESSAGE_SIZE 128
36 #include <sys/types.h>
37 #include <sys/stream.h>
38 #include <sys/param.h>
40 #include <sys/kernel.h>
42 #include <sys/errno.h>
43 #include <sys/syslog.h>
45 #include <sys/clkdefs.h>
47 static struct module_info rminfo
= { 0, "clk", 0, INFPSZ
, 0, 0 };
48 static struct module_info wminfo
= { 0, "clk", 0, INFPSZ
, 0, 0 };
49 static int clkopen(), clkrput(), clkwput(), clkclose();
51 static struct qinit rinit
= { clkrput
, NULL
, clkopen
, clkclose
, NULL
,
54 static struct qinit winit
= { clkwput
, NULL
, NULL
, NULL
, NULL
,
57 struct streamtab clkinfo
= { &rinit
, &winit
, NULL
, NULL
};
62 char string
[CLK_MAXSTRSIZE
];
68 * God only knows why, but linking with strchr() fails
69 * on my system, so here's a renamed copy.
83 static int clkopen(q
, dev
, flag
, sflag
)
91 /* Damn it! We can't even have the global data struct properly
92 initialized! So we have a mark to tell us to init the global
93 data on the first open */
100 priv_data
[i
].in_use
=0;
104 if(!priv_data
[i
].in_use
)
106 priv_data
[i
].in_use
++;
107 ((struct priv_data_type
*) (q
->q_ptr
))=priv_data
+i
;
108 priv_data
[i
].string
[0]=0;
116 static int clkclose(q
, flag
)
120 ((struct priv_data_type
*) (q
->q_ptr
))->in_use
=0;
126 * Now the crux of the biscuit.
128 * If it's an M_DATA package, we take each character and pass
134 static int clkrput(q
, mp
)
140 switch(mp
->b_datap
->db_type
)
144 for(bp
=mp
; bp
!=NULL
; bp
=bp
->b_cont
)
146 while(bp
->b_rptr
< bp
->b_wptr
)
147 clkchar( ((u_char
)*(bp
->b_rptr
++)) , q
, 0 );
160 * If it's a matching M_IOCTL, handle it.
163 static int clkwput(q
, mp
)
169 switch(mp
->b_datap
->db_type
)
172 iocp
=(struct iocblk
*) mp
->b_rptr
;
173 if (iocp
->ioc_cmd
==CLK_SETSTR
)
175 strncpy( ((struct priv_data_type
*) (RD(q
)->q_ptr
))->string
,
176 (char *) mp
->b_cont
->b_rptr
,CLK_MAXSTRSIZE
);
177 /* make sure it's null terminated */
178 ((struct priv_data_type
*) (RD(q
)->q_ptr
))->string
[CLK_MAXSTRSIZE
-1]=0;
179 mp
->b_datap
->db_type
= M_IOCACK
;
192 * Now clkchar. It takes a character, a queue pointer and an action
193 * flag and depending on the flag either:
195 * 0 - adds the character to the current message. If there's a
196 * timestamp to be done, do that too. If the message is less than
197 * 8 chars from being full, link in a new one, and set it up for
200 * 1 - sends the whole mess to Valhala.
204 * Yeah, it's an ugly hack. Complaints may be filed with /dev/null.
214 static mblk_t
*message
,*mp
;
217 /* Get a timestamp ASAP! */
227 mp
=message
= (mblk_t
*) allocb(MESSAGE_SIZE
,BPRI_LO
);
228 error
=(message
==NULL
);
230 log(LOG_ERR
,"clk: cannot allocate message - data lost");
233 if (error
) /* If we had an error, forget it. */
236 *mp
->b_wptr
++=c
; /* Put the char away first.
238 /* If it's in the special string, append a struct timeval */
240 if (str_chr( ((struct priv_data_type
*) (q
->q_ptr
))->string
,
245 for (i
=0;i
<sizeof(struct timeval
);i
++)
246 *mp
->b_wptr
++= *( ((char*)&tv
) + i
);
249 /* If we don't have space for a complete struct timeval, and a
250 char, it's time for a new mp block */
252 if (((mp
->b_wptr
-mp
->b_rptr
)+sizeof(struct timeval
)+2)>MESSAGE_SIZE
)
254 mp
->b_cont
= (mblk_t
*) allocb(MESSAGE_SIZE
,BPRI_LO
);
255 error
=(mp
->b_cont
==NULL
);
258 log(LOG_ERR
,"clk: cannot allocate message - data lost");