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
> 

Reply via email to