xref: /openbsd/sbin/wsconsctl/wsconsctl.c (revision 2b93bd72)
1 /*	$OpenBSD: wsconsctl.c,v 1.14 2004/06/23 07:37:23 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] 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;
98 	char *sep, *p;
99 	struct vartypesw *sw;
100 	struct field *f;
101 	int do_merge;
102 
103 	error = aflag = 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 			/* compat */
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 
129 	if (aflag != 0) {
130 		for (sw = typesw; sw->name; sw++) {
131 			if (sw->fd < 0 &&
132 			    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
133 			    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
134 				warn("%s", sw->file);
135 				error = 1;
136 				continue;
137 			}
138 			for (f = sw->field_tab; f->name; f++)
139 				if ((f->flags & (FLG_NOAUTO|FLG_WRONLY)) == 0)
140 					f->flags |= FLG_GET;
141 			(*sw->getval)(sw->name, sw->fd);
142 			for (f = sw->field_tab; f->name; f++)
143 				if (f->flags & FLG_DEAD)
144 					continue;
145 				else if (f->flags & FLG_NOAUTO)
146 					warnx("Use explicit arg to view %s.%s.",
147 					      sw->name, f->name);
148 				else if (f->flags & FLG_GET)
149 					pr_field(sw->name, f, sep);
150 		}
151 	} else if (argc > 0) {
152 		for (i = 0; i < argc; i++) {
153 			p = strchr(argv[i], '=');
154 			if (p == NULL) {
155 				sw = tab_by_name(argv[i]);
156 				if (!sw)
157 					continue;
158 				if (sw->fd < 0 &&
159 				    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
160 				    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
161 					warn("open: %s", sw->file);
162 					error = 1;
163 					continue;
164 				}
165 				f = field_by_name(sw->field_tab, argv[i]);
166 				if (f->flags & FLG_DEAD)
167 					continue;
168 				if ((f->flags & FLG_WRONLY) != 0) {
169 					warnx("%s: write only", argv[i]);
170 					continue;
171 				}
172 				f->flags |= FLG_GET;
173 				(*sw->getval)(sw->name, sw->fd);
174 				pr_field(sw->name, f, sep);
175 				continue;
176 			}
177 			if (p > argv[i] &&
178 			    (*(p - 1) == '+' || *(p - 1) == '-')) {
179 				do_merge = *(p - 1);
180 				*(p - 1) = '\0';
181 			} else
182 				do_merge = 0;
183 			*p++ = '\0';
184 			sw = tab_by_name(argv[i]);
185 			if (!sw)
186 				continue;
187 			if (sw->fd < 0 &&
188 			    (sw->fd = open(sw->file, O_WRONLY)) < 0 &&
189 			    (sw->fd = open(sw->file, O_RDONLY)) < 0) {
190 				warn("open: %s", sw->file);
191 				error = 1;
192 				continue;
193 			}
194 			f = field_by_name(sw->field_tab, argv[i]);
195 			if (f->flags & FLG_DEAD)
196 				continue;
197 			if ((f->flags & FLG_RDONLY) != 0) {
198 				warnx("%s: read only", argv[i]);
199 				continue;
200 			}
201 			if (do_merge || f->flags & FLG_INIT) {
202 				if ((f->flags & FLG_MODIFY) == 0)
203 					errx(1, "%s: can only be set",
204 					     argv[i]);
205 				f->flags |= FLG_GET;
206 				(*sw->getval)(sw->name, sw->fd);
207 				f->flags &= ~FLG_GET;
208 			}
209 			rd_field(f, p, do_merge);
210 			f->flags |= FLG_SET;
211 			(*sw->putval)(sw->name, sw->fd);
212 			f->flags &= ~FLG_SET;
213 		}
214 	} else
215 		usage(NULL);
216 
217 	return (error);
218 }
219 
220 struct vartypesw *
221 tab_by_name(const char *var)
222 {
223 	struct vartypesw *sw;
224 	const char *p = strchr(var, '.');
225 
226 	if (!p) {
227 		warnx("%s: illegal variable name", var);
228 		return (NULL);
229 	}
230 
231 	for (sw = typesw; sw->name; sw++)
232 		if (!strncmp(sw->name, var, p - var))
233 			break;
234 
235 	if (!sw->name) {
236 		warnx("%s: no such variable", var);
237 		return (NULL);
238 	}
239 
240 	return (sw);
241 }
242