free: Fix first column justification

free has for many years had a problem with translated header columns
or the first column. This is because printf("-9s", str) doesn't use
the wide length of the string but the char length meaning they are
mis-aligned.

Using the mbstowcs() function to get the wide length and then
a precision parameter to append the right number of spaces after the
number means we get what we need.

References:
 procps-ng/procps#229
 procps-ng/procps#204
 procps-ng/procps#206
 https://bugs.debian.org/1001689

Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
Craig Small 2022-01-31 18:14:12 +11:00
parent 50a0d9a56c
commit 9f4db0fb56
2 changed files with 31 additions and 6 deletions

1
NEWS
View File

@ -3,6 +3,7 @@ procps-ng-NEXT
* Rename pwait to pidwait * Rename pwait to pidwait
* free: Add committed line option merge #25 * free: Add committed line option merge #25
* free: Fix -h --si combined options issue #133, #223 * free: Fix -h --si combined options issue #133, #223
* free: Fix first column justification issue #229, #204, #206, Debian #1001689
* library: renamed to libproc-2 and reset to 0:0:0 * library: renamed to libproc-2 and reset to 0:0:0
* library: add support for accessing smaps_rollup issue #112, #201 * library: add support for accessing smaps_rollup issue #112, #201
* library: add support for accessing autogroups * library: add support for accessing autogroups

36
free.c
View File

@ -173,6 +173,30 @@ static void check_unit_set(int *unit_set)
*unit_set = 1; *unit_set = 1;
} }
/*
* Print the header columns.
* We cannot simply use the second printf because the length of the
* translated strings doesn't work with it. Instead we need to find
* the wide length of the string and use that.
* This method also removes the messy wprintf/printf buffering issues
*/
#define HC_WIDTH 9
static void print_head_col(const char *str)
{
int len;
int spaces = 9;
len = mbstowcs(NULL, str, 0);
if (len < 0)
spaces = 9;
else if (len < HC_WIDTH)
spaces = HC_WIDTH - len;
else
spaces = 0;
printf("%s%.*s", str, spaces, " ");
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int c, flags = 0, unit_set = 0; int c, flags = 0, unit_set = 0;
@ -343,7 +367,7 @@ int main(int argc, char **argv)
printf(_(" total used free shared buff/cache available")); printf(_(" total used free shared buff/cache available"));
} }
printf("\n"); printf("\n");
printf("%-9s", _("Mem:")); print_head_col(_("Mem:"));
printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_TOTAL, ul_int), flags, args)); printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_TOTAL, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_USED, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_USED, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_FREE, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_FREE, ul_int), flags, args));
@ -366,27 +390,27 @@ int main(int argc, char **argv)
* to print the high info, even if it is zero. * to print the high info, even if it is zero.
*/ */
if (flags & FREE_LOHI) { if (flags & FREE_LOHI) {
printf("%-9s", _("Low:")); print_head_col(_("Low:"));
printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_LOW_TOTAL, ul_int), flags, args)); printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_LOW_TOTAL, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_LOW_USED, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_LOW_USED, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_LOW_FREE, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_LOW_FREE, ul_int), flags, args));
printf("\n"); printf("\n");
printf("%-9s", _("High:")); print_head_col( _("High:"));
printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_HIGH_TOTAL, ul_int), flags, args)); printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_HIGH_TOTAL, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_HIGH_USED, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_HIGH_USED, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_HIGH_FREE, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_HIGH_FREE, ul_int), flags, args));
printf("\n"); printf("\n");
} }
printf("%-9s", _("Swap:")); print_head_col(_("Swap:"));
printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_TOTAL, ul_int), flags, args)); printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_TOTAL, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_USED, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_USED, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_FREE, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_SWAP_FREE, ul_int), flags, args));
printf("\n"); printf("\n");
if (flags & FREE_TOTAL) { if (flags & FREE_TOTAL) {
printf("%-9s", _("Total:")); print_head_col(_("Total:"));
printf("%11s", scale_size( printf("%11s", scale_size(
MEMINFO_GET(mem_info, MEMINFO_MEM_TOTAL, ul_int) + MEMINFO_GET(mem_info, MEMINFO_MEM_TOTAL, ul_int) +
MEMINFO_GET(mem_info, MEMINFO_SWAP_TOTAL, ul_int), flags, args)); MEMINFO_GET(mem_info, MEMINFO_SWAP_TOTAL, ul_int), flags, args));
@ -399,7 +423,7 @@ int main(int argc, char **argv)
printf("\n"); printf("\n");
} }
if (flags & FREE_COMMITTED) { if (flags & FREE_COMMITTED) {
printf("%-9s", _("Comm:")); print_head_col(_("Comm:"));
printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_COMMIT_LIMIT, ul_int), flags, args)); printf("%11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_COMMIT_LIMIT, ul_int), flags, args));
printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_COMMITTED_AS, ul_int), flags, args)); printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_COMMITTED_AS, ul_int), flags, args));
printf(" %11s", scale_size( printf(" %11s", scale_size(