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