1 /* $NetBSD: cons.c,v 1.65 2008/01/24 17:32:52 ad Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * from: Utah $Hdr: cons.c 1.7 92/01/21$
37 * @(#)cons.c 8.2 (Berkeley) 1/12/94
41 * Copyright (c) 1988 University of Utah.
43 * This code is derived from software contributed to Berkeley by
44 * the Systems Programming Group of the University of Utah Computer
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75 * from: Utah $Hdr: cons.c 1.7 92/01/21$
77 * @(#)cons.c 8.2 (Berkeley) 1/12/94
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.65 2008/01/24 17:32:52 ad Exp $");
83 #include <sys/param.h>
85 #include <sys/systm.h>
87 #include <sys/ioctl.h>
92 #include <sys/vnode.h>
93 #include <sys/kauth.h>
94 #include <sys/mutex.h>
98 dev_type_open(cnopen
);
99 dev_type_close(cnclose
);
100 dev_type_read(cnread
);
101 dev_type_write(cnwrite
);
102 dev_type_ioctl(cnioctl
);
103 dev_type_poll(cnpoll
);
104 dev_type_kqfilter(cnkqfilter
);
106 static bool cn_redirect(dev_t
*, int, int *);
108 const struct cdevsw cons_cdevsw
= {
109 cnopen
, cnclose
, cnread
, cnwrite
, cnioctl
,
110 nostop
, notty
, cnpoll
, nommap
, cnkqfilter
, D_TTY
113 struct tty
*constty
= NULL
; /* virtual console output device */
114 struct consdev
*cn_tab
; /* physical console device info */
115 struct vnode
*cn_devvp
[2]; /* vnode for underlying device. */
118 cnopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
131 * always open the 'real' console device, so we don't get nailed
132 * later. This follows normal device semantics; they always get
135 cndev
= cn_tab
->cn_dev
;
136 if (cndev
== NODEV
) {
138 * This is most likely an error in the console attach
139 * code. Panicking looks better than jumping into nowhere
140 * through cdevsw below....
142 panic("cnopen: no console device");
146 * This causes cnopen() to be called recursively, which
147 * is generally a bad thing. It is often caused when
148 * dev == 0 and cn_dev has not been set, but was probably
151 panic("cnopen: cn_tab->cn_dev == dev");
153 if (cn_devvp
[unit
] != NULLVP
)
155 if ((error
= cdevvp(cndev
, &cn_devvp
[unit
])) != 0)
156 printf("cnopen: unable to get vnode reference\n");
157 error
= vn_lock(cn_devvp
[unit
], LK_EXCLUSIVE
| LK_RETRY
);
159 error
= VOP_OPEN(cn_devvp
[unit
], flag
, kauth_cred_get());
160 VOP_UNLOCK(cn_devvp
[unit
], 0);
166 cnclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
177 cn_devvp
[unit
] = NULL
;
178 error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
180 error
= VOP_CLOSE(vp
, flag
, kauth_cred_get());
187 cnread(dev_t dev
, struct uio
*uio
, int flag
)
192 * If we would redirect input, punt. This will keep strange
193 * things from happening to people who are using the real
194 * console. Nothing should be using /dev/console for
195 * input (except a shell in single-user mode, but then,
196 * one wouldn't TIOCCONS then).
198 if (!cn_redirect(&dev
, 1, &error
))
200 return cdev_read(dev
, uio
, flag
);
204 cnwrite(dev_t dev
, struct uio
*uio
, int flag
)
208 /* Redirect output, if that's appropriate. */
209 if (!cn_redirect(&dev
, 0, &error
))
211 return cdev_write(dev
, uio
, flag
);
215 cnioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
222 * Superuser can always use this to wrest control of console
223 * output from the "virtual" console.
225 if (cmd
== TIOCCONS
&& constty
!= NULL
) {
226 error
= kauth_authorize_generic(l
->l_cred
,
227 KAUTH_GENERIC_ISSUSER
, NULL
);
234 * Redirect the ioctl, if that's appropriate.
235 * Note that strange things can happen, if a program does
236 * ioctls on /dev/console, then the console is redirected
239 if (!cn_redirect(&dev
, 0, &error
))
241 return cdev_ioctl(dev
, cmd
, data
, flag
, l
);
246 cnpoll(dev_t dev
, int events
, struct lwp
*l
)
251 * Redirect the poll, if that's appropriate.
252 * I don't want to think of the possible side effects
253 * of console redirection here.
255 if (!cn_redirect(&dev
, 0, &error
))
257 return cdev_poll(dev
, events
, l
);
262 cnkqfilter(dev_t dev
, struct knote
*kn
)
267 * Redirect the kqfilter, if that's appropriate.
268 * I don't want to think of the possible side effects
269 * of console redirection here.
271 if (!cn_redirect(&dev
, 0, &error
))
273 return cdev_kqfilter(dev
, kn
);
281 return ((*cn_tab
->cn_getc
)(cn_tab
->cn_dev
));
285 cngetsn(char *cp
, int size
)
313 case 'u'&037: /* CTRL-u */
319 if (len
+ 1 >= size
|| c
< ' ') {
338 (*cn_tab
->cn_putc
)(cn_tab
->cn_dev
, c
);
340 (*cn_tab
->cn_putc
)(cn_tab
->cn_dev
, '\r');
347 static int refcount
= 0;
354 (*cn_tab
->cn_pollc
)(cn_tab
->cn_dev
, on
);
360 nullcnpollc(dev_t dev
, int on
)
366 cnbell(u_int pitch
, u_int period
, u_int volume
)
369 if (cn_tab
== NULL
|| cn_tab
->cn_bell
== NULL
)
371 (*cn_tab
->cn_bell
)(cn_tab
->cn_dev
, pitch
, period
, volume
);
377 if (cn_tab
== NULL
|| cn_tab
->cn_flush
== NULL
)
379 (*cn_tab
->cn_flush
)(cn_tab
->cn_dev
);
385 if (cn_tab
== NULL
|| cn_tab
->cn_halt
== NULL
)
387 (*cn_tab
->cn_halt
)(cn_tab
->cn_dev
);
391 * Redirect output, if that's appropriate. If there's no real console,
394 * Call with tty_mutex held.
397 cn_redirect(dev_t
*devp
, int is_read
, int *error
)
402 if (constty
!= NULL
&& minor(dev
) == 0 &&
403 (cn_tab
== NULL
|| (cn_tab
->cn_pri
!= CN_REMOTE
))) {
408 dev
= constty
->t_dev
;
409 } else if (cn_tab
== NULL
)
412 dev
= cn_tab
->cn_dev
;