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
usage(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
main(int argc,char * argv[])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 *
tab_by_name(const char * var,int * idx)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