Do not leave VCTTYISOPEN set if our attempt to open /dev/tty fails, otherwise
[dragonfly.git] / sys / kern / tty_tty.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1982, 1986, 1991, 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
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)tty_tty.c 8.2 (Berkeley) 9/23/93
34 * $FreeBSD: src/sys/kern/tty_tty.c,v 1.30 1999/09/25 18:24:24 phk Exp $
9e08e2dd 35 * $DragonFly: src/sys/kern/tty_tty.c,v 1.12 2005/01/29 05:48:17 dillon Exp $
984263bc
MD
36 */
37
38/*
39 * Indirect driver for controlling tty.
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/conf.h>
45#include <sys/lock.h>
46#include <sys/proc.h>
47#include <sys/ttycom.h>
48#include <sys/vnode.h>
49#include <sys/kernel.h>
50
51static d_open_t cttyopen;
e4c9c0c8 52static d_close_t cttyclose;
984263bc
MD
53static d_read_t cttyread;
54static d_write_t cttywrite;
55static d_ioctl_t cttyioctl;
56static d_poll_t cttypoll;
57
58#define CDEV_MAJOR 1
59/* Don't make this static, since fdesc_vnops uses it. */
60struct cdevsw ctty_cdevsw = {
fabb8ceb
MD
61 /* name */ "ctty",
62 /* maj */ CDEV_MAJOR,
63 /* flags */ D_TTY,
64 /* port */ NULL,
455fcd7e 65 /* clone */ NULL,
fabb8ceb 66
984263bc 67 /* open */ cttyopen,
e4c9c0c8 68 /* close */ cttyclose,
984263bc
MD
69 /* read */ cttyread,
70 /* write */ cttywrite,
71 /* ioctl */ cttyioctl,
72 /* poll */ cttypoll,
73 /* mmap */ nommap,
74 /* strategy */ nostrategy,
984263bc 75 /* dump */ nodump,
fabb8ceb 76 /* psize */ nopsize
984263bc
MD
77};
78
79#define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
80
81/*ARGSUSED*/
82static int
dadab5e9 83cttyopen(dev_t dev, int flag, int mode, struct thread *td)
984263bc 84{
dadab5e9 85 struct proc *p = td->td_proc;
41c20dac 86 struct vnode *ttyvp;
984263bc
MD
87 int error;
88
dadab5e9
MD
89 KKASSERT(p);
90 ttyvp = cttyvp(p);
e4c9c0c8 91 if (ttyvp) {
5fd012e0
MD
92 if (ttyvp->v_flag & VCTTYISOPEN) {
93 error = 0;
94 } else {
95 vsetflags(ttyvp, VCTTYISOPEN);
96 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
fad57d0e 97 error = VOP_OPEN(ttyvp, flag, NOCRED, NULL, td);
9e08e2dd
MD
98 if (error)
99 vclrflags(ttyvp, VCTTYISOPEN);
5fd012e0
MD
100 VOP_UNLOCK(ttyvp, 0, td);
101 }
e4c9c0c8
MD
102 } else {
103 error = ENXIO;
104 }
984263bc
MD
105 return (error);
106}
107
e4c9c0c8
MD
108static int
109cttyclose(dev_t dev, int fflag, int devtype, struct thread *td)
110{
111 struct proc *p = td->td_proc;
112 struct vnode *ttyvp;
113 int error;
114
115 KKASSERT(p);
116 ttyvp = cttyvp(p);
5fd012e0
MD
117 if (ttyvp == NULL) {
118 /*
119 * The tty may have been TIOCNOTTY'd, don't return an
120 * error on close. We just have nothing to do.
121 */
122 /* error = EIO; */
123 error = 0;
124 } else if (ttyvp->v_flag & VCTTYISOPEN) {
125 vclrflags(ttyvp, VCTTYISOPEN);
126 error = vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
127 if (error == 0) {
128 error = VOP_CLOSE(ttyvp, fflag, td);
129 VOP_UNLOCK(ttyvp, 0, td);
130 }
131 } else {
132 error = 0;
133 }
e4c9c0c8
MD
134 return(error);
135}
136
984263bc
MD
137/*ARGSUSED*/
138static int
139cttyread(dev, uio, flag)
140 dev_t dev;
141 struct uio *uio;
142 int flag;
143{
dadab5e9
MD
144 struct thread *td = uio->uio_td;
145 struct proc *p = td->td_proc;
146 struct vnode *ttyvp;
984263bc
MD
147 int error;
148
dadab5e9
MD
149 KKASSERT(p);
150 ttyvp = cttyvp(p);
984263bc
MD
151 if (ttyvp == NULL)
152 return (EIO);
5fd012e0 153 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
984263bc 154 error = VOP_READ(ttyvp, uio, flag, NOCRED);
5fd012e0 155 VOP_UNLOCK(ttyvp, 0, td);
984263bc
MD
156 return (error);
157}
158
159/*ARGSUSED*/
160static int
161cttywrite(dev, uio, flag)
162 dev_t dev;
163 struct uio *uio;
164 int flag;
165{
dadab5e9
MD
166 struct thread *td = uio->uio_td;
167 struct proc *p = td->td_proc;
168 struct vnode *ttyvp;
984263bc
MD
169 int error;
170
dadab5e9
MD
171 KKASSERT(p);
172 ttyvp = cttyvp(p);
984263bc
MD
173 if (ttyvp == NULL)
174 return (EIO);
5fd012e0 175 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
984263bc 176 error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
5fd012e0 177 VOP_UNLOCK(ttyvp, 0, td);
984263bc
MD
178 return (error);
179}
180
181/*ARGSUSED*/
182static int
41c20dac 183cttyioctl(dev, cmd, addr, flag, td)
984263bc
MD
184 dev_t dev;
185 u_long cmd;
186 caddr_t addr;
187 int flag;
41c20dac 188 struct thread *td;
984263bc 189{
41c20dac 190 struct vnode *ttyvp;
dadab5e9 191 struct proc *p = td->td_proc;
984263bc 192
dadab5e9
MD
193 KKASSERT(p);
194 ttyvp = cttyvp(p);
984263bc
MD
195 if (ttyvp == NULL)
196 return (EIO);
197 if (cmd == TIOCSCTTY) /* don't allow controlling tty to be set */
198 return EINVAL; /* to controlling tty -- infinite recursion */
199 if (cmd == TIOCNOTTY) {
dadab5e9
MD
200 if (!SESS_LEADER(p)) {
201 p->p_flag &= ~P_CONTROLT;
984263bc
MD
202 return (0);
203 } else
204 return (EINVAL);
205 }
dadab5e9 206 return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, td));
984263bc
MD
207}
208
209/*ARGSUSED*/
210static int
dadab5e9 211cttypoll(dev_t dev, int events, struct thread *td)
984263bc 212{
41c20dac 213 struct vnode *ttyvp;
dadab5e9 214 struct proc *p = td->td_proc;
984263bc 215
dadab5e9
MD
216 KKASSERT(p);
217 ttyvp = cttyvp(p);
984263bc
MD
218 if (ttyvp == NULL)
219 /* try operation to get EOF/failure */
41c20dac 220 return (seltrue(dev, events, td));
dadab5e9 221 return (VOP_POLL(ttyvp, events, p->p_ucred, td));
984263bc
MD
222}
223
402ed7e1 224static void ctty_drvinit (void *unused);
984263bc
MD
225static void
226ctty_drvinit(unused)
227 void *unused;
228{
e4c9c0c8 229 cdevsw_add(&ctty_cdevsw, 0, 0);
984263bc
MD
230 make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "tty");
231}
232
233SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL)