summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty_pty.c
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2006-01-26 01:30:34 +0000
committercognet <cognet@FreeBSD.org>2006-01-26 01:30:34 +0000
commitaff5d6bf80c7cee1d2a2e3b664554663ba72ae78 (patch)
tree781a0e3abe81e06061d092e0f9ce65e0421206c0 /sys/kern/tty_pty.c
parentc912f7e052a7a4f90c0e7de657678a40d3d13619 (diff)
downloadFreeBSD-src-aff5d6bf80c7cee1d2a2e3b664554663ba72ae78.zip
FreeBSD-src-aff5d6bf80c7cee1d2a2e3b664554663ba72ae78.tar.gz
Bring in a sysv-style pts implementation, as found in the rwatson_pts perforce branch. It works the same as its SysV/linux counterpart : You obtain a fd to the master pseudo terminal by opening /dev/ptmx, which craetes a node for the master as /dev/pty[num] and a node for the slave as /dev/pts/[num].
It should play nicely with the existing BSD ptys. By default, the system will use the BSD ptys, one can set the sysctl kern.pts.enable to 1 to make it use the new pts system. The max number of pty that can be allocated on a system can be changed with the sysctl kern.pts.max. It defaults to 1000, and can be increased, but it is not recommanded, as any pty with a number > 999 won't be handled by whatever uses utmp(5).
Diffstat (limited to 'sys/kern/tty_pty.c')
-rw-r--r--sys/kern/tty_pty.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index 2fdab73..643f0c4 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -107,6 +107,7 @@ struct ptsc {
u_char pt_ucntl;
struct tty *pt_tty;
struct cdev *devs, *devc;
+ int pt_devs_open, pt_devc_open;
struct prison *pt_prison;
};
@@ -132,7 +133,6 @@ static char *names = "pqrsPQRS";
static struct cdev *
ptyinit(struct cdev *devc, struct thread *td)
{
- struct cdev *devs;
struct ptsc *pt;
int n;
@@ -143,19 +143,47 @@ ptyinit(struct cdev *devc, struct thread *td)
devc->si_flags &= ~SI_CHEAPCLONE;
+ /*
+ * Initially do not create a slave endpoint.
+ */
pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
- pt->devs = devs = make_dev_cred(&pts_cdevsw, n, td->td_ucred,
- UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
pt->devc = devc;
pt->pt_tty = ttyalloc();
pt->pt_tty->t_sc = pt;
- devs->si_drv1 = devc->si_drv1 = pt;
- devs->si_tty = devc->si_tty = pt->pt_tty;
- pt->pt_tty->t_dev = devs;
+ devc->si_drv1 = pt;
+ devc->si_tty = pt->pt_tty;
return (devc);
}
+static void
+pty_create_slave(struct ucred *cred, struct ptsc *pt, int n)
+{
+
+ pt->devs = make_dev_cred(&pts_cdevsw, n, cred, UID_ROOT, GID_WHEEL,
+ 0666, "tty%c%r", names[n / 32], n % 32);
+ pt->devs->si_drv1 = pt;
+ pt->devs->si_tty = pt->pt_tty;
+ pt->pt_tty->t_dev = pt->devs;
+}
+
+static void
+pty_destroy_slave(struct ptsc *pt)
+{
+
+ pt->pt_tty->t_dev = NULL;
+ destroy_dev(pt->devs);
+ pt->devs = NULL;
+}
+
+static void
+pty_maybe_destroy_slave(struct ptsc *pt)
+{
+
+ if (pt->pt_devc_open == 0 && pt->pt_devs_open == 0)
+ pty_destroy_slave(pt);
+}
+
/*ARGSUSED*/
static int
ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td)
@@ -185,20 +213,32 @@ ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td)
return (error);
}
error = ttyld_open(tp, dev);
- if (error == 0)
+ if (error == 0) {
ptcwakeup(tp, FREAD|FWRITE);
+ pt->pt_devs_open = 1;
+ } else
+ pty_maybe_destroy_slave(pt);
return (error);
}
static int
ptsclose(struct cdev *dev, int flag, int mode, struct thread *td)
{
+ struct ptsc *pti;
struct tty *tp;
int err;
tp = dev->si_tty;
+ pti = dev->si_drv1;
+
+ KASSERT(dev == pti->devs, ("ptsclose: dev != pti->devs"));
+
err = ttyld_close(tp, flag);
(void) tty_close(tp);
+
+ pti->pt_devs_open = 0;
+ pty_maybe_destroy_slave(pti);
+
return (err);
}
@@ -286,12 +326,17 @@ ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td)
pt->pt_flags = 0;
pt->pt_send = 0;
pt->pt_ucntl = 0;
+
+ pty_create_slave(td->td_ucred, pt, minor(dev));
+ pt->pt_devc_open = 1;
+
return (0);
}
static int
ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td)
{
+ struct ptsc *pti = dev->si_drv1;
struct tty *tp;
tp = dev->si_tty;
@@ -312,6 +357,8 @@ ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td)
}
tp->t_oproc = 0; /* mark closed */
+ pti->pt_devc_open = 0;
+ pty_maybe_destroy_slave(pti);
return (0);
}
OpenPOWER on IntegriCloud