xref: /openbsd/sbin/wsconsctl/wsconsctl.c (revision b1b7cd8f)
1 /*	$OpenBSD: wsconsctl.c,v 1.13 2003/07/10 00:00:58 david 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] name ...\n"
86 	    "       %s [-n] -w name=value ...\n"
87 	    "       %s [-n] -a\n", __progname,
88 		__progname, __progname);
89 
90 	exit(1);
91 }
92 
93 int
94 main(int argc, char *argv[])
95 {
96 	int i, ch, error;
97 	int aflag, wflag;
98 	char *sep, *p;
99 	struct vartypesw *sw;
100 	struct field *f;
101 	int do_merge;
102 
103 	error = aflag = wflag = 0;
104 	sw = NULL;
105 	sep = "=";
106 
107 	while ((ch = getopt(argc, argv, "anw")) != -1) {
108 		switch(ch) {
109 		case 'a':
110 			aflag = 1;
111 			break;
112 		case 'n':
113 			sep = NULL;
114 			break;
115 		case 'w':
116 			wflag = 1;
117 			break;
118 		default:
119 			usage(NULL);
120 		}
121 	}
122 
123 	argc -= optind;
124 	argv += optind;
125 
126 	if (argc > 0 && aflag != 0)
127 		usage("excess arguments after -a");
128 	if (aflag != 0 && wflag != 0)
129 		usage("only one of -a or -w may be given");
130 
131 	if (aflag != 0) {
132 		for (sw = typesw; sw->name; sw++) {
133 			if (sw->fd < 0 &&
134 			    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
135 			    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
136 				warn("%s", sw->file);
137 				error = 1;
138 				continue;
139 			}
140 			for (f = sw->field_tab; f->name; f++)
141 				if ((f->flags & (FLG_NOAUTO|FLG_WRONLY)) == 0)
142 					f->flags |= FLG_GET;
143 			(*sw->getval)(sw->name, sw->fd);
144 			for (f = sw->field_tab; f->name; f++)
145 				if (f->flags & FLG_DEAD)
146 					continue;
147 				else if (f->flags & FLG_NOAUTO)
148 					warnx("Use explicit arg to view %s.%s.",
149 					      sw->name, f->name);
150 				else if (f->flags & FLG_GET)
151 					pr_field(sw->name, f, sep);
152 		}
153 	} else if (argc > 0) {
154 		if (wflag != 0)
155 			for (i = 0; i < argc; i++) {
156 				p = strchr(argv[i], '=');
157 				if (p == NULL) {
158 					warnx("'=' not found");
159 					continue;
160 				}
161 				if (p > argv[i] &&
162 				    (*(p - 1) == '+' || *(p - 1) == '-')) {
163 					do_merge = *(p - 1);
164 					*(p - 1) = '\0';
165 				} else
166 					do_merge = 0;
167 				*p++ = '\0';
168 				sw = tab_by_name(argv[i]);
169 				if (!sw)
170 					continue;
171 				if (sw->fd < 0 &&
172 				    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
173 				    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
174 					warn("open: %s", sw->file);
175 					error = 1;
176 					continue;
177 				}
178 				f = field_by_name(sw->field_tab, argv[i]);
179 				if (f->flags & FLG_DEAD)
180 					continue;
181 				if ((f->flags & FLG_RDONLY) != 0) {
182 					warnx("%s: read only", argv[i]);
183 					continue;
184 				}
185 				if (do_merge || f->flags & FLG_INIT) {
186 					if ((f->flags & FLG_MODIFY) == 0)
187 						errx(1, "%s: can only be set",
188 						     argv[i]);
189 					f->flags |= FLG_GET;
190 					(*sw->getval)(sw->name, sw->fd);
191 					f->flags &= ~FLG_GET;
192 				}
193 				rd_field(f, p, do_merge);
194 				f->flags |= FLG_SET;
195 				(*sw->putval)(sw->name, sw->fd);
196 				f->flags &= ~FLG_SET;
197 			}
198 		else
199 			for (i = 0; i < argc; i++) {
200 				sw = tab_by_name(argv[i]);
201 				if (!sw)
202 					continue;
203 				if (sw->fd < 0 &&
204 				    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
205 				    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
206 					warn("open: %s", sw->file);
207 					error = 1;
208 					continue;
209 				}
210 				f = field_by_name(sw->field_tab, argv[i]);
211 				if (f->flags & FLG_DEAD)
212 					continue;
213 				if ((f->flags & FLG_WRONLY) != 0) {
214 					warnx("%s: write only", argv[i]);
215 					continue;
216 				}
217 				f->flags |= FLG_GET;
218 				(*sw->getval)(sw->name, sw->fd);
219 				pr_field(sw->name, f, sep);
220 			}
221 	} else
222 		usage(NULL);
223 
224 	return (error);
225 }
226 
227 struct vartypesw *
228 tab_by_name(const char *var)
229 {
230 	struct vartypesw *sw;
231 	const char *p = strchr(var, '.');
232 
233 	if (!p) {
234 		warnx("%s: illegal variable name", var);
235 		return (NULL);
236 	}
237 
238 	for (sw = typesw; sw->name; sw++)
239 		if (!strncmp(sw->name, var, p - var))
240 			break;
241 
242 	if (!sw->name) {
243 		warnx("%s: no such variable", var);
244 		return (NULL);
245 	}
246 
247 	return (sw);
248 }
249