diff --git a/CHANGELOG.md b/CHANGELOG.md index ee54fa13..c89f3b37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([`#2108`](https://github.com/polybar/polybar/issues/2108)) - `internal/xworkspaces`: Make the urgent hint persistent ([`#1081`](https://github.com/polybar/polybar/issues/1081)) +- `internal/network`: `interface-type` may be used in place of `interface` to + automatically select a network interface + ([`#2025`](https://github.com/polybar/polybar/pull/2025)) ### Changed - Slight changes to the value ranges the different ramp levels are responsible diff --git a/include/adapters/net.hpp b/include/adapters/net.hpp index fe73fc76..74ef7cea 100644 --- a/include/adapters/net.hpp +++ b/include/adapters/net.hpp @@ -1,15 +1,15 @@ #pragma once -#include -#include - #include #include +#include +#include + #include "common.hpp" -#include "settings.hpp" -#include "errors.hpp" #include "components/logger.hpp" +#include "errors.hpp" +#include "settings.hpp" #include "utils/math.hpp" #if WITH_LIBNL @@ -38,6 +38,8 @@ namespace net { DEFINE_ERROR(network_error); bool is_wireless_interface(const string& ifname); + std::string find_wireless_interface(); + std::string find_wired_interface(); // types {{{ diff --git a/src/adapters/net.cpp b/src/adapters/net.cpp index 1b1d8e09..99a421ff 100644 --- a/src/adapters/net.cpp +++ b/src/adapters/net.cpp @@ -1,6 +1,7 @@ #include "adapters/net.hpp" #include +#include #include #include #include @@ -9,6 +10,9 @@ #include #include #include +#include + +#include #include @@ -21,14 +25,65 @@ POLYBAR_NS namespace net { + enum class NetType { + WIRELESS, + ETHERNET, + OTHER, + }; + + static const string NO_IP = string("N/A"); + static const string NET_PATH = "/sys/class/net/"; + static const string VIRTUAL_PATH = "/sys/devices/virtual/"; + + static bool is_virtual(const std::string& ifname) { + char* target = realpath((NET_PATH + ifname).c_str(), nullptr); + const std::string real_path{target}; + free(target); + return real_path.rfind(VIRTUAL_PATH, 0) == 0; + } + + NetType iface_type(const std::string& ifname) { + if (file_util::exists(NET_PATH + ifname + "/wireless")) { + return NetType::WIRELESS; + } + + if (is_virtual(ifname)) { + return NetType::OTHER; + } + + return NetType::ETHERNET; + } + /** * Test if interface with given name is a wireless device */ bool is_wireless_interface(const string& ifname) { - return file_util::exists("/sys/class/net/" + ifname + "/wireless"); + return iface_type(ifname) == NetType::WIRELESS; } - static const string NO_IP = string("N/A"); + std::string find_interface(NetType type) { + struct ifaddrs* ifaddrs; + getifaddrs(&ifaddrs); + for (struct ifaddrs* i = ifaddrs; i != nullptr; i = i->ifa_next) { + const std::string name{i->ifa_name}; + const NetType iftype = iface_type(name); + if (iftype != type) { + continue; + } + freeifaddrs(ifaddrs); + return name; + } + freeifaddrs(ifaddrs); + return ""; + } + + std::string find_wireless_interface() { + return find_interface(NetType::WIRELESS); + } + + std::string find_wired_interface() { + return find_interface(NetType::ETHERNET); + } // class : network {{{ @@ -215,7 +270,7 @@ namespace net { * Test if the network interface is in a valid state */ bool network::test_interface() const { - auto operstate = file_util::contents("/sys/class/net/" + m_interface + "/operstate"); + auto operstate = file_util::contents(NET_PATH + m_interface + "/operstate"); bool up = operstate.compare(0, 2, "up") == 0; return m_unknown_up ? (up || operstate.compare(0, 7, "unknown") == 0) : up; } diff --git a/src/modules/network.cpp b/src/modules/network.cpp index ddebde02..4f365710 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -3,9 +3,8 @@ #include "drawtypes/animation.hpp" #include "drawtypes/label.hpp" #include "drawtypes/ramp.hpp" -#include "utils/factory.hpp" - #include "modules/meta/base.inl" +#include "utils/factory.hpp" POLYBAR_NS @@ -16,6 +15,32 @@ namespace modules { : timer_module(bar, move(name_)) { // Load configuration values m_interface = m_conf.get(name(), "interface", m_interface); + + if (m_interface.empty()) { + std::string type = m_conf.get(name(), "interface-type"); + if (type == "wired") { + m_interface = net::find_wired_interface(); + if (!m_interface.empty()) { + m_log.notice("%s: Discovered wired interface %s", name(), m_interface); + } + } else if (type == "wireless") { + m_interface = net::find_wireless_interface(); + if (!m_interface.empty()) { + m_log.notice("%s: Discovered wireless interface %s", name(), m_interface); + } + } else { + throw module_error("Invalid interface type '" + type + "'"); + } + + if (m_interface.empty()) { + throw module_error("No interface found for type '" + type + "'"); + } + } + + if (m_interface.empty()) { + throw module_error("missing 'interface' or 'interface-type'"); + } + m_ping_nth_update = m_conf.get(name(), "ping-interval", m_ping_nth_update); m_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth); m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate); @@ -189,6 +214,6 @@ namespace modules { m_log.trace("%s: Reached end of network subthread", name()); } -} +} // namespace modules POLYBAR_NS_END