Annotation of embedaddon/ntp/kernel/tty_clk_STREAMS.c, revision 1.1.1.1

1.1       misho       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: 
                     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();
                     48: 
                     49: static struct qinit rinit = { clkrput, NULL, clkopen, clkclose, NULL,
                     50:        &rminfo, NULL };
                     51: 
                     52: static struct qinit winit = { clkwput, NULL, NULL, NULL, NULL,
                     53:        &wminfo, NULL };
                     54: 
                     55: struct streamtab clkinfo = { &rinit, &winit, NULL, NULL };
                     56: 
                     57: struct priv_data_type
                     58: {
                     59:   char in_use;
                     60:   char string[CLK_MAXSTRSIZE];
                     61: } priv_data[NCLK];
                     62: 
                     63: char 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: 
                     70: u_char *str_chr(s,c)
                     71: u_char *s;
                     72: int c;
                     73: {
                     74:   while (*s)
                     75:     if(*s++ == c)
                     76:       return (s-1);
                     77:   return NULL;
                     78: }
                     79: 
                     80: /*ARGSUSED*/
                     81: static int clkopen(q, dev, flag, sflag)
                     82: queue_t *q;
                     83: dev_t dev;
                     84: int flag;
                     85: int 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*/
                    114: static int clkclose(q, flag)
                    115: queue_t *q;
                    116: int 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: 
                    130: void clkchar();
                    131: 
                    132: static int clkrput(q, mp)
                    133: queue_t *q;
                    134: mblk_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: 
                    161: static int clkwput(q, mp)
                    162: queue_t *q;
                    163: mblk_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: 
                    206: void 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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>