> Date: Sat, 22 Feb 2020 12:44:12 +0100 > From: Stefan Sperling <s...@stsp.name> > > This is another attempt at improving usability with non-ASCII network IDs. > > Previous attempts have been rejected in part because entering UTF-8 strings > is difficult to do for Americans and, to a lesser extent, Canadians. > > It occurred to me that the real issue might have been that previous attempts > were erasing the hex string representation in favour of UTF-8, instead of > amending the hex string with a human-readable representation of that string. > > With the diff below ifconfig shows both representations, provided the UTF-8 > locale is active and the string can be successfully decoded, and fits NWID > length restrictions, and contains printable Unicode only. > > We still need to enter a hex ID to use a network, but at least it becomes > much easier to tell which one to use. > > Before: > > $ ifconfig iwm0 scan > iwm0: flags=808843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,AUTOCONF4> mtu 1500 > [...] > nwid 0x6162616374c3a97269c3a96d69717565 chan 4 bssid > xx:xx:xx:xx:xx:xx 68% HT-MCS7 privacy,short_preamble,short_slottime,wpa2 > nwid 0x00000000000000000000000000000000000000000000 chan 6 > bssid xx:xx:xx:xx:xx:xx 25% HT-MCS15 privacy,short_slottime,wpa2 > > > After: > > $ ifconfig iwm0 scan iwm0: > flags=808843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,AUTOCONF4> mtu 1500 > [...] > nwid 0x6162616374c3a97269c3a96d69717565 ("abactériémique") chan > 4 bssid xx:xx:xx:xx:xx:xx 68% HT-MCS7 > privacy,short_preamble,short_slottime,wpa2 > nwid 0x00000000000000000000000000000000000000000000 chan 6 > bssid xx:xx:xx:xx:xx:xx 25% HT-MCS15 privacy,short_slottime,wpa2 > > > I'm making the man page point out that 'ifconfig nwid' accepts only > *printable ASCII* strings or hex. Based on that it should be clear what > the user needs to do with information shown in the scan result list. > > This feature also works with 'ifconfig joinlist'. While here fix a bug > where non-ASCII IDs on this list were improperly truncated to 32 columns > when displayed. The hexstring can be up to 66 colomns in length so capping > joinlist SSIDs to IEEE80211_NWID_LEN - 1 columns is wrong. > A human-readable representation needs additional space to be displayed. > > Since print_string() and len_string() are only used with NWIDs nowadays I > am renaming them to print_nwid() and width_nwid() (the latter function is > being used to compute a display width, not a string length in bytes). > > Is this acceptable or are there objections to the idea?
IMHO it is a bad idea to make the output of ifconfig locale-dependent. > diff c20bd74017ceeadb2db0f78a352ed1f1e2b77c2b /usr/src > blob - 3fb0780ba7cf1333894f5c3485a95e71885fbd6d > file + sbin/ifconfig/ifconfig.8 > --- sbin/ifconfig/ifconfig.8 > +++ sbin/ifconfig/ifconfig.8 > @@ -972,8 +972,9 @@ list if they are found during a scan. > .Pp > The > .Ar id > -can either be any text string up to 32 characters in length, > -or a series of hexadecimal digits up to 64 digits. > +can either be a printable ASCII string up to 32 characters in length, > +or a series of hexadecimal digits up to 64 digits preceded by > +.Dq 0x . > If > .Ar id > is the empty string > @@ -1077,6 +1078,12 @@ Remove specified flag. > .It Cm nwid Ar id > Connect to the network with NWID/ESSID > .Ar id . > +The > +.Ar id > +can either be a printable ASCII string up to 32 characters in length, > +or a series of hexadecimal digits up to 64 digits preceded by > +.Dq 0x . > +.Pp > Unlike > .Cm join , > the > blob - e1dc9dbb07bf109c3ec7f5fd4d851a7dbb5692f1 > file + sbin/ifconfig/ifconfig.c > --- sbin/ifconfig/ifconfig.c > +++ sbin/ifconfig/ifconfig.c > @@ -110,6 +110,12 @@ > #ifndef SMALL > #include <dev/usb/mbim.h> > #include <dev/usb/if_umb.h> > + > +/* UTF-8 support */ > +#include <langinfo.h> > +#include <locale.h> > +#include <wctype.h> > +#include <wchar.h> > #endif /* SMALL */ > > #include "ifconfig.h" > @@ -156,6 +162,7 @@ struct ifaliasreq addreq; > > int wconfig = 0; > int wcwconfig = 0; > +int is_utf8_locale = 0; > #endif /* SMALL */ > > char ifname[IFNAMSIZ]; > @@ -654,8 +661,9 @@ const char *get_linkstate(int, int); > void status(int, struct sockaddr_dl *, int); > __dead void usage(void); > const char *get_string(const char *, const char *, u_int8_t *, int *); > -int len_string(const u_int8_t *, int); > -int print_string(const u_int8_t *, int); > +int utf8_nwid(const u_int8_t *, int); > +int width_nwid(const u_int8_t *, int); > +int print_nwid(const u_int8_t *, int); > char *sec2str(time_t); > > const char *get_media_type_string(uint64_t); > @@ -731,6 +739,10 @@ main(int argc, char *argv[]) > int found_rulefile = 0; > int i; > > +#ifndef SMALL > + setlocale(LC_CTYPE, ""); > + is_utf8_locale = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0); > +#endif > /* If no args at all, print all interfaces. */ > if (argc < 2) { > /* no filesystem visibility */ > @@ -1678,9 +1690,44 @@ get_string(const char *val, const char *sep, u_int8_t > return val; > } > > +/* > + * Attempt to create a human-readable representation of an NWID in UTF-8. > + * Return the width of the representation (amount of terminal columns used) > + * and optionally print to stdout. > + */ > int > -len_string(const u_int8_t *buf, int len) > +utf8_nwid(const u_int8_t *buf, int print_nwid) > { > +#ifndef SMALL > + wchar_t wcid[IEEE80211_NWID_LEN + 1]; > + size_t nwc; > + int width, i; > + > + if (!is_utf8_locale) > + return 0; > + > + nwc = mbstowcs(wcid, buf, IEEE80211_NWID_LEN); > + if (nwc == (size_t)-1 || nwc > IEEE80211_NWID_LEN) > + return 0; > + wcid[nwc] = L'\0'; > + for (i = 0; i < nwc; i++) { > + if (!iswprint(wcid[i])) > + return 0; > + } > + width = wcswidth(wcid, IEEE80211_NWID_LEN); > + if (width == 0 || width == -1) > + return 0; > + if (print_nwid) > + printf(" (\"%ls\")", wcid); > + return width + 5; > +#else > + return 0; > +#endif > +} > + > +int > +width_nwid(const u_int8_t *buf, int len) > +{ > int i = 0, hasspc = 0; > > if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { > @@ -1698,11 +1745,11 @@ len_string(const u_int8_t *buf, int len) > else > return len; > } else > - return (len * 2) + 2; > + return (len * 2) + 2 + utf8_nwid(buf, 0); > } > > int > -print_string(const u_int8_t *buf, int len) > +print_nwid(const u_int8_t *buf, int len) > { > int i = 0, hasspc = 0; > > @@ -1727,7 +1774,7 @@ print_string(const u_int8_t *buf, int len) > printf("0x"); > for (i = 0; i < len; i++) > printf("%02x", buf[i]); > - return (len * 2) + 2; > + return (len * 2) + 2 + utf8_nwid(buf, 1); > } > } > > @@ -2440,7 +2487,7 @@ ieee80211_status(void) > fputs(" join ", stdout); > else > fputs(" nwid ", stdout); > - print_string(nwid.i_nwid, len); > + print_nwid(nwid.i_nwid, len); > } > > if (ichan == 0 && channel.i_channel != 0 && > @@ -2571,18 +2618,16 @@ join_status(void) > > maxlen = 0; > for (i = 0; i < ja.ja_nodes; i++) { > - len = len_string(jn[i].i_nwid, jn[i].i_len); > + len = width_nwid(jn[i].i_nwid, jn[i].i_len); > if (len > maxlen) > maxlen = len; > } > - if (maxlen > IEEE80211_NWID_LEN) > - maxlen = IEEE80211_NWID_LEN - 1; > > for (i = 0; i < ja.ja_nodes; i++) { > printf("\t "); > if (jn[i].i_len > IEEE80211_NWID_LEN) > jn[i].i_len = IEEE80211_NWID_LEN; > - len = print_string(jn[i].i_nwid, jn[i].i_len); > + len = print_nwid(jn[i].i_nwid, jn[i].i_len); > printf("%-*s", maxlen - len, " "); > if (jn[i].i_flags) { > const char *sep; > @@ -2717,7 +2762,7 @@ ieee80211_printnode(struct ieee80211_nodereq *nr) > if (len > IEEE80211_NWID_LEN) > len = IEEE80211_NWID_LEN; > printf("nwid "); > - print_string(nr->nr_nwid, len); > + print_nwid(nr->nr_nwid, len); > putchar(' '); > > printf("chan %u ", nr->nr_channel); > >