1 /* $OpenBSD: wsconsctl.c,v 1.32 2019/06/28 13:32:46 deraadt Exp $ */ 2 /* $NetBSD: wsconsctl.c,v 1.2 1998/12/29 22:40:20 hannken Exp $ */ 3 4 /*- 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Juergen Hannken-Illjes. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <fcntl.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include "wsconsctl.h" 41 42 extern const char *__progname; /* from crt0.o */ 43 44 extern struct field keyboard_field_tab[]; 45 extern struct field mouse_field_tab[]; 46 extern struct field display_field_tab[]; 47 48 void usage(void); 49 50 struct vartypesw { 51 const char *name; 52 struct field *field_tab; 53 void (*init)(int,int); 54 void (*getval)(int); 55 int (*putval)(int); 56 char * (*nextdev)(int); 57 } typesw[] = { 58 { "keyboard", keyboard_field_tab, NULL, 59 keyboard_get_values, keyboard_put_values, keyboard_next_device }, 60 { "mouse", mouse_field_tab, mouse_init, 61 mouse_get_values, mouse_put_values, mouse_next_device }, 62 { "display", display_field_tab, NULL, 63 display_get_values, display_put_values, display_next_device }, 64 { NULL } 65 }; 66 67 struct vartypesw *tab_by_name(const char *, int *); 68 69 void 70 usage(void) 71 { 72 fprintf(stderr, 73 "usage: %s [-an]\n" 74 " %s [-n] [-f file] name ...\n" 75 " %s [-n] [-f file] name=value ...\n", 76 __progname, __progname, __progname); 77 exit(1); 78 } 79 80 int 81 main(int argc, char *argv[]) 82 { 83 int i, ch, error = 0, aflag = 0, do_merge, putval, devidx, devfd; 84 struct vartypesw *sw = NULL; 85 char *getsep = "=", *setsep = " -> ", *p; 86 char *wdev = NULL; 87 char *device; 88 struct field *f; 89 char devname[20]; 90 91 while ((ch = getopt(argc, argv, "af:nw")) != -1) { 92 switch(ch) { 93 case 'a': 94 aflag = 1; 95 break; 96 case 'f': 97 wdev = optarg; 98 break; 99 case 'n': 100 getsep = setsep = NULL; 101 break; 102 case 'w': 103 /* compat */ 104 break; 105 default: 106 usage(); 107 } 108 } 109 110 argc -= optind; 111 argv += optind; 112 113 if (argc > 0 && aflag != 0) 114 errx(1, "excess arguments after -a"); 115 if (argc == 0) 116 aflag = 1; 117 118 if (aflag != 0) { 119 for (sw = typesw; sw->name; sw++) { 120 for (devidx = 0;; devidx++) { 121 device = (*sw->nextdev)(devidx); 122 if (!device || 123 ((devfd = open(device, O_WRONLY)) == -1 && 124 (devfd = open(device, O_RDONLY)) == -1)) { 125 if (!device || errno != ENXIO) { 126 if (device && errno != ENOENT) { 127 warn("%s", device); 128 error = 1; 129 } 130 break; 131 } else 132 continue; 133 } 134 135 if (devidx == 0) 136 snprintf(devname, sizeof(devname), 137 "%s", sw->name); 138 else 139 snprintf(devname, sizeof(devname), 140 "%s%d", sw->name, devidx); 141 142 if (sw->init != NULL) 143 (*sw->init)(devfd, devidx); 144 145 for (f = sw->field_tab; f->name; f++) 146 if (!(f->flags & 147 (FLG_NOAUTO|FLG_WRONLY))) 148 f->flags |= FLG_GET; 149 (*sw->getval)(devfd); 150 for (f = sw->field_tab; f->name; f++) 151 if (f->flags & FLG_DEAD) 152 continue; 153 else if (f->flags & FLG_NOAUTO) 154 warnx("Use explicit arg to " 155 "view %s.%s.", 156 devname, f->name); 157 else if (f->flags & FLG_GET) 158 pr_field(devname, f, getsep); 159 } 160 } 161 } else if (argc > 0) { 162 for (i = 0; i < argc; i++) { 163 sw = tab_by_name(argv[i], &devidx); 164 if (!sw) 165 continue; 166 167 if (!wdev) 168 device = (*sw->nextdev)(devidx); 169 else 170 device = wdev; 171 172 if (!device || 173 ((devfd = open(device, O_WRONLY)) == -1 && 174 (devfd = open(device, O_RDONLY)) == -1)) { 175 if (!device) { 176 const char *c = strchr(argv[i], '.'); 177 int k; 178 if (!c) 179 c = strchr(argv[i], '\0'); 180 k = c - argv[i]; 181 warnx("%*.*s: no such variable", 182 k, k, argv[i]); 183 } else 184 warn("%s", device); 185 error = 1; 186 continue; 187 } 188 189 if (devidx == 0) 190 snprintf(devname, sizeof(devname), 191 "%s", sw->name); 192 else 193 snprintf(devname, sizeof(devname), 194 "%s%d", sw->name, devidx); 195 196 if (sw->init != NULL) 197 (*sw->init)(devfd, devidx); 198 199 p = strchr(argv[i], '='); 200 if (p == NULL) { 201 if (!strchr(argv[i], '.')) { 202 for (f = sw->field_tab; f->name; f++) 203 if (!(f->flags & 204 (FLG_NOAUTO|FLG_WRONLY))) 205 f->flags |= FLG_GET; 206 (*sw->getval)(devfd); 207 for (f = sw->field_tab; f->name; f++) 208 if (f->flags & FLG_DEAD) 209 continue; 210 else if (f->flags & FLG_NOAUTO) 211 warnx("Use explicit " 212 "arg to view " 213 "%s.%s.", 214 devname, f->name); 215 else if (f->flags & FLG_GET) 216 pr_field(devname, f, 217 getsep); 218 continue; 219 } 220 221 f = field_by_name(sw->field_tab, argv[i]); 222 if (f->flags & FLG_DEAD) 223 continue; 224 if ((f->flags & FLG_WRONLY)) { 225 warnx("%s: write only", argv[i]); 226 continue; 227 } 228 f->flags |= FLG_GET; 229 (*sw->getval)(devfd); 230 if (f->flags & FLG_DEAD) 231 continue; 232 pr_field(devname, f, getsep); 233 } else { 234 if (!strchr(argv[i], '.') || 235 (strchr(argv[i], '.') > p)) { 236 warnx("%s: illegal variable name", 237 argv[i]); 238 continue; 239 } 240 if (p > argv[i] && 241 (*(p - 1) == '+' || *(p - 1) == '-')) { 242 do_merge = *(p - 1); 243 *(p - 1) = '\0'; 244 } else 245 do_merge = 0; 246 *p++ = '\0'; 247 248 f = field_by_name(sw->field_tab, argv[i]); 249 if (f->flags & FLG_DEAD) 250 continue; 251 if (f->flags & FLG_RDONLY) { 252 warnx("%s: read only", argv[i]); 253 continue; 254 } 255 if (do_merge || f->flags & FLG_INIT) { 256 if (!(f->flags & FLG_MODIFY)) 257 errx(1, "%s: can only be set", 258 argv[i]); 259 f->flags |= FLG_GET; 260 (*sw->getval)(devfd); 261 f->flags &= ~FLG_GET; 262 } 263 rd_field(f, p, do_merge); 264 f->flags |= FLG_SET; 265 putval = (*sw->putval)(devfd); 266 f->flags &= ~FLG_SET; 267 if (putval != 0 || 268 f->flags & (FLG_DEAD|FLG_NOAUTO)) 269 continue; 270 if (f->flags & FLG_WRONLY) { 271 pr_field(devname, f, setsep); 272 } else { 273 if (!(f->flags & FLG_NORDBACK)) { 274 f->flags |= FLG_GET; 275 (*sw->getval)(devfd); 276 } 277 if (f->flags & FLG_DEAD) 278 continue; 279 pr_field(devname, f, setsep); 280 } 281 } 282 283 close(devfd); 284 } 285 } else 286 usage(); 287 288 exit(error); 289 } 290 291 struct vartypesw * 292 tab_by_name(const char *var, int *idx) 293 { 294 struct vartypesw *sw; 295 const char *p = strchr(var, '.'); 296 char *c; 297 int i; 298 299 for (sw = typesw; sw->name; sw++) 300 if (!strncmp(sw->name, var, strlen(sw->name))) 301 break; 302 303 if (!p) 304 p = strchr(var, '\0'); 305 306 if (!sw->name) { 307 i = p - var; 308 warnx("%*.*s: no such variable", i, i, var); 309 return (NULL); 310 } 311 312 if ((p - var) > strlen(sw->name)) { 313 c = (char *)var; 314 c = c + strlen(sw->name); 315 i = 0; 316 while (c < p) { 317 if (*c >= '0' && *c <= '9') 318 i = i * 10 + *c - '0'; 319 else 320 i = -1; 321 c++; 322 } 323 if (i < 0 || i > 32) { 324 i = p - var; 325 warnx("%*.*s: no such variable", i, i, var); 326 return (NULL); 327 } 328 } else 329 i = 0; 330 331 *idx = i; 332 333 return (sw); 334 } 335