source: trunk/third/xntp/kernel/tty_clk_STREAMS.c @ 10832

Revision 10832, 5.4 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
1/* tty_clk_STREAMS.c,v 3.1 1993/07/06 01:07:34 jbj Exp
2 * Timestamp STREAMS module for SunOS 4.1
3 *
4 * Copyright 1991, Nick Sayer
5 *
6 * Special thanks to Greg Onufer for his debug assists.
7 *
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.
11 *
12 * BUGS:
13 *
14 * Only so many characters can be timestamped. This number, however,
15 * is adjustable.
16 *
17 * The null character ($00) cannot be timestamped.
18 *
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.
23 *
24 */
25
26#include "clk.h"
27#if NCLK > 0
28/*
29 * How big should the messages we pass upstream be?
30 */
31#define MESSAGE_SIZE 128
32
33#include <string.h>
34#include <sys/types.h>
35#include <sys/stream.h>
36#include <sys/param.h>
37#include <sys/time.h>
38#include <sys/kernel.h>
39#include <sys/user.h>
40#include <sys/errno.h>
41#include <sys/syslog.h>
42
43#include <sys/clkdefs.h>
44
45static struct module_info rminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
46static struct module_info wminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
47static int clkopen(), clkrput(), clkwput(), clkclose();
48
49static struct qinit rinit = { clkrput, NULL, clkopen, clkclose, NULL,
50        &rminfo, NULL };
51
52static struct qinit winit = { clkwput, NULL, NULL, NULL, NULL,
53        &wminfo, NULL };
54
55struct streamtab clkinfo = { &rinit, &winit, NULL, NULL };
56
57struct priv_data_type
58{
59  char in_use;
60  char string[CLK_MAXSTRSIZE];
61} priv_data[NCLK];
62
63char first_open=1;
64
65/*
66 * God only knows why, but linking with strchr() fails
67 * on my system, so here's a renamed copy.
68 */
69
70u_char *str_chr(s,c)
71u_char *s;
72int c;
73{
74  while (*s)
75    if(*s++ == c)
76      return (s-1);
77  return NULL;
78}
79
80/*ARGSUSED*/
81static int clkopen(q, dev, flag, sflag)
82queue_t *q;
83dev_t dev;
84int flag;
85int sflag;
86{
87  int i;
88
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 */
92
93  if (first_open)
94  {
95    first_open=0;
96
97    for(i=0;i<NCLK;i++)
98      priv_data[i].in_use=0;
99  }
100
101  for(i=0;i<NCLK;i++)
102    if(!priv_data[i].in_use)
103    {
104      priv_data[i].in_use++;
105      ((struct priv_data_type *) (q->q_ptr))=priv_data+i;
106      priv_data[i].string[0]=0;
107      return (0);
108    }
109  u.u_error = EBUSY;
110  return (OPENFAIL);
111}
112
113/*ARGSUSED*/
114static int clkclose(q, flag)
115queue_t *q;
116int flag;
117{
118  ((struct priv_data_type *) (q->q_ptr))->in_use=0;
119
120  return (0);
121}
122
123/*
124 * Now the crux of the biscuit.
125 *
126 * If it's an M_DATA package, we take each character and pass
127 * it to clkchar.
128 */
129
130void clkchar();
131
132static int clkrput(q, mp)
133queue_t *q;
134mblk_t *mp;
135{
136  mblk_t *bp;
137
138  switch(mp->b_datap->db_type)
139  {
140    case M_DATA:
141      clkchar(0,q,2);
142      for(bp=mp; bp!=NULL; bp=bp->b_cont)
143      {
144        while(bp->b_rptr < bp->b_wptr)
145          clkchar( ((u_char)*(bp->b_rptr++)) , q , 0 );
146      }
147      clkchar(0,q,1);
148      freemsg(mp);
149    break;
150    default:
151      putnext(q,mp);
152    break;
153  }
154
155}
156
157/*
158 * If it's a matching M_IOCTL, handle it.
159 */
160
161static int clkwput(q, mp)
162queue_t *q;
163mblk_t *mp;
164{
165  struct iocblk *iocp;
166
167  switch(mp->b_datap->db_type)
168  {
169    case M_IOCTL:
170      iocp=(struct iocblk*) mp->b_rptr;
171      if (iocp->ioc_cmd==CLK_SETSTR)
172      {
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;
178        qreply(q,mp);
179      }
180      else
181        putnext(q,mp);
182    break;
183    default:
184      putnext(q,mp);
185    break;
186  }
187}
188
189/*
190 * Now clkchar. It takes a character, a queue pointer and an action
191 * flag and depending on the flag either:
192 *
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
196 * the next call.
197 *
198 * 1 - sends the whole mess to Valhala.
199 *
200 * 2 - set things up.
201 *
202 * Yeah, it's an ugly hack. Complaints may be filed with /dev/null.
203 */
204
205
206void clkchar(c,q,f)
207        register u_char c;
208        queue_t *q;
209        char f;
210{
211  static char error;
212  static mblk_t *message,*mp;
213  struct timeval tv;
214
215/* Get a timestamp ASAP! */
216  uniqtime(&tv);
217
218  switch(f)
219  {
220    case 1:
221      if (!error)
222        putnext(q,message);
223    break;
224    case 2:
225      mp=message= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
226      error=(message==NULL);
227      if (error)
228        log(LOG_ERR,"clk: cannot allocate message - data lost");
229    break;
230    case 0:
231      if (error) /* If we had an error, forget it. */
232        return;
233
234      *mp->b_wptr++=c; /* Put the char away first.
235
236      /* If it's in the special string, append a struct timeval */
237
238      if (str_chr( ((struct priv_data_type *) (q->q_ptr))->string ,
239        c )!=NULL)
240      {
241          int i;
242
243          for (i=0;i<sizeof(struct timeval);i++)
244            *mp->b_wptr++= *( ((char*)&tv) + i );
245      }
246
247      /* If we don't have space for a complete struct timeval, and a
248         char, it's time for a new mp block */
249
250      if (((mp->b_wptr-mp->b_rptr)+sizeof(struct timeval)+2)>MESSAGE_SIZE)
251      {
252          mp->b_cont= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
253          error=(mp->b_cont==NULL);
254          if (error)
255          {
256            log(LOG_ERR,"clk: cannot allocate message - data lost");
257            freemsg(message);
258          }
259          mp=mp->b_cont;
260      }
261
262    break;
263  }
264}
265
266#endif
Note: See TracBrowser for help on using the repository browser.