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 130259 2004-06-09 09:09:54Z 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, flag, devtype, td)
165 dev_t dev;
166 int flag, devtype;
167 struct thread *td;
168{
169 struct tty *tp;
170 int error;
171 struct pt_ioctl *pti;
172
173 if (!dev->si_drv1)
174 return(ENXIO);
175 pti = dev->si_drv1;
--- 21 unchanged lines hidden (view full) ---
197 }
198 error = ttyld_open(tp, dev);
199 if (error == 0)
200 ptcwakeup(tp, FREAD|FWRITE);
201 return (error);
202}
203
204static int
205ptsclose(dev, flag, mode, td)
206 dev_t dev;
207 int flag, mode;
208 struct thread *td;
209{
210 struct tty *tp;
211 int err;
212
213 tp = dev->si_tty;
214 err = ttyld_close(tp, flag);
215 (void) ttyclose(tp);
216 return (err);
217}
218
219static int
220ptsread(dev, uio, flag)
221 dev_t dev;
222 struct uio *uio;
223 int flag;
224{
225 struct thread *td = curthread;
226 struct proc *p = td->td_proc;
227 struct tty *tp = dev->si_tty;
228 struct pt_ioctl *pti = dev->si_drv1;
229 struct pgrp *pg;
230 int error = 0;
231
--- 46 unchanged lines hidden (view full) ---
278}
279
280/*
281 * Write to pseudo-tty.
282 * Wakeups of controlling tty will happen
283 * indirectly, when tty driver calls ptsstart.
284 */
285static int
286ptswrite(dev, uio, flag)
287 dev_t dev;
288 struct uio *uio;
289 int flag;
290{
291 struct tty *tp;
292
293 tp = dev->si_tty;
294 if (tp->t_oproc == 0)
295 return (EIO);
296 return (ttyld_write(tp, uio, flag));
297}
298
299/*
300 * Start output on pseudo-tty.
301 * Wake up process selecting or sleeping for input from controlling tty.
302 */
303static void
304ptsstart(tp)
305 struct tty *tp;
306{
307 struct pt_ioctl *pti = tp->t_dev->si_drv1;
308
309 if (tp->t_state & TS_TTSTOP)
310 return;
311 if (pti->pt_flags & PF_STOPPED) {
312 pti->pt_flags &= ~PF_STOPPED;
313 pti->pt_send = TIOCPKT_START;
314 }
315 ptcwakeup(tp, FREAD);
316}
317
318static void
319ptcwakeup(tp, flag)
320 struct tty *tp;
321 int flag;
322{
323 struct pt_ioctl *pti = tp->t_dev->si_drv1;
324
325 if (flag & FREAD) {
326 selwakeuppri(&pti->pt_selr, TTIPRI);
327 wakeup(TSA_PTC_READ(tp));
328 }
329 if (flag & FWRITE) {
330 selwakeuppri(&pti->pt_selw, TTOPRI);
331 wakeup(TSA_PTC_WRITE(tp));
332 }
333}
334
335static int
336ptcopen(dev, flag, devtype, td)
337 dev_t dev;
338 int flag, devtype;
339 struct thread *td;
340{
341 struct tty *tp;
342 struct pt_ioctl *pti;
343
344 if (!dev->si_drv1)
345 ptyinit(dev);
346 if (!dev->si_drv1)
347 return(ENXIO);
--- 9 unchanged lines hidden (view full) ---
357 pti->pt_prison = td->td_ucred->cr_prison;
358 pti->pt_flags = 0;
359 pti->pt_send = 0;
360 pti->pt_ucntl = 0;
361 return (0);
362}
363
364static int
365ptcclose(dev, flags, fmt, td)
366 dev_t dev;
367 int flags;
368 int fmt;
369 struct thread *td;
370{
371 struct tty *tp;
372
373 tp = dev->si_tty;
374 (void)ttyld_modem(tp, 0);
375
376 /*
377 * XXX MDMBUF makes no sense for ptys but would inhibit the above
--- 9 unchanged lines hidden (view full) ---
387 ttyflush(tp, FREAD | FWRITE);
388 }
389
390 tp->t_oproc = 0; /* mark closed */
391 return (0);
392}
393
394static int
395ptcread(dev, uio, flag)
396 dev_t dev;
397 struct uio *uio;
398 int flag;
399{
400 struct tty *tp = dev->si_tty;
401 struct pt_ioctl *pti = dev->si_drv1;
402 char buf[BUFSIZ];
403 int error = 0, cc;
404
405 /*
406 * We want to block until the slave
--- 41 unchanged lines hidden (view full) ---
448 break;
449 error = uiomove(buf, cc, uio);
450 }
451 ttwwakeup(tp);
452 return (error);
453}
454
455static void
456ptsstop(tp, flush)
457 struct tty *tp;
458 int flush;
459{
460 struct pt_ioctl *pti = tp->t_dev->si_drv1;
461 int flag;
462
463 /* note: FLUSHREAD and FLUSHWRITE already ok */
464 if (flush == 0) {
465 flush = TIOCPKT_STOP;
466 pti->pt_flags |= PF_STOPPED;
--- 5 unchanged lines hidden (view full) ---
472 if (flush & FREAD)
473 flag |= FWRITE;
474 if (flush & FWRITE)
475 flag |= FREAD;
476 ptcwakeup(tp, flag);
477}
478
479static int
480ptcpoll(dev, events, td)
481 dev_t dev;
482 int events;
483 struct thread *td;
484{
485 struct tty *tp = dev->si_tty;
486 struct pt_ioctl *pti = dev->si_drv1;
487 int revents = 0;
488 int s;
489
490 if ((tp->t_state & TS_CONNECTED) == 0)
491 return (events &
--- 31 unchanged lines hidden (view full) ---
523 selrecord(td, &pti->pt_selw);
524 }
525 splx(s);
526
527 return (revents);
528}
529
530static int
531ptcwrite(dev, uio, flag)
532 dev_t dev;
533 struct uio *uio;
534 int flag;
535{
536 struct tty *tp = dev->si_tty;
537 u_char *cp = 0;
538 int cc = 0;
539 u_char locbuf[BUFSIZ];
540 int cnt = 0;
541 struct pt_ioctl *pti = dev->si_drv1;
542 int error = 0;
--- 91 unchanged lines hidden (view full) ---
634 uio->uio_resid += cc;
635 return (error);
636 }
637 goto again;
638}
639
640/*ARGSUSED*/
641static int
642ptyioctl(dev, cmd, data, flag, td)
643 dev_t dev;
644 u_long cmd;
645 caddr_t data;
646 int flag;
647 struct thread *td;
648{
649 struct tty *tp = dev->si_tty;
650 struct pt_ioctl *pti = dev->si_drv1;
651 u_char *cc = tp->t_cc;
652 int stop, error;
653
654 if (devsw(dev)->d_open == ptcopen) {
655 switch (cmd) {
--- 149 unchanged lines hidden (view full) ---
805 pti->pt_send |= TIOCPKT_NOSTOP;
806 pti->pt_flags |= PF_NOSTOP;
807 ptcwakeup(tp, FREAD);
808 }
809 }
810 return (error);
811}
812
813
814static void ptc_drvinit(void *unused);
815
816static void pty_clone(void *arg, char *name, int namelen, dev_t *dev);
817
818static void
819pty_clone(arg, name, namelen, dev)
820 void *arg;
821 char *name;
822 int namelen;
823 dev_t *dev;
824{
825 int u;
826
827 if (*dev != NODEV)
828 return;
829 if (bcmp(name, "pty", 3) != 0)
830 return;
831 if (name[5] != '\0')
--- 17 unchanged lines hidden (view full) ---
849 return;
850 *dev = make_dev(&ptc_cdevsw, u,
851 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
852 (*dev)->si_flags |= SI_CHEAPCLONE;
853 return;
854}
855
856static void
857ptc_drvinit(unused)
858 void *unused;
859{
860
861 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
862}
863
864SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
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 130259 2004-06-09 09:09:54Z 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, flag, devtype, td)
165 dev_t dev;
166 int flag, devtype;
167 struct thread *td;
168{
169 struct tty *tp;
170 int error;
171 struct pt_ioctl *pti;
172
173 if (!dev->si_drv1)
174 return(ENXIO);
175 pti = dev->si_drv1;
--- 21 unchanged lines hidden (view full) ---
197 }
198 error = ttyld_open(tp, dev);
199 if (error == 0)
200 ptcwakeup(tp, FREAD|FWRITE);
201 return (error);
202}
203
204static int
205ptsclose(dev, flag, mode, td)
206 dev_t dev;
207 int flag, mode;
208 struct thread *td;
209{
210 struct tty *tp;
211 int err;
212
213 tp = dev->si_tty;
214 err = ttyld_close(tp, flag);
215 (void) ttyclose(tp);
216 return (err);
217}
218
219static int
220ptsread(dev, uio, flag)
221 dev_t dev;
222 struct uio *uio;
223 int flag;
224{
225 struct thread *td = curthread;
226 struct proc *p = td->td_proc;
227 struct tty *tp = dev->si_tty;
228 struct pt_ioctl *pti = dev->si_drv1;
229 struct pgrp *pg;
230 int error = 0;
231
--- 46 unchanged lines hidden (view full) ---
278}
279
280/*
281 * Write to pseudo-tty.
282 * Wakeups of controlling tty will happen
283 * indirectly, when tty driver calls ptsstart.
284 */
285static int
286ptswrite(dev, uio, flag)
287 dev_t dev;
288 struct uio *uio;
289 int flag;
290{
291 struct tty *tp;
292
293 tp = dev->si_tty;
294 if (tp->t_oproc == 0)
295 return (EIO);
296 return (ttyld_write(tp, uio, flag));
297}
298
299/*
300 * Start output on pseudo-tty.
301 * Wake up process selecting or sleeping for input from controlling tty.
302 */
303static void
304ptsstart(tp)
305 struct tty *tp;
306{
307 struct pt_ioctl *pti = tp->t_dev->si_drv1;
308
309 if (tp->t_state & TS_TTSTOP)
310 return;
311 if (pti->pt_flags & PF_STOPPED) {
312 pti->pt_flags &= ~PF_STOPPED;
313 pti->pt_send = TIOCPKT_START;
314 }
315 ptcwakeup(tp, FREAD);
316}
317
318static void
319ptcwakeup(tp, flag)
320 struct tty *tp;
321 int flag;
322{
323 struct pt_ioctl *pti = tp->t_dev->si_drv1;
324
325 if (flag & FREAD) {
326 selwakeuppri(&pti->pt_selr, TTIPRI);
327 wakeup(TSA_PTC_READ(tp));
328 }
329 if (flag & FWRITE) {
330 selwakeuppri(&pti->pt_selw, TTOPRI);
331 wakeup(TSA_PTC_WRITE(tp));
332 }
333}
334
335static int
336ptcopen(dev, flag, devtype, td)
337 dev_t dev;
338 int flag, devtype;
339 struct thread *td;
340{
341 struct tty *tp;
342 struct pt_ioctl *pti;
343
344 if (!dev->si_drv1)
345 ptyinit(dev);
346 if (!dev->si_drv1)
347 return(ENXIO);
--- 9 unchanged lines hidden (view full) ---
357 pti->pt_prison = td->td_ucred->cr_prison;
358 pti->pt_flags = 0;
359 pti->pt_send = 0;
360 pti->pt_ucntl = 0;
361 return (0);
362}
363
364static int
365ptcclose(dev, flags, fmt, td)
366 dev_t dev;
367 int flags;
368 int fmt;
369 struct thread *td;
370{
371 struct tty *tp;
372
373 tp = dev->si_tty;
374 (void)ttyld_modem(tp, 0);
375
376 /*
377 * XXX MDMBUF makes no sense for ptys but would inhibit the above
--- 9 unchanged lines hidden (view full) ---
387 ttyflush(tp, FREAD | FWRITE);
388 }
389
390 tp->t_oproc = 0; /* mark closed */
391 return (0);
392}
393
394static int
395ptcread(dev, uio, flag)
396 dev_t dev;
397 struct uio *uio;
398 int flag;
399{
400 struct tty *tp = dev->si_tty;
401 struct pt_ioctl *pti = dev->si_drv1;
402 char buf[BUFSIZ];
403 int error = 0, cc;
404
405 /*
406 * We want to block until the slave
--- 41 unchanged lines hidden (view full) ---
448 break;
449 error = uiomove(buf, cc, uio);
450 }
451 ttwwakeup(tp);
452 return (error);
453}
454
455static void
456ptsstop(tp, flush)
457 struct tty *tp;
458 int flush;
459{
460 struct pt_ioctl *pti = tp->t_dev->si_drv1;
461 int flag;
462
463 /* note: FLUSHREAD and FLUSHWRITE already ok */
464 if (flush == 0) {
465 flush = TIOCPKT_STOP;
466 pti->pt_flags |= PF_STOPPED;
--- 5 unchanged lines hidden (view full) ---
472 if (flush & FREAD)
473 flag |= FWRITE;
474 if (flush & FWRITE)
475 flag |= FREAD;
476 ptcwakeup(tp, flag);
477}
478
479static int
480ptcpoll(dev, events, td)
481 dev_t dev;
482 int events;
483 struct thread *td;
484{
485 struct tty *tp = dev->si_tty;
486 struct pt_ioctl *pti = dev->si_drv1;
487 int revents = 0;
488 int s;
489
490 if ((tp->t_state & TS_CONNECTED) == 0)
491 return (events &
--- 31 unchanged lines hidden (view full) ---
523 selrecord(td, &pti->pt_selw);
524 }
525 splx(s);
526
527 return (revents);
528}
529
530static int
531ptcwrite(dev, uio, flag)
532 dev_t dev;
533 struct uio *uio;
534 int flag;
535{
536 struct tty *tp = dev->si_tty;
537 u_char *cp = 0;
538 int cc = 0;
539 u_char locbuf[BUFSIZ];
540 int cnt = 0;
541 struct pt_ioctl *pti = dev->si_drv1;
542 int error = 0;
--- 91 unchanged lines hidden (view full) ---
634 uio->uio_resid += cc;
635 return (error);
636 }
637 goto again;
638}
639
640/*ARGSUSED*/
641static int
642ptyioctl(dev, cmd, data, flag, td)
643 dev_t dev;
644 u_long cmd;
645 caddr_t data;
646 int flag;
647 struct thread *td;
648{
649 struct tty *tp = dev->si_tty;
650 struct pt_ioctl *pti = dev->si_drv1;
651 u_char *cc = tp->t_cc;
652 int stop, error;
653
654 if (devsw(dev)->d_open == ptcopen) {
655 switch (cmd) {
--- 149 unchanged lines hidden (view full) ---
805 pti->pt_send |= TIOCPKT_NOSTOP;
806 pti->pt_flags |= PF_NOSTOP;
807 ptcwakeup(tp, FREAD);
808 }
809 }
810 return (error);
811}
812
813
814static void ptc_drvinit(void *unused);
815
816static void pty_clone(void *arg, char *name, int namelen, dev_t *dev);
817
818static void
819pty_clone(arg, name, namelen, dev)
820 void *arg;
821 char *name;
822 int namelen;
823 dev_t *dev;
824{
825 int u;
826
827 if (*dev != NODEV)
828 return;
829 if (bcmp(name, "pty", 3) != 0)
830 return;
831 if (name[5] != '\0')
--- 17 unchanged lines hidden (view full) ---
849 return;
850 *dev = make_dev(&ptc_cdevsw, u,
851 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
852 (*dev)->si_flags |= SI_CHEAPCLONE;
853 return;
854}
855
856static void
857ptc_drvinit(unused)
858 void *unused;
859{
860
861 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
862}
863
864SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)