On Thu, Sep 29, 2016 at 02:19:43PM +0200, Mark Kettenis wrote: > This diff adds a WSKBDIO_GETENCODINGS ioctl and uses it to print a > list of supported encodings like the old kvm groveling code did. The > ioctl will clamp the number of entries that are returns to the number > that was passed in. This means that if the number returned is the > same as the number passed in, there might be more entries and you > probably want to retry with a larger buffer. The new implementation > does this. > > Waring; this did not go through a make release yet. And that might be > relevant, since this code gets included in the ramdisks. > > Thoughts? >
amd64 release builds fine with this patch. I tested it on both a normal system and with bsd.rd, works fine. I like the fact that extended keyboard encodings are now also listed in bsd.rd. There is one change of behavior: previously, if a non-root user ran kbd -l, it would exit with status 1 and print the error message: kbd: kvm_openfiles: /dev/mem: permission denied which gave at least some indication that it must be run as root. Now it fails silently with exit code 0 without printing anything since opening the /dev/wskbd? devices fails, as they are owned by root:wheel with permissions 600. Perhaps it would be appropriate to error out before calling kbd_list() if getuid() != 0. > Index: sys/dev/wscons/wsconsio.h > =================================================================== > RCS file: /cvs/src/sys/dev/wscons/wsconsio.h,v > retrieving revision 1.75 > diff -u -p -r1.75 wsconsio.h > --- sys/dev/wscons/wsconsio.h 14 Sep 2016 03:25:51 -0000 1.75 > +++ sys/dev/wscons/wsconsio.h 29 Sep 2016 12:10:57 -0000 > @@ -207,6 +207,12 @@ struct wskbd_backlight { > #define WSKBD_TRANSLATED 0 > #define WSKBD_RAW 1 > > +struct wskbd_encoding_data { > + int nencodings; > + kbd_t *encodings; > +}; > +#define WSKBDIO_GETENCODINGS _IOWR('W', 21, struct wskbd_encoding_data) > + > /* > * Mouse ioctls (32 - 63) > */ > Index: sys/dev/wscons/wskbd.c > =================================================================== > RCS file: /cvs/src/sys/dev/wscons/wskbd.c,v > retrieving revision 1.83 > diff -u -p -r1.83 wskbd.c > --- sys/dev/wscons/wskbd.c 12 Dec 2015 12:30:18 -0000 1.83 > +++ sys/dev/wscons/wskbd.c 29 Sep 2016 12:10:57 -0000 > @@ -1001,9 +1001,11 @@ wskbd_displayioctl(struct device *dev, u > struct wskbd_bell_data *ubdp, *kbdp; > struct wskbd_keyrepeat_data *ukdp, *kkdp; > struct wskbd_map_data *umdp; > + struct wskbd_encoding_data *uedp; > kbd_t enc; > void *buf; > int len, error; > + int count, i; > > switch (cmd) { > case WSKBDIO_BELL: > @@ -1159,6 +1161,20 @@ getkeyrepeat: > wsmux_set_layout(sc->sc_base.me_parent, enc); > #endif > return (0); > + > + case WSKBDIO_GETENCODINGS: > + uedp = (struct wskbd_encoding_data *)data; > + for (count = 0; sc->id->t_keymap.keydesc[count].name; count++) > + ; > + if (uedp->nencodings > count) > + uedp->nencodings = count; > + for (i = 0; i < uedp->nencodings; i++) { > + error = copyout(&sc->id->t_keymap.keydesc[i].name, > + &uedp->encodings[i], sizeof(kbd_t)); > + if (error) > + return (error); > + } > + return(0); > > case WSKBDIO_GETBACKLIGHT: > if (wskbd_get_backlight != NULL) > Index: sbin/kbd/kbd_wscons.c > =================================================================== > RCS file: /cvs/src/sbin/kbd/kbd_wscons.c,v > retrieving revision 1.30 > diff -u -p -r1.30 kbd_wscons.c > --- sbin/kbd/kbd_wscons.c 27 Sep 2016 22:03:49 -0000 1.30 > +++ sbin/kbd/kbd_wscons.c 29 Sep 2016 12:10:57 -0000 > @@ -34,6 +34,7 @@ > #include <fcntl.h> > #include <limits.h> > #include <stdio.h> > +#include <stdlib.h> > #include <string.h> > #include <unistd.h> > > @@ -82,31 +83,83 @@ struct nameint kbdvar_tab[] = { > > extern char *__progname; > > -void kbd_show_enc(int idx); > +void kbd_show_enc(struct wskbd_encoding_data *encs, int idx); > +void kbd_get_encs(int fd, struct wskbd_encoding_data *encs); > void kbd_list(void); > void kbd_set(char *name, int verbose); > > void > -kbd_show_enc(int idx) > +kbd_show_enc(struct wskbd_encoding_data *encs, int idx) > { > + int found; > + kbd_t encoding, variant; > + struct nameint *n; > int i; > > printf("tables available for %s keyboard:\nencoding\n\n", > kbtype_tab[idx]); > > - for (i = 0; kbdenc_tab[i].value; i++) > - printf("%s\n", kbdenc_tab[i].name); > + for (i = 0; i < encs->nencodings; i++) { > + n = &kbdenc_tab[0]; > + found = 0; > + encoding = encs->encodings[i]; > + while (n->value) { > + if (n->value == KB_ENCODING(encoding)) { > + printf("%s", n->name); > + found++; > + } > + n++; > + } > + if (found == 0) > + printf("<encoding 0x%04x>", KB_ENCODING(encoding)); > + n = &kbdvar_tab[0]; > + found = 0; > + variant = KB_VARIANT(encoding); > + while (n->value) { > + if ((n->value & KB_VARIANT(encoding)) == n->value) { > + printf(".%s", n->name); > + variant &= ~n->value; > + } > + n++; > + } > + if (variant != 0) > + printf(".<variant 0x%08x>", variant); > + printf("\n"); > + } > printf("\n"); > } > > void > +kbd_get_encs(int fd, struct wskbd_encoding_data *encs) > +{ > + int nencodings = 64; > + > + encs->nencodings = nencodings; > + while (encs->nencodings == nencodings) { > + encs->encodings = reallocarray(encs->encodings, > + encs->nencodings, sizeof(kbd_t)); > + if (encs->encodings == NULL) > + err(1, "reallocarray"); > + if (ioctl(fd, WSKBDIO_GETENCODINGS, encs) < 0) > + err(1, "WSKBDIO_GETENCODINGS"); > + if (encs->nencodings == nencodings) { > + nencodings *= 2; > + encs->nencodings = nencodings; > + } > + } > +} > + > +void > kbd_list(void) > { > int kbds[SA_MAX]; > - int fd, i, kbtype; > + struct wskbd_encoding_data encs[SA_MAX]; > + int fd, i, kbtype, t; > char device[PATH_MAX]; > + int j; > > - bzero(kbds, sizeof(kbds)); > + memset(kbds, 0, sizeof(kbds)); > + memset(encs, 0, sizeof(encs)); > > /* Go through all keyboards. */ > for (i = 0; i < NUM_KBD; i++) { > @@ -120,41 +173,50 @@ kbd_list(void) > switch (kbtype) { > case WSKBD_TYPE_PC_XT: > case WSKBD_TYPE_PC_AT: > - kbds[SA_PCKBD]++; > + t = SA_PCKBD; > break; > case WSKBD_TYPE_USB: > - kbds[SA_UKBD]++; > + t = SA_UKBD; > break; > case WSKBD_TYPE_ADB: > - kbds[SA_AKBD]++; > + t = SA_AKBD; > break; > case WSKBD_TYPE_LK201: > case WSKBD_TYPE_LK401: > - kbds[SA_LKKBD]++; > + t = SA_LKKBD; > break; > case WSKBD_TYPE_SUN: > - kbds[SA_SUNKBD]++; > + t = SA_SUNKBD; > break; > case WSKBD_TYPE_SUN5: > - kbds[SA_SUN5KBD]++; > + t = SA_SUN5KBD; > break; > case WSKBD_TYPE_HIL: > - kbds[SA_HILKBD]++; > + t = SA_HILKBD; > break; > case WSKBD_TYPE_GSC: > - kbds[SA_GSCKBD]++; > + t = SA_GSCKBD; > break; > case WSKBD_TYPE_SGI: > - kbds[SA_SGIKBD]++; > + t = SA_SGIKBD; > + break; > + default: > + t = SA_MAX; > break; > }; > + > + if (t != SA_MAX) { > + kbds[t]++; > + if (encs[t].encodings == NULL) > + kbd_get_encs(fd, &encs[t]); > + } > close(fd); > } > } > > for (i = 0; i < SA_MAX; i++) > if (kbds[i] != 0) > - kbd_show_enc(i); > + kbd_show_enc(&encs[i], i); > } > > void >