summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/gentty.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/gentty.c')
-rw-r--r--usr/src/uts/common/io/gentty.c114
1 files changed, 66 insertions, 48 deletions
diff --git a/usr/src/uts/common/io/gentty.c b/usr/src/uts/common/io/gentty.c
index 9cb3e23b87..431e80245d 100644
--- a/usr/src/uts/common/io/gentty.c
+++ b/usr/src/uts/common/io/gentty.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1990-1992,1996,1998-2003 Sun Microsystems, Inc.
+ * Copyright 2006 Sun Microsystems, Inc.
* All rights reserved.
* Use is subject to license terms.
*/
@@ -198,17 +197,20 @@ syopen(dev_t *devp, int flag, int otyp, struct cred *cr)
{
dev_t ttyd;
vnode_t *ttyvp;
- sess_t *sp = curproc->p_sessp;
+ sess_t *sp;
int error;
- if ((ttyd = sp->s_dev) == NODEV)
+ if ((sp = tty_hold()) == NULL)
+ return (EINTR);
+
+ if (sp->s_dev == NODEV) {
+ tty_rele(sp);
return (ENXIO);
- TTY_HOLD(sp);
- if ((ttyvp = sp->s_vp) == NULL) {
- TTY_RELE(sp);
- return (EIO);
}
+ ttyd = sp->s_dev;
+ ttyvp = sp->s_vp;
+
/*
* Open the control terminal. The control terminal may be
* opened multiple times and it is closed in freectty().
@@ -237,10 +239,12 @@ syopen(dev_t *devp, int flag, int otyp, struct cred *cr)
ASSERT(vn_matchops(ttyvp, spec_getvnodeops()));
csp = VTOS(VTOS(ttyvp)->s_commonvp);
mutex_enter(&csp->s_lock);
+ ASSERT(csp->s_count > 1);
csp->s_count--;
mutex_exit(&csp->s_lock);
}
- TTY_RELE(sp);
+
+ tty_rele(sp);
return (error);
}
@@ -255,41 +259,41 @@ syclose(dev_t dev, int flag, int otyp, struct cred *cr)
int
syread(dev_t dev, struct uio *uiop, struct cred *cr)
{
- vnode_t *ttyvp;
- sess_t *sp = curproc->p_sessp;
+ sess_t *sp;
int error;
- if (sp->s_dev == NODEV)
+ if ((sp = tty_hold()) == NULL)
+ return (EINTR);
+
+ if (sp->s_dev == NODEV) {
+ tty_rele(sp);
return (ENXIO);
- TTY_HOLD(sp);
- if ((ttyvp = sp->s_vp) == NULL) {
- TTY_RELE(sp);
- return (EIO);
}
- error = VOP_READ(ttyvp, uiop, 0, cr, NULL);
- TTY_RELE(sp);
- return (error);
+ error = VOP_READ(sp->s_vp, uiop, 0, cr, NULL);
+
+ tty_rele(sp);
+ return (error);
}
/* ARGSUSED */
int
sywrite(dev_t dev, struct uio *uiop, struct cred *cr)
{
- vnode_t *ttyvp;
- sess_t *sp = curproc->p_sessp;
+ sess_t *sp;
int error;
- if (sp->s_dev == NODEV)
+ if ((sp = tty_hold()) == NULL)
+ return (EINTR);
+
+ if (sp->s_dev == NODEV) {
+ tty_rele(sp);
return (ENXIO);
- TTY_HOLD(sp);
- if ((ttyvp = sp->s_vp) == NULL) {
- TTY_RELE(sp);
- return (EIO);
}
- error = VOP_WRITE(ttyvp, uiop, 0, cr, NULL);
- TTY_RELE(sp);
+ error = VOP_WRITE(sp->s_vp, uiop, 0, cr, NULL);
+
+ tty_rele(sp);
return (error);
}
@@ -299,19 +303,32 @@ int
syioctl(dev_t dev, int cmd, intptr_t arg, int mode, struct cred *cr,
int *rvalp)
{
- vnode_t *ttyvp;
- sess_t *sp = curproc->p_sessp;
+ sess_t *sp;
int error;
- if (sp->s_dev == NODEV)
+ if (cmd == TIOCNOTTY) {
+ /*
+ * we can't allow this ioctl. the reason is that it
+ * attempts to remove the ctty for a session. to do
+ * this the ctty can't be in use but we grab a hold on
+ * the current ctty (via tty_hold) to perform this ioctl.
+ * if we were to allow this ioctl to pass through we
+ * would deadlock with ourselves.
+ */
+ return (EINVAL);
+ }
+
+ if ((sp = tty_hold()) == NULL)
+ return (EINTR);
+
+ if (sp->s_dev == NODEV) {
+ tty_rele(sp);
return (ENXIO);
- TTY_HOLD(sp);
- if ((ttyvp = sp->s_vp) == NULL) {
- TTY_RELE(sp);
- return (EIO);
}
- error = VOP_IOCTL(ttyvp, cmd, arg, mode, cr, rvalp);
- TTY_RELE(sp);
+
+ error = VOP_IOCTL(sp->s_vp, cmd, arg, mode, cr, rvalp);
+
+ tty_rele(sp);
return (error);
}
@@ -322,18 +339,19 @@ int
sypoll(dev_t dev, short events, int anyyet, short *reventsp,
struct pollhead **phpp)
{
- vnode_t *ttyvp;
- sess_t *sp = curproc->p_sessp;
+ sess_t *sp;
int error;
- if (sp->s_dev == NODEV)
+ if ((sp = tty_hold()) == NULL)
+ return (EINTR);
+
+ if (sp->s_dev == NODEV) {
+ tty_rele(sp);
return (ENXIO);
- TTY_HOLD(sp);
- if ((ttyvp = sp->s_vp) == NULL) {
- TTY_RELE(sp);
- return (EIO);
}
- error = VOP_POLL(ttyvp, events, anyyet, reventsp, phpp);
- TTY_RELE(sp);
+
+ error = VOP_POLL(sp->s_vp, events, anyyet, reventsp, phpp);
+
+ tty_rele(sp);
return (error);
}