1/* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 30 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 130262 2004-06-09 10:16:14Z phk $"); |
34 35/* 36 * Pseudo-teletype Driver 37 * (Actually two drivers, requiring two entries in 'cdevsw') 38 */ 39#include "opt_compat.h" 40#include "opt_tty.h" 41#include <sys/param.h> --- 114 unchanged lines hidden (view full) --- 156 devs->si_drv1 = devc->si_drv1 = pt; 157 devs->si_tty = devc->si_tty = pt->pt_tty; 158 pt->pt_tty->t_dev = devs; 159 return (devc); 160} 161 162/*ARGSUSED*/ 163static int |
164ptsopen(dev_t dev, int flag, int devtype, struct thread *td) |
165{ 166 struct tty *tp; 167 int error; 168 struct pt_ioctl *pti; 169 170 if (!dev->si_drv1) 171 return(ENXIO); 172 pti = dev->si_drv1; --- 21 unchanged lines hidden (view full) --- 194 } 195 error = ttyld_open(tp, dev); 196 if (error == 0) 197 ptcwakeup(tp, FREAD|FWRITE); 198 return (error); 199} 200 201static int |
202ptsclose(dev_t dev, int flag, int mode, struct thread *td) |
203{ 204 struct tty *tp; 205 int err; 206 207 tp = dev->si_tty; 208 err = ttyld_close(tp, flag); 209 (void) ttyclose(tp); 210 return (err); 211} 212 213static int |
214ptsread(dev_t dev, struct uio *uio, int flag) |
215{ 216 struct thread *td = curthread; 217 struct proc *p = td->td_proc; 218 struct tty *tp = dev->si_tty; 219 struct pt_ioctl *pti = dev->si_drv1; 220 struct pgrp *pg; 221 int error = 0; 222 --- 46 unchanged lines hidden (view full) --- 269} 270 271/* 272 * Write to pseudo-tty. 273 * Wakeups of controlling tty will happen 274 * indirectly, when tty driver calls ptsstart. 275 */ 276static int |
277ptswrite(dev_t dev, struct uio *uio, int flag) |
278{ 279 struct tty *tp; 280 281 tp = dev->si_tty; 282 if (tp->t_oproc == 0) 283 return (EIO); 284 return (ttyld_write(tp, uio, flag)); 285} 286 287/* 288 * Start output on pseudo-tty. 289 * Wake up process selecting or sleeping for input from controlling tty. 290 */ 291static void |
292ptsstart(struct tty *tp) |
293{ 294 struct pt_ioctl *pti = tp->t_dev->si_drv1; 295 296 if (tp->t_state & TS_TTSTOP) 297 return; 298 if (pti->pt_flags & PF_STOPPED) { 299 pti->pt_flags &= ~PF_STOPPED; 300 pti->pt_send = TIOCPKT_START; 301 } 302 ptcwakeup(tp, FREAD); 303} 304 305static void |
306ptcwakeup(struct tty *tp, int flag) |
307{ 308 struct pt_ioctl *pti = tp->t_dev->si_drv1; 309 310 if (flag & FREAD) { 311 selwakeuppri(&pti->pt_selr, TTIPRI); 312 wakeup(TSA_PTC_READ(tp)); 313 } 314 if (flag & FWRITE) { 315 selwakeuppri(&pti->pt_selw, TTOPRI); 316 wakeup(TSA_PTC_WRITE(tp)); 317 } 318} 319 320static int |
321ptcopen(dev_t dev, int flag, int devtype, struct thread *td) |
322{ 323 struct tty *tp; 324 struct pt_ioctl *pti; 325 326 if (!dev->si_drv1) 327 ptyinit(dev); 328 if (!dev->si_drv1) 329 return(ENXIO); --- 9 unchanged lines hidden (view full) --- 339 pti->pt_prison = td->td_ucred->cr_prison; 340 pti->pt_flags = 0; 341 pti->pt_send = 0; 342 pti->pt_ucntl = 0; 343 return (0); 344} 345 346static int |
347ptcclose(dev_t dev, int flags, int fmt, struct thread *td) |
348{ 349 struct tty *tp; 350 351 tp = dev->si_tty; 352 (void)ttyld_modem(tp, 0); 353 354 /* 355 * XXX MDMBUF makes no sense for ptys but would inhibit the above --- 9 unchanged lines hidden (view full) --- 365 ttyflush(tp, FREAD | FWRITE); 366 } 367 368 tp->t_oproc = 0; /* mark closed */ 369 return (0); 370} 371 372static int |
373ptcread(dev_t dev, struct uio *uio, int flag) |
374{ 375 struct tty *tp = dev->si_tty; 376 struct pt_ioctl *pti = dev->si_drv1; 377 char buf[BUFSIZ]; 378 int error = 0, cc; 379 380 /* 381 * We want to block until the slave --- 41 unchanged lines hidden (view full) --- 423 break; 424 error = uiomove(buf, cc, uio); 425 } 426 ttwwakeup(tp); 427 return (error); 428} 429 430static void |
431ptsstop(struct tty *tp, int flush) |
432{ 433 struct pt_ioctl *pti = tp->t_dev->si_drv1; 434 int flag; 435 436 /* note: FLUSHREAD and FLUSHWRITE already ok */ 437 if (flush == 0) { 438 flush = TIOCPKT_STOP; 439 pti->pt_flags |= PF_STOPPED; --- 5 unchanged lines hidden (view full) --- 445 if (flush & FREAD) 446 flag |= FWRITE; 447 if (flush & FWRITE) 448 flag |= FREAD; 449 ptcwakeup(tp, flag); 450} 451 452static int |
453ptcpoll(dev_t dev, int events, struct thread *td) |
454{ 455 struct tty *tp = dev->si_tty; 456 struct pt_ioctl *pti = dev->si_drv1; 457 int revents = 0; 458 int s; 459 460 if ((tp->t_state & TS_CONNECTED) == 0) 461 return (events & --- 31 unchanged lines hidden (view full) --- 493 selrecord(td, &pti->pt_selw); 494 } 495 splx(s); 496 497 return (revents); 498} 499 500static int |
501ptcwrite(dev_t dev, struct uio *uio, int flag) |
502{ 503 struct tty *tp = dev->si_tty; 504 u_char *cp = 0; 505 int cc = 0; 506 u_char locbuf[BUFSIZ]; 507 int cnt = 0; 508 struct pt_ioctl *pti = dev->si_drv1; 509 int error = 0; --- 91 unchanged lines hidden (view full) --- 601 uio->uio_resid += cc; 602 return (error); 603 } 604 goto again; 605} 606 607/*ARGSUSED*/ 608static int |
609ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) |
610{ 611 struct tty *tp = dev->si_tty; 612 struct pt_ioctl *pti = dev->si_drv1; 613 u_char *cc = tp->t_cc; 614 int stop, error; 615 616 if (devsw(dev)->d_open == ptcopen) { 617 switch (cmd) { --- 149 unchanged lines hidden (view full) --- 767 pti->pt_send |= TIOCPKT_NOSTOP; 768 pti->pt_flags |= PF_NOSTOP; 769 ptcwakeup(tp, FREAD); 770 } 771 } 772 return (error); 773} 774 |
775static void |
776pty_clone(void *arg, char *name, int namelen, dev_t *dev) |
777{ 778 int u; 779 780 if (*dev != NODEV) 781 return; 782 if (bcmp(name, "pty", 3) != 0) 783 return; 784 if (name[5] != '\0') --- 17 unchanged lines hidden (view full) --- 802 return; 803 *dev = make_dev(&ptc_cdevsw, u, 804 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 805 (*dev)->si_flags |= SI_CHEAPCLONE; 806 return; 807} 808 809static void |
810ptc_drvinit(void *unused) |
811{ 812 813 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 814} 815 816SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL) |