Hello community,

here is the log from the commit of package i3status for openSUSE:Factory 
checked in at 2018-05-13 16:06:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/i3status (Old)
 and      /work/SRC/openSUSE:Factory/.i3status.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "i3status"

Sun May 13 16:06:41 2018 rev:8 rq:606760 version:2.12

Changes:
--------
--- /work/SRC/openSUSE:Factory/i3status/i3status.changes        2017-04-24 
09:48:48.459754661 +0200
+++ /work/SRC/openSUSE:Factory/.i3status.new/i3status.changes   2018-05-13 
16:08:13.275423376 +0200
@@ -1,0 +2,28 @@
+Sat May 12 03:32:58 UTC 2018 - [email protected]
+
+- update to version 2.12:
+ * show IP address when address has a label
+ * treat zero battery capacity as "not available"
+ * add IPv6 address when IPv4 isn't available
+ * call tzset at each time print to pick up time zone changes
+ * doc: fixed minor typos
+ * be more cautious about handling invalid battery measurements.
+ * fix CPU unit tests
+ * use local timezone for battery %emptytime
+ * fix memory leak/use BEGINS_WITH macro
+ * _first_: add check for virtual ethernet devices
+ * add battery capacity parsing
+ * multiple CPU support for cpu_usage
+ * remove useless checks (we use char, not unsigned char) to fix
+   compilation warnings
+ * disk: sanitize trailing slashes
+ * suppress printing :00 seconds of remaining battery lifetime, as
+   apm(4)'s estimate only has a granularity of minutes.
+ * Makefile: make PKG_CONFIG overridable
+ * man page updates
+- cleanup with spec-cleaner
+- use https urls
+- remove yajl fallback from source to ensure ours is used
+- remove SLOC comment from description (no longer valid)
+
+-------------------------------------------------------------------

Old:
----
  i3status-2.11.tar.bz2

New:
----
  i3status-2.12.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ i3status.spec ++++++
--- /var/tmp/diff_new_pack.8Bsb9C/_old  2018-05-13 16:08:13.971397986 +0200
+++ /var/tmp/diff_new_pack.8Bsb9C/_new  2018-05-13 16:08:13.975397841 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package i3status
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 # Copyright (c) 2014 Thomas Pfeiffer <[email protected]>
 #
 # All modifications and additions to the file contributed by third parties
@@ -18,14 +18,13 @@
 
 
 Name:           i3status
-Version:        2.11
+Version:        2.12
 Release:        0
 Summary:        I3 Status Bar
 License:        BSD-3-Clause
 Group:          System/Monitoring
-Source:         http://i3wm.org/i3status/%{name}-%{version}.tar.bz2
-Url:            http://i3wm.org/i3status/
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
+URL:            https://i3wm.org/i3status/
+Source0:        https://i3wm.org/i3status/%{name}-%{version}.tar.bz2
 BuildRequires:  alsa-devel
 BuildRequires:  asciidoc
 BuildRequires:  libasound2
@@ -38,33 +37,31 @@
 BuildRequires:  libyajl-devel
 
 %description
-i3status is a small program (about 1500 SLOC) for generating a status bar for
-i3bar, dzen2, xmobar or similar programs. It is designed to be very efficient
-by issuing a very small number of system calls, as one generally wants to
-update such a status line every second. This ensures that even under high load,
-your status bar is updated correctly. Also, it saves a bit of energy by not
+i3status is a small program for generating a status bar for i3bar, dzen2,
+xmobar or similar programs. It is designed to be very efficient by issuing
+a very small number of system calls, as one generally wants to update such
+a status line every second. This ensures that even under high load, your
+status bar is updated correctly. Also, it saves a bit of energy by not
 hogging your CPU as much as spawning the corresponding amount of shell commands
 would.
 
 %prep
 %setup -q
-
+rm -fr yajl-fallback
 chmod -x contrib/*.*
 
 %build
-%__make %{?_smp_mflags} \
-    OPTFLAGS="%{optflags}" \
-    PREFIX="%{_prefix}" \
-    SYSCONFDIR="%{_sysconfdir}"
+make %{?_smp_mflags} \
+    OPTFLAGS="%{optflags}"
 
 %install
 %make_install
 
 %files
-%defattr(-,root,root)
-%doc CHANGELOG LICENSE contrib/
-%config(noreplace) %{_sysconfdir}/i3status.conf
-%{_bindir}/i3status
-%doc %{_mandir}/man1/i3status.1*
+%license LICENSE
+%doc CHANGELOG contrib/
+%config(noreplace) %{_sysconfdir}/%{name}.conf
+%{_bindir}/%{name}
+%{_mandir}/man1/%{name}.1%{?ext_man}
 
 %changelog

++++++ i3status-2.11.tar.bz2 -> i3status-2.12.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/CHANGELOG new/i3status-2.12/CHANGELOG
--- old/i3status-2.11/CHANGELOG 2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/CHANGELOG 2018-05-11 11:10:46.000000000 +0200
@@ -1,3 +1,30 @@
+2018-05-11 i3status 2.12
+
+ • fix NULL value on OpenBSD when there is no acpitz0
+ • show IP address when address has a label
+ • man: explicitly use format_up/format_down in ethernet, wireless conf
+ • man: remove SLOC comment
+ • treat zero battery capacity as "not available"
+ • add IPv6 address when IPv4 isn't available
+ • call tzset at each time print to pick up time zone changes
+ • doc: fixed minor typos
+ • be more cautious about handling invalid battery measurements.
+ • Makefile: make PKG_CONFIG overridable
+ • fix CPU unit tests
+ • use local timezone for battery %emptytime
+ • fix memory leak/use BEGINS_WITH macro
+ • _first_: add check for virtual ethernet devices
+ • add battery capacity parsing
+ • multiple CPU support for cpu_usage
+ • remove useless checks (we use char, not unsigned char) to fix compilation 
warnings
+ • disk: sanitize trailing slashes
+ • plug an fd leak in the OpenBSD-specific code for
+ • suppress printing :00 seconds of remaining battery lifetime, as apm(4)'s
+   estimate only has a granularity of minutes.
+ • fix the deciKelvin to Celsius conversion on FreeBSD
+ • make first_eth_interface() work on OpenBSD
+ • include sys/select.h on OpenBSD
+
 2017-01-21 i3status 2.11
 
  • re-add forgotten wakeup call from SIGUSR1 handler
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/I3STATUS_VERSION 
new/i3status-2.12/I3STATUS_VERSION
--- old/i3status-2.11/I3STATUS_VERSION  2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/I3STATUS_VERSION  2018-05-11 11:10:46.000000000 +0200
@@ -1 +1 @@
-2.11 (2017-01-21)
+2.12 (2018-05-11)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/Makefile new/i3status-2.12/Makefile
--- old/i3status-2.11/Makefile  2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/Makefile  2018-05-11 11:10:46.000000000 +0200
@@ -14,6 +14,7 @@
   endif
 endif
 
+PKG_CONFIG ?= pkg-config
 CFLAGS+=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare
 CFLAGS+=-g
 CFLAGS+=-std=gnu99
@@ -40,8 +41,8 @@
 ifeq ($(OS),Linux)
 CPPFLAGS+=-DLINUX
 CPPFLAGS+=-D_GNU_SOURCE
-CFLAGS += $(shell pkg-config --cflags libnl-genl-3.0)
-LIBS += $(shell pkg-config --libs libnl-genl-3.0)
+CFLAGS += $(shell $(PKG_CONFIG) --cflags libnl-genl-3.0)
+LIBS += $(shell $(PKG_CONFIG) --libs libnl-genl-3.0)
 LIBS+=-lasound
 endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/README.md new/i3status-2.12/README.md
--- old/i3status-2.11/README.md 2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/README.md 2018-05-11 11:10:46.000000000 +0200
@@ -2,12 +2,12 @@
 
 ## Description
 
-i3status is a small program (about 1500 SLOC) for generating a status bar for
-i3bar, dzen2, xmobar or similar programs. It is designed to be very efficient 
by
-issuing a very small number of system calls, as one generally wants to update
-such a status line every second. This ensures that even under high load, your
-status bar is updated correctly. Also, it saves a bit of energy by not hogging
-your CPU as much as spawning the corresponding amount of shell commands would.
+i3status is a small program for generating a status bar for i3bar, dzen2, 
xmobar
+or similar programs. It is designed to be very efficient by issuing a very 
small
+number of system calls, as one generally wants to update such a status line
+every second. This ensures that even under high load, your status bar is 
updated
+correctly. Also, it saves a bit of energy by not hogging your CPU as much as
+spawning the corresponding amount of shell commands would.
 
 ## Development
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/i3status.c new/i3status-2.12/i3status.c
--- old/i3status-2.11/i3status.c        2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/i3status.c        2018-05-11 11:10:46.000000000 +0200
@@ -111,6 +111,9 @@
 }
 
 char *sstrdup(const char *str) {
+    if (str == NULL) {
+        return NULL;
+    }
     char *result = strdup(str);
     exit_if_null(result, "Error: out of memory (strdup())\n");
     return result;
@@ -422,6 +425,7 @@
         CFG_STR("format", "%usage", CFGF_NONE),
         CFG_STR("format_above_threshold", NULL, CFGF_NONE),
         CFG_STR("format_above_degraded_threshold", NULL, CFGF_NONE),
+        CFG_STR("path", "/proc/stat", CFGF_NONE),
         CFG_FLOAT("max_threshold", 95, CFGF_NONE),
         CFG_FLOAT("degraded_threshold", 90, CFGF_NONE),
         CFG_CUSTOM_ALIGN_OPT,
@@ -627,6 +631,11 @@
         die("Could not create socket\n");
 
     int interval = cfg_getint(cfg_general, "interval");
+    if (interval <= 0) {
+        die("Invalid interval attribute found in section %s, line %d: %d\n"
+            "Expected positive integer\n",
+            cfg_general->name, cfg_general->line, interval);
+    }
 
     /* One memory page which each plugin can use to buffer output.
      * Even though it’s unclean, we just assume that the user will not
@@ -751,7 +760,7 @@
 
             CASE_SEC("cpu_usage") {
                 SEC_OPEN_MAP("cpu_usage");
-                print_cpu_usage(json_gen, buffer, cfg_getstr(sec, "format"), 
cfg_getstr(sec, "format_above_threshold"), cfg_getstr(sec, 
"format_above_degraded_threshold"), cfg_getfloat(sec, "max_threshold"), 
cfg_getfloat(sec, "degraded_threshold"));
+                print_cpu_usage(json_gen, buffer, cfg_getstr(sec, "format"), 
cfg_getstr(sec, "format_above_threshold"), cfg_getstr(sec, 
"format_above_degraded_threshold"), cfg_getstr(sec, "path"), cfg_getfloat(sec, 
"max_threshold"), cfg_getfloat(sec, "degraded_threshold"));
                 SEC_CLOSE_MAP;
             }
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/include/i3status.h 
new/i3status-2.12/include/i3status.h
--- old/i3status-2.11/include/i3status.h        2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/include/i3status.h        2018-05-11 11:10:46.000000000 
+0200
@@ -215,12 +215,12 @@
 void print_battery_info(yajl_gen json_gen, char *buffer, int number, const 
char *path, const char *format, const char *format_down, const char 
*status_chr, const char *status_bat, const char *status_unk, const char 
*status_full, int low_threshold, char *threshold_type, bool last_full_capacity, 
bool integer_battery_capacity, bool hide_seconds);
 void print_time(yajl_gen json_gen, char *buffer, const char *title, const char 
*format, const char *tz, const char *locale, const char *format_time, time_t t);
 void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t 
t);
-const char *get_ip_addr(const char *interface);
+const char *get_ip_addr(const char *interface, int family);
 void print_wireless_info(yajl_gen json_gen, char *buffer, const char 
*interface, const char *format_up, const char *format_down);
 void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const 
char *pidfile, const char *format, const char *format_down);
 void print_path_exists(yajl_gen json_gen, char *buffer, const char *title, 
const char *path, const char *format, const char *format_down);
 void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, 
const char *path, const char *format, const char *format_above_threshold, int);
-void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, 
const char *format_above_threshold, const char 
*format_above_degraded_threshold, const float max_threshold, const float 
degraded_threshold);
+void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, 
const char *format_above_threshold, const char 
*format_above_degraded_threshold, const char *path, const float max_threshold, 
const float degraded_threshold);
 void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, 
const char *format_up, const char *format_down);
 void print_load(yajl_gen json_gen, char *buffer, const char *format, const 
char *format_above_threshold, const float max_threshold);
 void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char 
*fmt_muted, const char *device, const char *mixer, int mixer_idx);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/man/asciidoc.conf 
new/i3status-2.12/man/asciidoc.conf
--- old/i3status-2.11/man/asciidoc.conf 2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/man/asciidoc.conf 2018-05-11 11:10:46.000000000 +0200
@@ -7,7 +7,7 @@
 <refentrytitle>{mantitle}</refentrytitle>
 <manvolnum>{manvolnum}</manvolnum>
 <refmiscinfo class="source">i3status</refmiscinfo>
-<refmiscinfo class="version">v2.11</refmiscinfo>
+<refmiscinfo class="version">v2.12</refmiscinfo>
 <refmiscinfo class="manual">i3 Manual</refmiscinfo>
 </refmeta>
 <refnamediv>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/man/i3status.man 
new/i3status-2.12/man/i3status.man
--- old/i3status-2.11/man/i3status.man  2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/man/i3status.man  2018-05-11 11:10:46.000000000 +0200
@@ -1,7 +1,7 @@
 i3status(1)
 ===========
 Michael Stapelberg <[email protected]>
-v2.11, January 2017
+v2.12, May 2018
 
 == NAME
 
@@ -24,13 +24,12 @@
 
 == DESCRIPTION
 
-i3status is a small program (about 1500 SLOC) for generating a status bar for
-i3bar, dzen2, xmobar, lemonbar or similar programs. It is designed to be very
-efficient by issuing a very small number of system calls, as one generally
-wants to update such a status line every second. This ensures that even under
-high load, your status bar is updated correctly. Also, it saves a bit of energy
-by not hogging your CPU as much as spawning the corresponding amount of shell
-commands would.
+i3status is a small program for generating a status bar for i3bar, dzen2,
+xmobar, lemonbar or similar programs. It is designed to be very efficient by
+issuing a very small number of system calls, as one generally wants to update
+such a status line every second. This ensures that even under high load, your
+status bar is updated correctly. Also, it saves a bit of energy by not hogging
+your CPU as much as spawning the corresponding amount of shell commands would.
 
 == CONFIGURATION
 
@@ -142,7 +141,7 @@
 The +interval+ directive specifies the time in seconds for which i3status will
 sleep before printing the next status line.
 
-Using +output_format+ you can chose which format strings i3status should
+Using +output_format+ you can choose which format strings i3status should
 use in its output. Currently available are:
 
 i3bar::
@@ -178,14 +177,14 @@
 
 If you don't fancy the vertical separators between modules i3status/i3bar
 uses by default, you can employ the +separator+ directive to configure how
-modules are separated. You can either disable the default separator altogether
+modules are separated. You can also disable the default separator altogether by
 setting it to the empty string. You might then define separation as part of a
 module's format string. This is your only option when using the i3bar output
 format as the separator is drawn by i3bar directly otherwise. For the other
 output formats, the provided non-empty string will be automatically enclosed
 with the necessary coloring bits if color support is enabled.
 
-i3bar supports Pango markup, allowing your format strings to specify font
+i3bar supports Pango markup, allowing your format strings to specify font,
 color, size, etc. by setting the +markup+ directive to "pango". Note that the
 ampersand ("&"), less-than ("<"), greater-than (">"), single-quote ("'"), and
 double-quote (""") characters need to be replaced with "`&amp;`", "`&lt;`",
@@ -300,20 +299,25 @@
 
 *Example order*: +wireless wlan0+
 
-*Example format*: +W: (%quality at %essid, %bitrate / %frequency) %ip+
+*Example format_up*: +W: (%quality at %essid, %bitrate / %frequency) %ip+
+
+*Example format_down*: +W: down+
 
 === Ethernet
 
 Gets the IP address and (if possible) the link speed of the given ethernet
-interface. Getting the link speed requires the cap_net_admin capability. Set
-it using +setcap cap_net_admin=ep $(which i3status)+.
+interface. If no IPv4 address is available and an IPv6 address is, it will be
+displayed. Getting the link speed requires the cap_net_admin capability.
+Set it using +setcap cap_net_admin=ep $(which i3status)+.
 
 The special interface name `_first_` will be replaced by the first non-wireless
 network interface found on the system (excluding devices starting with "lo").
 
 *Example order*: +ethernet eth0+
 
-*Example format*: +E: %ip (%speed)+
+*Example format_up*: +E: %ip (%speed)+
+
+*Example format_down*: +E: down+
 
 === Battery
 
@@ -405,13 +409,16 @@
 
 It is possible to define a degraded_threshold that will color the load
 value yellow in case the CPU average over the last interval is getting
-higher than the configured threshold.  Defaults to 90. The output format
+higher than the configured threshold. Defaults to 90. The output format
 when above degraded threshold can be customized with
 format_above_degraded_threshold.
 
+For displaying the Nth CPU usage, you can use the %cpu<N> format string,
+starting from %cpu0. This feature is currently not supported in FreeBSD.
+
 *Example order*: +cpu_usage+
 
-*Example format*: +%usage+
+*Example format*: +all: %usage CPU_0: %cpu0 CPU_1: %cpu1+
 
 *Example max_threshold*: +75+
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/first_network_device.c 
new/i3status-2.12/src/first_network_device.c
--- old/i3status-2.11/src/first_network_device.c        2017-01-21 
16:00:31.000000000 +0100
+++ new/i3status-2.12/src/first_network_device.c        2018-05-11 
11:10:46.000000000 +0200
@@ -3,9 +3,23 @@
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <ifaddrs.h>
+#ifdef __OpenBSD__
+#include <sys/types.h>
+#include <sys/sockio.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_ioctl.h>
+#endif
 
 #include "i3status.h"
 
+#ifdef __OpenBSD__
+#define LOOPBACK_DEV "lo0"
+#else
+#define LOOPBACK_DEV "lo"
+#endif
+
 static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) {
     FILE *fp;
     char buf[1024];
@@ -36,12 +50,72 @@
     return true;
 }
 
+static bool is_virtual(const char *ifname) {
+    char path[1024];
+    char *target = NULL;
+    bool is_virtual = false;
+
+    snprintf(path, sizeof(path), "/sys/class/net/%s", ifname);
+    if ((target = realpath(path, NULL))) {
+        if (BEGINS_WITH(target, "/sys/devices/virtual/")) {
+            is_virtual = true;
+        }
+    }
+
+    free(target);
+    return is_virtual;
+}
+
 static net_type_t iface_type(const char *ifname) {
+#ifdef __OpenBSD__
+    /*
+     *First determine if the device is a wireless device by trying two ioctl(2)
+     * commands against it. If either succeeds we can be sure it's a wireless
+     * device.
+     * Otherwise we try another ioctl(2) to determine the interface media. If 
that
+     * fails it's not an ethernet device eiter.
+     */
+    struct ifreq ifr;
+    struct ieee80211_bssid bssid;
+    struct ieee80211_nwid nwid;
+    struct ifmediareq ifmr;
+
+    int s, ibssid, inwid;
+
+    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+        return NET_TYPE_OTHER;
+
+    memset(&ifr, 0, sizeof(ifr));
+    ifr.ifr_data = (caddr_t)&nwid;
+    (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr);
+
+    memset(&bssid, 0, sizeof(bssid));
+    strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name));
+    ibssid = ioctl(s, SIOCG80211BSSID, &bssid);
+
+    if (ibssid == 0 || inwid == 0) {
+        close(s);
+        return NET_TYPE_WIRELESS;
+    }
+
+    (void)memset(&ifmr, 0, sizeof(ifmr));
+    (void)strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+
+    if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+        close(s);
+        return NET_TYPE_OTHER;
+    } else {
+        close(s);
+        return NET_TYPE_ETHERNET;
+    }
+#else
     char devtype[32];
 
     if (!sysfs_devtype(devtype, sizeof(devtype), ifname))
         return NET_TYPE_OTHER;
 
+    /* Default to Ethernet when no devtype is available */
     if (!devtype[0])
         return NET_TYPE_ETHERNET;
 
@@ -52,6 +126,8 @@
         return NET_TYPE_OTHER;
 
     return NET_TYPE_OTHER;
+#endif
+    return NET_TYPE_OTHER;
 }
 
 const char *first_eth_interface(const net_type_t type) {
@@ -69,19 +145,26 @@
     for (addrp = ifaddr;
          addrp != NULL;
          addrp = addrp->ifa_next) {
-        if (strncasecmp("lo", addrp->ifa_name, strlen("lo")) == 0)
+        if (strncasecmp(LOOPBACK_DEV, addrp->ifa_name, strlen(LOOPBACK_DEV)) 
== 0)
             continue;
         if (addrp->ifa_addr == NULL)
             continue;
+#ifdef __OpenBSD__
+        if (addrp->ifa_addr->sa_family != AF_LINK)
+            continue;
+#else
         // Skip PF_PACKET addresses (MAC addresses), as they are present on any
         // ethernet interface.
         if (addrp->ifa_addr->sa_family != AF_INET &&
             addrp->ifa_addr->sa_family != AF_INET6)
             continue;
+#endif /* !__OpenBSD__ */
         // Skip this interface if it is a wireless interface.
         iftype = iface_type(addrp->ifa_name);
         if (iftype != type)
             continue;
+        if (is_virtual(addrp->ifa_name))
+            continue;
         interface = strdup(addrp->ifa_name);
         break;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/output.c 
new/i3status-2.12/src/output.c
--- old/i3status-2.11/src/output.c      2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/src/output.c      2018-05-11 11:10:46.000000000 +0200
@@ -111,12 +111,11 @@
             default:
                 if ((0x1 <= *text && *text <= 0x8) ||
                     (0xb <= *text && *text <= 0xc) ||
-                    (0xe <= *text && *text <= 0x1f) ||
-                    (0x7f <= *text && *text <= 0x84) ||
-                    (0x86 <= *text && *text <= 0x9f))
+                    (0xe <= *text && *text <= 0x1f)) {
                     *buffer += sprintf(*buffer, "&#x%x;", *text);
-                else
+                } else {
                     *(*buffer)++ = *text;
+                }
                 break;
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_battery_info.c 
new/i3status-2.12/src/print_battery_info.c
--- old/i3status-2.11/src/print_battery_info.c  2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_battery_info.c  2018-05-11 11:10:46.000000000 
+0200
@@ -138,9 +138,13 @@
         if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW=")) {
             watt_as_unit = true;
             batt_info->remaining = atoi(walk + 1);
+            batt_info->percentage_remaining = -1;
         } else if (BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW=")) {
             watt_as_unit = false;
             batt_info->remaining = atoi(walk + 1);
+            batt_info->percentage_remaining = -1;
+        } else if (BEGINS_WITH(last, "POWER_SUPPLY_CAPACITY=") && 
batt_info->remaining == -1) {
+            batt_info->percentage_remaining = atoi(walk + 1);
         } else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW="))
             batt_info->present_rate = abs(atoi(walk + 1));
         else if (BEGINS_WITH(last, "POWER_SUPPLY_VOLTAGE_NOW="))
@@ -171,11 +175,19 @@
      * POWER_SUPPLY_CHARGE_NOW is the unit of measurement. The energy is
      * given in mWh, the charge in mAh. So calculate every value given in
      * ampere to watt */
-    if (!watt_as_unit && voltage != -1) {
-        batt_info->present_rate = (((float)voltage / 1000.0) * 
((float)batt_info->present_rate / 1000.0));
-        batt_info->remaining = (((float)voltage / 1000.0) * 
((float)batt_info->remaining / 1000.0));
-        batt_info->full_design = (((float)voltage / 1000.0) * 
((float)batt_info->full_design / 1000.0));
-        batt_info->full_last = (((float)voltage / 1000.0) * 
((float)batt_info->full_last / 1000.0));
+    if (!watt_as_unit && voltage >= 0) {
+        if (batt_info->present_rate > 0) {
+            batt_info->present_rate = (((float)voltage / 1000.0) * 
((float)batt_info->present_rate / 1000.0));
+        }
+        if (batt_info->remaining > 0) {
+            batt_info->remaining = (((float)voltage / 1000.0) * 
((float)batt_info->remaining / 1000.0));
+        }
+        if (batt_info->full_design > 0) {
+            batt_info->full_design = (((float)voltage / 1000.0) * 
((float)batt_info->full_design / 1000.0));
+        }
+        if (batt_info->full_last > 0) {
+            batt_info->full_last = (((float)voltage / 1000.0) * 
((float)batt_info->full_last / 1000.0));
+        }
     }
 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || 
defined(__DragonFly__)
     int state;
@@ -482,7 +494,7 @@
     /* These OSes report battery stats in whole percent. */
     integer_battery_capacity = true;
 #endif
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || 
defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || 
defined(__DragonFly__) || defined(__OpenBSD__)
     /* These OSes report battery time in minutes. */
     hide_seconds = true;
 #endif
@@ -495,8 +507,19 @@
             return;
     }
 
-    int full = (last_full_capacity ? batt_info.full_last : 
batt_info.full_design);
-    if (full < 0 && batt_info.percentage_remaining < 0) {
+    // *Choose* a measure of the 'full' battery. It is whichever is better of
+    // the battery's (hardware-given) design capacity (batt_info.full_design)
+    // and the battery's last known good charge (batt_info.full_last).
+    // We prefer the design capacity, but use the last capacity if we don't 
have it,
+    // or if we are asked to (last_full_capacity == true); but similarly we use
+    // the design capacity if we don't have the last capacity.
+    // If we don't have either then both full_design and full_last <= 0,
+    // which implies full <= 0, which bails out on the following line.
+    int full = batt_info.full_design;
+    if (full <= 0 || (last_full_capacity && batt_info.full_last > 0)) {
+        full = batt_info.full_last;
+    }
+    if (full <= 0 && batt_info.remaining < 0 && batt_info.percentage_remaining 
< 0) {
         /* We have no physical measurements and no estimates. Nothing
          * much we can report, then. */
         OUTPUT_FULL_TEXT(format_down);
@@ -598,6 +621,7 @@
         } else if (BEGINS_WITH(walk + 1, "emptytime")) {
             if (batt_info.seconds_remaining >= 0) {
                 time_t empty_time = time(NULL) + batt_info.seconds_remaining;
+                set_timezone(NULL); /* Use local time. */
                 struct tm *empty_tm = localtime(&empty_time);
 
                 if (hide_seconds)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_cpu_temperature.c 
new/i3status-2.12/src/print_cpu_temperature.c
--- old/i3status-2.11/src/print_cpu_temperature.c       2017-01-21 
16:00:31.000000000 +0100
+++ new/i3status-2.12/src/print_cpu_temperature.c       2018-05-11 
11:10:46.000000000 +0200
@@ -13,7 +13,7 @@
 #include <err.h>
 #include <sys/types.h>
 #include <sys/sysctl.h>
-#define TZ_ZEROC 2732
+#define TZ_ZEROC 2731
 #define TZ_KELVTOC(x) (((x)-TZ_ZEROC) / 10), abs(((x)-TZ_ZEROC) % 10)
 #define TZ_AVG(x) ((x)-TZ_ZEROC) / 10
 #endif
@@ -112,7 +112,7 @@
         /* 'path' is the node within the full path (defaults to acpitz0). */
         if (BEGINS_WITH(sensordev.xname, thermal_zone)) {
             mib[3] = SENSOR_TEMP;
-            /* Limit to temo0, but should retrieve from a full path... */
+            /* Limit to temp0, but should retrieve from a full path... */
             for (numt = 0; numt < 1 /*sensordev.maxnumt[SENSOR_TEMP]*/; 
numt++) {
                 mib[4] = numt;
                 if (sysctl(mib, 5, &sensor, &slen, NULL, 0) == -1) {
@@ -205,7 +205,7 @@
 
 /*
  * Reads the CPU temperature from /sys/class/thermal/thermal_zone%d/temp (or
- * the user provided path) and returns the temperature in degree celcius.
+ * the user provided path) and returns the temperature in degree celsius.
  *
  */
 void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, 
const char *path, const char *format, const char *format_above_threshold, int 
max_threshold) {
@@ -216,6 +216,8 @@
     bool colorful_output = false;
     char *thermal_zone;
     temperature_t temperature;
+    temperature.raw_value = 0;
+    sprintf(temperature.formatted_value, "%.2f", 0.0);
 
     if (path == NULL)
         asprintf(&thermal_zone, THERMAL_ZONE, zone);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_cpu_usage.c 
new/i3status-2.12/src/print_cpu_usage.c
--- old/i3status-2.11/src/print_cpu_usage.c     2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_cpu_usage.c     2018-05-11 11:10:46.000000000 
+0200
@@ -33,36 +33,68 @@
 
 #include "i3status.h"
 
-static int prev_total = 0;
-static int prev_idle = 0;
+struct cpu_usage {
+    int user;
+    int nice;
+    int system;
+    int idle;
+    int total;
+};
+
+static int cpu_count = 0;
+static struct cpu_usage prev_all = {0, 0, 0, 0, 0};
+static struct cpu_usage *prev_cpus = NULL;
+static struct cpu_usage *curr_cpus = NULL;
 
 /*
  * Reads the CPU utilization from /proc/stat and returns the usage as a
  * percentage.
  *
  */
-void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, 
const char *format_above_threshold, const char 
*format_above_degraded_threshold, const float max_threshold, const float 
degraded_threshold) {
+void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, 
const char *format_above_threshold, const char 
*format_above_degraded_threshold, const char *path, const float max_threshold, 
const float degraded_threshold) {
     const char *selected_format = format;
     const char *walk;
     char *outwalk = buffer;
-    int curr_user = 0, curr_nice = 0, curr_system = 0, curr_idle = 0, 
curr_total;
+    struct cpu_usage curr_all = {0, 0, 0, 0, 0};
     int diff_idle, diff_total, diff_usage;
     bool colorful_output = false;
 
 #if defined(LINUX)
-    static char statpath[512];
-    char buf[1024];
-    strcpy(statpath, "/proc/stat");
-    if (!slurp(statpath, buf, sizeof(buf)) ||
-        sscanf(buf, "cpu %d %d %d %d", &curr_user, &curr_nice, &curr_system, 
&curr_idle) != 4)
+
+    // Detecting if CPU count has changed
+    int curr_cpu_count = sysconf(_SC_NPROCESSORS_ONLN);
+    if (curr_cpu_count != cpu_count) {
+        cpu_count = curr_cpu_count;
+        free(prev_cpus);
+        prev_cpus = (struct cpu_usage *)calloc(cpu_count, sizeof(struct 
cpu_usage));
+        free(curr_cpus);
+        curr_cpus = (struct cpu_usage *)calloc(cpu_count, sizeof(struct 
cpu_usage));
+    }
+
+    char buf[4096];
+    if (!slurp(path, buf, sizeof(buf)))
         goto error;
+    // Parsing all cpu values using strtok
+    if (strtok(buf, "\n") == NULL)
+        goto error;
+    char *buf_itr = NULL;
+    for (int cpu_idx = 0; cpu_idx < cpu_count; cpu_idx++) {
+        buf_itr = strtok(NULL, "\n");
+        int curr_cpu_idx = -1;
+        if (!buf_itr || sscanf(buf_itr, "cpu%d %d %d %d %d", &curr_cpu_idx, 
&curr_cpus[cpu_idx].user, &curr_cpus[cpu_idx].nice, &curr_cpus[cpu_idx].system, 
&curr_cpus[cpu_idx].idle) != 5 || curr_cpu_idx != cpu_idx)
+            goto error;
+        curr_cpus[cpu_idx].total = curr_cpus[cpu_idx].user + 
curr_cpus[cpu_idx].nice + curr_cpus[cpu_idx].system + curr_cpus[cpu_idx].idle;
+        curr_all.user += curr_cpus[cpu_idx].user;
+        curr_all.nice += curr_cpus[cpu_idx].nice;
+        curr_all.system += curr_cpus[cpu_idx].system;
+        curr_all.idle += curr_cpus[cpu_idx].idle;
+        curr_all.total += curr_cpus[cpu_idx].total;
+    }
 
-    curr_total = curr_user + curr_nice + curr_system + curr_idle;
-    diff_idle = curr_idle - prev_idle;
-    diff_total = curr_total - prev_total;
+    diff_idle = curr_all.idle - prev_all.idle;
+    diff_total = curr_all.total - prev_all.total;
     diff_usage = (diff_total ? (1000 * (diff_total - diff_idle) / diff_total + 
5) / 10 : 0);
-    prev_total = curr_total;
-    prev_idle = curr_idle;
+    prev_all = curr_all;
 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || 
defined(__DragonFly__)
 
 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
@@ -84,16 +116,15 @@
         goto error;
 #endif
 
-    curr_user = cp_time[CP_USER];
-    curr_nice = cp_time[CP_NICE];
-    curr_system = cp_time[CP_SYS];
-    curr_idle = cp_time[CP_IDLE];
-    curr_total = curr_user + curr_nice + curr_system + curr_idle;
-    diff_idle = curr_idle - prev_idle;
-    diff_total = curr_total - prev_total;
+    curr_all.user = cp_time[CP_USER];
+    curr_all.nice = cp_time[CP_NICE];
+    curr_all.system = cp_time[CP_SYS];
+    curr_all.idle = cp_time[CP_IDLE];
+    curr_all.total = curr_all.user + curr_all.nice + curr_all.system + 
curr_all.idle;
+    diff_idle = curr_all.idle - prev_all.idle;
+    diff_total = curr_all.total - prev_all.total;
     diff_usage = (diff_total ? (1000 * (diff_total - diff_idle) / diff_total + 
5) / 10 : 0);
-    prev_total = curr_total;
-    prev_idle = curr_idle;
+    prev_all = curr_all;
 #else
     goto error;
 #endif
@@ -120,8 +151,32 @@
             outwalk += sprintf(outwalk, "%02d%s", diff_usage, pct_mark);
             walk += strlen("usage");
         }
+#if defined(LINUX)
+        if (BEGINS_WITH(walk + 1, "cpu")) {
+            int number = 0;
+            sscanf(walk + 1, "cpu%d", &number);
+            if (number < 0 || number >= cpu_count) {
+                fprintf(stderr, "provided CPU number '%d' above detected 
number of CPU %d\n", number, cpu_count);
+            } else {
+                int cpu_diff_idle = curr_cpus[number].idle - 
prev_cpus[number].idle;
+                int cpu_diff_total = curr_cpus[number].total - 
prev_cpus[number].total;
+                int cpu_diff_usage = (cpu_diff_total ? (1000 * (cpu_diff_total 
- cpu_diff_idle) / cpu_diff_total + 5) / 10 : 0);
+                outwalk += sprintf(outwalk, "%02d%s", cpu_diff_usage, 
pct_mark);
+            }
+            int padding = 1;
+            int step = 10;
+            while (step < number) {
+                step *= 10;
+                padding++;
+            }
+            walk += strlen("cpu") + padding;
+        }
+#endif
     }
 
+    for (int i = 0; i < cpu_count; i++)
+        prev_cpus[i] = curr_cpus[i];
+
     if (colorful_output)
         END_COLOR;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_disk_info.c 
new/i3status-2.12/src/print_disk_info.c
--- old/i3status-2.11/src/print_disk_info.c     2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_disk_info.c     2018-05-11 11:10:46.000000000 
+0200
@@ -141,16 +141,20 @@
          * we consider the device not mounted. */
         mounted = false;
     } else {
+        char *sanitized = sstrdup(path);
+        if (strlen(sanitized) > 1 && sanitized[strlen(sanitized) - 1] == '/')
+            sanitized[strlen(sanitized) - 1] = '\0';
         FILE *mntentfile = setmntent("/etc/mtab", "r");
         struct mntent *m;
 
         while ((m = getmntent(mntentfile)) != NULL) {
-            if (strcmp(m->mnt_dir, path) == 0) {
+            if (strcmp(m->mnt_dir, sanitized) == 0) {
                 mounted = true;
                 break;
             }
         }
         endmntent(mntentfile);
+        free(sanitized);
     }
 #endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_eth_info.c 
new/i3status-2.12/src/print_eth_info.c
--- old/i3status-2.11/src/print_eth_info.c      2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_eth_info.c      2018-05-11 11:10:46.000000000 
+0200
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -118,25 +119,60 @@
 /*
  * Combines ethernet IP addresses and speed (if requested) for displaying
  *
+ * Table summarizing what is the decision to prefer IPv4 or IPv6
+ * based their values.
+ *
+ * | ipv4_address | ipv6_address | Chosen IP | Color             |
+ * |--------------|--------------|-----------|-------------------|
+ * | NULL         | NULL         | None      | bad (red)         |
+ * | NULL         | no IP        | IPv6      | degraded (orange) |
+ * | NULL         | ::1/128      | IPv6      | ok (green)        |
+ * | no IP        | NULL         | IPv4      | degraded          |
+ * | no IP        | no IP        | IPv4      | degraded          |
+ * | no IP        | ::1/128      | IPv6      | ok                |
+ * | 127.0.0.1    | NULL         | IPv4      | ok                |
+ * | 127.0.0.1    | no IP        | IPv4      | ok                |
+ * | 127.0.0.1    | ::1/128      | IPv4      | ok                |
  */
 void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, 
const char *format_up, const char *format_down) {
     const char *walk;
-    const char *ip_address = get_ip_addr(interface);
     char *outwalk = buffer;
 
     INSTANCE(interface);
 
-    if (ip_address == NULL) {
-        START_COLOR("color_bad");
-        outwalk += sprintf(outwalk, "%s", format_down);
-        goto out;
+    char *ipv4_address = sstrdup(get_ip_addr(interface, AF_INET));
+    char *ipv6_address = sstrdup(get_ip_addr(interface, AF_INET6));
+
+    /*
+     * Removing '%' and following characters from IPv6 since the interface 
identifier is redundant,
+     * as the output already includes the interface name.
+    */
+    if (ipv6_address != NULL) {
+        char *prct_ptr = strstr(ipv6_address, "%");
+        if (prct_ptr != NULL) {
+            *prct_ptr = '\0';
+        }
+    }
+
+    bool prefer_ipv4 = true;
+    if (ipv4_address == NULL) {
+        if (ipv6_address == NULL) {
+            START_COLOR("color_bad");
+            outwalk += sprintf(outwalk, "%s", format_down);
+            goto out;
+        } else {
+            prefer_ipv4 = false;
+        }
+    } else if (BEGINS_WITH(ipv4_address, "no IP") && ipv6_address != NULL && 
!BEGINS_WITH(ipv6_address, "no IP")) {
+        prefer_ipv4 = false;
     }
 
-    if (BEGINS_WITH(ip_address, "no IP"))
+    const char *ip_address = (prefer_ipv4) ? ipv4_address : ipv6_address;
+    if (BEGINS_WITH(ip_address, "no IP")) {
         START_COLOR("color_degraded");
-    else
+    } else {
         START_COLOR("color_good");
-
+    }
     for (walk = format_up; *walk != '\0'; walk++) {
         if (*walk != '%') {
             *(outwalk++) = *walk;
@@ -154,5 +190,7 @@
 
 out:
     END_COLOR;
+    free(ipv4_address);
+    free(ipv6_address);
     OUTPUT_FULL_TEXT(buffer);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_ip_addr.c 
new/i3status-2.12/src/print_ip_addr.c
--- old/i3status-2.11/src/print_ip_addr.c       2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_ip_addr.c       2018-05-11 11:10:46.000000000 
+0200
@@ -17,30 +17,36 @@
  * interface is up and running but hasn't got an IP address yet
  *
  */
-const char *get_ip_addr(const char *interface) {
+const char *get_ip_addr(const char *interface, int family) {
     static char part[512];
-    socklen_t len = sizeof(struct sockaddr_in);
+    socklen_t len = 0;
+    if (family == AF_INET)
+        len = sizeof(struct sockaddr_in);
+    else if (family == AF_INET6)
+        len = sizeof(struct sockaddr_in6);
+
     memset(part, 0, sizeof(part));
 
     struct ifaddrs *ifaddr, *addrp;
     bool found = false;
+    int interface_len = strlen(interface);
 
     getifaddrs(&ifaddr);
 
     if (ifaddr == NULL)
         return NULL;
 
-    /* Skip until we are at the AF_INET address of interface */
+    /* Skip until we are at the input family address of interface */
     for (addrp = ifaddr;
 
          (addrp != NULL &&
-          (strcmp(addrp->ifa_name, interface) != 0 ||
+          (strncmp(addrp->ifa_name, interface, interface_len) != 0 ||
            addrp->ifa_addr == NULL ||
-           addrp->ifa_addr->sa_family != AF_INET));
+           addrp->ifa_addr->sa_family != family));
 
          addrp = addrp->ifa_next) {
         /* Check if the interface is down */
-        if (strcmp(addrp->ifa_name, interface) != 0)
+        if (strncmp(addrp->ifa_name, interface, interface_len) != 0)
             continue;
         found = true;
         if ((addrp->ifa_flags & IFF_RUNNING) == 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_time.c 
new/i3status-2.12/src/print_time.c
--- old/i3status-2.11/src/print_time.c  2017-01-21 16:00:31.000000000 +0100
+++ new/i3status-2.12/src/print_time.c  2018-05-11 11:10:46.000000000 +0200
@@ -29,9 +29,9 @@
         } else {
             unsetenv("TZ");
         }
-        tzset();
         current_timezone = tz;
     }
+    tzset();
 }
 
 void print_time(yajl_gen json_gen, char *buffer, const char *title, const char 
*format, const char *tz, const char *locale, const char *format_time, time_t t) 
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_volume.c 
new/i3status-2.12/src/print_volume.c
--- old/i3status-2.11/src/print_volume.c        2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_volume.c        2018-05-11 11:10:46.000000000 
+0200
@@ -211,6 +211,7 @@
 
 #if defined(__OpenBSD__)
     int oclass_idx = -1, master_idx = -1, master_mute_idx = -1;
+    int master_next = AUDIO_MIXER_LAST;
     mixer_devinfo_t devinfo, devinfo2;
     mixer_ctrl_t vinfo;
 
@@ -228,12 +229,17 @@
 
     devinfo2.index = 0;
     while (ioctl(mixfd, AUDIO_MIXER_DEVINFO, &devinfo2) >= 0) {
-        if ((devinfo2.type == AUDIO_MIXER_VALUE) && (devinfo2.mixer_class == 
oclass_idx) && (strncmp(devinfo2.label.name, AudioNmaster, MAX_AUDIO_DEV_LEN) 
== 0))
+        if ((devinfo2.type == AUDIO_MIXER_VALUE) && (devinfo2.mixer_class == 
oclass_idx) && (strncmp(devinfo2.label.name, AudioNmaster, MAX_AUDIO_DEV_LEN) 
== 0)) {
             master_idx = devinfo2.index;
+            master_next = devinfo2.next;
+        }
 
         if ((devinfo2.type == AUDIO_MIXER_ENUM) && (devinfo2.mixer_class == 
oclass_idx) && (strncmp(devinfo2.label.name, AudioNmute, MAX_AUDIO_DEV_LEN) == 
0))
-            master_mute_idx = devinfo2.index;
+            if (master_next == devinfo2.index)
+                master_mute_idx = devinfo2.index;
 
+        if (master_next != AUDIO_MIXER_LAST)
+            master_next = devinfo2.next;
         devinfo2.index++;
     }
 
@@ -246,6 +252,7 @@
 
     vinfo.dev = master_idx;
     vinfo.type = AUDIO_MIXER_VALUE;
+    vinfo.un.value.num_channels = devinfo.un.v.num_channels;
     if (ioctl(mixfd, AUDIO_MIXER_READ, &vinfo) == -1)
         goto out;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3status-2.11/src/print_wireless_info.c 
new/i3status-2.12/src/print_wireless_info.c
--- old/i3status-2.11/src/print_wireless_info.c 2017-01-21 16:00:31.000000000 
+0100
+++ new/i3status-2.12/src/print_wireless_info.c 2018-05-11 11:10:46.000000000 
+0200
@@ -49,6 +49,7 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
+#include <sys/select.h>
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
@@ -463,6 +464,21 @@
     return 0;
 }
 
+/* Table summarizing what is the decision to prefer IPv4 or IPv6
+ * based their values.
+ *
+ * | ipv4_address | ipv6_address | Chosen IP | Color             |
+ * |--------------|--------------|-----------|-------------------|
+ * | NULL         | NULL         | None      | bad (red)         |
+ * | NULL         | no IP        | IPv6      | degraded (orange) |
+ * | NULL         | ::1/128      | IPv6      | ok (green)        |
+ * | no IP        | NULL         | IPv4      | degraded          |
+ * | no IP        | no IP        | IPv4      | degraded          |
+ * | no IP        | ::1/128      | IPv6      | ok                |
+ * | 127.0.0.1    | NULL         | IPv4      | ok                |
+ * | 127.0.0.1    | no IP        | IPv4      | ok                |
+ * | 127.0.0.1    | ::1/128      | IPv4      | ok                |
+ */
 void print_wireless_info(yajl_gen json_gen, char *buffer, const char 
*interface, const char *format_up, const char *format_down) {
     const char *walk;
     char *outwalk = buffer;
@@ -470,22 +486,48 @@
 
     INSTANCE(interface);
 
-    const char *ip_address = get_ip_addr(interface);
-    if (ip_address == NULL) {
-        START_COLOR("color_bad");
-        outwalk += sprintf(outwalk, "%s", format_down);
-        goto out;
+    char *ipv4_address = sstrdup(get_ip_addr(interface, AF_INET));
+    char *ipv6_address = sstrdup(get_ip_addr(interface, AF_INET6));
+
+    /*
+     * Removing '%' and following characters from IPv6 since the interface 
identifier is redundant,
+     * as the output already includes the interface name.
+    */
+    if (ipv6_address != NULL) {
+        char *prct_ptr = strstr(ipv6_address, "%");
+        if (prct_ptr != NULL) {
+            *prct_ptr = '\0';
+        }
+    }
+
+    bool prefer_ipv4 = true;
+    if (ipv4_address == NULL) {
+        if (ipv6_address == NULL) {
+            START_COLOR("color_bad");
+            outwalk += sprintf(outwalk, "%s", format_down);
+            goto out;
+        } else {
+            prefer_ipv4 = false;
+        }
+    } else if (BEGINS_WITH(ipv4_address, "no IP") && ipv6_address != NULL && 
!BEGINS_WITH(ipv6_address, "no IP")) {
+        prefer_ipv4 = false;
     }
 
-    if (get_wireless_info(interface, &info)) {
+    const char *ip_address = (prefer_ipv4) ? ipv4_address : ipv6_address;
+    if (!get_wireless_info(interface, &info)) {
+        walk = format_down;
+        START_COLOR("color_bad");
+    } else {
         walk = format_up;
         if (info.flags & WIRELESS_INFO_FLAG_HAS_QUALITY)
             START_COLOR((info.quality < info.quality_average ? 
"color_degraded" : "color_good"));
-        else
-            START_COLOR((BEGINS_WITH(ip_address, "no IP") ? "color_degraded" : 
"color_good"));
-    } else {
-        walk = format_down;
-        START_COLOR("color_bad");
+        else {
+            if (BEGINS_WITH(ip_address, "no IP")) {
+                START_COLOR("color_degraded");
+            } else {
+                START_COLOR("color_good");
+            }
+        }
     }
 
     for (; *walk != '\0'; walk++) {
@@ -567,5 +609,7 @@
 
 out:
     END_COLOR;
+    free(ipv4_address);
+    free(ipv6_address);
     OUTPUT_FULL_TEXT(buffer);
 }


Reply via email to