Date: Thu, 22 Aug 2019 20:01:16 -0700 From: Conrad Meyer <cem@freebsd.org> To: Eugene Grosbein <eugen@freebsd.org> Cc: src-committers <src-committers@freebsd.org>, svn-src-all <svn-src-all@freebsd.org>, svn-src-head <svn-src-head@freebsd.org> Subject: Re: svn commit: r351413 - head/usr.bin/last Message-ID: <CAG6CVpXFtrfrdTJporKx%2BBXif1%2BL-pH_WAzDN%2BB78yugTy7cCA@mail.gmail.com> In-Reply-To: <201908230125.x7N1PdTN070890@repo.freebsd.org> References: <201908230125.x7N1PdTN070890@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi Eugene, Should this be done more generally? Last time I looked it seemed like libxo was completely locale-unaware and just assumed all input was UTF-8. It might make more sense to have libxo take locale into account when formatting %s strings. Best, Conrad On Thu, Aug 22, 2019 at 6:25 PM Eugene Grosbein <eugen@freebsd.org> wrote: > > Author: eugen > Date: Fri Aug 23 01:25:38 2019 > New Revision: 351413 > URL: https://svnweb.freebsd.org/changeset/base/351413 > > Log: > last(1): unbreak for 8-bit locales > > Ouput format of last(1) is broken for non UTF-8 locales > since it got libxo(3) support. It uses strftime(3) that produces > non UTF-8 strings passed to xo_emit(3) with wrong %s format - > it should be %hs in this case, so xo_emit(3) produces empty output. > > This change is basically no-op when locale is of UTF-8 type, > f.e. en_GB.UTF-8 or ru_RU.UTF-8 or sr_RS.UTF-8@latin. > It fixes output for other locales. > > MFC after: 2 weeks > > Modified: > head/usr.bin/last/last.c > > Modified: head/usr.bin/last/last.c > ============================================================================== > --- head/usr.bin/last/last.c Fri Aug 23 01:16:12 2019 (r351412) > +++ head/usr.bin/last/last.c Fri Aug 23 01:25:38 2019 (r351413) > @@ -93,6 +93,7 @@ static time_t currentout; /* current logout value */ > static long maxrec; /* records to display */ > static const char *file = NULL; /* utx.log file */ > static int sflag = 0; /* show delta in seconds */ > +static int utf8flag; /* current locale is UTF-8 */ > static int width = 5; /* show seconds in delta */ > static int yflag; /* show year */ > static int d_first; > @@ -103,6 +104,7 @@ static time_t snaptime; /* if != 0, we will only > */ > > static void addarg(int, char *); > +static const char *ctf(const char *); > static time_t dateconv(char *); > static void doentry(struct utmpx *); > static void hostconv(char *); > @@ -112,6 +114,31 @@ static int want(struct utmpx *); > static void usage(void); > static void wtmp(void); > > +static const char* > +ctf(const char *fmt) { > + static char buf[31]; > + const char *src, *end; > + char *dst; > + > + if (utf8flag) > + return (fmt); > + > + end = buf + sizeof(buf); > + for (src = fmt, dst = buf; dst < end; *dst++ = *src++) { > + if (*src == '\0') { > + *dst = '\0'; > + break; > + } else if (*src == '%' && *(src+1) == 's') { > + *dst++ = '%'; > + *dst++ = 'h'; > + *dst++ = 's'; > + strlcpy(dst, src+2, end - dst); > + return (buf); > + } > + } > + return (buf); > +} > + > static void > usage(void) > { > @@ -130,6 +157,9 @@ main(int argc, char *argv[]) > (void) setlocale(LC_TIME, ""); > d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); > > + (void) setlocale(LC_CTYPE, ""); > + utf8flag = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0); > + > argc = xo_parse_args(argc, argv); > if (argc < 0) > exit(1); > @@ -262,7 +292,7 @@ wtmp(void) > (void) strftime(ct, sizeof(ct), "%+", tm); > xo_emit("\n{:utxdb/%s}", (file == NULL) ? "utx.log" : file); > xo_attr("seconds", "%lu", (unsigned long) t); > - xo_emit(" begins {:begins/%s}\n", ct); > + xo_emit(ctf(" begins {:begins/%s}\n"), ct); > xo_close_container("last-information"); > } > > @@ -379,7 +409,7 @@ printentry(struct utmpx *bp, struct idtab *tt) > break; > } > xo_attr("seconds", "%lu", (unsigned long)t); > - xo_emit(" {:login-time/%s%c/%s}", ct, tt == NULL ? '\n' : ' '); > + xo_emit(ctf(" {:login-time/%s%c/%s}"), ct, tt == NULL ? '\n' : ' '); > if (tt == NULL) > goto end; > if (!tt->logout) { > @@ -393,7 +423,7 @@ printentry(struct utmpx *bp, struct idtab *tt) > tm = localtime(&tt->logout); > (void) strftime(ct, sizeof(ct), "%R", tm); > xo_attr("seconds", "%lu", (unsigned long)tt->logout); > - xo_emit("- {:logout-time/%s}", ct); > + xo_emit(ctf("- {:logout-time/%s}"), ct); > } > delta = tt->logout - bp->ut_tv.tv_sec; > xo_attr("seconds", "%ld", (long)delta); > @@ -403,9 +433,9 @@ printentry(struct utmpx *bp, struct idtab *tt) > tm = gmtime(&delta); > (void) strftime(ct, sizeof(ct), width >= 8 ? "%T" : "%R", tm); > if (delta < 86400) > - xo_emit(" ({:session-length/%s})\n", ct); > + xo_emit(ctf(" ({:session-length/%s})\n"), ct); > else > - xo_emit(" ({:session-length/%ld+%s})\n", > + xo_emit(ctf(" ({:session-length/%ld+%s})\n"), > (long)delta / 86400, ct); > } > >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAG6CVpXFtrfrdTJporKx%2BBXif1%2BL-pH_WAzDN%2BB78yugTy7cCA>