cons.c revision 1.16 1 /*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)cons.c 7.2 (Berkeley) 5/9/91
39 * $Id: cons.c,v 1.16 1994/06/08 11:19:41 mycroft Exp $
40 */
41
42 #include <sys/param.h>
43 #include <sys/proc.h>
44 #include <sys/user.h>
45 #include <sys/systm.h>
46 #include <sys/buf.h>
47 #include <sys/ioctl.h>
48 #include <sys/tty.h>
49 #include <sys/file.h>
50 #include <sys/conf.h>
51 #include <sys/vnode.h>
52
53 #include <dev/cons.h>
54
55 extern struct consdev constab[];
56
57 struct tty *constty = NULL; /* virtual console output device */
58 struct consdev *cn_tab; /* physical console device info */
59 struct vnode *cn_devvp; /* vnode for underlying device. */
60
61
62 void
63 cninit()
64 {
65 register struct consdev *cp;
66
67 /*
68 * Collect information about all possible consoles
69 * and find the one with highest priority
70 */
71 for (cp = constab; cp->cn_probe; cp++) {
72 (*cp->cn_probe)(cp);
73 if (cp->cn_pri > CN_DEAD &&
74 (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri))
75 cn_tab = cp;
76 }
77 /*
78 * No console, we can handle it
79 */
80 if ((cp = cn_tab) == NULL)
81 return;
82 /*
83 * Turn on console
84 */
85 (*cp->cn_init)(cp);
86 }
87
88 int
89 cnopen(dev, flag, mode, p)
90 dev_t dev;
91 int flag, mode;
92 struct proc *p;
93 {
94 if (cn_tab == NULL)
95 return (0);
96
97 /*
98 * always open the 'real' console device, so we don't get nailed
99 * later. This follows normal device semantics; they always get
100 * open() calls.
101 */
102 dev = cn_tab->cn_dev;
103 if (cn_devvp == NULLVP) {
104 /* try to get a reference on its vnode, but fail silently */
105 cdevvp(dev, &cn_devvp);
106 }
107 return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p));
108 }
109
110 int
111 cnclose(dev, flag, mode, p)
112 dev_t dev;
113 int flag, mode;
114 struct proc *p;
115 {
116 struct vnode *vp;
117
118 if (cn_tab == NULL)
119 return (0);
120
121 /*
122 * If the real console isn't otherwise open, close it.
123 * If it's otherwise open, don't close it, because that'll
124 * screw up others who have it open.
125 */
126 dev = cn_tab->cn_dev;
127 if (cn_devvp != NULLVP) {
128 /* release our reference to real dev's vnode */
129 vrele(cn_devvp);
130 cn_devvp = NULLVP;
131 }
132 if (vfinddev(dev, VCHR, &vp) && vcount(vp))
133 return (0);
134 return ((*cdevsw[major(dev)].d_close)(dev, flag, mode, p));
135 }
136
137 int
138 cnread(dev, uio, flag)
139 dev_t dev;
140 struct uio *uio;
141 {
142 /*
143 * If we would redirect input, punt. This will keep strange
144 * things from happening to people who are using the real
145 * console. Nothing should be using /dev/console for
146 * input (except a shell in single-user mode, but then,
147 * one wouldn't TIOCCONS then).
148 */
149 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE))
150 return 0;
151 else if (cn_tab == NULL)
152 return ENXIO;
153
154 dev = cn_tab->cn_dev;
155 return ((*cdevsw[major(dev)].d_read)(dev, uio, flag));
156 }
157
158 int
159 cnwrite(dev, uio, flag)
160 dev_t dev;
161 struct uio *uio;
162 {
163 /*
164 * Redirect output, if that's appropriate.
165 * If there's no real console, return ENXIO.
166 */
167 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE))
168 dev = constty->t_dev;
169 else if (cn_tab == NULL)
170 return ENXIO;
171 else
172 dev = cn_tab->cn_dev;
173 return ((*cdevsw[major(dev)].d_write)(dev, uio, flag));
174 }
175
176 int
177 cnioctl(dev, cmd, data, flag, p)
178 dev_t dev;
179 caddr_t data;
180 struct proc *p;
181 {
182 int error;
183
184 /*
185 * Superuser can always use this to wrest control of console
186 * output from the "virtual" console.
187 */
188 if (cmd == TIOCCONS && constty != NULL) {
189 error = suser(p->p_ucred, (u_short *) NULL);
190 if (error)
191 return (error);
192 constty = NULL;
193 return (0);
194 }
195
196 /*
197 * Redirect the ioctl, if that's appropriate.
198 * Note that strange things can happen, if a program does
199 * ioctls on /dev/console, then the console is redirected
200 * out from under it.
201 */
202 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE))
203 dev = constty->t_dev;
204 else if (cn_tab == NULL)
205 return ENXIO;
206 else
207 dev = cn_tab->cn_dev;
208 return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p));
209 }
210
211 /*ARGSUSED*/
212 int
213 cnselect(dev, rw, p)
214 dev_t dev;
215 int rw;
216 struct proc *p;
217 {
218 /*
219 * Redirect the ioctl, if that's appropriate.
220 * I don't want to think of the possible side effects
221 * of console redirection here.
222 */
223 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE))
224 dev = constty->t_dev;
225 else if (cn_tab == NULL)
226 return ENXIO;
227 else
228 dev = cn_tab->cn_dev;
229 return (ttselect(cn_tab->cn_dev, rw, p));
230 }
231
232 int
233 cngetc()
234 {
235 if (cn_tab == NULL)
236 return (0);
237 return ((*cn_tab->cn_getc)(cn_tab->cn_dev));
238 }
239
240 int
241 cnputc(c)
242 register int c;
243 {
244 if (cn_tab == NULL)
245 return;
246 if (c) {
247 (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
248 if (c == '\n')
249 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
250 }
251 }
252