For one: Tobias Stoeckmann already stated more yesterday,
including that exit(3) in a signal handler is a bad thing.
(It surely should have been _exit(2).)
Version 3 (1) doesn't trash errno no more, (2) is hopefully less
messy and (3) does no longer introduce a new file, so also more
easyness for cvs(1).
It fixes a compiler warning in tab_by_name().
Beside that: :c
Thank you very much.
--steffen
Index: src/sbin/wsconsctl/wsconsctl.8
===================================================================
RCS file: /cvs/src/sbin/wsconsctl/wsconsctl.8,v
retrieving revision 1.23
diff -a -p -u -r1.23 wsconsctl.8
--- wsconsctl.8 4 Aug 2008 07:32:51 -0000 1.23
+++ wsconsctl.8 1 Feb 2012 14:41:11 -0000
@@ -49,6 +49,8 @@
.Op Fl n
.Op Fl f Ar file
.Ar name Ns += Ns Ar value ...
+.Nm wsconsctl
+.Fl r
.Sh DESCRIPTION
The
.Nm
@@ -81,6 +83,12 @@ symbol.
See the
.Sx EXAMPLES
section for more details.
+.It Fl r
+Enters a raw interactive mode in which keypresses are displayed
+as their keycodes.
+This mode always operates on standard input
+and does not work on pseudo terminals.
+After five seconds of inactivity the program terminates.
.El
.Pp
The
Index: src/sbin/wsconsctl/wsconsctl.c
===================================================================
RCS file: /cvs/src/sbin/wsconsctl/wsconsctl.c,v
retrieving revision 1.26
diff -a -p -u -r1.26 wsconsctl.c
--- wsconsctl.c 20 Aug 2010 00:20:55 -0000 1.26
+++ wsconsctl.c 1 Feb 2012 14:48:27 -0000
@@ -30,12 +30,18 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsksymdef.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>
+#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <termios.h>
#include <unistd.h>
#include "wsconsctl.h"
@@ -45,9 +51,7 @@ extern struct field keyboard_field_tab[]
extern struct field mouse_field_tab[];
extern struct field display_field_tab[];
-void usage(void);
-
-struct vartypesw {
+static struct vartypesw {
const char *name;
struct field *field_tab;
void (*getval)(int);
@@ -63,24 +67,15 @@ struct vartypesw {
{ NULL }
};
-struct vartypesw *tab_by_name(const char *, int *);
-
-void
-usage()
-{
- fprintf(stderr,
- "usage: %s [-an]\n"
- " %s [-n] [-f file] name ...\n"
- " %s [-n] [-f file] name=value ...\n"
- " %s [-n] [-f file] name+=value ...\n",
- __progname, __progname, __progname, __progname);
- exit(1);
-}
+static void usage(void);
+static struct vartypesw *tab_by_name(const char *, int *);
+static int raw_mode(void);
int
main(int argc, char *argv[])
{
- int i, ch, error = 0, aflag = 0, do_merge, putval, devidx, devfd;
+ int i, ch, error = 0, aflag = 0, rflag = 0,
+ do_merge, putval, devidx, devfd;
struct vartypesw *sw = NULL;
char *getsep = "=", *setsep = " -> ", *p;
char *wdev = NULL;
@@ -88,7 +83,7 @@ main(int argc, char *argv[])
struct field *f;
char devname[20];
- while ((ch = getopt(argc, argv, "af:nw")) != -1) {
+ while ((ch = getopt(argc, argv, "af:nrw")) != -1) {
switch(ch) {
case 'a':
aflag = 1;
@@ -99,6 +94,9 @@ main(int argc, char *argv[])
case 'n':
getsep = setsep = NULL;
break;
+ case 'r':
+ rflag = 1;
+ break;
case 'w':
/* compat */
break;
@@ -110,12 +108,17 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (argc > 0 && aflag != 0)
- errx(1, "excess arguments after -a");
- if (argc == 0)
- aflag = 1;
+ if (argc > 0 && (aflag != 0 || rflag != 0))
+ errx(1, "excess arguments after -%c", (aflag ? 'a' : 'r'));
+ if (rflag == 0) {
+ if (argc == 0)
+ aflag = 1;
+ } else if (aflag != 0 || wdev != NULL || getsep == NULL)
+ errx(1, "-r is mutual exclusive with other options");
- if (aflag != 0) {
+ if (rflag != 0)
+ error = raw_mode();
+ else if (aflag != 0) {
for (sw = typesw; sw->name; sw++) {
for (devidx = 0;; devidx++) {
device = (*sw->nextdev)(devidx);
@@ -280,7 +283,20 @@ main(int argc, char *argv[])
exit(error);
}
-struct vartypesw *
+static void
+usage()
+{
+ fprintf(stderr,
+ "usage: %s [-an]\n"
+ " %s [-n] [-f file] name ...\n"
+ " %s [-n] [-f file] name=value ...\n"
+ " %s [-n] [-f file] name+=value ...\n"
+ " %s -r\n",
+ __progname, __progname, __progname, __progname, __progname);
+ exit(1);
+}
+
+static struct vartypesw *
tab_by_name(const char *var, int *idx)
{
struct vartypesw *sw;
@@ -295,13 +311,13 @@ tab_by_name(const char *var, int *idx)
if (!p)
p = strchr(var, '\0');
+ i = (int)(p - var);
if (!sw->name) {
- i = p - var;
warnx("%*.*s: no such variable", i, i, var);
return (NULL);
}
- if ((p - var) > strlen(sw->name)) {
+ if ((size_t)i > strlen(sw->name)) {
c = (char *)var;
c = c + strlen(sw->name);
i = 0;
@@ -324,3 +340,104 @@ tab_by_name(const char *var, int *idx)
return (sw);
}
+
+static int raw_caught_sig;
+static struct termios raw_tios_orig, raw_tios_raw;
+
+static void raw_onsig(int sig);
+static void raw_on(void), raw_off(void);
+
+int
+raw_mode(void)
+{
+ ssize_t i, skip;
+ struct sigaction sa;
+ struct itimerval it;
+ unsigned char *cursor, buffer[64];
+
+ if (tcgetattr(STDIN_FILENO, &raw_tios_orig) < 0)
+ err(1, "Can't query terminal attributes");
+ raw_tios_raw = raw_tios_orig;
+ (void)cfmakeraw(&raw_tios_raw);
+
+ sa.sa_handler = &raw_onsig;
+ sa.sa_flags = 0;
+ (void)sigfillset(&sa.sa_mask);
+ for (i = 0; i++ < NSIG;)
+ if (sigaction((int)i, &sa, NULL) < 0 && i == SIGALRM)
+ err(1, "Can't install SIGALRM signal handler");
+
+ it.it_value.tv_sec = 5;
+ it.it_value.tv_usec = 0;
+ it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
+
+ raw_on();
+ (void)printf("You may now use the keyboard.\r\n"
+ "After %d seconds of inactivity the program terminates\r\n",
+ (int)it.it_value.tv_sec);
+ for (i = skip = 0;;) {
+ if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
+ raw_off();
+ err(1, "Can't install wakeup timer");
+ }
+
+ i = read(STDIN_FILENO, buffer + skip, sizeof(buffer) - skip);
+ if (i <= 0)
+ break;
+ i += skip;
+
+ for (cursor = buffer; --i >= 0;) {
+ unsigned int k = *cursor++;
+ if ((k & 0xF0) == 0xE0 || (k & 0xF8) == 0xF0) {
+ if (--i < 0) {
+ buffer[0] = (unsigned char)k;
+ skip = 1;
+ break;
+ }
+ k <<= 8;
+ k |= *cursor++;
+ k &= ((k & 0xF000) == 0xE000) ? 0x0FFF : 0x00FF;
+ }
+ (void)printf("keycode %3u %-7s\r\n",
+ (k & ~0x0080), (k & 0x0080) ? "release" : "press");
+ skip = 0;
+ }
+ }
+ raw_off();
+
+ return (raw_caught_sig < 2);
+}
+
+static void
+raw_onsig(int sig)
+{
+ raw_caught_sig = 1 + (sig == SIGALRM);
+}
+
+static void
+raw_on(void)
+{
+ int arg = WSKBD_RAW;
+
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_tios_raw) < 0)
+ err(1, "Can't set terminal attributes");
+ if (ioctl(STDIN_FILENO, WSKBDIO_SETMODE, &arg) < 0) {
+ arg = errno;
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &raw_tios_orig);
+ errx(1, ((arg == ENOTTY)
+ ? "This mode won't work on pseudo terminals"
+ : "Can't put keyboard in raw mode (the "
+ "WSDISPLAY_COMPAT_RAWKBD kernel option is required)"));
+ }
+ return;
+}
+
+static void
+raw_off(void)
+{
+ int arg = WSKBD_TRANSLATED;
+
+ (void)ioctl(STDIN_FILENO, WSKBDIO_SETMODE, &arg);
+ (void)tcsetattr(STDIN_FILENO, TCSANOW, &raw_tios_orig);
+ return;
+}