1 /* $NetBSD: wsmuxctl.c,v 1.14 2019/03/29 07:49:38 mlelstv Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Author: Lennart Augustsson <augustss@carlstedt.se> 8 * Carlstedt Research & Technology 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 #include <ctype.h> 37 #include <sys/types.h> 38 #include <sys/ioctl.h> 39 #include <err.h> 40 #include <errno.h> 41 42 #include <dev/wscons/wsconsio.h> 43 44 __dead static void usage(void); 45 46 static const char *ctlpath = "/dev/wsmuxctl"; 47 48 static void 49 usage(void) 50 { 51 52 fprintf(stderr, "usage: %s [-a dev] -f wsmux [-l] [-L] [-r dev]\n", 53 getprogname()); 54 exit(1); 55 } 56 57 static void 58 parsedev(const char *dev, struct wsmux_device *mdev) 59 { 60 if (sscanf(dev, "wsmouse%d", &mdev->idx) == 1) { 61 mdev->type = WSMUX_MOUSE; 62 return; 63 } 64 if (sscanf(dev, "wskbd%d", &mdev->idx) == 1) { 65 mdev->type = WSMUX_KBD; 66 return; 67 } 68 if (sscanf(dev, "wsmux%d", &mdev->idx) == 1) { 69 mdev->type = WSMUX_MUX; 70 return; 71 } 72 if (sscanf(dev, "wsbell%d", &mdev->idx) == 1) { 73 mdev->type = WSMUX_BELL; 74 return; 75 } 76 errx(1, "bad device: `%s', use wsmouse, wskdb, wsmux or wsbell", dev); 77 } 78 79 static void 80 listdevs(int fd, int rec, int ind) 81 { 82 int i, rfd; 83 char buf[100]; 84 struct wsmux_device_list devs; 85 const char *name; 86 87 if (ioctl(fd, WSMUXIO_LIST_DEVICES, &devs) < 0) 88 err(1, "WSMUXIO_LIST_DEVICES"); 89 for (i = 0; i < devs.ndevices; i++) { 90 switch (devs.devices[i].type) { 91 case WSMUX_MOUSE: name = "wsmouse"; break; 92 case WSMUX_KBD: name = "wskbd"; break; 93 case WSMUX_MUX: name = "wsmux"; break; 94 case WSMUX_BELL: name = "wsbell"; break; 95 default: name = "?"; break; 96 } 97 printf("%*s%s%d\n", ind, "", name, devs.devices[i].idx); 98 if (rec && devs.devices[i].type == WSMUX_MUX) { 99 snprintf(buf, sizeof(buf), "%s%d", ctlpath, 100 devs.devices[i].idx); 101 rfd = open(buf, O_WRONLY, 0); 102 if (rfd < 0) 103 warn("%s", buf); 104 listdevs(rfd, rec, ind+2); 105 close(rfd); 106 } 107 } 108 } 109 110 int 111 main(int argc, char **argv) 112 { 113 char *wsdev, *dev; 114 int wsfd, list, c, add, rem, recursive; 115 struct wsmux_device mdev; 116 char buf[100]; 117 118 wsdev = NULL; 119 dev = NULL; 120 add = 0; 121 rem = 0; 122 list = 0; 123 recursive = 0; 124 125 while ((c = getopt(argc, argv, "a:f:lLr:")) != -1) { 126 switch (c) { 127 case 'a': 128 if (dev) 129 usage(); 130 dev = optarg; 131 add++; 132 break; 133 case 'r': 134 if (dev) 135 usage(); 136 dev = optarg; 137 rem++; 138 break; 139 case 'f': 140 wsdev = optarg; 141 break; 142 case 'L': 143 recursive++; 144 /* FALLTHROUGH */ 145 case 'l': 146 list++; 147 break; 148 case '?': 149 default: 150 usage(); 151 break; 152 } 153 } 154 argc -= optind; 155 argv += optind; 156 157 if (wsdev == NULL) 158 usage(); 159 160 wsfd = open(wsdev, O_WRONLY, 0); 161 if (wsfd < 0) { 162 if (isdigit((unsigned char)wsdev[0])) { 163 snprintf(buf, sizeof(buf), "%s%s", ctlpath, wsdev); 164 wsdev = buf; 165 wsfd = open(wsdev, O_WRONLY, 0); 166 } 167 if (wsfd < 0) 168 err(2, "%s", wsdev); 169 } 170 171 if (list) { 172 if (add || rem) 173 usage(); 174 listdevs(wsfd, recursive, 0); 175 exit(0); 176 } 177 178 if (add) { 179 parsedev(dev, &mdev); 180 if (ioctl(wsfd, WSMUXIO_ADD_DEVICE, &mdev) < 0) 181 err(1, "WSMUXIO_ADD_DEVICE"); 182 } 183 184 if (rem) { 185 parsedev(dev, &mdev); 186 if (ioctl(wsfd, WSMUXIO_REMOVE_DEVICE, &mdev) < 0) 187 err(1, "WSMUXIO_REMOVE_DEVICE"); 188 } 189 190 close(wsfd); 191 return (0); 192 } 193