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
>