1 /* $OpenBSD: wsconsctl.c,v 1.24 2009/07/19 15:34:45 martynas 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 <string.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include "wsconsctl.h" 40 41 #define PATH_KEYBOARD "/dev/wskbd0" 42 #define PATH_MOUSE "/dev/wsmouse0" 43 #define PATH_DISPLAY "/dev/ttyC0" 44 45 extern const char *__progname; /* from crt0.o */ 46 47 extern struct field keyboard_field_tab[]; 48 extern struct field mouse_field_tab[]; 49 extern struct field display_field_tab[]; 50 51 void usage(char *); 52 53 struct vartypesw { 54 const char *name, *file; 55 int fd; 56 struct field *field_tab; 57 void (*getval)(const char *pre, int); 58 int (*putval)(const char *pre, int); 59 } typesw[] = { 60 { "keyboard", PATH_KEYBOARD, -1, keyboard_field_tab, 61 keyboard_get_values, keyboard_put_values }, 62 { "mouse", PATH_MOUSE, -1, mouse_field_tab, 63 mouse_get_values, mouse_put_values }, 64 { "display", PATH_DISPLAY, -1, display_field_tab, 65 display_get_values, display_put_values }, 66 { NULL } 67 }; 68 69 struct vartypesw *tab_by_name(const char *); 70 71 void 72 usage(char *msg) 73 { 74 if (msg != NULL) 75 fprintf(stderr, "%s: %s\n", __progname, msg); 76 77 fprintf(stderr, 78 "usage: %s [-an]\n" 79 " %s [-n] [-f file] name ...\n" 80 " %s [-n] [-f file] name=value ...\n" 81 " %s [-n] [-f file] name+=value ...\n", 82 __progname, __progname, __progname, __progname); 83 84 exit(1); 85 } 86 87 int 88 main(int argc, char *argv[]) 89 { 90 int i, ch, error = 0, aflag = 0, do_merge, putval; 91 struct vartypesw *sw = NULL; 92 char *getsep = "=", *setsep = " -> ", *p; 93 char *wdev = NULL; 94 struct field *f; 95 96 while ((ch = getopt(argc, argv, "af:nw")) != -1) { 97 switch(ch) { 98 case 'a': 99 aflag = 1; 100 break; 101 case 'f': 102 wdev = optarg; 103 break; 104 case 'n': 105 getsep = setsep = NULL; 106 break; 107 case 'w': 108 /* compat */ 109 break; 110 default: 111 usage(NULL); 112 } 113 } 114 115 argc -= optind; 116 argv += optind; 117 118 if (argc > 0 && aflag != 0) 119 usage("excess arguments after -a"); 120 if (argc == 0) 121 aflag = 1; 122 123 if (aflag != 0) { 124 for (sw = typesw; sw->name; sw++) { 125 if (sw->fd < 0 && 126 (sw->fd = open(sw->file, O_WRONLY)) < 0 && 127 (sw->fd = open(sw->file, O_RDONLY)) < 0) { 128 warn("%s", sw->file); 129 error = 1; 130 continue; 131 } 132 for (f = sw->field_tab; f->name; f++) 133 if ((f->flags & (FLG_NOAUTO|FLG_WRONLY)) == 0) 134 f->flags |= FLG_GET; 135 (*sw->getval)(sw->name, sw->fd); 136 for (f = sw->field_tab; f->name; f++) 137 if (f->flags & FLG_DEAD) 138 continue; 139 else if (f->flags & FLG_NOAUTO) 140 warnx("Use explicit arg to view %s.%s.", 141 sw->name, f->name); 142 else if (f->flags & FLG_GET) 143 pr_field(sw->name, f, getsep); 144 } 145 } else if (argc > 0) { 146 for (i = 0; i < argc; i++) { 147 p = strchr(argv[i], '='); 148 if (p == NULL) { 149 sw = tab_by_name(argv[i]); 150 if (!sw) 151 continue; 152 153 if (wdev != NULL) 154 sw->file = (const char *)wdev; 155 156 if (sw->fd < 0 && 157 (sw->fd = open(sw->file, O_WRONLY)) < 0 && 158 (sw->fd = open(sw->file, O_RDONLY)) < 0) { 159 warn("open: %s", sw->file); 160 error = 1; 161 continue; 162 } 163 f = field_by_name(sw->field_tab, argv[i]); 164 if (f->flags & FLG_DEAD) 165 continue; 166 if ((f->flags & FLG_WRONLY) != 0) { 167 warnx("%s: write only", argv[i]); 168 continue; 169 } 170 f->flags |= FLG_GET; 171 (*sw->getval)(sw->name, sw->fd); 172 if (f->flags & FLG_DEAD) 173 continue; 174 pr_field(sw->name, f, getsep); 175 continue; 176 } 177 if (p > argv[i] && 178 (*(p - 1) == '+' || *(p - 1) == '-')) { 179 do_merge = *(p - 1); 180 *(p - 1) = '\0'; 181 } else 182 do_merge = 0; 183 *p++ = '\0'; 184 sw = tab_by_name(argv[i]); 185 if (!sw) 186 continue; 187 188 if (wdev != NULL) 189 sw->file = (const char *)wdev; 190 191 if (sw->fd < 0 && 192 (sw->fd = open(sw->file, O_WRONLY)) < 0 && 193 (sw->fd = open(sw->file, O_RDONLY)) < 0) { 194 warn("open: %s", sw->file); 195 error = 1; 196 continue; 197 } 198 f = field_by_name(sw->field_tab, argv[i]); 199 if (f->flags & FLG_DEAD) 200 continue; 201 if ((f->flags & FLG_RDONLY) != 0) { 202 warnx("%s: read only", argv[i]); 203 continue; 204 } 205 if (do_merge || f->flags & FLG_INIT) { 206 if ((f->flags & FLG_MODIFY) == 0) 207 errx(1, "%s: can only be set", 208 argv[i]); 209 f->flags |= FLG_GET; 210 (*sw->getval)(sw->name, sw->fd); 211 f->flags &= ~FLG_GET; 212 } 213 rd_field(f, p, do_merge); 214 f->flags |= FLG_SET; 215 putval = (*sw->putval)(sw->name, sw->fd); 216 f->flags &= ~FLG_SET; 217 if (putval != 0 || f->flags & (FLG_DEAD | FLG_NOAUTO)) 218 continue; 219 if (f->flags & FLG_WRONLY) { 220 pr_field(sw->name, f, setsep); 221 } else { 222 f->flags |= FLG_GET; 223 (*sw->getval)(sw->name, sw->fd); 224 if (f->flags & FLG_DEAD) 225 continue; 226 pr_field(sw->name, f, setsep); 227 } 228 } 229 } else 230 usage(NULL); 231 232 return (error); 233 } 234 235 struct vartypesw * 236 tab_by_name(const char *var) 237 { 238 struct vartypesw *sw; 239 const char *p = strchr(var, '.'); 240 241 if (!p) { 242 warnx("%s: illegal variable name", var); 243 return (NULL); 244 } 245 246 for (sw = typesw; sw->name; sw++) 247 if (!strncmp(sw->name, var, p - var)) 248 break; 249 250 if (!sw->name) { 251 warnx("%s: no such variable", var); 252 return (NULL); 253 } 254 255 return (sw); 256 } 257