Deleted Added
full compact
kern_cons.c (50477) kern_cons.c (51654)
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
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 * $FreeBSD: head/sys/kern/tty_cons.c 50477 1999-08-28 01:08:13Z peter $
39 * $FreeBSD: head/sys/kern/tty_cons.c 51654 1999-09-25 16:21:39Z phk $
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/conf.h>
45#include <sys/kernel.h>
46#include <sys/reboot.h>
47#include <sys/sysctl.h>
48#include <sys/proc.h>
49#include <sys/tty.h>
50#include <sys/uio.h>
51#include <sys/cons.h>
52
53#include <machine/cpu.h>
54
55static d_open_t cnopen;
56static d_close_t cnclose;
57static d_read_t cnread;
58static d_write_t cnwrite;
59static d_ioctl_t cnioctl;
60static d_poll_t cnpoll;
61
62#define CDEV_MAJOR 0
63static struct cdevsw cn_cdevsw = {
64 /* open */ cnopen,
65 /* close */ cnclose,
66 /* read */ cnread,
67 /* write */ cnwrite,
68 /* ioctl */ cnioctl,
69 /* stop */ nostop,
70 /* reset */ noreset,
71 /* devtotty */ nodevtotty,
72 /* poll */ cnpoll,
73 /* mmap */ nommap,
74 /* strategy */ nostrategy,
75 /* name */ "console",
76 /* parms */ noparms,
77 /* maj */ CDEV_MAJOR,
78 /* dump */ nodump,
79 /* psize */ nopsize,
80 /* flags */ D_TTY,
81 /* maxio */ 0,
82 /* bmaj */ -1
83};
84
85static dev_t cn_dev_t; /* seems to be never really used */
86static udev_t cn_udev_t;
87SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD,
88 &cn_udev_t, sizeof cn_udev_t, "T,dev_t", "");
89
90static int cn_mute;
91
92int cons_unavail = 0; /* XXX:
93 * physical console not available for
94 * input (i.e., it is in graphics mode)
95 */
96
97static u_char cn_is_open; /* nonzero if logical console is open */
98static int openmode, openflag; /* how /dev/console was openned */
99static u_char cn_phys_is_open; /* nonzero if physical device is open */
100static d_close_t *cn_phys_close; /* physical device close function */
101static d_open_t *cn_phys_open; /* physical device open function */
102struct consdev *cn_tab; /* physical console device info */
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/conf.h>
45#include <sys/kernel.h>
46#include <sys/reboot.h>
47#include <sys/sysctl.h>
48#include <sys/proc.h>
49#include <sys/tty.h>
50#include <sys/uio.h>
51#include <sys/cons.h>
52
53#include <machine/cpu.h>
54
55static d_open_t cnopen;
56static d_close_t cnclose;
57static d_read_t cnread;
58static d_write_t cnwrite;
59static d_ioctl_t cnioctl;
60static d_poll_t cnpoll;
61
62#define CDEV_MAJOR 0
63static struct cdevsw cn_cdevsw = {
64 /* open */ cnopen,
65 /* close */ cnclose,
66 /* read */ cnread,
67 /* write */ cnwrite,
68 /* ioctl */ cnioctl,
69 /* stop */ nostop,
70 /* reset */ noreset,
71 /* devtotty */ nodevtotty,
72 /* poll */ cnpoll,
73 /* mmap */ nommap,
74 /* strategy */ nostrategy,
75 /* name */ "console",
76 /* parms */ noparms,
77 /* maj */ CDEV_MAJOR,
78 /* dump */ nodump,
79 /* psize */ nopsize,
80 /* flags */ D_TTY,
81 /* maxio */ 0,
82 /* bmaj */ -1
83};
84
85static dev_t cn_dev_t; /* seems to be never really used */
86static udev_t cn_udev_t;
87SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD,
88 &cn_udev_t, sizeof cn_udev_t, "T,dev_t", "");
89
90static int cn_mute;
91
92int cons_unavail = 0; /* XXX:
93 * physical console not available for
94 * input (i.e., it is in graphics mode)
95 */
96
97static u_char cn_is_open; /* nonzero if logical console is open */
98static int openmode, openflag; /* how /dev/console was openned */
99static u_char cn_phys_is_open; /* nonzero if physical device is open */
100static d_close_t *cn_phys_close; /* physical device close function */
101static d_open_t *cn_phys_open; /* physical device open function */
102struct consdev *cn_tab; /* physical console device info */
103static struct tty *cn_tp; /* physical console tty struct */
104static dev_t condev_t; /* represents the device private info */
105
106CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL);
107
108void
109cninit()
110{
111 struct consdev **list, *best_cp, *cp;
112
113 /*
114 * Find the first console with the highest priority.
115 */
116 best_cp = NULL;
117 list = (struct consdev **)cons_set.ls_items;
118 while ((cp = *list++) != NULL) {
119 if (cp->cn_probe == NULL)
120 continue;
121 (*cp->cn_probe)(cp);
122 if (cp->cn_pri > CN_DEAD &&
123 (best_cp == NULL || cp->cn_pri > best_cp->cn_pri))
124 best_cp = cp;
125 }
126
127 /*
128 * Check if we should mute the console (for security reasons perhaps)
129 * It can be changes dynamically using sysctl kern.consmute
130 * once we are up and going.
131 *
132 */
133 cn_mute = ((boothowto & (RB_MUTE
134 |RB_SINGLE
135 |RB_VERBOSE
136 |RB_ASKNAME
137 |RB_CONFIG)) == RB_MUTE);
138
139 /*
140 * If no console, give up.
141 */
142 if (best_cp == NULL) {
143 if (cn_tab != NULL && cn_tab->cn_term != NULL)
144 (*cn_tab->cn_term)(cn_tab);
145 cn_tab = best_cp;
146 return;
147 }
148
149 /*
150 * Initialize console, then attach to it. This ordering allows
151 * debugging using the previous console, if any.
152 */
153 (*best_cp->cn_init)(best_cp);
154 if (cn_tab != NULL && cn_tab != best_cp) {
155 /* Turn off the previous console. */
156 if (cn_tab->cn_term != NULL)
157 (*cn_tab->cn_term)(cn_tab);
158 }
159 cn_tab = best_cp;
160}
161
162void
163cninit_finish()
164{
165 struct cdevsw *cdp;
166
167 if ((cn_tab == NULL) || cn_mute)
168 return;
169
170 /*
171 * Hook the open and close functions.
172 */
173 cdp = devsw(cn_tab->cn_dev);
174 cn_phys_close = cdp->d_close;
175 cdp->d_close = cnclose;
176 cn_phys_open = cdp->d_open;
177 cdp->d_open = cnopen;
103static dev_t condev_t; /* represents the device private info */
104
105CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL);
106
107void
108cninit()
109{
110 struct consdev **list, *best_cp, *cp;
111
112 /*
113 * Find the first console with the highest priority.
114 */
115 best_cp = NULL;
116 list = (struct consdev **)cons_set.ls_items;
117 while ((cp = *list++) != NULL) {
118 if (cp->cn_probe == NULL)
119 continue;
120 (*cp->cn_probe)(cp);
121 if (cp->cn_pri > CN_DEAD &&
122 (best_cp == NULL || cp->cn_pri > best_cp->cn_pri))
123 best_cp = cp;
124 }
125
126 /*
127 * Check if we should mute the console (for security reasons perhaps)
128 * It can be changes dynamically using sysctl kern.consmute
129 * once we are up and going.
130 *
131 */
132 cn_mute = ((boothowto & (RB_MUTE
133 |RB_SINGLE
134 |RB_VERBOSE
135 |RB_ASKNAME
136 |RB_CONFIG)) == RB_MUTE);
137
138 /*
139 * If no console, give up.
140 */
141 if (best_cp == NULL) {
142 if (cn_tab != NULL && cn_tab->cn_term != NULL)
143 (*cn_tab->cn_term)(cn_tab);
144 cn_tab = best_cp;
145 return;
146 }
147
148 /*
149 * Initialize console, then attach to it. This ordering allows
150 * debugging using the previous console, if any.
151 */
152 (*best_cp->cn_init)(best_cp);
153 if (cn_tab != NULL && cn_tab != best_cp) {
154 /* Turn off the previous console. */
155 if (cn_tab->cn_term != NULL)
156 (*cn_tab->cn_term)(cn_tab);
157 }
158 cn_tab = best_cp;
159}
160
161void
162cninit_finish()
163{
164 struct cdevsw *cdp;
165
166 if ((cn_tab == NULL) || cn_mute)
167 return;
168
169 /*
170 * Hook the open and close functions.
171 */
172 cdp = devsw(cn_tab->cn_dev);
173 cn_phys_close = cdp->d_close;
174 cdp->d_close = cnclose;
175 cn_phys_open = cdp->d_open;
176 cdp->d_open = cnopen;
178 cn_tp = (*cdp->d_devtotty)(cn_tab->cn_dev);
179 cn_dev_t = cn_tab->cn_dev;
180 cn_udev_t = dev2udev(cn_dev_t);
181}
182
183static void
184cnuninit(void)
185{
186 struct cdevsw *cdp;
187
188 if (cn_tab == NULL)
189 return;
190
191 /*
192 * Unhook the open and close functions.
193 */
194 cdp = devsw(cn_tab->cn_dev);
195 cdp->d_close = cn_phys_close;
196 cn_phys_close = NULL;
197 cdp->d_open = cn_phys_open;
198 cn_phys_open = NULL;
177 cn_dev_t = cn_tab->cn_dev;
178 cn_udev_t = dev2udev(cn_dev_t);
179}
180
181static void
182cnuninit(void)
183{
184 struct cdevsw *cdp;
185
186 if (cn_tab == NULL)
187 return;
188
189 /*
190 * Unhook the open and close functions.
191 */
192 cdp = devsw(cn_tab->cn_dev);
193 cdp->d_close = cn_phys_close;
194 cn_phys_close = NULL;
195 cdp->d_open = cn_phys_open;
196 cn_phys_open = NULL;
199 cn_tp = NULL;
200 cn_dev_t = NODEV;
201 cn_udev_t = NOUDEV;
202}
203
204/*
205 * User has changed the state of the console muting.
206 * This may require us to open or close the device in question.
207 */
208static int
209sysctl_kern_consmute SYSCTL_HANDLER_ARGS
210{
211 int error;
212 int ocn_mute;
213
214 ocn_mute = cn_mute;
215 error = sysctl_handle_int(oidp, &cn_mute, 0, req);
216 if((error == 0) && (cn_tab != NULL) && (req->newptr != NULL)) {
217 if(ocn_mute && !cn_mute) {
218 /*
219 * going from muted to unmuted.. open the physical dev
220 * if the console has been openned
221 */
222 cninit_finish();
223 if(cn_is_open)
224 /* XXX curproc is not what we want really */
225 error = cnopen(cn_dev_t, openflag,
226 openmode, curproc);
227 /* if it failed, back it out */
228 if ( error != 0) cnuninit();
229 } else if (!ocn_mute && cn_mute) {
230 /*
231 * going from unmuted to muted.. close the physical dev
232 * if it's only open via /dev/console
233 */
234 if(cn_is_open)
235 error = cnclose(cn_dev_t, openflag,
236 openmode, curproc);
237 if ( error == 0) cnuninit();
238 }
239 if (error != 0) {
240 /*
241 * back out the change if there was an error
242 */
243 cn_mute = ocn_mute;
244 }
245 }
246 return (error);
247}
248
249SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
250 0, sizeof cn_mute, sysctl_kern_consmute, "I", "");
251
252static int
253cnopen(dev, flag, mode, p)
254 dev_t dev;
255 int flag, mode;
256 struct proc *p;
257{
258 dev_t cndev, physdev;
259 int retval = 0;
260
261 if (cn_tab == NULL)
262 return (0);
263 cndev = cn_tab->cn_dev;
264 physdev = (major(dev) == major(cndev) ? dev : cndev);
265 /*
266 * If mute is active, then non console opens don't get here
267 * so we don't need to check for that. They
268 * bypass this and go straight to the device.
269 */
270 if(!cn_mute)
271 retval = (*cn_phys_open)(physdev, flag, mode, p);
272 if (retval == 0) {
273 /*
274 * check if we openned it via /dev/console or
275 * via the physical entry (e.g. /dev/sio0).
276 */
277 if (dev == cndev)
278 cn_phys_is_open = 1;
279 else if (physdev == cndev) {
280 openmode = mode;
281 openflag = flag;
282 cn_is_open = 1;
283 }
197 cn_dev_t = NODEV;
198 cn_udev_t = NOUDEV;
199}
200
201/*
202 * User has changed the state of the console muting.
203 * This may require us to open or close the device in question.
204 */
205static int
206sysctl_kern_consmute SYSCTL_HANDLER_ARGS
207{
208 int error;
209 int ocn_mute;
210
211 ocn_mute = cn_mute;
212 error = sysctl_handle_int(oidp, &cn_mute, 0, req);
213 if((error == 0) && (cn_tab != NULL) && (req->newptr != NULL)) {
214 if(ocn_mute && !cn_mute) {
215 /*
216 * going from muted to unmuted.. open the physical dev
217 * if the console has been openned
218 */
219 cninit_finish();
220 if(cn_is_open)
221 /* XXX curproc is not what we want really */
222 error = cnopen(cn_dev_t, openflag,
223 openmode, curproc);
224 /* if it failed, back it out */
225 if ( error != 0) cnuninit();
226 } else if (!ocn_mute && cn_mute) {
227 /*
228 * going from unmuted to muted.. close the physical dev
229 * if it's only open via /dev/console
230 */
231 if(cn_is_open)
232 error = cnclose(cn_dev_t, openflag,
233 openmode, curproc);
234 if ( error == 0) cnuninit();
235 }
236 if (error != 0) {
237 /*
238 * back out the change if there was an error
239 */
240 cn_mute = ocn_mute;
241 }
242 }
243 return (error);
244}
245
246SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
247 0, sizeof cn_mute, sysctl_kern_consmute, "I", "");
248
249static int
250cnopen(dev, flag, mode, p)
251 dev_t dev;
252 int flag, mode;
253 struct proc *p;
254{
255 dev_t cndev, physdev;
256 int retval = 0;
257
258 if (cn_tab == NULL)
259 return (0);
260 cndev = cn_tab->cn_dev;
261 physdev = (major(dev) == major(cndev) ? dev : cndev);
262 /*
263 * If mute is active, then non console opens don't get here
264 * so we don't need to check for that. They
265 * bypass this and go straight to the device.
266 */
267 if(!cn_mute)
268 retval = (*cn_phys_open)(physdev, flag, mode, p);
269 if (retval == 0) {
270 /*
271 * check if we openned it via /dev/console or
272 * via the physical entry (e.g. /dev/sio0).
273 */
274 if (dev == cndev)
275 cn_phys_is_open = 1;
276 else if (physdev == cndev) {
277 openmode = mode;
278 openflag = flag;
279 cn_is_open = 1;
280 }
281 dev->si_tty = physdev->si_tty;
284 }
285 return (retval);
286}
287
288static int
289cnclose(dev, flag, mode, p)
290 dev_t dev;
291 int flag, mode;
292 struct proc *p;
293{
294 dev_t cndev;
282 }
283 return (retval);
284}
285
286static int
287cnclose(dev, flag, mode, p)
288 dev_t dev;
289 int flag, mode;
290 struct proc *p;
291{
292 dev_t cndev;
293 struct tty *cn_tp;
295
296 if (cn_tab == NULL)
297 return (0);
298 cndev = cn_tab->cn_dev;
294
295 if (cn_tab == NULL)
296 return (0);
297 cndev = cn_tab->cn_dev;
298 cn_tp = cndev->si_tty;
299 /*
300 * act appropriatly depending on whether it's /dev/console
301 * or the pysical device (e.g. /dev/sio) that's being closed.
302 * in either case, don't actually close the device unless
303 * both are closed.
304 */
305 if (dev == cndev) {
306 /* the physical device is about to be closed */
307 cn_phys_is_open = 0;
308 if (cn_is_open) {
309 if (cn_tp) {
310 /* perform a ttyhalfclose() */
311 /* reset session and proc group */
312 cn_tp->t_pgrp = NULL;
313 cn_tp->t_session = NULL;
314 }
315 return (0);
316 }
317 } else if (major(dev) != major(cndev)) {
318 /* the logical console is about to be closed */
319 cn_is_open = 0;
320 if (cn_phys_is_open)
321 return (0);
322 dev = cndev;
323 }
324 if(cn_phys_close)
325 return ((*cn_phys_close)(dev, flag, mode, p));
326 return (0);
327}
328
329static int
330cnread(dev, uio, flag)
331 dev_t dev;
332 struct uio *uio;
333 int flag;
334{
335 if ((cn_tab == NULL) || cn_mute)
336 return (0);
337 dev = cn_tab->cn_dev;
338 return ((*devsw(dev)->d_read)(dev, uio, flag));
339}
340
341static int
342cnwrite(dev, uio, flag)
343 dev_t dev;
344 struct uio *uio;
345 int flag;
346{
347 if ((cn_tab == NULL) || cn_mute) {
348 uio->uio_resid = 0; /* dump the data */
349 return (0);
350 }
351 if (constty)
352 dev = constty->t_dev;
353 else
354 dev = cn_tab->cn_dev;
355 return ((*devsw(dev)->d_write)(dev, uio, flag));
356}
357
358static int
359cnioctl(dev, cmd, data, flag, p)
360 dev_t dev;
361 u_long cmd;
362 caddr_t data;
363 int flag;
364 struct proc *p;
365{
366 int error;
367
368 if ((cn_tab == NULL) || cn_mute)
369 return (0);
370 /*
371 * Superuser can always use this to wrest control of console
372 * output from the "virtual" console.
373 */
374 if (cmd == TIOCCONS && constty) {
375 error = suser(p);
376 if (error)
377 return (error);
378 constty = NULL;
379 return (0);
380 }
381 dev = cn_tab->cn_dev;
382 return ((*devsw(dev)->d_ioctl)(dev, cmd, data, flag, p));
383}
384
385static int
386cnpoll(dev, events, p)
387 dev_t dev;
388 int events;
389 struct proc *p;
390{
391 if ((cn_tab == NULL) || cn_mute)
392 return (1);
393
394 dev = cn_tab->cn_dev;
395
396 return ((*devsw(dev)->d_poll)(dev, events, p));
397}
398
399int
400cngetc()
401{
402 int c;
403 if ((cn_tab == NULL) || cn_mute)
404 return (-1);
405 c = (*cn_tab->cn_getc)(cn_tab->cn_dev);
406 if (c == '\r') c = '\n'; /* console input is always ICRNL */
407 return (c);
408}
409
410int
411cncheckc()
412{
413 if ((cn_tab == NULL) || cn_mute)
414 return (-1);
415 return ((*cn_tab->cn_checkc)(cn_tab->cn_dev));
416}
417
418void
419cnputc(c)
420 register int c;
421{
422 if ((cn_tab == NULL) || cn_mute)
423 return;
424 if (c) {
425 if (c == '\n')
426 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
427 (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
428 }
429}
430
431static void
432cn_drvinit(void *unused)
433{
434
435 cdevsw_add(&cn_cdevsw);
436 condev_t = make_dev (&cn_cdevsw, 0,
437 UID_ROOT, GID_WHEEL, 0600, "console");
438}
439
440SYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL)
441
442
299 /*
300 * act appropriatly depending on whether it's /dev/console
301 * or the pysical device (e.g. /dev/sio) that's being closed.
302 * in either case, don't actually close the device unless
303 * both are closed.
304 */
305 if (dev == cndev) {
306 /* the physical device is about to be closed */
307 cn_phys_is_open = 0;
308 if (cn_is_open) {
309 if (cn_tp) {
310 /* perform a ttyhalfclose() */
311 /* reset session and proc group */
312 cn_tp->t_pgrp = NULL;
313 cn_tp->t_session = NULL;
314 }
315 return (0);
316 }
317 } else if (major(dev) != major(cndev)) {
318 /* the logical console is about to be closed */
319 cn_is_open = 0;
320 if (cn_phys_is_open)
321 return (0);
322 dev = cndev;
323 }
324 if(cn_phys_close)
325 return ((*cn_phys_close)(dev, flag, mode, p));
326 return (0);
327}
328
329static int
330cnread(dev, uio, flag)
331 dev_t dev;
332 struct uio *uio;
333 int flag;
334{
335 if ((cn_tab == NULL) || cn_mute)
336 return (0);
337 dev = cn_tab->cn_dev;
338 return ((*devsw(dev)->d_read)(dev, uio, flag));
339}
340
341static int
342cnwrite(dev, uio, flag)
343 dev_t dev;
344 struct uio *uio;
345 int flag;
346{
347 if ((cn_tab == NULL) || cn_mute) {
348 uio->uio_resid = 0; /* dump the data */
349 return (0);
350 }
351 if (constty)
352 dev = constty->t_dev;
353 else
354 dev = cn_tab->cn_dev;
355 return ((*devsw(dev)->d_write)(dev, uio, flag));
356}
357
358static int
359cnioctl(dev, cmd, data, flag, p)
360 dev_t dev;
361 u_long cmd;
362 caddr_t data;
363 int flag;
364 struct proc *p;
365{
366 int error;
367
368 if ((cn_tab == NULL) || cn_mute)
369 return (0);
370 /*
371 * Superuser can always use this to wrest control of console
372 * output from the "virtual" console.
373 */
374 if (cmd == TIOCCONS && constty) {
375 error = suser(p);
376 if (error)
377 return (error);
378 constty = NULL;
379 return (0);
380 }
381 dev = cn_tab->cn_dev;
382 return ((*devsw(dev)->d_ioctl)(dev, cmd, data, flag, p));
383}
384
385static int
386cnpoll(dev, events, p)
387 dev_t dev;
388 int events;
389 struct proc *p;
390{
391 if ((cn_tab == NULL) || cn_mute)
392 return (1);
393
394 dev = cn_tab->cn_dev;
395
396 return ((*devsw(dev)->d_poll)(dev, events, p));
397}
398
399int
400cngetc()
401{
402 int c;
403 if ((cn_tab == NULL) || cn_mute)
404 return (-1);
405 c = (*cn_tab->cn_getc)(cn_tab->cn_dev);
406 if (c == '\r') c = '\n'; /* console input is always ICRNL */
407 return (c);
408}
409
410int
411cncheckc()
412{
413 if ((cn_tab == NULL) || cn_mute)
414 return (-1);
415 return ((*cn_tab->cn_checkc)(cn_tab->cn_dev));
416}
417
418void
419cnputc(c)
420 register int c;
421{
422 if ((cn_tab == NULL) || cn_mute)
423 return;
424 if (c) {
425 if (c == '\n')
426 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
427 (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
428 }
429}
430
431static void
432cn_drvinit(void *unused)
433{
434
435 cdevsw_add(&cn_cdevsw);
436 condev_t = make_dev (&cn_cdevsw, 0,
437 UID_ROOT, GID_WHEEL, 0600, "console");
438}
439
440SYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL)
441
442