1193323Sed/*- 2193323Sed * Copyright (c) 2001 Jonathan Lemon <jlemon@FreeBSD.org> 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 14193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18226633Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19224145Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20218893Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24193323Sed * SUCH DAMAGE. 25193323Sed */ 26204642Srdivacky 27204642Srdivacky#include <sys/cdefs.h> 28193323Sed__FBSDID("$FreeBSD: releng/10.2/sbin/conscontrol/conscontrol.c 220801 2011-04-18 20:28:07Z ru $"); 29239462Sdim 30193323Sed#include <sys/types.h> 31193323Sed#include <sys/sysctl.h> 32193323Sed#include <sys/ioctl.h> 33193323Sed#include <sys/ttycom.h> 34193323Sed 35210299Sed#include <err.h> 36210299Sed#include <errno.h> 37210299Sed#include <fcntl.h> 38210299Sed#include <stdio.h> 39239462Sdim#include <stdlib.h> 40239462Sdim#include <string.h> 41239462Sdim#include <unistd.h> 42239462Sdim 43239462Sdim#define DEVDIR "/dev/" 44193323Sed 45193323Sedstatic void __dead2 46193323Sedusage(void) 47193323Sed{ 48193323Sed 49193323Sed (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", 50226633Sdim "usage: conscontrol [list]", 51226633Sdim " conscontrol mute on | off", 52226633Sdim " conscontrol add | delete console", 53226633Sdim " conscontrol set | unset console"); 54206083Srdivacky exit(1); 55193323Sed} 56193323Sed 57193323Sedstatic void 58193323Sedconsstatus(void) 59193323Sed{ 60193323Sed int mute; 61193323Sed size_t len; 62193323Sed char *buf, *p, *avail; 63193323Sed 64193323Sed len = sizeof(mute); 65193323Sed if (sysctlbyname("kern.consmute", &mute, &len, NULL, 0) == -1) 66249423Sdim err(1, "kern.consmute retrieval failed"); 67249423Sdim if (sysctlbyname("kern.console", NULL, &len, NULL, 0) == -1) 68207618Srdivacky err(1, "kern.console estimate failed"); 69249423Sdim if ((buf = malloc(len)) == NULL) 70249423Sdim errx(1, "kern.console malloc failed"); 71249423Sdim if (sysctlbyname("kern.console", buf, &len, NULL, 0) == -1) 72251662Sdim err(1, "kern.console retrieval failed"); 73251662Sdim if ((avail = strchr(buf, '/')) == NULL) 74251662Sdim errx(1, "kern.console format not understood"); 75251662Sdim p = avail; 76251662Sdim *avail++ = '\0'; 77249423Sdim if (p != buf) 78193323Sed *--p = '\0'; /* remove trailing ',' */ 79193323Sed p = avail + strlen(avail); 80193323Sed if (p != avail) 81 *--p = '\0'; /* remove trailing ',' */ 82 printf("Configured: %s\n", buf); 83 printf(" Available: %s\n", avail); 84 printf(" Muting: %s\n", mute ? "on" : "off"); 85 free(buf); 86} 87 88static void 89consmute(const char *onoff) 90{ 91 int mute; 92 size_t len; 93 94 if (strcmp(onoff, "on") == 0) 95 mute = 1; 96 else if (strcmp(onoff, "off") == 0) 97 mute = 0; 98 else 99 usage(); 100 len = sizeof(mute); 101 if (sysctlbyname("kern.consmute", NULL, NULL, &mute, len) == -1) 102 err(1, "could not change console muting"); 103} 104 105/* 106 * The name we supply to the sysctls should be an entry in /dev. If 107 * the user has specified the full pathname in /dev, DTRT. If he 108 * specifies a name in some other directory, it's an error. 109 */ 110 111static char* 112stripdev(char *devnam) 113{ 114 if (memcmp (devnam, DEVDIR, strlen(DEVDIR)) == 0) 115 return (&devnam[strlen(DEVDIR)]); /* remove /dev */ 116 else if (strchr (devnam, '/')) { 117 fprintf(stderr, "Not a device in /dev: %s\n", devnam); 118 return (NULL); /* end of string */ 119 } else 120 return (devnam); /* passed */ 121} 122 123static void 124consadd(char *devnam) 125{ 126 size_t len; 127 128 devnam = stripdev(devnam); 129 if (devnam == NULL) 130 return; 131 len = strlen(devnam); 132 if (sysctlbyname("kern.console", NULL, NULL, devnam, len) == -1) 133 err(1, "could not add %s as a console", devnam); 134} 135 136static void 137consdel(char *devnam) 138{ 139 char *buf; 140 size_t len; 141 142 devnam = stripdev(devnam); 143 if (devnam == NULL) 144 return; 145 len = strlen(devnam) + sizeof("-"); 146 if ((buf = malloc(len)) == NULL) 147 errx(1, "malloc failed"); 148 buf[0] = '-'; 149 strcpy(buf + 1, devnam); 150 if (sysctlbyname("kern.console", NULL, NULL, buf, len) == -1) 151 err(1, "could not remove %s as a console", devnam); 152 free(buf); 153} 154 155static void 156consset(char *devnam, int flag) 157{ 158 int ttyfd; 159 160 ttyfd = open(devnam, O_RDONLY); 161 if (ttyfd == -1) 162 err(1, "opening %s", devnam); 163 if (ioctl(ttyfd, TIOCCONS, &flag) == -1) 164 err(1, "could not %s %s as virtual console", 165 flag ? "set" : "unset", devnam); 166 close(ttyfd); 167} 168 169int 170main(int argc, char **argv) 171{ 172 173 if (getopt(argc, argv, "") != -1) 174 usage(); 175 argc -= optind; 176 argv += optind; 177 178 if (argc > 0 && strcmp(argv[0], "list") != 0) { 179 if (argc != 2) 180 usage(); 181 else if (strcmp(argv[0], "mute") == 0) 182 consmute(argv[1]); 183 else if (strcmp(argv[0], "add") == 0) 184 consadd(argv[1]); 185 else if (strcmp(argv[0], "delete") == 0) 186 consdel(argv[1]); 187 else if (strcmp(argv[0], "set") == 0) 188 consset(argv[1], 1); 189 else if (strcmp(argv[0], "unset") == 0) 190 consset(argv[1], 0); 191 else 192 usage(); 193 } 194 consstatus(); 195 exit(0); 196} 197