summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/kernel/tty_clk_STREAMS.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/kernel/tty_clk_STREAMS.c')
-rw-r--r--contrib/ntp/kernel/tty_clk_STREAMS.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/contrib/ntp/kernel/tty_clk_STREAMS.c b/contrib/ntp/kernel/tty_clk_STREAMS.c
new file mode 100644
index 0000000..13b0a25
--- /dev/null
+++ b/contrib/ntp/kernel/tty_clk_STREAMS.c
@@ -0,0 +1,266 @@
+/* tty_clk_STREAMS.c,v 3.1 1993/07/06 01:07:34 jbj Exp
+ * Timestamp STREAMS module for SunOS 4.1
+ *
+ * Copyright 1991, Nick Sayer
+ *
+ * Special thanks to Greg Onufer for his debug assists.
+ *
+ * Should be PUSHed directly on top of a serial I/O channel.
+ * For any character in a user-designated set, adds a kernel
+ * timestamp to that character.
+ *
+ * BUGS:
+ *
+ * Only so many characters can be timestamped. This number, however,
+ * is adjustable.
+ *
+ * The null character ($00) cannot be timestamped.
+ *
+ * The M_DATA messages passed upstream will not be the same
+ * size as when they arrive from downstream, even if no
+ * timestamp character is in the message. This, however,
+ * should not affect anything.
+ *
+ */
+
+#include "clk.h"
+#if NCLK > 0
+/*
+ * How big should the messages we pass upstream be?
+ */
+#define MESSAGE_SIZE 128
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/user.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+
+#include <sys/clkdefs.h>
+
+static struct module_info rminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
+static struct module_info wminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
+static int clkopen(), clkrput(), clkwput(), clkclose();
+
+static struct qinit rinit = { clkrput, NULL, clkopen, clkclose, NULL,
+ &rminfo, NULL };
+
+static struct qinit winit = { clkwput, NULL, NULL, NULL, NULL,
+ &wminfo, NULL };
+
+struct streamtab clkinfo = { &rinit, &winit, NULL, NULL };
+
+struct priv_data_type
+{
+ char in_use;
+ char string[CLK_MAXSTRSIZE];
+} priv_data[NCLK];
+
+char first_open=1;
+
+/*
+ * God only knows why, but linking with strchr() fails
+ * on my system, so here's a renamed copy.
+ */
+
+u_char *str_chr(s,c)
+u_char *s;
+int c;
+{
+ while (*s)
+ if(*s++ == c)
+ return (s-1);
+ return NULL;
+}
+
+/*ARGSUSED*/
+static int clkopen(q, dev, flag, sflag)
+queue_t *q;
+dev_t dev;
+int flag;
+int sflag;
+{
+ int i;
+
+/* Damn it! We can't even have the global data struct properly
+ initialized! So we have a mark to tell us to init the global
+ data on the first open */
+
+ if (first_open)
+ {
+ first_open=0;
+
+ for(i=0;i<NCLK;i++)
+ priv_data[i].in_use=0;
+ }
+
+ for(i=0;i<NCLK;i++)
+ if(!priv_data[i].in_use)
+ {
+ priv_data[i].in_use++;
+ ((struct priv_data_type *) (q->q_ptr))=priv_data+i;
+ priv_data[i].string[0]=0;
+ return (0);
+ }
+ u.u_error = EBUSY;
+ return (OPENFAIL);
+}
+
+/*ARGSUSED*/
+static int clkclose(q, flag)
+queue_t *q;
+int flag;
+{
+ ((struct priv_data_type *) (q->q_ptr))->in_use=0;
+
+ return (0);
+}
+
+/*
+ * Now the crux of the biscuit.
+ *
+ * If it's an M_DATA package, we take each character and pass
+ * it to clkchar.
+ */
+
+void clkchar();
+
+static int clkrput(q, mp)
+queue_t *q;
+mblk_t *mp;
+{
+ mblk_t *bp;
+
+ switch(mp->b_datap->db_type)
+ {
+ case M_DATA:
+ clkchar(0,q,2);
+ for(bp=mp; bp!=NULL; bp=bp->b_cont)
+ {
+ while(bp->b_rptr < bp->b_wptr)
+ clkchar( ((u_char)*(bp->b_rptr++)) , q , 0 );
+ }
+ clkchar(0,q,1);
+ freemsg(mp);
+ break;
+ default:
+ putnext(q,mp);
+ break;
+ }
+
+}
+
+/*
+ * If it's a matching M_IOCTL, handle it.
+ */
+
+static int clkwput(q, mp)
+queue_t *q;
+mblk_t *mp;
+{
+ struct iocblk *iocp;
+
+ switch(mp->b_datap->db_type)
+ {
+ case M_IOCTL:
+ iocp=(struct iocblk*) mp->b_rptr;
+ if (iocp->ioc_cmd==CLK_SETSTR)
+ {
+ strncpy( ((struct priv_data_type *) (RD(q)->q_ptr))->string,
+ (char *) mp->b_cont->b_rptr,CLK_MAXSTRSIZE);
+ /* make sure it's null terminated */
+ ((struct priv_data_type *) (RD(q)->q_ptr))->string[CLK_MAXSTRSIZE-1]=0;
+ mp->b_datap->db_type = M_IOCACK;
+ qreply(q,mp);
+ }
+ else
+ putnext(q,mp);
+ break;
+ default:
+ putnext(q,mp);
+ break;
+ }
+}
+
+/*
+ * Now clkchar. It takes a character, a queue pointer and an action
+ * flag and depending on the flag either:
+ *
+ * 0 - adds the character to the current message. If there's a
+ * timestamp to be done, do that too. If the message is less than
+ * 8 chars from being full, link in a new one, and set it up for
+ * the next call.
+ *
+ * 1 - sends the whole mess to Valhala.
+ *
+ * 2 - set things up.
+ *
+ * Yeah, it's an ugly hack. Complaints may be filed with /dev/null.
+ */
+
+
+void clkchar(c,q,f)
+ register u_char c;
+ queue_t *q;
+ char f;
+{
+ static char error;
+ static mblk_t *message,*mp;
+ struct timeval tv;
+
+/* Get a timestamp ASAP! */
+ uniqtime(&tv);
+
+ switch(f)
+ {
+ case 1:
+ if (!error)
+ putnext(q,message);
+ break;
+ case 2:
+ mp=message= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
+ error=(message==NULL);
+ if (error)
+ log(LOG_ERR,"clk: cannot allocate message - data lost");
+ break;
+ case 0:
+ if (error) /* If we had an error, forget it. */
+ return;
+
+ *mp->b_wptr++=c; /* Put the char away first.
+
+ /* If it's in the special string, append a struct timeval */
+
+ if (str_chr( ((struct priv_data_type *) (q->q_ptr))->string ,
+ c )!=NULL)
+ {
+ int i;
+
+ for (i=0;i<sizeof(struct timeval);i++)
+ *mp->b_wptr++= *( ((char*)&tv) + i );
+ }
+
+ /* If we don't have space for a complete struct timeval, and a
+ char, it's time for a new mp block */
+
+ if (((mp->b_wptr-mp->b_rptr)+sizeof(struct timeval)+2)>MESSAGE_SIZE)
+ {
+ mp->b_cont= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
+ error=(mp->b_cont==NULL);
+ if (error)
+ {
+ log(LOG_ERR,"clk: cannot allocate message - data lost");
+ freemsg(message);
+ }
+ mp=mp->b_cont;
+ }
+
+ break;
+ }
+}
+
+#endif
OpenPOWER on IntegriCloud