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