1/*
2 * Copyright 1992 by Rich Murphey <Rich@Rice.edu>
3 * Copyright 1993 by David Wexelblat <dwex@goblin.org>
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the names of Rich Murphey and David Wexelblat
10 * not be used in advertising or publicity pertaining to distribution of
11 * the software without specific, written prior permission.  Rich Murphey and
12 * David Wexelblat make no representations about the suitability of this
13 * software for any purpose.  It is provided "as is" without express or
14 * implied warranty.
15 *
16 * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
17 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR
19 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
21 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 */
25
26#ifdef HAVE_XORG_CONFIG_H
27#include <xorg-config.h>
28#endif
29
30#include <X11/X.h>
31
32#include "compiler.h"
33
34#include "xf86.h"
35#include "xf86Priv.h"
36#include "xf86_OSlib.h"
37
38#include <sys/utsname.h>
39#include <sys/ioctl.h>
40#include <stdlib.h>
41#include <errno.h>
42
43static Bool KeepTty = FALSE;
44static int devConsoleFd = -1;
45#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
46static int VTnum = -1;
47static int initialVT = -1;
48static Bool ShareVTs = FALSE;
49#endif
50
51#ifdef PCCONS_SUPPORT
52/* Stock 0.1 386bsd pccons console driver interface */
53#define PCCONS_CONSOLE_DEV1 "/dev/ttyv0"
54#define PCCONS_CONSOLE_DEV2 "/dev/vga"
55#define PCCONS_CONSOLE_MODE O_RDWR|O_NDELAY
56#endif
57
58#ifdef SYSCONS_SUPPORT
59/* The FreeBSD 1.1 version syscons driver uses /dev/ttyv0 */
60#define SYSCONS_CONSOLE_DEV1 "/dev/ttyv0"
61#define SYSCONS_CONSOLE_DEV2 "/dev/vga"
62#define SYSCONS_CONSOLE_MODE O_RDWR|O_NDELAY
63#endif
64
65#ifdef PCVT_SUPPORT
66/* Hellmuth Michaelis' pcvt driver */
67#ifndef __OpenBSD__
68#  define PCVT_CONSOLE_DEV "/dev/ttyv0"
69#else
70#  define PCVT_CONSOLE_DEV "/dev/ttyC0"
71#endif
72#define PCVT_CONSOLE_MODE O_RDWR|O_NDELAY
73#endif
74
75#if defined(WSCONS_SUPPORT) && defined(__NetBSD__)
76/* NetBSD's new console driver */
77#define WSCONS_PCVT_COMPAT_CONSOLE_DEV "/dev/ttyE0"
78#endif
79
80#ifdef __GLIBC__
81#define setpgrp setpgid
82#endif
83
84#define CHECK_DRIVER_MSG \
85  "Check your kernel's console driver configuration and /dev entries"
86
87static char *supported_drivers[] = {
88#ifdef PCCONS_SUPPORT
89	"pccons (with X support)",
90#endif
91#ifdef SYSCONS_SUPPORT
92	"syscons",
93#endif
94#ifdef PCVT_SUPPORT
95	"pcvt",
96#endif
97#ifdef WSCONS_SUPPORT
98	"wscons",
99#endif
100};
101
102
103/*
104 * Functions to probe for the existance of a supported console driver.
105 * Any function returns either a valid file descriptor (driver probed
106 * succesfully), -1 (driver not found), or uses FatalError() if the
107 * driver was found but proved to not support the required mode to run
108 * an X server.
109 */
110
111typedef int (*xf86ConsOpen_t)(void);
112
113#ifdef PCCONS_SUPPORT
114static int xf86OpenPccons(void);
115#endif /* PCCONS_SUPPORT */
116
117#ifdef SYSCONS_SUPPORT
118static int xf86OpenSyscons(void);
119#endif /* SYSCONS_SUPPORT */
120
121#ifdef PCVT_SUPPORT
122static int xf86OpenPcvt(void);
123#endif /* PCVT_SUPPORT */
124
125#ifdef WSCONS_SUPPORT
126static int xf86OpenWScons(void);
127#endif
128
129/*
130 * The sequence of the driver probes is important; start with the
131 * driver that is best distinguishable, and end with the most generic
132 * driver.  (Otherwise, pcvt would also probe as syscons, and either
133 * pcvt or syscons might succesfully probe as pccons.)
134 */
135static xf86ConsOpen_t xf86ConsTab[] = {
136#ifdef PCVT_SUPPORT
137    xf86OpenPcvt,
138#endif
139#ifdef SYSCONS_SUPPORT
140    xf86OpenSyscons,
141#endif
142#ifdef PCCONS_SUPPORT
143    xf86OpenPccons,
144#endif
145#ifdef WSCONS_SUPPORT
146    xf86OpenWScons,
147#endif
148    (xf86ConsOpen_t)NULL
149};
150
151
152void
153xf86OpenConsole()
154{
155    int i, fd = -1;
156    xf86ConsOpen_t *driver;
157#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
158    int result;
159#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
160    struct utsname uts;
161#endif
162    vtmode_t vtmode;
163#endif
164
165    if (serverGeneration == 1)
166    {
167	/* check if we are run with euid==0 */
168	if (geteuid() != 0)
169	{
170	    FatalError("xf86OpenConsole: Server must be suid root");
171	}
172
173	if (!KeepTty)
174	{
175	    /*
176	     * detaching the controlling tty solves problems of kbd character
177	     * loss.  This is not interesting for CO driver, because it is
178	     * exclusive.
179	     */
180	    setpgrp(0, getpid());
181	    if ((i = open("/dev/tty",O_RDWR)) >= 0)
182	    {
183		ioctl(i,TIOCNOTTY,(char *)0);
184		close(i);
185	    }
186	}
187
188	/* detect which driver we are running on */
189	for (driver = xf86ConsTab; *driver; driver++)
190	{
191	    if ((fd = (*driver)()) >= 0)
192		break;
193	}
194
195	/* Check that a supported console driver was found */
196	if (fd < 0)
197	{
198	    char cons_drivers[80] = {0, };
199	    for (i = 0; i < sizeof(supported_drivers) / sizeof(char *); i++)
200	    {
201		if (i)
202		{
203		    strcat(cons_drivers, ", ");
204		}
205		strcat(cons_drivers, supported_drivers[i]);
206	    }
207	    FatalError(
208		"%s: No console driver found\n\tSupported drivers: %s\n\t%s",
209		"xf86OpenConsole", cons_drivers, CHECK_DRIVER_MSG);
210	}
211#if 0 /* stdin is already closed in OsInit() */
212	fclose(stdin);
213#endif
214	xf86Info.consoleFd = fd;
215	xf86Info.screenFd = fd;
216
217	switch (xf86Info.consType)
218	{
219#ifdef PCCONS_SUPPORT
220	case PCCONS:
221	    if (ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_ON, 0) < 0)
222	    {
223		FatalError("%s: CONSOLE_X_MODE_ON failed (%s)\n%s",
224			   "xf86OpenConsole", strerror(errno),
225			   CHECK_DRIVER_MSG);
226	    }
227	    /*
228	     * Hack to prevent keyboard hanging when syslogd closes
229	     * /dev/console
230	     */
231	    if ((devConsoleFd = open("/dev/console", O_WRONLY,0)) < 0)
232	    {
233		xf86Msg(X_WARNING,
234			"xf86OpenConsole: couldn't open /dev/console (%s)\n",
235			strerror(errno));
236	    }
237	    break;
238#endif
239#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
240	case SYSCONS:
241	    /* as of FreeBSD 2.2.8, syscons driver does not need the #1 vt
242	     * switching anymore. Here we check for FreeBSD 3.1 and up.
243	     * Add cases for other *BSD that behave the same.
244	    */
245#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
246	    uname (&uts);
247	    i = atof(uts.release) * 100;
248	    if (i >= 310) goto acquire_vt;
249#endif
250	    /* otherwise fall through */
251	case PCVT:
252#if !(defined(__NetBSD__) && (__NetBSD_Version__ >= 200000000))
253	    /*
254	     * First activate the #1 VT.  This is a hack to allow a server
255	     * to be started while another one is active.  There should be
256	     * a better way.
257	     */
258	    if (initialVT != 1) {
259
260		if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) != 0)
261		{
262		    xf86Msg(X_WARNING,
263				"xf86OpenConsole: VT_ACTIVATE failed\n");
264		}
265		sleep(1);
266	    }
267#endif
268acquire_vt:
269	    if (!ShareVTs) {
270		    /*
271		     * now get the VT
272		     */
273		    SYSCALL(result =
274			    ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
275		    if (result != 0)
276		    {
277			xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
278		    }
279		    SYSCALL(result =
280		    ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
281		    if (result != 0)
282		    {
283			xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
284		    }
285
286		    signal(SIGUSR1, xf86VTRequest);
287
288		    vtmode.mode = VT_PROCESS;
289		    vtmode.relsig = SIGUSR1;
290		    vtmode.acqsig = SIGUSR1;
291		    vtmode.frsig = SIGUSR1;
292		    if (ioctl(xf86Info.consoleFd, VT_SETMODE, &vtmode) < 0)
293		    {
294			FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed");
295		    }
296	#if !defined(USE_DEV_IO) && !defined(USE_I386_IOPL)
297		    if (ioctl(xf86Info.consoleFd, KDENABIO, 0) < 0)
298		    {
299			FatalError("xf86OpenConsole: KDENABIO failed (%s)",
300				   strerror(errno));
301		    }
302	#endif
303		    if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
304		    {
305			FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed");
306		    }
307	    } else { /* ShareVTs */
308		    close(xf86Info.consoleFd);
309	    }
310  	    break;
311#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
312#ifdef WSCONS_SUPPORT
313	case WSCONS:
314	    /* Nothing to do */
315   	    break;
316#endif
317        }
318    }
319    else
320    {
321	/* serverGeneration != 1 */
322#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
323    	if (!ShareVTs) if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)
324    	{
325	    if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
326	    {
327	        xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
328	    }
329        }
330#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
331    }
332    return;
333}
334
335
336#ifdef PCCONS_SUPPORT
337
338static int
339xf86OpenPccons()
340{
341    int fd = -1;
342
343    if ((fd = open(PCCONS_CONSOLE_DEV1, PCCONS_CONSOLE_MODE, 0))
344	>= 0 ||
345	(fd = open(PCCONS_CONSOLE_DEV2, PCCONS_CONSOLE_MODE, 0))
346	>= 0)
347    {
348	if (ioctl(fd, CONSOLE_X_MODE_OFF, 0) < 0)
349	{
350	    FatalError(
351		"%s: CONSOLE_X_MODE_OFF failed (%s)\n%s\n%s",
352		"xf86OpenPccons",
353		strerror(errno),
354		"Was expecting pccons driver with X support",
355		CHECK_DRIVER_MSG);
356	}
357	xf86Info.consType = PCCONS;
358	xf86Msg(X_PROBED, "Using pccons driver with X support\n");
359    }
360    return fd;
361}
362
363#endif /* PCCONS_SUPPORT */
364
365#ifdef SYSCONS_SUPPORT
366
367static int
368xf86OpenSyscons()
369{
370    int fd = -1;
371    vtmode_t vtmode;
372    char vtname[12];
373    struct stat status;
374    long syscons_version;
375    MessageType from;
376
377    /* Check for syscons */
378    if ((fd = open(SYSCONS_CONSOLE_DEV1, SYSCONS_CONSOLE_MODE, 0)) >= 0
379	|| (fd = open(SYSCONS_CONSOLE_DEV2, SYSCONS_CONSOLE_MODE, 0)) >= 0)
380    {
381	if (ioctl(fd, VT_GETMODE, &vtmode) >= 0)
382	{
383	    /* Get syscons version */
384	    if (ioctl(fd, CONS_GETVERS, &syscons_version) < 0)
385	    {
386		syscons_version = 0;
387	    }
388
389	    xf86Info.vtno = VTnum;
390	    from = X_CMDLINE;
391
392#ifdef VT_GETACTIVE
393	    if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
394		initialVT = -1;
395#endif
396            if (ShareVTs)
397		xf86Info.vtno = initialVT;
398
399	    if (xf86Info.vtno == -1)
400	    {
401		/*
402		 * For old syscons versions (<0x100), VT_OPENQRY returns
403		 * the current VT rather than the next free VT.  In this
404		 * case, the server gets started on the current VT instead
405		 * of the next free VT.
406		 */
407
408#if 0
409		/* check for the fixed VT_OPENQRY */
410		if (syscons_version >= 0x100)
411		{
412#endif
413		    if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0)
414		    {
415			/* No free VTs */
416			xf86Info.vtno = -1;
417		    }
418#if 0
419		}
420#endif
421
422		if (xf86Info.vtno == -1)
423		{
424		    /*
425		     * All VTs are in use.  If initialVT was found, use it.
426		     * Otherwise, if stdin is a VT, use that one.
427		     * XXX stdin is already closed, so this won't work.
428		     */
429		    if (initialVT != -1)
430		    {
431			xf86Info.vtno = initialVT;
432		    }
433		    else if ((fstat(0, &status) >= 0)
434			     && S_ISCHR(status.st_mode)
435			     && (ioctl(0, VT_GETMODE, &vtmode) >= 0))
436		    {
437			/* stdin is a VT */
438			xf86Info.vtno = minor(status.st_rdev) + 1;
439		    }
440		    else
441		    {
442			if (syscons_version >= 0x100)
443			{
444			    FatalError("%s: Cannot find a free VT",
445				       "xf86OpenSyscons");
446			}
447			/* Should no longer reach here */
448			FatalError("%s: %s %s\n\t%s %s",
449				   "xf86OpenSyscons",
450				   "syscons versions prior to 1.0 require",
451				   "either the",
452				   "server's stdin be a VT",
453				   "or the use of the vtxx server option");
454		    }
455		}
456		from = X_PROBED;
457	    }
458
459	    close(fd);
460#ifndef __OpenBSD__
461	    sprintf(vtname, "/dev/ttyv%01x", xf86Info.vtno - 1);
462#else
463	    sprintf(vtname, "/dev/ttyC%01x", xf86Info.vtno - 1);
464#endif
465	    if ((fd = open(vtname, SYSCONS_CONSOLE_MODE, 0)) < 0)
466	    {
467		FatalError("xf86OpenSyscons: Cannot open %s (%s)",
468			   vtname, strerror(errno));
469	    }
470	    if (ioctl(fd, VT_GETMODE, &vtmode) < 0)
471	    {
472		FatalError("xf86OpenSyscons: VT_GETMODE failed");
473	    }
474	    xf86Info.consType = SYSCONS;
475	    xf86Msg(X_PROBED, "Using syscons driver with X support");
476	    if (syscons_version >= 0x100)
477	    {
478		xf86ErrorF(" (version %ld.%ld)\n", syscons_version >> 8,
479			   syscons_version & 0xFF);
480	    }
481	    else
482	    {
483		xf86ErrorF(" (version 0.x)\n");
484	    }
485	    xf86Msg(from, "using VT number %d\n", xf86Info.vtno);
486	}
487	else
488	{
489	    /* VT_GETMODE failed, probably not syscons */
490	    close(fd);
491	    fd = -1;
492	}
493    }
494    return fd;
495}
496
497#endif /* SYSCONS_SUPPORT */
498
499
500#ifdef PCVT_SUPPORT
501
502static int
503xf86OpenPcvt()
504{
505    /* This looks much like syscons, since pcvt is API compatible */
506    int fd = -1;
507    vtmode_t vtmode;
508    char vtname[12], *vtprefix;
509    struct stat status;
510    struct pcvtid pcvt_version;
511
512#ifndef __OpenBSD__
513    vtprefix = "/dev/ttyv";
514#else
515    vtprefix = "/dev/ttyC";
516#endif
517
518    fd = open(PCVT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0);
519#ifdef WSCONS_PCVT_COMPAT_CONSOLE_DEV
520    if (fd < 0)
521    {
522	fd = open(WSCONS_PCVT_COMPAT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0);
523	vtprefix = "/dev/ttyE";
524    }
525#endif
526    if (fd >= 0)
527    {
528	if (ioctl(fd, VGAPCVTID, &pcvt_version) >= 0)
529	{
530	    if(ioctl(fd, VT_GETMODE, &vtmode) < 0)
531	    {
532		FatalError("%s: VT_GETMODE failed\n%s%s\n%s",
533			   "xf86OpenPcvt",
534			   "Found pcvt driver but X11 seems to be",
535			   " not supported.", CHECK_DRIVER_MSG);
536	    }
537
538	    xf86Info.vtno = VTnum;
539
540	    if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
541		initialVT = -1;
542
543	    if (xf86Info.vtno == -1)
544	    {
545		if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0)
546		{
547		    /* No free VTs */
548		    xf86Info.vtno = -1;
549		}
550
551		if (xf86Info.vtno == -1)
552		{
553		    /*
554		     * All VTs are in use.  If initialVT was found, use it.
555		     * Otherwise, if stdin is a VT, use that one.
556		     * XXX stdin is already closed, so this won't work.
557		     */
558		    if (initialVT != -1)
559		    {
560			xf86Info.vtno = initialVT;
561		    }
562		    else if ((fstat(0, &status) >= 0)
563			     && S_ISCHR(status.st_mode)
564			     && (ioctl(0, VT_GETMODE, &vtmode) >= 0))
565		    {
566			/* stdin is a VT */
567			xf86Info.vtno = minor(status.st_rdev) + 1;
568		    }
569		    else
570		    {
571			FatalError("%s: Cannot find a free VT",
572				   "xf86OpenPcvt");
573		    }
574		}
575	    }
576
577	    close(fd);
578            sprintf(vtname, "%s%01x", vtprefix, xf86Info.vtno - 1);
579	    if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0)
580	    {
581		ErrorF("xf86OpenPcvt: Cannot open %s (%s)",
582			   vtname, strerror(errno));
583		xf86Info.vtno = initialVT;
584	        sprintf(vtname, "%s%01x", vtprefix, xf86Info.vtno - 1);
585		if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0) {
586			FatalError("xf86OpenPcvt: Cannot open %s (%s)",
587			   	vtname, strerror(errno));
588		}
589	    }
590	    if (ioctl(fd, VT_GETMODE, &vtmode) < 0)
591	    {
592		FatalError("xf86OpenPcvt: VT_GETMODE failed");
593	    }
594	    xf86Info.consType = PCVT;
595#ifdef WSCONS_SUPPORT
596	    xf86Msg(X_PROBED,
597		    "Using wscons driver on %s in pcvt compatibility mode "
598		    "(version %d.%d)\n", vtname,
599		    pcvt_version.rmajor, pcvt_version.rminor);
600#else
601	    xf86Msg(X_PROBED, "Using pcvt driver (version %d.%d)\n",
602		    pcvt_version.rmajor, pcvt_version.rminor);
603#endif
604	    xf86Msg(X_PROBED, "using VT number %d\n", xf86Info.vtno);
605	}
606	else
607	{
608	    /* Not pcvt */
609	    close(fd);
610	    fd = -1;
611	}
612    }
613    return fd;
614}
615
616#endif /* PCVT_SUPPORT */
617
618#ifdef WSCONS_SUPPORT
619
620static int
621xf86OpenWScons()
622{
623    int fd = -1;
624    int mode = WSDISPLAYIO_MODE_MAPPED;
625    int i;
626    char ttyname[16];
627
628    /* XXX Is this ok? */
629    for (i = 0; i < 8; i++) {
630#if defined(__NetBSD__)
631	sprintf(ttyname, "/dev/ttyE%d", i);
632#elif defined(__OpenBSD__)
633	sprintf(ttyname, "/dev/ttyC%x", i);
634#endif
635	if ((fd = open(ttyname, 2)) != -1)
636	    break;
637    }
638    if (fd != -1) {
639	if (ioctl(fd, WSDISPLAYIO_SMODE, &mode) < 0) {
640	    FatalError("%s: WSDISPLAYIO_MODE_MAPPED failed (%s)\n%s",
641		       "xf86OpenConsole", strerror(errno),
642		       CHECK_DRIVER_MSG);
643	}
644	xf86Info.consType = WSCONS;
645	xf86Msg(X_PROBED, "Using wscons driver\n");
646    }
647    return fd;
648}
649
650#endif /* WSCONS_SUPPORT */
651
652void
653xf86CloseConsole()
654{
655#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
656    struct vt_mode   VT;
657#endif
658
659#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
660    if (ShareVTs) return;
661#endif
662
663    switch (xf86Info.consType)
664    {
665#ifdef PCCONS_SUPPORT
666    case PCCONS:
667	ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_OFF, 0);
668	break;
669#endif /* PCCONS_SUPPORT */
670#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
671    case SYSCONS:
672    case PCVT:
673        ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT);  /* Back to text mode */
674        if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
675        {
676	    VT.mode = VT_AUTO;
677	    ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* dflt vt handling */
678        }
679#if !defined(OpenBSD) && !defined(USE_DEV_IO) && !defined(USE_I386_IOPL)
680        if (ioctl(xf86Info.consoleFd, KDDISABIO, 0) < 0)
681        {
682            xf86FatalError("xf86CloseConsole: KDDISABIO failed (%s)",
683	                   strerror(errno));
684        }
685#endif
686	if (initialVT != -1)
687		ioctl(xf86Info.consoleFd, VT_ACTIVATE, initialVT);
688        break;
689#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
690#ifdef WSCONS_SUPPORT
691    case WSCONS:
692      {
693	int mode = WSDISPLAYIO_MODE_EMUL;
694	ioctl(xf86Info.screenFd, WSDISPLAYIO_SMODE, &mode);
695	break;
696      }
697#endif
698    }
699
700    if (xf86Info.screenFd != xf86Info.consoleFd)
701    {
702	close(xf86Info.screenFd);
703	close(xf86Info.consoleFd);
704	if ((xf86Info.consoleFd = open("/dev/console",O_RDONLY,0)) <0)
705	{
706	    xf86FatalError("xf86CloseConsole: Cannot open /dev/console (%s)",
707			   strerror(errno));
708	}
709    }
710    close(xf86Info.consoleFd);
711    if (devConsoleFd >= 0)
712	close(devConsoleFd);
713    return;
714}
715
716int
717xf86ProcessArgument(int argc, char *argv[], int i)
718{
719	/*
720	 * Keep server from detaching from controlling tty.  This is useful
721	 * when debugging (so the server can receive keyboard signals.
722	 */
723	if (!strcmp(argv[i], "-keeptty"))
724	{
725		KeepTty = TRUE;
726		return 1;
727	}
728#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
729	if (!strcmp(argv[i], "-sharevts"))
730	{
731		ShareVTs = TRUE;
732		return 1;
733	}
734	if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
735	{
736		if (sscanf(argv[i], "vt%2d", &VTnum) == 0 ||
737		    VTnum < 1 || VTnum > 12)
738		{
739			UseMsg();
740			VTnum = -1;
741			return 0;
742		}
743		return 1;
744	}
745#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
746	return 0;
747}
748
749void
750xf86UseMsg()
751{
752#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
753	ErrorF("vtXX                   use the specified VT number (1-12)\n");
754	ErrorF("-sharevts              share VTs with another X server\n");
755#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
756	ErrorF("-keeptty               ");
757	ErrorF("don't detach controlling tty (for debugging only)\n");
758	return;
759}
760