xref: /openbsd/sbin/wsconsctl/wsconsctl.c (revision f9d3d2c5)
1 /*	$OpenBSD: wsconsctl.c,v 1.16 2004/08/09 18:39:22 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  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <fcntl.h>
41 #include <err.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include "wsconsctl.h"
47 
48 #define PATH_KEYBOARD		"/dev/wskbd0"
49 #define PATH_MOUSE		"/dev/wsmouse0"
50 #define PATH_DISPLAY		"/dev/ttyC0"
51 
52 extern const char *__progname;		/* from crt0.o */
53 
54 extern struct field keyboard_field_tab[];
55 extern struct field mouse_field_tab[];
56 extern struct field display_field_tab[];
57 
58 void usage(char *);
59 
60 struct vartypesw {
61 	const char *name, *file;
62 	int fd;
63 	struct field *field_tab;
64 	void (*getval)(const char *pre, int);
65 	void (*putval)(const char *pre, int);
66 } typesw[] = {
67 	{ "keyboard", PATH_KEYBOARD, -1, keyboard_field_tab,
68 	  keyboard_get_values, keyboard_put_values },
69 	{ "mouse", PATH_MOUSE, -1, mouse_field_tab,
70 	  mouse_get_values, mouse_put_values },
71 	{ "display", PATH_DISPLAY, -1, display_field_tab,
72 	  display_get_values, display_put_values },
73 	{ NULL }
74 };
75 
76 struct vartypesw *tab_by_name(const char *);
77 
78 void
79 usage(char *msg)
80 {
81 	if (msg != NULL)
82 		fprintf(stderr, "%s: %s\n", __progname, msg);
83 
84 	fprintf(stderr,
85 	    "usage: %s [-n] -a\n"
86 	    "       %s [-n] name ...\n"
87 	    "       %s [-n] name=value ...\n"
88 	    "       %s [-n] name+=value ...\n",
89 	    __progname, __progname, __progname, __progname);
90 
91 	exit(1);
92 }
93 
94 int
95 main(int argc, char *argv[])
96 {
97 	int i, ch, error = 0, aflag = 0, do_merge;
98 	struct vartypesw *sw = NULL;
99 	char *sep = "=", *p;
100 	struct field *f;
101 
102 	while ((ch = getopt(argc, argv, "anw")) != -1) {
103 		switch(ch) {
104 		case 'a':
105 			aflag = 1;
106 			break;
107 		case 'n':
108 			sep = NULL;
109 			break;
110 		case 'w':
111 			/* compat */
112 			break;
113 		default:
114 			usage(NULL);
115 		}
116 	}
117 
118 	argc -= optind;
119 	argv += optind;
120 
121 	if (argc > 0 && aflag != 0)
122 		usage("excess arguments after -a");
123 
124 	if (aflag != 0) {
125 		for (sw = typesw; sw->name; sw++) {
126 			if (sw->fd < 0 &&
127 			    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
128 			    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
129 				warn("%s", sw->file);
130 				error = 1;
131 				continue;
132 			}
133 			for (f = sw->field_tab; f->name; f++)
134 				if ((f->flags & (FLG_NOAUTO|FLG_WRONLY)) == 0)
135 					f->flags |= FLG_GET;
136 			(*sw->getval)(sw->name, sw->fd);
137 			for (f = sw->field_tab; f->name; f++)
138 				if (f->flags & FLG_DEAD)
139 					continue;
140 				else if (f->flags & FLG_NOAUTO)
141 					warnx("Use explicit arg to view %s.%s.",
142 					      sw->name, f->name);
143 				else if (f->flags & FLG_GET)
144 					pr_field(sw->name, f, sep);
145 		}
146 	} else if (argc > 0) {
147 		for (i = 0; i < argc; i++) {
148 			p = strchr(argv[i], '=');
149 			if (p == NULL) {
150 				sw = tab_by_name(argv[i]);
151 				if (!sw)
152 					continue;
153 				if (sw->fd < 0 &&
154 				    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
155 				    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
156 					warn("open: %s", sw->file);
157 					error = 1;
158 					continue;
159 				}
160 				f = field_by_name(sw->field_tab, argv[i]);
161 				if (f->flags & FLG_DEAD)
162 					continue;
163 				if ((f->flags & FLG_WRONLY) != 0) {
164 					warnx("%s: write only", argv[i]);
165 					continue;
166 				}
167 				f->flags |= FLG_GET;
168 				(*sw->getval)(sw->name, sw->fd);
169 				pr_field(sw->name, f, sep);
170 				continue;
171 			}
172 			if (p > argv[i] &&
173 			    (*(p - 1) == '+' || *(p - 1) == '-')) {
174 				do_merge = *(p - 1);
175 				*(p - 1) = '\0';
176 			} else
177 				do_merge = 0;
178 			*p++ = '\0';
179 			sw = tab_by_name(argv[i]);
180 			if (!sw)
181 				continue;
182 			if (sw->fd < 0 &&
183 			    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
184 			    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
185 				warn("open: %s", sw->file);
186 				error = 1;
187 				continue;
188 			}
189 			f = field_by_name(sw->field_tab, argv[i]);
190 			if (f->flags & FLG_DEAD)
191 				continue;
192 			if ((f->flags & FLG_RDONLY) != 0) {
193 				warnx("%s: read only", argv[i]);
194 				continue;
195 			}
196 			if (do_merge || f->flags & FLG_INIT) {
197 				if ((f->flags & FLG_MODIFY) == 0)
198 					errx(1, "%s: can only be set",
199 					     argv[i]);
200 				f->flags |= FLG_GET;
201 				(*sw->getval)(sw->name, sw->fd);
202 				f->flags &= ~FLG_GET;
203 			}
204 			rd_field(f, p, do_merge);
205 			f->flags |= FLG_SET;
206 			(*sw->putval)(sw->name, sw->fd);
207 			f->flags &= ~FLG_SET;
208 		}
209 	} else
210 		usage(NULL);
211 
212 	return (error);
213 }
214 
215 struct vartypesw *
216 tab_by_name(const char *var)
217 {
218 	struct vartypesw *sw;
219 	const char *p = strchr(var, '.');
220 
221 	if (!p) {
222 		warnx("%s: illegal variable name", var);
223 		return (NULL);
224 	}
225 
226 	for (sw = typesw; sw->name; sw++)
227 		if (!strncmp(sw->name, var, p - var))
228 			break;
229 
230 	if (!sw->name) {
231 		warnx("%s: no such variable", var);
232 		return (NULL);
233 	}
234 
235 	return (sw);
236 }
237