1/* 2 * Copyright (c) 1995 Ugen J.S.Antsilevich 3 * 4 * Redistribution and use in source forms, with and without modification, 5 * are permitted provided that this entire comment appears intact. 6 * 7 * Redistribution in binary form may occur without any restrictions. 8 * Obviously, it would be nice if you gave credit where credit is due 9 * but requiring it would be too onerous. 10 * 11 * This software is provided ``AS IS'' without any warranties of any kind. 12 * 13 * Snoop stuff. 14 */ 15 16#include "snp.h" 17 18#if NSNP > 0 19 20#include <sys/param.h> 21#include <sys/systm.h> 22#include <sys/ioctl.h> 23#include <sys/ioctl_compat.h> /* Oooh..We need O/NTTYDISC */ 24#include <sys/proc.h>
| 1/* 2 * Copyright (c) 1995 Ugen J.S.Antsilevich 3 * 4 * Redistribution and use in source forms, with and without modification, 5 * are permitted provided that this entire comment appears intact. 6 * 7 * Redistribution in binary form may occur without any restrictions. 8 * Obviously, it would be nice if you gave credit where credit is due 9 * but requiring it would be too onerous. 10 * 11 * This software is provided ``AS IS'' without any warranties of any kind. 12 * 13 * Snoop stuff. 14 */ 15 16#include "snp.h" 17 18#if NSNP > 0 19 20#include <sys/param.h> 21#include <sys/systm.h> 22#include <sys/ioctl.h> 23#include <sys/ioctl_compat.h> /* Oooh..We need O/NTTYDISC */ 24#include <sys/proc.h>
|
25#define TTYDEFCHARS
| |
26#include <sys/tty.h>
| 25#include <sys/tty.h>
|
27#undef TTYDEFCHARS
| |
28#include <sys/file.h> 29#include <sys/conf.h> 30#include <sys/uio.h> 31#include <sys/kernel.h> 32#include <sys/malloc.h> 33#ifdef DEVFS 34#include <sys/devfsext.h> 35#endif /*DEVFS*/ 36 37#include <sys/snoop.h> 38 39static d_open_t snpopen; 40static d_close_t snpclose; 41static d_read_t snpread; 42static d_write_t snpwrite; 43static d_ioctl_t snpioctl; 44static d_select_t snpselect; 45 46#define CDEV_MAJOR 53 47static struct cdevsw snp_cdevsw = 48 { snpopen, snpclose, snpread, snpwrite, /*53*/ 49 snpioctl, nostop, nullreset, nodevtotty,/* snoop */ 50 snpselect, nommap, NULL, "snp", NULL, -1 }; 51 52 53#ifndef MIN 54#define MIN(a,b) (((a)<(b))?(a):(b)) 55#endif 56 57static struct snoop snoopsw[NSNP]; 58 59static struct tty *devtotty __P((dev_t dev));
| 26#include <sys/file.h> 27#include <sys/conf.h> 28#include <sys/uio.h> 29#include <sys/kernel.h> 30#include <sys/malloc.h> 31#ifdef DEVFS 32#include <sys/devfsext.h> 33#endif /*DEVFS*/ 34 35#include <sys/snoop.h> 36 37static d_open_t snpopen; 38static d_close_t snpclose; 39static d_read_t snpread; 40static d_write_t snpwrite; 41static d_ioctl_t snpioctl; 42static d_select_t snpselect; 43 44#define CDEV_MAJOR 53 45static struct cdevsw snp_cdevsw = 46 { snpopen, snpclose, snpread, snpwrite, /*53*/ 47 snpioctl, nostop, nullreset, nodevtotty,/* snoop */ 48 snpselect, nommap, NULL, "snp", NULL, -1 }; 49 50 51#ifndef MIN 52#define MIN(a,b) (((a)<(b))?(a):(b)) 53#endif 54 55static struct snoop snoopsw[NSNP]; 56 57static struct tty *devtotty __P((dev_t dev));
|
| 58static int snp_detach __P((struct snoop *snp));
|
60 61static struct tty * 62devtotty (dev) 63 dev_t dev; 64{ 65 if (major(dev) > nchrdev) 66 return (NULL); /* no such device available */ 67 68 return (*cdevsw[major(dev)]->d_devtotty)(dev); 69} 70 71#define SNP_INPUT_BUF 5 /* This is even too much,the maximal 72 * interactive mode write is 3 bytes 73 * length for function keys... 74 */ 75 76static int 77snpwrite(dev, uio, flag) 78 dev_t dev; 79 struct uio *uio; 80 int flag; 81{ 82 int unit = minor(dev), len, i, error; 83 struct snoop *snp = &snoopsw[unit]; 84 struct tty *tp; 85 char c[SNP_INPUT_BUF]; 86 87 if (snp->snp_tty == NULL) 88 return (EIO); 89 90 tp = snp->snp_tty; 91 92 if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 93 (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) 94 goto tty_input; 95 96 printf("Snoop: attempt to write to bad tty.\n"); 97 return (EIO); 98 99tty_input: 100 if (!(tp->t_state & TS_ISOPEN)) 101 return (EIO); 102 103 while (uio->uio_resid > 0) { 104 len = MIN(uio->uio_resid,SNP_INPUT_BUF); 105 if ((error = uiomove(c, len, uio)) != 0) 106 return (error); 107 for (i=0;i<len;i++) { 108 if (ttyinput(c[i] , tp)) 109 return (EIO); 110 } 111 } 112 return 0; 113 114} 115 116 117static int 118snpread(dev, uio, flag) 119 dev_t dev; 120 struct uio *uio; 121 int flag; 122{ 123 int unit = minor(dev), s; 124 struct snoop *snp = &snoopsw[unit]; 125 int len, n, nblen, error = 0; 126 caddr_t from; 127 char *nbuf; 128 129#ifdef DIAGNOSTIC 130 if ((snp->snp_len + snp->snp_base) > snp->snp_blen) 131 panic("snoop buffer error"); 132#endif 133 134 if (snp->snp_tty == NULL) 135 return (EIO); 136 137 snp->snp_flags &= ~SNOOP_RWAIT; 138 139 do { 140 if (snp->snp_len == 0) { 141 if (snp->snp_flags & SNOOP_NBIO) { 142 return EWOULDBLOCK; 143 } 144 snp->snp_flags |= SNOOP_RWAIT; 145 tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0); 146 } 147 } while (snp->snp_len == 0); 148 149 n = snp->snp_len; 150 151 while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) { 152 len = MIN(uio->uio_resid, snp->snp_len); 153 from = (caddr_t) (snp->snp_buf + snp->snp_base); 154 if (len == 0) 155 break; 156 157 error = uiomove(from, len, uio); 158 snp->snp_base += len; 159 snp->snp_len -= len; 160 } 161 if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) { 162 snp->snp_flags &= ~SNOOP_OFLOW; 163 } 164 s = spltty(); 165 nblen = snp->snp_blen; 166 if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) { 167 while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN)) 168 nblen = nblen / 2; 169 if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) { 170 bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 171 free(snp->snp_buf, M_TTYS); 172 snp->snp_buf = nbuf; 173 snp->snp_blen = nblen; 174 snp->snp_base = 0; 175 } 176 } 177 splx(s); 178 179 return error; 180} 181 182int 183snpinc(snp, c) 184 struct snoop *snp; 185 char c; 186{ 187 char buf[1]; 188 189 buf[0]=c; 190 return (snpin(snp,buf,1)); 191} 192 193 194int 195snpin(snp, buf, n) 196 struct snoop *snp; 197 char *buf; 198 int n; 199{ 200 int s_free, s_tail; 201 int s, len, nblen; 202 caddr_t from, to; 203 char *nbuf; 204 205 206 if (n == 0) 207 return 0; 208 209#ifdef DIAGNOSTIC 210 if (n < 0) 211 panic("bad snoop char count"); 212 213 if (!(snp->snp_flags & SNOOP_OPEN)) { 214 printf("Snoop: data coming to closed device.\n"); 215 return 0; 216 } 217#endif 218 if (snp->snp_flags & SNOOP_DOWN) { 219 printf("Snoop: more data to down interface.\n"); 220 return 0; 221 } 222 223 if (snp->snp_flags & SNOOP_OFLOW) { 224 printf("Snoop: buffer overflow.\n"); 225 /* 226 * On overflow we just repeat the standart close 227 * procedure...yes , this is waste of space but.. Then next 228 * read from device will fail if one would recall he is 229 * snooping and retry... 230 */ 231 232 return (snpdown(snp)); 233 } 234 s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base); 235 s_free = snp->snp_blen - snp->snp_len; 236 237 238 if (n > s_free) { 239 s = spltty(); 240 nblen = snp->snp_blen; 241 while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) { 242 nblen = snp->snp_blen * 2; 243 s_free = nblen - (snp->snp_len + snp->snp_base); 244 } 245 if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) { 246 bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 247 free(snp->snp_buf, M_TTYS); 248 snp->snp_buf = nbuf; 249 snp->snp_blen = nblen; 250 snp->snp_base = 0; 251 } else { 252 snp->snp_flags |= SNOOP_OFLOW; 253 if (snp->snp_flags & SNOOP_RWAIT) { 254 snp->snp_flags &= ~SNOOP_RWAIT; 255 wakeup((caddr_t) snp); 256 } 257 splx(s); 258 return 0; 259 } 260 splx(s); 261 } 262 if (n > s_tail) { 263 from = (caddr_t) (snp->snp_buf + snp->snp_base); 264 to = (caddr_t) (snp->snp_buf); 265 len = snp->snp_len; 266 bcopy(from, to, len); 267 snp->snp_base = 0; 268 } 269 to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len); 270 bcopy(buf, to, n); 271 snp->snp_len += n; 272 273 if (snp->snp_flags & SNOOP_RWAIT) { 274 snp->snp_flags &= ~SNOOP_RWAIT; 275 wakeup((caddr_t) snp); 276 } 277 selwakeup(&snp->snp_sel); 278 snp->snp_sel.si_pid = 0; 279 280 return n; 281} 282 283static int 284snpopen(dev, flag, mode, p) 285 dev_t dev; 286 int flag, mode; 287 struct proc *p; 288{ 289 struct snoop *snp; 290 register int unit, error; 291 292 if (error = suser(p->p_ucred, &p->p_acflag)) 293 return (error); 294 295 if ((unit = minor(dev)) >= NSNP) 296 return (ENXIO); 297 298 snp = &snoopsw[unit]; 299 300 if (snp->snp_flags & SNOOP_OPEN) 301 return (ENXIO); 302 303 /* 304 * We intentionally do not OR flags with SNOOP_OPEN,but set them so 305 * all previous settings (especially SNOOP_OFLOW) will be cleared. 306 */ 307 snp->snp_flags = SNOOP_OPEN; 308 309 snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 310 snp->snp_blen = SNOOP_MINLEN; 311 snp->snp_base = 0; 312 snp->snp_len = 0; 313 314 /* 315 * snp_tty == NULL is for inactive snoop devices. 316 */ 317 snp->snp_tty = NULL; 318 snp->snp_target = -1; 319 return (0); 320} 321 322
| 59 60static struct tty * 61devtotty (dev) 62 dev_t dev; 63{ 64 if (major(dev) > nchrdev) 65 return (NULL); /* no such device available */ 66 67 return (*cdevsw[major(dev)]->d_devtotty)(dev); 68} 69 70#define SNP_INPUT_BUF 5 /* This is even too much,the maximal 71 * interactive mode write is 3 bytes 72 * length for function keys... 73 */ 74 75static int 76snpwrite(dev, uio, flag) 77 dev_t dev; 78 struct uio *uio; 79 int flag; 80{ 81 int unit = minor(dev), len, i, error; 82 struct snoop *snp = &snoopsw[unit]; 83 struct tty *tp; 84 char c[SNP_INPUT_BUF]; 85 86 if (snp->snp_tty == NULL) 87 return (EIO); 88 89 tp = snp->snp_tty; 90 91 if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 92 (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) 93 goto tty_input; 94 95 printf("Snoop: attempt to write to bad tty.\n"); 96 return (EIO); 97 98tty_input: 99 if (!(tp->t_state & TS_ISOPEN)) 100 return (EIO); 101 102 while (uio->uio_resid > 0) { 103 len = MIN(uio->uio_resid,SNP_INPUT_BUF); 104 if ((error = uiomove(c, len, uio)) != 0) 105 return (error); 106 for (i=0;i<len;i++) { 107 if (ttyinput(c[i] , tp)) 108 return (EIO); 109 } 110 } 111 return 0; 112 113} 114 115 116static int 117snpread(dev, uio, flag) 118 dev_t dev; 119 struct uio *uio; 120 int flag; 121{ 122 int unit = minor(dev), s; 123 struct snoop *snp = &snoopsw[unit]; 124 int len, n, nblen, error = 0; 125 caddr_t from; 126 char *nbuf; 127 128#ifdef DIAGNOSTIC 129 if ((snp->snp_len + snp->snp_base) > snp->snp_blen) 130 panic("snoop buffer error"); 131#endif 132 133 if (snp->snp_tty == NULL) 134 return (EIO); 135 136 snp->snp_flags &= ~SNOOP_RWAIT; 137 138 do { 139 if (snp->snp_len == 0) { 140 if (snp->snp_flags & SNOOP_NBIO) { 141 return EWOULDBLOCK; 142 } 143 snp->snp_flags |= SNOOP_RWAIT; 144 tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0); 145 } 146 } while (snp->snp_len == 0); 147 148 n = snp->snp_len; 149 150 while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) { 151 len = MIN(uio->uio_resid, snp->snp_len); 152 from = (caddr_t) (snp->snp_buf + snp->snp_base); 153 if (len == 0) 154 break; 155 156 error = uiomove(from, len, uio); 157 snp->snp_base += len; 158 snp->snp_len -= len; 159 } 160 if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) { 161 snp->snp_flags &= ~SNOOP_OFLOW; 162 } 163 s = spltty(); 164 nblen = snp->snp_blen; 165 if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) { 166 while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN)) 167 nblen = nblen / 2; 168 if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) { 169 bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 170 free(snp->snp_buf, M_TTYS); 171 snp->snp_buf = nbuf; 172 snp->snp_blen = nblen; 173 snp->snp_base = 0; 174 } 175 } 176 splx(s); 177 178 return error; 179} 180 181int 182snpinc(snp, c) 183 struct snoop *snp; 184 char c; 185{ 186 char buf[1]; 187 188 buf[0]=c; 189 return (snpin(snp,buf,1)); 190} 191 192 193int 194snpin(snp, buf, n) 195 struct snoop *snp; 196 char *buf; 197 int n; 198{ 199 int s_free, s_tail; 200 int s, len, nblen; 201 caddr_t from, to; 202 char *nbuf; 203 204 205 if (n == 0) 206 return 0; 207 208#ifdef DIAGNOSTIC 209 if (n < 0) 210 panic("bad snoop char count"); 211 212 if (!(snp->snp_flags & SNOOP_OPEN)) { 213 printf("Snoop: data coming to closed device.\n"); 214 return 0; 215 } 216#endif 217 if (snp->snp_flags & SNOOP_DOWN) { 218 printf("Snoop: more data to down interface.\n"); 219 return 0; 220 } 221 222 if (snp->snp_flags & SNOOP_OFLOW) { 223 printf("Snoop: buffer overflow.\n"); 224 /* 225 * On overflow we just repeat the standart close 226 * procedure...yes , this is waste of space but.. Then next 227 * read from device will fail if one would recall he is 228 * snooping and retry... 229 */ 230 231 return (snpdown(snp)); 232 } 233 s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base); 234 s_free = snp->snp_blen - snp->snp_len; 235 236 237 if (n > s_free) { 238 s = spltty(); 239 nblen = snp->snp_blen; 240 while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) { 241 nblen = snp->snp_blen * 2; 242 s_free = nblen - (snp->snp_len + snp->snp_base); 243 } 244 if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) { 245 bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 246 free(snp->snp_buf, M_TTYS); 247 snp->snp_buf = nbuf; 248 snp->snp_blen = nblen; 249 snp->snp_base = 0; 250 } else { 251 snp->snp_flags |= SNOOP_OFLOW; 252 if (snp->snp_flags & SNOOP_RWAIT) { 253 snp->snp_flags &= ~SNOOP_RWAIT; 254 wakeup((caddr_t) snp); 255 } 256 splx(s); 257 return 0; 258 } 259 splx(s); 260 } 261 if (n > s_tail) { 262 from = (caddr_t) (snp->snp_buf + snp->snp_base); 263 to = (caddr_t) (snp->snp_buf); 264 len = snp->snp_len; 265 bcopy(from, to, len); 266 snp->snp_base = 0; 267 } 268 to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len); 269 bcopy(buf, to, n); 270 snp->snp_len += n; 271 272 if (snp->snp_flags & SNOOP_RWAIT) { 273 snp->snp_flags &= ~SNOOP_RWAIT; 274 wakeup((caddr_t) snp); 275 } 276 selwakeup(&snp->snp_sel); 277 snp->snp_sel.si_pid = 0; 278 279 return n; 280} 281 282static int 283snpopen(dev, flag, mode, p) 284 dev_t dev; 285 int flag, mode; 286 struct proc *p; 287{ 288 struct snoop *snp; 289 register int unit, error; 290 291 if (error = suser(p->p_ucred, &p->p_acflag)) 292 return (error); 293 294 if ((unit = minor(dev)) >= NSNP) 295 return (ENXIO); 296 297 snp = &snoopsw[unit]; 298 299 if (snp->snp_flags & SNOOP_OPEN) 300 return (ENXIO); 301 302 /* 303 * We intentionally do not OR flags with SNOOP_OPEN,but set them so 304 * all previous settings (especially SNOOP_OFLOW) will be cleared. 305 */ 306 snp->snp_flags = SNOOP_OPEN; 307 308 snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 309 snp->snp_blen = SNOOP_MINLEN; 310 snp->snp_base = 0; 311 snp->snp_len = 0; 312 313 /* 314 * snp_tty == NULL is for inactive snoop devices. 315 */ 316 snp->snp_tty = NULL; 317 snp->snp_target = -1; 318 return (0); 319} 320 321
|
323int
| 322static int
|
324snp_detach(snp) 325 struct snoop *snp; 326{ 327 struct tty *tp; 328 329 snp->snp_base = 0; 330 snp->snp_len = 0; 331 332 /* 333 * If line disc. changed we do not touch this pointer,SLIP/PPP will 334 * change it anyway. 335 */ 336 337 if (snp->snp_tty == NULL) 338 goto detach_notty; 339 340 tp = snp->snp_tty; 341 342 if (tp && (tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 343 (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) { 344 tp->t_sc = NULL; 345 tp->t_state &= ~TS_SNOOP; 346 } else 347 printf("Snoop: bad attached tty data.\n"); 348 349 snp->snp_tty = NULL; 350 snp->snp_target = -1; 351 352detach_notty: 353 selwakeup(&snp->snp_sel); 354 snp->snp_sel.si_pid = 0; 355 356 return (0); 357} 358 359static int 360snpclose(dev, flags, fmt, p) 361 dev_t dev; 362 int flags; 363 int fmt; 364 struct proc *p; 365{ 366 register int unit = minor(dev); 367 struct snoop *snp = &snoopsw[unit]; 368 369 snp->snp_blen = 0; 370 free(snp->snp_buf, M_TTYS); 371 snp->snp_flags &= ~SNOOP_OPEN; 372 373 return (snp_detach(snp)); 374} 375 376int 377snpdown(snp) 378 struct snoop *snp; 379{ 380 snp->snp_blen = SNOOP_MINLEN; 381 free(snp->snp_buf, M_TTYS); 382 snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 383 snp->snp_flags |= SNOOP_DOWN; 384 385 return (snp_detach(snp)); 386} 387 388 389static int 390snpioctl(dev, cmd, data, flags, p) 391 dev_t dev; 392 int cmd; 393 caddr_t data; 394 int flags; 395 struct proc *p; 396{ 397 int unit = minor(dev), s; 398 dev_t tdev; 399 struct snoop *snp = &snoopsw[unit]; 400 struct tty *tp, *tpo; 401 402 switch (cmd) { 403 case SNPSTTY: 404 tdev = *((dev_t *) data); 405 if (tdev == -1) 406 return (snpdown(snp)); 407 408 tp = devtotty(tdev); 409 if (!tp) 410 return (EINVAL); 411 412 if ((tp->t_sc != (caddr_t) snp) && (tp->t_state & TS_SNOOP)) 413 return (EBUSY); 414 415 if ((tp->t_line != OTTYDISC) && (tp->t_line != NTTYDISC)) 416 return (EBUSY); 417 418 s = spltty(); 419 420 if (snp->snp_target == -1) { 421 tpo = snp->snp_tty; 422 if (tpo) 423 tpo->t_state &= ~TS_SNOOP; 424 } 425 426 tp->t_sc = (caddr_t) snp; 427 tp->t_state |= TS_SNOOP; 428 snp->snp_tty = tp; 429 snp->snp_target = tdev; 430 431 /* 432 * Clean overflow and down flags - 433 * we'll have a chance to get them in the future :))) 434 */ 435 snp->snp_flags &= ~SNOOP_OFLOW; 436 snp->snp_flags &= ~SNOOP_DOWN; 437 splx(s); 438 break; 439 440 case SNPGTTY: 441 /* 442 * We keep snp_target field specially to make 443 * SNPGTTY happy,else we can't know what is device 444 * major/minor for tty. 445 */ 446 *((dev_t *) data) = snp->snp_target; 447 break; 448 449 case FIONBIO: 450 if (*(int *) data) 451 snp->snp_flags |= SNOOP_NBIO; 452 else 453 snp->snp_flags &= ~SNOOP_NBIO; 454 break; 455 456 case FIOASYNC: 457 if (*(int *) data) 458 snp->snp_flags |= SNOOP_ASYNC; 459 else 460 snp->snp_flags &= ~SNOOP_ASYNC; 461 break; 462 463 case FIONREAD: 464 s = spltty(); 465 if (snp->snp_tty != NULL) 466 *(int *) data = snp->snp_len; 467 else 468 if (snp->snp_flags & SNOOP_DOWN) { 469 if (snp->snp_flags & SNOOP_OFLOW) 470 *(int *) data = SNP_OFLOW; 471 else 472 *(int *) data = SNP_TTYCLOSE; 473 } else { 474 *(int *) data = SNP_DETACH; 475 } 476 splx(s); 477 break; 478 479 default: 480 return (ENOTTY); 481 } 482 return (0); 483} 484 485 486static int 487snpselect(dev, rw, p) 488 dev_t dev; 489 int rw; 490 struct proc *p; 491{ 492 int unit = minor(dev); 493 struct snoop *snp = &snoopsw[unit]; 494 495 if (rw != FREAD) 496 return 1; 497 498 if (snp->snp_len > 0) 499 return 1; 500 501 /* 502 * If snoop is down,we don't want to select() forever so we return 1. 503 * Caller should see if we down via FIONREAD ioctl().The last should 504 * return -1 to indicate down state. 505 */ 506 if (snp->snp_flags & SNOOP_DOWN) 507 return 1; 508 509 selrecord(p, &snp->snp_sel); 510 return 0; 511} 512 513static void *snp_devfs_token[NSNP]; 514static snp_devsw_installed = 0; 515 516static void 517snp_drvinit(void *unused) 518{ 519 dev_t dev; 520 char name[32]; 521 int i; 522 523 if( ! snp_devsw_installed ) { 524 dev = makedev(CDEV_MAJOR, 0); 525 cdevsw_add(&dev,&snp_cdevsw, NULL); 526 snp_devsw_installed = 1; 527#ifdef DEVFS 528 for ( i = 0 ; i < NSNP ; i++) { 529 sprintf(name,"snp%d",i); 530 snp_devfs_token[i] = 531 devfs_add_devsw( "/", name, &snp_cdevsw, i, 532 DV_CHR, 0, 0, 0600); 533 } 534#endif 535 } 536} 537 538SYSINIT(snpdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,snp_drvinit,NULL) 539 540 541#endif
| 323snp_detach(snp) 324 struct snoop *snp; 325{ 326 struct tty *tp; 327 328 snp->snp_base = 0; 329 snp->snp_len = 0; 330 331 /* 332 * If line disc. changed we do not touch this pointer,SLIP/PPP will 333 * change it anyway. 334 */ 335 336 if (snp->snp_tty == NULL) 337 goto detach_notty; 338 339 tp = snp->snp_tty; 340 341 if (tp && (tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 342 (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) { 343 tp->t_sc = NULL; 344 tp->t_state &= ~TS_SNOOP; 345 } else 346 printf("Snoop: bad attached tty data.\n"); 347 348 snp->snp_tty = NULL; 349 snp->snp_target = -1; 350 351detach_notty: 352 selwakeup(&snp->snp_sel); 353 snp->snp_sel.si_pid = 0; 354 355 return (0); 356} 357 358static int 359snpclose(dev, flags, fmt, p) 360 dev_t dev; 361 int flags; 362 int fmt; 363 struct proc *p; 364{ 365 register int unit = minor(dev); 366 struct snoop *snp = &snoopsw[unit]; 367 368 snp->snp_blen = 0; 369 free(snp->snp_buf, M_TTYS); 370 snp->snp_flags &= ~SNOOP_OPEN; 371 372 return (snp_detach(snp)); 373} 374 375int 376snpdown(snp) 377 struct snoop *snp; 378{ 379 snp->snp_blen = SNOOP_MINLEN; 380 free(snp->snp_buf, M_TTYS); 381 snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 382 snp->snp_flags |= SNOOP_DOWN; 383 384 return (snp_detach(snp)); 385} 386 387 388static int 389snpioctl(dev, cmd, data, flags, p) 390 dev_t dev; 391 int cmd; 392 caddr_t data; 393 int flags; 394 struct proc *p; 395{ 396 int unit = minor(dev), s; 397 dev_t tdev; 398 struct snoop *snp = &snoopsw[unit]; 399 struct tty *tp, *tpo; 400 401 switch (cmd) { 402 case SNPSTTY: 403 tdev = *((dev_t *) data); 404 if (tdev == -1) 405 return (snpdown(snp)); 406 407 tp = devtotty(tdev); 408 if (!tp) 409 return (EINVAL); 410 411 if ((tp->t_sc != (caddr_t) snp) && (tp->t_state & TS_SNOOP)) 412 return (EBUSY); 413 414 if ((tp->t_line != OTTYDISC) && (tp->t_line != NTTYDISC)) 415 return (EBUSY); 416 417 s = spltty(); 418 419 if (snp->snp_target == -1) { 420 tpo = snp->snp_tty; 421 if (tpo) 422 tpo->t_state &= ~TS_SNOOP; 423 } 424 425 tp->t_sc = (caddr_t) snp; 426 tp->t_state |= TS_SNOOP; 427 snp->snp_tty = tp; 428 snp->snp_target = tdev; 429 430 /* 431 * Clean overflow and down flags - 432 * we'll have a chance to get them in the future :))) 433 */ 434 snp->snp_flags &= ~SNOOP_OFLOW; 435 snp->snp_flags &= ~SNOOP_DOWN; 436 splx(s); 437 break; 438 439 case SNPGTTY: 440 /* 441 * We keep snp_target field specially to make 442 * SNPGTTY happy,else we can't know what is device 443 * major/minor for tty. 444 */ 445 *((dev_t *) data) = snp->snp_target; 446 break; 447 448 case FIONBIO: 449 if (*(int *) data) 450 snp->snp_flags |= SNOOP_NBIO; 451 else 452 snp->snp_flags &= ~SNOOP_NBIO; 453 break; 454 455 case FIOASYNC: 456 if (*(int *) data) 457 snp->snp_flags |= SNOOP_ASYNC; 458 else 459 snp->snp_flags &= ~SNOOP_ASYNC; 460 break; 461 462 case FIONREAD: 463 s = spltty(); 464 if (snp->snp_tty != NULL) 465 *(int *) data = snp->snp_len; 466 else 467 if (snp->snp_flags & SNOOP_DOWN) { 468 if (snp->snp_flags & SNOOP_OFLOW) 469 *(int *) data = SNP_OFLOW; 470 else 471 *(int *) data = SNP_TTYCLOSE; 472 } else { 473 *(int *) data = SNP_DETACH; 474 } 475 splx(s); 476 break; 477 478 default: 479 return (ENOTTY); 480 } 481 return (0); 482} 483 484 485static int 486snpselect(dev, rw, p) 487 dev_t dev; 488 int rw; 489 struct proc *p; 490{ 491 int unit = minor(dev); 492 struct snoop *snp = &snoopsw[unit]; 493 494 if (rw != FREAD) 495 return 1; 496 497 if (snp->snp_len > 0) 498 return 1; 499 500 /* 501 * If snoop is down,we don't want to select() forever so we return 1. 502 * Caller should see if we down via FIONREAD ioctl().The last should 503 * return -1 to indicate down state. 504 */ 505 if (snp->snp_flags & SNOOP_DOWN) 506 return 1; 507 508 selrecord(p, &snp->snp_sel); 509 return 0; 510} 511 512static void *snp_devfs_token[NSNP]; 513static snp_devsw_installed = 0; 514 515static void 516snp_drvinit(void *unused) 517{ 518 dev_t dev; 519 char name[32]; 520 int i; 521 522 if( ! snp_devsw_installed ) { 523 dev = makedev(CDEV_MAJOR, 0); 524 cdevsw_add(&dev,&snp_cdevsw, NULL); 525 snp_devsw_installed = 1; 526#ifdef DEVFS 527 for ( i = 0 ; i < NSNP ; i++) { 528 sprintf(name,"snp%d",i); 529 snp_devfs_token[i] = 530 devfs_add_devsw( "/", name, &snp_cdevsw, i, 531 DV_CHR, 0, 0, 0600); 532 } 533#endif 534 } 535} 536 537SYSINIT(snpdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,snp_drvinit,NULL) 538 539 540#endif
|