PageRenderTime 24ms CodeModel.GetById 12ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/kernel/tty_clk_STREAMS.c

https://bitbucket.org/freebsd/freebsd-head/
C | 266 lines | 162 code | 38 blank | 66 comment | 16 complexity | 3b74ab8bee09244d3a96dcac4d85fdc1 MD5 | raw file
  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