185378Sjlemon/*-
285378Sjlemon * Copyright (c) 2001 Jonathan Lemon <jlemon@FreeBSD.org>
385378Sjlemon * All rights reserved.
485378Sjlemon *
585378Sjlemon * Redistribution and use in source and binary forms, with or without
685378Sjlemon * modification, are permitted provided that the following conditions
785378Sjlemon * are met:
885378Sjlemon * 1. Redistributions of source code must retain the above copyright
985378Sjlemon *    notice, this list of conditions and the following disclaimer.
1085378Sjlemon * 2. Redistributions in binary form must reproduce the above copyright
1185378Sjlemon *    notice, this list of conditions and the following disclaimer in the
1285378Sjlemon *    documentation and/or other materials provided with the distribution.
1385378Sjlemon *
1485378Sjlemon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1585378Sjlemon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1685378Sjlemon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1785378Sjlemon * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1885378Sjlemon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1985378Sjlemon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2085378Sjlemon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2185378Sjlemon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2285378Sjlemon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2385378Sjlemon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2485378Sjlemon * SUCH DAMAGE.
2585378Sjlemon */
2685378Sjlemon
2785486Sjlemon#include <sys/cdefs.h>
2885486Sjlemon__FBSDID("$FreeBSD$");
2985486Sjlemon
3085486Sjlemon#include <sys/types.h>
3185486Sjlemon#include <sys/sysctl.h>
32130676Sgreen#include <sys/ioctl.h>
33130676Sgreen#include <sys/ttycom.h>
3485486Sjlemon
3585486Sjlemon#include <err.h>
3685378Sjlemon#include <errno.h>
37130676Sgreen#include <fcntl.h>
3885378Sjlemon#include <stdio.h>
3985378Sjlemon#include <stdlib.h>
4085378Sjlemon#include <string.h>
4185486Sjlemon#include <unistd.h>
4285378Sjlemon
43125923Sgrog#define DEVDIR	"/dev/"
44125923Sgrog
4585378Sjlemonstatic void __dead2
4685378Sjlemonusage(void)
4785378Sjlemon{
4885378Sjlemon
49130676Sgreen	(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
5085486Sjlemon	    "usage: conscontrol [list]",
5185486Sjlemon	    "       conscontrol mute on | off",
52130676Sgreen	    "       conscontrol add | delete console",
53220801Sru	    "       conscontrol set | unset console");
5485378Sjlemon	exit(1);
5585378Sjlemon}
5685378Sjlemon
5785378Sjlemonstatic void
5885486Sjlemonconsstatus(void)
5985378Sjlemon{
6085378Sjlemon	int mute;
6185378Sjlemon	size_t len;
6285378Sjlemon	char *buf, *p, *avail;
6385378Sjlemon
6485378Sjlemon	len = sizeof(mute);
6585378Sjlemon	if (sysctlbyname("kern.consmute", &mute, &len, NULL, 0) == -1)
6685486Sjlemon		err(1, "kern.consmute retrieval failed");
6785486Sjlemon	if (sysctlbyname("kern.console", NULL, &len, NULL, 0) == -1)
6885486Sjlemon		err(1, "kern.console estimate failed");
6985486Sjlemon	if ((buf = malloc(len)) == NULL)
7085486Sjlemon		errx(1, "kern.console malloc failed");
7185486Sjlemon	if (sysctlbyname("kern.console", buf, &len, NULL, 0) == -1)
7285486Sjlemon		err(1, "kern.console retrieval failed");
7385486Sjlemon	if ((avail = strchr(buf, '/')) == NULL)
7485486Sjlemon		errx(1, "kern.console format not understood");
7585378Sjlemon	p = avail;
7685378Sjlemon	*avail++ = '\0';
7785378Sjlemon	if (p != buf)
7885378Sjlemon		*--p = '\0';			/* remove trailing ',' */
7985378Sjlemon	p = avail + strlen(avail);
8085378Sjlemon	if (p != avail)
8185378Sjlemon		*--p = '\0';			/* remove trailing ',' */
8285378Sjlemon	printf("Configured: %s\n", buf);
8385378Sjlemon	printf(" Available: %s\n", avail);
8485378Sjlemon	printf("    Muting: %s\n", mute ? "on" : "off");
8585378Sjlemon	free(buf);
8685378Sjlemon}
8785378Sjlemon
8885378Sjlemonstatic void
8985378Sjlemonconsmute(const char *onoff)
9085378Sjlemon{
9185378Sjlemon	int mute;
9285378Sjlemon	size_t len;
9385378Sjlemon
9485378Sjlemon	if (strcmp(onoff, "on") == 0)
9585378Sjlemon		mute = 1;
9685378Sjlemon	else if (strcmp(onoff, "off") == 0)
9785378Sjlemon		mute = 0;
9885378Sjlemon	else
9985378Sjlemon		usage();
10085378Sjlemon	len = sizeof(mute);
10185378Sjlemon	if (sysctlbyname("kern.consmute", NULL, NULL, &mute, len) == -1)
10285486Sjlemon		err(1, "could not change console muting");
10385378Sjlemon}
10485378Sjlemon
105125923Sgrog/*
106125923Sgrog * The name we supply to the sysctls should be an entry in /dev.  If
107125923Sgrog * the user has specified the full pathname in /dev, DTRT.  If he
108125923Sgrog * specifies a name in some other directory, it's an error.
109125923Sgrog */
110125923Sgrog
111125923Sgrogstatic char*
112125923Sgrogstripdev(char *devnam)
113125923Sgrog{
114125923Sgrog	if (memcmp (devnam, DEVDIR, strlen(DEVDIR)) == 0)
115125923Sgrog		return (&devnam[strlen(DEVDIR)]);	    /* remove /dev */
116125923Sgrog	else if (strchr (devnam, '/')) {
117125923Sgrog		fprintf(stderr, "Not a device in /dev: %s\n", devnam);
118125923Sgrog		return (NULL);				    /* end of string */
119125923Sgrog	} else
120125923Sgrog		return (devnam);			    /* passed */
121125923Sgrog}
122125923Sgrog
12385378Sjlemonstatic void
12485486Sjlemonconsadd(char *devnam)
12585378Sjlemon{
12685378Sjlemon	size_t len;
12785378Sjlemon
128125923Sgrog	devnam = stripdev(devnam);
129125923Sgrog	if (devnam == NULL)
130125923Sgrog		return;
13185486Sjlemon	len = strlen(devnam);
13285486Sjlemon	if (sysctlbyname("kern.console", NULL, NULL, devnam, len) == -1)
13385486Sjlemon		err(1, "could not add %s as a console", devnam);
13485378Sjlemon}
13585378Sjlemon
13685378Sjlemonstatic void
137125923Sgrogconsdel(char *devnam)
13885378Sjlemon{
13985486Sjlemon	char *buf;
14085378Sjlemon	size_t len;
14185378Sjlemon
142125923Sgrog	devnam = stripdev(devnam);
143125923Sgrog	if (devnam == NULL)
144125923Sgrog		return;
14585486Sjlemon	len = strlen(devnam) + sizeof("-");
14685486Sjlemon	if ((buf = malloc(len)) == NULL)
14785486Sjlemon		errx(1, "malloc failed");
14885486Sjlemon	buf[0] = '-';
14985486Sjlemon	strcpy(buf + 1, devnam);
15085486Sjlemon	if (sysctlbyname("kern.console", NULL, NULL, buf, len) == -1)
15185486Sjlemon		err(1, "could not remove %s as a console", devnam);
15285486Sjlemon	free(buf);
15385378Sjlemon}
15485378Sjlemon
155130676Sgreenstatic void
156220801Sruconsset(char *devnam, int flag)
157130676Sgreen{
158220801Sru	int ttyfd;
159130676Sgreen
160130676Sgreen	ttyfd = open(devnam, O_RDONLY);
161130676Sgreen	if (ttyfd == -1)
162130676Sgreen		err(1, "opening %s", devnam);
163130676Sgreen	if (ioctl(ttyfd, TIOCCONS, &flag) == -1)
164220801Sru		err(1, "could not %s %s as virtual console",
165220801Sru		    flag ? "set" : "unset", devnam);
166130676Sgreen	close(ttyfd);
167130676Sgreen}
168130676Sgreen
16985378Sjlemonint
17085378Sjlemonmain(int argc, char **argv)
17185378Sjlemon{
17285378Sjlemon
17385486Sjlemon	if (getopt(argc, argv, "") != -1)
17485378Sjlemon		usage();
17585486Sjlemon	argc -= optind;
17685486Sjlemon	argv += optind;
17785486Sjlemon
17885486Sjlemon	if (argc > 0 && strcmp(argv[0], "list") != 0) {
179220801Sru		if (argc != 2)
18085486Sjlemon			usage();
181130676Sgreen		else if (strcmp(argv[0], "mute") == 0)
18285486Sjlemon			consmute(argv[1]);
18385486Sjlemon		else if (strcmp(argv[0], "add") == 0)
18485486Sjlemon			consadd(argv[1]);
18585486Sjlemon		else if (strcmp(argv[0], "delete") == 0)
18685486Sjlemon			consdel(argv[1]);
187130676Sgreen		else if (strcmp(argv[0], "set") == 0)
188220801Sru			consset(argv[1], 1);
189220801Sru		else if (strcmp(argv[0], "unset") == 0)
190220801Sru			consset(argv[1], 0);
19185486Sjlemon		else
19285486Sjlemon			usage();
19385486Sjlemon	}
19485486Sjlemon	consstatus();
19585486Sjlemon	exit(0);
19685378Sjlemon}
197