1*df69c215Sderaadt /* $OpenBSD: wsconsctl.c,v 1.32 2019/06/28 13:32:46 deraadt Exp $ */
2e0b2c52dSmickey /* $NetBSD: wsconsctl.c,v 1.2 1998/12/29 22:40:20 hannken Exp $ */
3e0b2c52dSmickey
4e0b2c52dSmickey /*-
5e0b2c52dSmickey * Copyright (c) 1998 The NetBSD Foundation, Inc.
6e0b2c52dSmickey * All rights reserved.
7e0b2c52dSmickey *
8e0b2c52dSmickey * This code is derived from software contributed to The NetBSD Foundation
9e0b2c52dSmickey * by Juergen Hannken-Illjes.
10e0b2c52dSmickey *
11e0b2c52dSmickey * Redistribution and use in source and binary forms, with or without
12e0b2c52dSmickey * modification, are permitted provided that the following conditions
13e0b2c52dSmickey * are met:
14e0b2c52dSmickey * 1. Redistributions of source code must retain the above copyright
15e0b2c52dSmickey * notice, this list of conditions and the following disclaimer.
16e0b2c52dSmickey * 2. Redistributions in binary form must reproduce the above copyright
17e0b2c52dSmickey * notice, this list of conditions and the following disclaimer in the
18e0b2c52dSmickey * documentation and/or other materials provided with the distribution.
19e0b2c52dSmickey *
20e0b2c52dSmickey * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21e0b2c52dSmickey * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22e0b2c52dSmickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23e0b2c52dSmickey * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24e0b2c52dSmickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25e0b2c52dSmickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26e0b2c52dSmickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27e0b2c52dSmickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28e0b2c52dSmickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29e0b2c52dSmickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30e0b2c52dSmickey * POSSIBILITY OF SUCH DAMAGE.
31e0b2c52dSmickey */
32e0b2c52dSmickey
33e0b2c52dSmickey #include <fcntl.h>
34e0b2c52dSmickey #include <err.h>
3554e3cb1dSfgsch #include <errno.h>
36e0b2c52dSmickey #include <string.h>
37e0b2c52dSmickey #include <stdio.h>
38b1b7cd8fSdavid #include <stdlib.h>
39e0b2c52dSmickey #include <unistd.h>
40e0b2c52dSmickey #include "wsconsctl.h"
41e0b2c52dSmickey
42e0b2c52dSmickey extern const char *__progname; /* from crt0.o */
43e0b2c52dSmickey
44e0b2c52dSmickey extern struct field keyboard_field_tab[];
45e0b2c52dSmickey extern struct field mouse_field_tab[];
46e0b2c52dSmickey extern struct field display_field_tab[];
47e0b2c52dSmickey
4854e3cb1dSfgsch void usage(void);
49e0b2c52dSmickey
502bd5d6fcSmickey struct vartypesw {
511222b15bSmaja const char *name;
5282bc7287Smickey struct field *field_tab;
53d22ea701Sbru void (*init)(int,int);
5454e3cb1dSfgsch void (*getval)(int);
5554e3cb1dSfgsch int (*putval)(int);
5654e3cb1dSfgsch char * (*nextdev)(int);
5782bc7287Smickey } typesw[] = {
58d22ea701Sbru { "keyboard", keyboard_field_tab, NULL,
591222b15bSmaja keyboard_get_values, keyboard_put_values, keyboard_next_device },
60d22ea701Sbru { "mouse", mouse_field_tab, mouse_init,
611222b15bSmaja mouse_get_values, mouse_put_values, mouse_next_device },
62d22ea701Sbru { "display", display_field_tab, NULL,
631222b15bSmaja display_get_values, display_put_values, display_next_device },
6482bc7287Smickey { NULL }
6582bc7287Smickey };
6682bc7287Smickey
671222b15bSmaja struct vartypesw *tab_by_name(const char *, int *);
6882bc7287Smickey
6982bc7287Smickey void
usage(void)704a2a0733Sshadchin usage(void)
71e0b2c52dSmickey {
7282bc7287Smickey fprintf(stderr,
73fdae1d23Sderaadt "usage: %s [-an]\n"
7418f4b016Sjmc " %s [-n] [-f file] name ...\n"
75d6068540Sjmc " %s [-n] [-f file] name=value ...\n",
76d6068540Sjmc __progname, __progname, __progname);
77e0b2c52dSmickey exit(1);
78e0b2c52dSmickey }
79e0b2c52dSmickey
80e0b2c52dSmickey int
main(int argc,char * argv[])812875d50eSderaadt main(int argc, char *argv[])
82e0b2c52dSmickey {
831222b15bSmaja int i, ch, error = 0, aflag = 0, do_merge, putval, devidx, devfd;
84f9d3d2c5Sderaadt struct vartypesw *sw = NULL;
85b554194aSmartynas char *getsep = "=", *setsep = " -> ", *p;
8653ec592cSrobert char *wdev = NULL;
8754e3cb1dSfgsch char *device;
8882bc7287Smickey struct field *f;
891222b15bSmaja char devname[20];
90e0b2c52dSmickey
9153ec592cSrobert while ((ch = getopt(argc, argv, "af:nw")) != -1) {
92e0b2c52dSmickey switch(ch) {
93e0b2c52dSmickey case 'a':
94e0b2c52dSmickey aflag = 1;
95e0b2c52dSmickey break;
9653ec592cSrobert case 'f':
9753ec592cSrobert wdev = optarg;
9853ec592cSrobert break;
99e0b2c52dSmickey case 'n':
100b554194aSmartynas getsep = setsep = NULL;
101e0b2c52dSmickey break;
102e0b2c52dSmickey case 'w':
1032b93bd72Sdavid /* compat */
104e0b2c52dSmickey break;
105e0b2c52dSmickey default:
10654e3cb1dSfgsch usage();
107e0b2c52dSmickey }
108e0b2c52dSmickey }
109e0b2c52dSmickey
110e0b2c52dSmickey argc -= optind;
111e0b2c52dSmickey argv += optind;
112e0b2c52dSmickey
113e0b2c52dSmickey if (argc > 0 && aflag != 0)
11454e3cb1dSfgsch errx(1, "excess arguments after -a");
115fdae1d23Sderaadt if (argc == 0)
116fdae1d23Sderaadt aflag = 1;
117e0b2c52dSmickey
118e0b2c52dSmickey if (aflag != 0) {
11982bc7287Smickey for (sw = typesw; sw->name; sw++) {
12054e3cb1dSfgsch for (devidx = 0;; devidx++) {
12154e3cb1dSfgsch device = (*sw->nextdev)(devidx);
12254e3cb1dSfgsch if (!device ||
123*df69c215Sderaadt ((devfd = open(device, O_WRONLY)) == -1 &&
124*df69c215Sderaadt (devfd = open(device, O_RDONLY)) == -1)) {
12554e3cb1dSfgsch if (!device || errno != ENXIO) {
12654e3cb1dSfgsch if (device && errno != ENOENT) {
12754e3cb1dSfgsch warn("%s", device);
12854e3cb1dSfgsch error = 1;
12954e3cb1dSfgsch }
13054e3cb1dSfgsch break;
13154e3cb1dSfgsch } else
13282bc7287Smickey continue;
13354e3cb1dSfgsch }
1341222b15bSmaja
1351222b15bSmaja if (devidx == 0)
13654e3cb1dSfgsch snprintf(devname, sizeof(devname),
13754e3cb1dSfgsch "%s", sw->name);
1381222b15bSmaja else
13954e3cb1dSfgsch snprintf(devname, sizeof(devname),
14054e3cb1dSfgsch "%s%d", sw->name, devidx);
1411222b15bSmaja
142d22ea701Sbru if (sw->init != NULL)
143d22ea701Sbru (*sw->init)(devfd, devidx);
144d22ea701Sbru
145b8557c36Smickey for (f = sw->field_tab; f->name; f++)
14654e3cb1dSfgsch if (!(f->flags &
14754e3cb1dSfgsch (FLG_NOAUTO|FLG_WRONLY)))
148b8557c36Smickey f->flags |= FLG_GET;
14954e3cb1dSfgsch (*sw->getval)(devfd);
150b8557c36Smickey for (f = sw->field_tab; f->name; f++)
151b8557c36Smickey if (f->flags & FLG_DEAD)
152b8557c36Smickey continue;
153b8557c36Smickey else if (f->flags & FLG_NOAUTO)
15454e3cb1dSfgsch warnx("Use explicit arg to "
15554e3cb1dSfgsch "view %s.%s.",
1561222b15bSmaja devname, f->name);
157b8557c36Smickey else if (f->flags & FLG_GET)
1581222b15bSmaja pr_field(devname, f, getsep);
1591222b15bSmaja }
16082bc7287Smickey }
161e0b2c52dSmickey } else if (argc > 0) {
162e0b2c52dSmickey for (i = 0; i < argc; i++) {
1631222b15bSmaja sw = tab_by_name(argv[i], &devidx);
1642b93bd72Sdavid if (!sw)
1652b93bd72Sdavid continue;
16653ec592cSrobert
16754e3cb1dSfgsch if (!wdev)
16854e3cb1dSfgsch device = (*sw->nextdev)(devidx);
16954e3cb1dSfgsch else
17054e3cb1dSfgsch device = wdev;
17154e3cb1dSfgsch
17254e3cb1dSfgsch if (!device ||
173*df69c215Sderaadt ((devfd = open(device, O_WRONLY)) == -1 &&
174*df69c215Sderaadt (devfd = open(device, O_RDONLY)) == -1)) {
17554e3cb1dSfgsch if (!device) {
1761222b15bSmaja const char *c = strchr(argv[i], '.');
1771222b15bSmaja int k;
1781222b15bSmaja if (!c)
1791222b15bSmaja c = strchr(argv[i], '\0');
1801222b15bSmaja k = c - argv[i];
18154e3cb1dSfgsch warnx("%*.*s: no such variable",
18254e3cb1dSfgsch k, k, argv[i]);
18354e3cb1dSfgsch } else
18454e3cb1dSfgsch warn("%s", device);
1852b93bd72Sdavid error = 1;
1862b93bd72Sdavid continue;
1872b93bd72Sdavid }
1881222b15bSmaja
18954e3cb1dSfgsch if (devidx == 0)
19054e3cb1dSfgsch snprintf(devname, sizeof(devname),
19154e3cb1dSfgsch "%s", sw->name);
19254e3cb1dSfgsch else
19354e3cb1dSfgsch snprintf(devname, sizeof(devname),
19454e3cb1dSfgsch "%s%d", sw->name, devidx);
1951222b15bSmaja
196d22ea701Sbru if (sw->init != NULL)
197d22ea701Sbru (*sw->init)(devfd, devidx);
198d22ea701Sbru
19954e3cb1dSfgsch p = strchr(argv[i], '=');
20054e3cb1dSfgsch if (p == NULL) {
2011222b15bSmaja if (!strchr(argv[i], '.')) {
2021222b15bSmaja for (f = sw->field_tab; f->name; f++)
20354e3cb1dSfgsch if (!(f->flags &
20454e3cb1dSfgsch (FLG_NOAUTO|FLG_WRONLY)))
2051222b15bSmaja f->flags |= FLG_GET;
20654e3cb1dSfgsch (*sw->getval)(devfd);
2071222b15bSmaja for (f = sw->field_tab; f->name; f++)
2081222b15bSmaja if (f->flags & FLG_DEAD)
2091222b15bSmaja continue;
2101222b15bSmaja else if (f->flags & FLG_NOAUTO)
21154e3cb1dSfgsch warnx("Use explicit "
21254e3cb1dSfgsch "arg to view "
21354e3cb1dSfgsch "%s.%s.",
2141222b15bSmaja devname, f->name);
2151222b15bSmaja else if (f->flags & FLG_GET)
21654e3cb1dSfgsch pr_field(devname, f,
21754e3cb1dSfgsch getsep);
2181222b15bSmaja continue;
2191222b15bSmaja }
2201222b15bSmaja
2212b93bd72Sdavid f = field_by_name(sw->field_tab, argv[i]);
2222b93bd72Sdavid if (f->flags & FLG_DEAD)
2232b93bd72Sdavid continue;
22454e3cb1dSfgsch if ((f->flags & FLG_WRONLY)) {
2252b93bd72Sdavid warnx("%s: write only", argv[i]);
2262b93bd72Sdavid continue;
2272b93bd72Sdavid }
2282b93bd72Sdavid f->flags |= FLG_GET;
22954e3cb1dSfgsch (*sw->getval)(devfd);
230c859ff6cSmiod if (f->flags & FLG_DEAD)
231c859ff6cSmiod continue;
2321222b15bSmaja pr_field(devname, f, getsep);
23354e3cb1dSfgsch } else {
2341222b15bSmaja if (!strchr(argv[i], '.') ||
2351222b15bSmaja (strchr(argv[i], '.') > p)) {
23654e3cb1dSfgsch warnx("%s: illegal variable name",
23754e3cb1dSfgsch argv[i]);
23882bc7287Smickey continue;
23982bc7287Smickey }
240b8557c36Smickey if (p > argv[i] &&
241b8557c36Smickey (*(p - 1) == '+' || *(p - 1) == '-')) {
242b8557c36Smickey do_merge = *(p - 1);
243e0b2c52dSmickey *(p - 1) = '\0';
244e0b2c52dSmickey } else
245e0b2c52dSmickey do_merge = 0;
246e0b2c52dSmickey *p++ = '\0';
2471222b15bSmaja
24882bc7287Smickey f = field_by_name(sw->field_tab, argv[i]);
249b8557c36Smickey if (f->flags & FLG_DEAD)
250b8557c36Smickey continue;
25154e3cb1dSfgsch if (f->flags & FLG_RDONLY) {
25282bc7287Smickey warnx("%s: read only", argv[i]);
25382bc7287Smickey continue;
25482bc7287Smickey }
255b8557c36Smickey if (do_merge || f->flags & FLG_INIT) {
25654e3cb1dSfgsch if (!(f->flags & FLG_MODIFY))
257e0b2c52dSmickey errx(1, "%s: can only be set",
258e0b2c52dSmickey argv[i]);
259e0b2c52dSmickey f->flags |= FLG_GET;
26054e3cb1dSfgsch (*sw->getval)(devfd);
261e0b2c52dSmickey f->flags &= ~FLG_GET;
262e0b2c52dSmickey }
263e0b2c52dSmickey rd_field(f, p, do_merge);
264e0b2c52dSmickey f->flags |= FLG_SET;
26554e3cb1dSfgsch putval = (*sw->putval)(devfd);
266e0b2c52dSmickey f->flags &= ~FLG_SET;
26754e3cb1dSfgsch if (putval != 0 ||
26854e3cb1dSfgsch f->flags & (FLG_DEAD|FLG_NOAUTO))
269f0cd74dfSmartynas continue;
270f0cd74dfSmartynas if (f->flags & FLG_WRONLY) {
2711222b15bSmaja pr_field(devname, f, setsep);
272f0cd74dfSmartynas } else {
27335d84bc0Smiod if (!(f->flags & FLG_NORDBACK)) {
274f0cd74dfSmartynas f->flags |= FLG_GET;
27554e3cb1dSfgsch (*sw->getval)(devfd);
27635d84bc0Smiod }
277f0cd74dfSmartynas if (f->flags & FLG_DEAD)
278f0cd74dfSmartynas continue;
2791222b15bSmaja pr_field(devname, f, setsep);
280f0cd74dfSmartynas }
281e0b2c52dSmickey }
282e0b2c52dSmickey
28354e3cb1dSfgsch close(devfd);
28454e3cb1dSfgsch }
28554e3cb1dSfgsch } else
28654e3cb1dSfgsch usage();
28754e3cb1dSfgsch
28854e3cb1dSfgsch exit(error);
28982bc7287Smickey }
29082bc7287Smickey
2912bd5d6fcSmickey struct vartypesw *
tab_by_name(const char * var,int * idx)2921222b15bSmaja tab_by_name(const char *var, int *idx)
29382bc7287Smickey {
2942bd5d6fcSmickey struct vartypesw *sw;
29582bc7287Smickey const char *p = strchr(var, '.');
2961222b15bSmaja char *c;
2971222b15bSmaja int i;
29882bc7287Smickey
29982bc7287Smickey for (sw = typesw; sw->name; sw++)
3001222b15bSmaja if (!strncmp(sw->name, var, strlen(sw->name)))
30182bc7287Smickey break;
30282bc7287Smickey
3031222b15bSmaja if (!p)
3041222b15bSmaja p = strchr(var, '\0');
3051222b15bSmaja
30682bc7287Smickey if (!sw->name) {
3071222b15bSmaja i = p - var;
3081222b15bSmaja warnx("%*.*s: no such variable", i, i, var);
30982bc7287Smickey return (NULL);
31082bc7287Smickey }
31182bc7287Smickey
3121222b15bSmaja if ((p - var) > strlen(sw->name)) {
3131222b15bSmaja c = (char *)var;
3141222b15bSmaja c = c + strlen(sw->name);
3151222b15bSmaja i = 0;
3161222b15bSmaja while (c < p) {
3171222b15bSmaja if (*c >= '0' && *c <= '9')
3181222b15bSmaja i = i * 10 + *c - '0';
3191222b15bSmaja else
3201222b15bSmaja i = -1;
3211222b15bSmaja c++;
3221222b15bSmaja }
3231222b15bSmaja if (i < 0 || i > 32) {
3241222b15bSmaja i = p - var;
3251222b15bSmaja warnx("%*.*s: no such variable", i, i, var);
3261222b15bSmaja return (NULL);
3271222b15bSmaja }
3281222b15bSmaja } else
3291222b15bSmaja i = 0;
3301222b15bSmaja
3311222b15bSmaja *idx = i;
3321222b15bSmaja
33382bc7287Smickey return (sw);
334e0b2c52dSmickey }
335