xref: /openbsd-src/sbin/wsconsctl/wsconsctl.c (revision df69c215c7c66baf660f3f65414fd34796c96152)
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