1/*	$NetBSD: wsconsctl.c,v 1.17 2008/04/28 20:23:09 martin Exp $ */
2
3/*-
4 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Juergen Hannken-Illjes.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33#include <err.h>
34#include <fcntl.h>
35#include <string.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <unistd.h>
39
40#include "wsconsctl.h"
41
42#define PATH_KEYBOARD		"/dev/wskbd"
43#define PATH_MOUSE		"/dev/wsmouse"
44#define PATH_DISPLAY		"/dev/ttyE0"
45
46extern struct field keyboard_field_tab[];
47extern struct field mouse_field_tab[];
48extern struct field display_field_tab[];
49extern int keyboard_field_tab_len;
50extern int mouse_field_tab_len;
51extern int display_field_tab_len;
52
53static void usage(const char *) __dead;
54
55static void
56usage(const char *msg)
57{
58	const char *progname = getprogname();
59
60	if (msg != NULL)
61		(void)fprintf(stderr, "%s: %s\n\n", progname, msg);
62
63	(void)fprintf(stderr,
64	    "Usage: %s [-kmd] [-f file] [-n] name ...\n"
65	    " -or-  %s [-kmd] [-f file] [-n] -w name=value ...\n"
66	    " -or-  %s [-kmd] [-f file] [-n] -w name+=value ...\n"
67	    " -or-  %s [-kmd] [-f file] [-n] -a\n",
68	    progname, progname, progname, progname);
69
70	exit(EXIT_FAILURE);
71}
72
73int
74main(int argc, char **argv)
75{
76	int i, ch, fd;
77	int aflag, dflag, kflag, mflag, wflag;
78	char *p;
79	const char *sep, *file;
80	struct field *f, *field_tab;
81	int do_merge, field_tab_len;
82	void (*getval)(int);
83	void (*putval)(int);
84
85	aflag = 0;
86	dflag = 0;
87	kflag = 0;
88	mflag = 0;
89	wflag = 0;
90	file = NULL;
91	sep = "=";
92	field_tab = NULL;
93	field_tab_len = 0;
94	getval = NULL;
95	putval = NULL;
96
97	while ((ch = getopt(argc, argv, "adf:kmnw")) != -1) {
98		switch(ch) {
99		case 'a':
100			aflag = 1;
101			break;
102		case 'd':
103			dflag = 1;
104			break;
105		case 'f':
106			file = optarg;
107			break;
108		case 'k':
109			kflag = 1;
110			break;
111		case 'm':
112			mflag = 1;
113			break;
114		case 'n':
115			sep = NULL;
116			break;
117		case 'w':
118			wflag = 1;
119			break;
120		case '?':
121		default:
122			usage(NULL);
123		}
124	}
125
126	argc -= optind;
127	argv += optind;
128
129	if (dflag + kflag + mflag == 0)
130		kflag = 1;
131	if (dflag + kflag + mflag > 1)
132		usage("only one of -k, -d or -m may be given");
133	if (argc > 0 && aflag != 0)
134		usage("excess arguments after -a");
135	if (aflag != 0 && wflag != 0)
136		usage("only one of -a or -w may be given");
137
138	if (kflag) {
139		if (file == NULL)
140			file = PATH_KEYBOARD;
141		field_tab = keyboard_field_tab;
142		field_tab_len = keyboard_field_tab_len;
143		getval = keyboard_get_values;
144		putval = keyboard_put_values;
145	} else if (mflag) {
146		if (file == NULL)
147			file = PATH_MOUSE;
148		field_tab = mouse_field_tab;
149		field_tab_len = mouse_field_tab_len;
150		getval = mouse_get_values;
151		putval = mouse_put_values;
152	} else if (dflag) {
153		if (file == NULL)
154			file = PATH_DISPLAY;
155		field_tab = display_field_tab;
156		field_tab_len = display_field_tab_len;
157		getval = display_get_values;
158		putval = display_put_values;
159	}
160
161	field_setup(field_tab, field_tab_len);
162
163	fd = open(file, O_WRONLY);
164	if (fd < 0)
165		fd = open(file, O_RDONLY);
166	if (fd < 0)
167		err(EXIT_FAILURE, "%s", file);
168
169	if (aflag != 0) {
170		for (i = 0; i < field_tab_len; i++)
171			if ((field_tab[i].flags & (FLG_NOAUTO|FLG_WRONLY)) == 0)
172				field_tab[i].flags |= FLG_GET;
173		(*getval)(fd);
174		for (i = 0; i < field_tab_len; i++)
175			if (field_tab[i].flags & FLG_NOAUTO)
176				warnx("\"%s\" not shown with -a; use \"%s %s\""
177				    " to view.",
178				    field_tab[i].name,
179				    getprogname(), field_tab[i].name);
180			else if (field_tab[i].flags & FLG_GET &&
181				 !(field_tab[i].flags & FLG_DISABLED))
182				pr_field(field_tab + i, sep);
183	} else if (argc > 0) {
184		if (wflag != 0) {
185			for (i = 0; i < argc; i++) {
186				p = strchr(argv[i], '=');
187				if (p == NULL)
188					errx(EXIT_FAILURE, "'=' not found");
189				if (p > argv[i] && *(p - 1) == '+') {
190					*(p - 1) = '\0';
191					do_merge = 1;
192				} else
193					do_merge = 0;
194				*p++ = '\0';
195				f = field_by_name(argv[i]);
196				if ((f->flags & FLG_RDONLY) != 0)
197					errx(EXIT_FAILURE, "%s: read only",
198					    argv[i]);
199				if (do_merge) {
200					if ((f->flags & FLG_MODIFY) == 0)
201						errx(EXIT_FAILURE,
202						    "%s: can only be set",
203						    argv[i]);
204					f->flags |= FLG_GET;
205					(*getval)(fd);
206					f->flags &= ~FLG_GET;
207				}
208				rd_field(f, p, do_merge);
209				f->flags |= FLG_SET;
210				(*putval)(fd);
211				f->flags &= ~FLG_SET;
212			}
213		} else {
214			for (i = 0; i < argc; i++) {
215				f = field_by_name(argv[i]);
216				if ((f->flags & FLG_WRONLY) != 0)
217					errx(EXIT_FAILURE, "%s: write only",
218					    argv[i]);
219				f->flags |= FLG_GET;
220			}
221			(*getval)(fd);
222			for (i = 0; i < field_tab_len; i++) {
223				if (field_tab[i].flags & FLG_DISABLED)
224					errx(EXIT_FAILURE,
225					    "%s: no kernel support",
226					    field_tab[i].name);
227				if (field_tab[i].flags & FLG_GET)
228					pr_field(field_tab + i, sep);
229			}
230		}
231	} else {
232		close(fd);
233		usage(NULL);
234	}
235
236	close(fd);
237
238	return EXIT_SUCCESS;
239}
240