Fix OpenBSD build (#2080)

- Fix unclosed OBJ in core.cc when target is OpenBSD
- `to_real_path` changes:
  - Canonicalize result to mimic `realpath` behavior
  - Partially implement `to_real_path` for OpenBSD
  - Add more tests for `to_real_path`.
- Build system improvements:
  - Use same i18n include/link logic for all platforms
  - Replace `HAVE_SOME_SOUNDCARD_H` and `HAVE_LINUX_SOUNDCARD_H` with `HAVE_SOUNDCARD_H`
    and use other defines (__linux__) to guard include
  - Replace `<XXX>_LIBRARIES` with `<XXX>_LINK_LIBRARIES` for linking.
    - Libraries weren't in default linker search path on OpenBSD
- OpenBSD specific:
  - Fix bsdapm.cc
  - Remove diskio stats stubs
  - Stub get_battery_short_status
  - Remove `-stdlib=libc++` build flag on OpenBSD

Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
Co-authored-by: gmb <gmb@openbsd76.my.domain>
Co-authored-by: Tin Švagelj <tin.svagelj@live.com>
This commit is contained in:
Tóth János
2024-11-23 00:45:11 +01:00
committed by GitHub
parent 9449818c4d
commit 47ec9f911c
16 changed files with 386 additions and 189 deletions

View File

@@ -115,7 +115,12 @@ template<> Vc_ALWAYS_INLINE void sincos(const Scalar::Vector<double> &x, Scalar:
#elif Vc_HAS_BUILTIN(__builtin_sincos) || defined Vc_GCC
__builtin_sincos(x.data(), &sin->data(), &cos->data());
#else
::sincos(x.data(), &sin->data(), &cos->data());
#if defined(__OpenBSD__)
sin->data() = ::sin(x.data());
cos->data() = ::cos(x.data());
#else /* OpenBSD */
::sincos(x.data(), &sin->data(), &cos->data());
#endif /* OpenBSD */
#endif
}

View File

@@ -96,13 +96,13 @@ set(conky_includes ${CMAKE_BINARY_DIR})
# enabled! Thus disable this and _LARGEFILE64_SOURCE isnt needed, it is already
# used on macOS.
#
if(NOT OS_DARWIN)
if(NOT OS_DARWIN AND NOT OS_OPENBSD)
add_definitions(-D_LARGEFILE64_SOURCE -D_POSIX_C_SOURCE=200809L) # Standard definitions
set(
CMAKE_REQUIRED_DEFINITIONS
"${CMAKE_REQUIRED_DEFINITIONS} -D_LARGEFILE64_SOURCE -D_POSIX_C_SOURCE=200809L"
)
endif(NOT OS_DARWIN)
endif(NOT OS_DARWIN AND NOT OS_OPENBSD)
if(OS_FREEBSD)
add_definitions(-D__BSD_VISIBLE=1 -D_XOPEN_SOURCE=700)
@@ -117,6 +117,15 @@ if(OS_DRAGONFLY)
set(conky_includes ${conky_includes} -I/usr/pkg/include)
endif(OS_DRAGONFLY)
if(OS_OPENBSD)
# For asprintf
add_definitions(-D_GNU_SOURCE) # Standard definitions
set(
CMAKE_REQUIRED_DEFINITIONS
"${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE"
)
endif(OS_OPENBSD)
if(OS_SOLARIS)
set(conky_libs ${conky_libs} -L/usr/local/lib)
endif(OS_SOLARIS)

View File

@@ -50,12 +50,17 @@ if(MAINTAINER_MODE)
set(BUILD_TESTS true)
endif(MAINTAINER_MODE)
# Always use libc++ when compiling w/ clang
if(NOT OS_OPENBSD)
# Always use libc++ when compiling w/ clang
# Not on OpenBSD because that's the default for its vendored Clang
add_compile_options(
$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>)
add_link_options($<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>)
endif(NOT OS_OPENBSD)
add_compile_options(
$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>
$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-Wno-unknown-warning-option>
$<$<COMPILE_LANG_AND_ID:CXX,GCC>:-Wno-unknown-warning>)
add_link_options($<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>)
option(CHECK_CODE_QUALITY "Check code formatting/quality with clang" false)
@@ -228,6 +233,8 @@ dependent_option(BUILD_LUA_RSVG "Build rsvg bindings for Lua" false
"BUILD_GUI" false
"RSVG Lua bindings depend on BUILD_GUI")
option(BUILD_OPENSOUNDSYS "Build with Open Sound System support" true)
option(BUILD_AUDACIOUS "Build audacious (music player) support" false)
option(BUILD_MPD "Enable if you want MPD (music player) support" true)

View File

@@ -65,7 +65,7 @@ endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(OS_FREEBSD true)
set(conky_libs ${conky_libs} -lkvm -ldevstat -lintl -linotify)
set(conky_libs ${conky_libs} -lkvm -ldevstat -linotify)
if(BUILD_IRC)
set(conky_libs ${conky_libs} -lssl -lcrypto)
@@ -83,6 +83,7 @@ endif(CMAKE_SYSTEM_NAME MATCHES "DragonFly")
if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
set(OS_OPENBSD true)
set(conky_libs ${conky_libs} -lkvm)
else(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
set(OS_OPENBSD false)
endif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
@@ -102,7 +103,7 @@ endif(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
if(CMAKE_SYSTEM_NAME MATCHES "Haiku")
set(OS_HAIKU true)
set(conky_libs ${conky_libs} -lnetwork -lintl)
set(conky_libs ${conky_libs} -lnetwork)
else(CMAKE_SYSTEM_NAME MATCHES "Haiku")
set(OS_HAIKU false)
endif(CMAKE_SYSTEM_NAME MATCHES "Haiku")
@@ -145,42 +146,45 @@ endif(NOT
NOT
OS_DARWIN)
# Check for soundcard header
if(OS_LINUX)
check_include_files("linux/soundcard.h" HAVE_SOME_SOUNDCARD_H)
check_include_files("linux/soundcard.h" HAVE_LINUX_SOUNDCARD_H)
check_include_files("linux/sockios.h" HAVE_LINUX_SOCKIOS_H)
elseif(OS_OPENBSD)
check_include_files("soundcard.h" HAVE_SOME_SOUNDCARD_H)
else(OS_LINUX)
check_include_files("sys/soundcard.h" HAVE_SOME_SOUNDCARD_H)
endif(OS_LINUX)
if(BUILD_I18N AND OS_DRAGONFLY)
set(conky_libs ${conky_libs} -lintl)
endif(BUILD_I18N AND OS_DRAGONFLY)
# Handle Open Sound System
if(BUILD_OPENSOUNDSYS)
if(OS_LINUX)
check_include_files("linux/soundcard.h" HAVE_SOUNDCARD_H)
elseif(OS_OPENBSD)
check_include_files("soundcard.h" HAVE_SOUNDCARD_H)
# OpenBSD (and FreeBSD?) provide emulation layer on top of sndio.
if(HAVE_SOUNDCARD_H)
find_library(OSS_AUDIO_LIB
NAMES ossaudio
PATHS /usr/lib
/usr/local/lib)
set(conky_libs ${conky_libs} ${OSS_AUDIO_LIB})
endif(HAVE_SOUNDCARD_H)
else(OS_LINUX)
check_include_files("sys/soundcard.h" HAVE_SOUNDCARD_H)
endif(OS_LINUX)
endif(BUILD_OPENSOUNDSYS)
if(BUILD_I18N AND OS_DARWIN)
find_path(LIBINTL_H_N libintl.h
PATHS /usr/local/opt/gettext/include
/usr/include
/usr/local/include
/usr/local/opt/include)
if(LIBINTL_H_N)
include_directories(${LIBINTL_H_N})
else(LIBINTL_H_N)
message(FATAL_ERROR "Unable to find libintl.h (try `brew install gettext`)")
endif(LIBINTL_H_N)
if(BUILD_I18N)
include(FindIntl)
find_package(Intl)
find_library(INTL_LIB
NAMES intl
PATHS /usr/local/opt/gettext/lib
/usr/lib
/usr/local/lib
/usr/local/opt/lib)
set(conky_libs ${conky_libs} ${INTL_LIB})
endif(BUILD_I18N AND OS_DARWIN)
if(NOT Intl_FOUND)
if(OS_DARWIN)
message(WARNING "Try running `brew install gettext` for I18N support")
# Should be present by default everywhere else
endif(OS_DARWIN)
message(FATAL_ERROR "Unable to find libintl")
endif(NOT Intl_FOUND)
include_directories(${Intl_INCLUDE_DIRS})
set(conky_libs ${conky_libs} ${Intl_LIBRARIES})
endif(BUILD_I18N)
if(BUILD_NCURSES AND OS_DARWIN)
set(conky_libs ${conky_libs} -lncurses)
@@ -239,7 +243,7 @@ endif(BUILD_IPV6)
if(BUILD_HTTP)
pkg_check_modules(MICROHTTPD REQUIRED libmicrohttpd>=0.9.25)
set(conky_libs ${conky_libs} ${MICROHTTPD_LIBRARIES})
set(conky_libs ${conky_libs} ${MICROHTTPD_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${MICROHTTPD_INCLUDE_DIRS})
endif(BUILD_HTTP)
@@ -468,28 +472,28 @@ if(BUILD_WAYLAND)
if(OS_DARWIN OR OS_DRAGONFLY OR OS_FREEBSD OR OS_NETBSD OR OS_OPENBSD)
pkg_check_modules(EPOLL REQUIRED epoll-shim)
set(conky_libs ${conky_libs} ${EPOLL_LIBRARIES})
set(conky_libs ${conky_libs} ${EPOLL_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${EPOLL_INCLUDE_DIRS})
endif(OS_DARWIN OR OS_DRAGONFLY OR OS_FREEBSD OR OS_NETBSD OR OS_OPENBSD)
pkg_check_modules(CAIRO REQUIRED cairo)
set(conky_libs ${conky_libs} ${CAIRO_LIBRARIES})
set(conky_libs ${conky_libs} ${CAIRO_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${CAIRO_INCLUDE_DIR})
pkg_check_modules(PANGO REQUIRED pango)
set(conky_libs ${conky_libs} ${PANGO_LIBRARIES})
set(conky_libs ${conky_libs} ${PANGO_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${PANGO_INCLUDE_DIRS})
pkg_check_modules(PANGOCAIRO pangocairo)
set(conky_libs ${conky_libs} ${PANGOCAIRO_LIBRARIES})
set(conky_libs ${conky_libs} ${PANGOCAIRO_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${PANGOCAIRO_INCLUDE_DIRS})
pkg_check_modules(PANGOFC pangofc)
set(conky_libs ${conky_libs} ${PANGOFC_LIBRARIES})
set(conky_libs ${conky_libs} ${PANGOFC_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${PANGOFC_INCLUDE_DIRS})
pkg_check_modules(PANGOFT2 pangoft2)
set(conky_libs ${conky_libs} ${PANGOFT2_LIBRARIES})
set(conky_libs ${conky_libs} ${PANGOFT2_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${PANGOFT2_INCLUDE_DIRS})
endif(BUILD_WAYLAND)
@@ -502,12 +506,12 @@ include_directories(3rdparty/toluapp/include)
# Check for libraries used by Lua bindings
if(BUILD_LUA_CAIRO)
pkg_check_modules(CAIRO REQUIRED cairo>=1.14)
set(luacairo_libs ${CAIRO_LIBRARIES} ${LUA_LIBRARIES})
set(luacairo_libs ${CAIRO_LINK_LIBRARIES} ${LUA_LIBRARIES})
set(luacairo_includes ${CAIRO_INCLUDE_DIRS} ${LUA_INCLUDE_DIR})
if(BUILD_LUA_CAIRO_XLIB)
pkg_check_modules(CAIROXLIB REQUIRED cairo-xlib)
set(luacairo_libs ${CAIROXLIB_LIBRARIES} ${luacairo_libs})
set(luacairo_libs ${CAIROXLIB_LINK_LIBRARIES} ${luacairo_libs})
set(luacairo_includes ${CAIROXLIB_INCLUDE_DIRS} ${luacairo_includes})
endif(BUILD_LUA_CAIRO_XLIB)
@@ -529,7 +533,7 @@ endif(BUILD_LUA_IMLIB2)
if(BUILD_LUA_RSVG)
pkg_check_modules(RSVG REQUIRED librsvg-2.0>=2.52)
set(luarsvg_libs ${RSVG_LIBRARIES} ${LUA_LIBRARIES})
set(luarsvg_libs ${RSVG_LINK_LIBRARIES} ${LUA_LIBRARIES})
set(luarsvg_includes ${RSVG_INCLUDE_DIRS} ${LUA_INCLUDE_DIR})
endif(BUILD_LUA_RSVG)
@@ -544,7 +548,7 @@ if(BUILD_AUDACIOUS)
pkg_check_modules(AUDACIOUS REQUIRED audacious<1.4.0)
endif(NEW_AUDACIOUS_FOUND)
set(conky_libs ${conky_libs} ${AUDACIOUS_LIBRARIES} ${DBUS_GLIB_LIBRARIES})
set(conky_libs ${conky_libs} ${AUDACIOUS_LINK_LIBRARIES} ${DBUS_GLIB_LIBRARIES})
set(conky_includes
${conky_includes}
${AUDACIOUS_INCLUDE_DIRS}
@@ -553,7 +557,7 @@ endif(BUILD_AUDACIOUS)
if(BUILD_XMMS2)
pkg_check_modules(XMMS2 REQUIRED xmms2-client>=0.6)
set(conky_libs ${conky_libs} ${XMMS2_LIBRARIES})
set(conky_libs ${conky_libs} ${XMMS2_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${XMMS2_INCLUDE_DIRS})
endif(BUILD_XMMS2)
@@ -593,26 +597,26 @@ endif(BUILD_JOURNAL)
if(BUILD_PULSEAUDIO)
pkg_check_modules(PULSEAUDIO REQUIRED libpulse)
set(conky_libs ${conky_libs} ${PULSEAUDIO_LIBRARIES})
set(conky_libs ${conky_libs} ${PULSEAUDIO_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${PULSEAUDIO_INCLUDE_DIRS})
endif(BUILD_PULSEAUDIO)
if(WANT_CURL)
pkg_check_modules(CURL REQUIRED libcurl)
set(conky_libs ${conky_libs} ${CURL_LIBRARIES})
set(conky_libs ${conky_libs} ${CURL_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${CURL_INCLUDE_DIRS})
endif(WANT_CURL)
# Common libraries
if(WANT_GLIB)
pkg_check_modules(GLIB REQUIRED glib-2.0>=2.36)
set(conky_libs ${conky_libs} ${GLIB_LIBRARIES})
set(conky_libs ${conky_libs} ${GLIB_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${GLIB_INCLUDE_DIRS})
endif(WANT_GLIB)
if(WANT_CURL)
pkg_check_modules(CURL REQUIRED libcurl)
set(conky_libs ${conky_libs} ${CURL_LIBRARIES})
set(conky_libs ${conky_libs} ${CURL_LINK_LIBRARIES})
set(conky_includes ${conky_includes} ${CURL_INCLUDE_DIRS})
endif(WANT_CURL)

View File

@@ -29,8 +29,7 @@
#cmakedefine HAVE_SYS_INOTIFY_H 1
#cmakedefine HAVE_DIRENT_H 1
#cmakedefine HAVE_SOME_SOUNDCARD_H 1
#cmakedefine HAVE_LINUX_SOUNDCARD_H 1
#cmakedefine HAVE_SOUNDCARD_H 1
#cmakedefine HAVE_STRNDUP 1

View File

@@ -189,10 +189,10 @@ if(OS_DARWIN)
endif(OS_DARWIN)
# Optional sources
if(HAVE_SOME_SOUNDCARD_H)
if(HAVE_SOUNDCARD_H)
set(mixer mixer.cc mixer.h)
set(optional_sources ${optional_sources} ${mixer})
endif(HAVE_SOME_SOUNDCARD_H)
endif(HAVE_SOUNDCARD_H)
if(BUILD_AUDACIOUS)
set(audacious audacious.cc audacious.h)

View File

@@ -27,15 +27,21 @@
*
*/
#include <fcntl.h>
#include <machine/apm_bios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "config.h"
#include "conky.h"
#include "text_object.h"
#define APMDEV "/dev/apm"
#define APM_UNKNOWN 255
#if defined(__OpenBSD__)
#include <machine/apmvar.h>
#else
#include <machine/apm_bios.h>
#endif
const char *APMDEV = "/dev/apm";
const u_int APM_UNKNOWN = 255;
#ifndef APM_AC_OFF
#define APM_AC_OFF 0
@@ -49,27 +55,26 @@
#define APM_BATT_CHARGING 3
#endif
static int apm_getinfo(int fd, apm_info_t aip) {
#ifdef __OpenBSD__
if (ioctl(fd, APM_IOC_GETPOWER, aip) == -1) {
const u_long GET_APM_INFO = APM_IOC_GETPOWER;
using apm_info = apm_power_info;
#define seconds_left minutes_left * 1000
#else
if (ioctl(fd, APMIO_GETINFO, aip) == -1) {
const u_long GET_APM_INFO = APMIO_GETINFO;
#define ac_state ai_acline
#define battery_state ai_batt_stat
#define battery_life ai_batt_life
#define seconds_left ai_batt_time
#endif
return -1;
}
return 0;
static bool apm_getinfo(int fd, apm_info *aip) {
return ioctl(fd, GET_APM_INFO, aip) == -1;
}
void print_apm_adapter(struct text_object *obj, char *p,
unsigned int p_max_size) {
int fd;
const char *out;
#ifdef __OpenBSD__
struct apm_power_info a_info;
#else
struct apm_info a_info;
#endif
apm_info info;
(void)obj;
@@ -79,25 +84,20 @@ void print_apm_adapter(struct text_object *obj, char *p,
return;
}
if (apm_getinfo(fd, &a_info) != 0) {
if (!apm_getinfo(fd, &info)) {
close(fd);
snprintf(p, p_max_size, "%s", "ERR");
return;
}
close(fd);
#ifdef __OpenBSD__
#define ai_acline ac_state
#endif
switch (a_info.ai_acline) {
const char *out;
switch (info.ac_state) {
case APM_AC_OFF:
out = "off-line";
break;
case APM_AC_ON:
#ifdef __OpenBSD__
#define ai_batt_stat battery_state
#endif
if (a_info.ai_batt_stat == APM_BATT_CHARGING) {
if (info.battery_state == APM_BATT_CHARGING) {
out = "charging";
} else {
out = "on-line";
@@ -113,13 +113,7 @@ void print_apm_adapter(struct text_object *obj, char *p,
void print_apm_battery_life(struct text_object *obj, char *p,
unsigned int p_max_size) {
int fd;
u_int batt_life;
const char *out;
#ifdef __OpenBSD__
struct apm_power_info a_info;
#else
struct apm_info a_info;
#endif
apm_info info;
(void)obj;
@@ -129,40 +123,33 @@ void print_apm_battery_life(struct text_object *obj, char *p,
return;
}
if (apm_getinfo(fd, &a_info) != 0) {
if (!apm_getinfo(fd, &info)) {
close(fd);
snprintf(p, p_max_size, "%s", "ERR");
return;
}
close(fd);
#ifdef __OpenBSD__
#define ai_batt_life battery_life
#endif
batt_life = a_info.ai_batt_life;
if (batt_life == APM_UNKNOWN) {
out = "unknown";
} else if (batt_life <= 100) {
snprintf(p, p_max_size, "%d%%", batt_life);
if (info.battery_life <= 100) {
snprintf(p, p_max_size, "%d%%", info.battery_life);
return;
}
const char *out;
if (info.battery_life == APM_UNKNOWN) {
out = "unknown";
} else {
out = "ERR";
}
snprintf(p, p_max_size, "%s", out);
}
void print_apm_battery_time(struct text_object *obj, char *p,
unsigned int p_max_size) {
int fd;
int batt_time;
#ifdef __OpenBSD__
int h, m;
struct apm_power_info a_info;
#else
int h, m, s;
struct apm_info a_info;
#endif
apm_info info;
(void)obj;
@@ -172,29 +159,17 @@ void print_apm_battery_time(struct text_object *obj, char *p,
return;
}
if (apm_getinfo(fd, &a_info) != 0) {
if (!apm_getinfo(fd, &info)) {
close(fd);
snprintf(p, p_max_size, "%s", "ERR");
return;
}
close(fd);
#ifdef __OpenBSD__
#define ai_batt_time minutes_left
#endif
batt_time = a_info.ai_batt_time;
int batt_time = info.seconds_left;
if (batt_time == -1) {
snprintf(p, p_max_size, "%s", "unknown");
} else
#ifdef __OpenBSD__
{
h = batt_time / 60;
m = batt_time % 60;
snprintf(p, p_max_size, "%2d:%02d", h, m);
}
#else
{
} else {
h = batt_time;
s = h % 60;
h /= 60;
@@ -202,5 +177,4 @@ void print_apm_battery_time(struct text_object *obj, char *p,
h /= 60;
snprintf(p, p_max_size, "%2d:%02d:%02d", h, m, s);
}
#endif
}

View File

@@ -27,18 +27,23 @@
*
*/
#include "common.h"
#include <fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <pthread.h>
#include <pwd.h>
#include <semaphore.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cctype>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <wordexp.h>
#include "config.h"
#include "conky.h"
#include "core.h"
@@ -51,6 +56,10 @@
#include "timeinfo.h"
#include "top.h"
#if defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
#include <wordexp.h>
#endif
/* check for OS and include appropriate headers */
#if defined(__linux__)
#include "linux.h"
@@ -130,21 +139,55 @@ double get_time() {
return tv.tv_sec + (tv.tv_nsec * 1e-9);
}
/* Converts '~/...' paths to '/home/blah/...'. It's similar to
* variable_substitute, works for any enviroment variable */
std::string to_real_path(const std::string &source) {
wordexp_t p;
char **w;
int i;
const char *csource = source.c_str();
if (wordexp(csource, &p, 0) != 0) {
return nullptr;
}
w = p.we_wordv;
const char *resolved_path = strdup(w[0]);
wordfree(&p);
return std::string(resolved_path);
#if defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
std::filesystem::path to_real_path(const std::string &source) {
wordexp_t p;
char **w;
int i;
const char *csource = source.c_str();
if (wordexp(csource, &p, 0) != 0) {
return std::string();
}
w = p.we_wordv;
const char *resolved_path = strdup(w[0]);
wordfree(&p);
return std::filesystem::weakly_canonical(resolved_path);
}
#else
// TODO: Use this implementation once it's finished.
// `wordexp` calls shell which is inconsistent across different environments.
std::filesystem::path to_real_path(const std::string &source) {
/*
Wordexp (via default shell) does:
- [x] tilde substitution `~`
- [x] variable substitution (via `variable_substitute`)
- [ ] command substitution `$(command)`
- exec.cc does execution already; missing recursive descent parser for
$(...) because they can be nested and mixed with self & other expressions
from this list
- [ ] [arithmetic
expansion](https://www.gnu.org/software/bash/manual/html_node/Arithmetic-Expansion.html)
`$((10 + 2))`
- would be nice to have for other things as well, could possibly use lua and
replace stuff like $VAR and $(...) with equivalent functions.
- [ ] [field
splitting](https://www.gnu.org/software/bash/manual/html_node/Word-Splitting.html)
- [ ] wildcard expansion
- [ ] quote removal Extra:
- canonicalization added
*/
try {
std::string input = tilde_expand(source);
std::string expanded = variable_substitute(input);
std::filesystem::path absolute = std::filesystem::absolute(expanded);
return std::filesystem::weakly_canonical(absolute);
} catch (const std::filesystem::filesystem_error &e) {
// file not found or permission issues
NORM_ERR("can't canonicalize path: %s", source.c_str());
return source;
}
}
#endif
int open_fifo(const char *file, int *reported) {
int fd = 0;
@@ -178,6 +221,103 @@ FILE *open_file(const char *file, int *reported) {
return fp;
}
std::filesystem::path get_cwd() {
char *cwd;
char buffer[1024];
// Attempt to get the current working directory
cwd = getcwd(buffer, sizeof(buffer));
if (cwd == NULL) {
const char *error;
perror(error);
NORM_ERR("can't get conky current working directory: %s", error);
DBGP("returning '.' as PWD"); // hope things work out well
return std::string(".");
}
return std::string(buffer);
}
std::string current_username() {
const char *user = std::getenv("USER");
if (!user) {
NORM_ERR(
"can't determine current user (USER environment variable not set)");
return std::string();
}
return std::string(user);
}
std::optional<std::filesystem::path> user_home(const std::string &username) {
if (username == current_username()) {
const char *home = std::getenv("HOME");
if (home) { return std::filesystem::path(home); }
}
struct passwd *pw = getpwnam(username.c_str());
if (!pw) {
DBGP(
"can't determine HOME directory for user %s (neither w/ HOME nor "
"getpwnam)",
username.c_str());
return std::nullopt;
}
return std::filesystem::path(pw->pw_dir);
}
std::optional<std::filesystem::path> user_home() {
return user_home(current_username());
}
std::string tilde_expand(const std::string &unexpanded) {
if (unexpanded.compare(0, 1, "~") != 0) { return unexpanded; }
if (unexpanded.length() == 1) {
auto home = user_home();
if (home->empty()) {
NORM_ERR(
"can't expand '~' path because user_home couldn't locate home "
"directory");
return unexpanded;
}
return home.value();
}
char next = unexpanded.at(1);
if (next == '/') {
auto home = user_home();
if (home->empty()) {
NORM_ERR(
"can't expand '~' path because user_home couldn't locate home "
"directory");
return unexpanded;
}
return home.value().string() + unexpanded.substr(1);
}
if (next == '+') { return get_cwd().string() + unexpanded.substr(2); }
// if (next == '-') {
// auto oldpwd = std::getenv("OLDPWD");
// if (oldpwd == nullptr) {
// return unexpanded;
// }
// return std::string(oldpwd) + unexpanded.substr(2);
// }
// ~+/-N is tied to bash functionality
if (std::isalpha(next)) { // handles ~USERNAME
auto name_end = unexpanded.find_first_of('/', 1);
std::string name;
if (name_end == std::string::npos) {
name = unexpanded.substr(1);
name_end = unexpanded.length();
} else {
name = unexpanded.substr(1, name_end - 1);
}
auto home = user_home(name);
if (home->empty()) { return unexpanded; }
return home.value().string() + unexpanded.substr(name_end);
}
return unexpanded;
}
std::string variable_substitute(std::string s) {
std::string::size_type pos = 0;
while ((pos = s.find('$', pos)) != std::string::npos) {

View File

@@ -29,7 +29,10 @@
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <filesystem>
#include <optional>
#include <string>
#include "setting.hh"
#include "text_object.h"
@@ -58,11 +61,27 @@ struct process *get_first_process(void);
void get_cpu_count(void);
double get_time(void);
/* Converts '~/...' paths to '/home/blah/...'. It's similar to
* variable_substitute, works for any enviroment variable */
std::string to_real_path(const std::string &source);
/// @brief Handles environment variable expansion in paths and canonicalization.
///
/// Examples:
/// - `~/conky` -> `/home/conky_user/conky`
/// - `$HOME/conky` -> `/home/conky_user/conky`
/// - `$HOME/a/b/../c/../../conky` -> `/home/conky_user/conky`
std::filesystem::path to_real_path(const std::string &source);
FILE *open_file(const char *file, int *reported);
int open_fifo(const char *file, int *reported);
/// Returns current working directory of conky.
std::filesystem::path get_cwd();
/// Returns the username of user/account that started conky.
std::string current_username();
/// Returns home directory of user with `username`.
std::optional<std::filesystem::path> user_home(const std::string &username);
/// Returns home directory of user with `current_username`.
std::optional<std::filesystem::path> user_home();
/// Performs tilde expansion on a path-like string and returns the result.
std::string tilde_expand(const std::string &unexpanded);
/// Performs variable substitution on a string and returns the result.
std::string variable_substitute(std::string s);
void format_seconds(char *buf, unsigned int n, long seconds);

View File

@@ -432,8 +432,9 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
}
obj->callbacks.print = &print_acpiacadapter;
obj->callbacks.free = &gen_free_opaque;
END
#endif /* !__OpenBSD__ */
END OBJ(freq, nullptr) get_cpu_count();
OBJ(freq, nullptr) get_cpu_count();
if ((arg == nullptr) || strlen(arg) >= 3 ||
strtol(&arg[0], nullptr, 10) == 0 ||
static_cast<unsigned int>(strtol(&arg[0], nullptr, 10)) >
@@ -1246,7 +1247,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
END OBJ(memwithbuffersgraph, &update_meminfo) scan_graph(obj, arg, 1, FALSE);
obj->callbacks.graphval = &mem_with_buffers_barval;
#endif /* BUILD_GUI*/
#ifdef HAVE_SOME_SOUNDCARD_H
#ifdef HAVE_SOUNDCARD_H
END OBJ(mixer, 0) parse_mixer_arg(obj, arg);
obj->callbacks.percentage = &mixer_percentage;
END OBJ(mixerl, 0) parse_mixer_arg(obj, arg);
@@ -1261,7 +1262,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
obj->callbacks.barval = &mixerr_barval;
END OBJ_IF(if_mixer_mute, 0) parse_mixer_arg(obj, arg);
obj->callbacks.iftest = &check_mixer_muted;
#endif /* HAVE_SOME_SOUNDCARD_H */
#endif /* HAVE_SOUNDCARD_H */
#ifdef BUILD_GUI
END OBJ(monitor, nullptr) obj->callbacks.print = &print_monitor;
END OBJ(monitor_number, nullptr) obj->callbacks.print = &print_monitor_number;

View File

@@ -49,6 +49,8 @@
#if defined(__FreeBSD__)
#include "freebsd.h"
#elif defined(__OpenBSD__)
#include "openbsd.h"
#elif defined(__DragonFly__)
#include "dragonfly.h"
#elif defined(__HAIKU__)

View File

@@ -124,9 +124,9 @@ static void print_version() {
#ifdef BUILD_IMLIB2
<< _(" * Imlib2\n")
#endif /* BUILD_IMLIB2 */
#ifdef HAVE_SOME_SOUNDCARD_H
#ifdef HAVE_SOUNDCARD_H
<< _(" * OSS mixer support\n")
#endif /* HAVE_SOME_SOUNDCARD_H */
#endif /* HAVE_SOUNDCARD_H */
#ifdef BUILD_MIXER_ALSA
<< _(" * ALSA mixer support\n")
#endif /* BUILD_MIXER_ALSA */

View File

@@ -36,15 +36,15 @@
#include "specials.h"
#include "text_object.h"
#ifdef HAVE_LINUX_SOUNDCARD_H
#ifdef HAVE_SOUNDCARD_H
#if defined(__linux__)
#include <linux/soundcard.h>
#else
#ifdef __OpenBSD__
#elif defined(__OpenBSD__)
#include <soundcard.h>
#else
#include <sys/soundcard.h>
#endif /* __OpenBSD__ */
#endif /* HAVE_LINUX_SOUNDCARD_H */
#endif
#endif /* HAVE_SOUNDCARD_H */
#if defined(__sun)
#include <stropts.h>

View File

@@ -28,11 +28,11 @@
*/
#include <kvm.h>
#include <sys/dkstat.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/proc.h>
#include <sys/sensors.h>
#include <sys/socket.h>
#include <sys/swap.h>
@@ -62,6 +62,7 @@
#include "logging.h"
#include "net_stat.h"
#include "openbsd.h"
#include "temphelper.h"
#include "top.h"
#define MAXSHOWDEVS 16
@@ -69,6 +70,13 @@
#define LOG1024 10
#define pagetok(size) ((size) << pageshift)
#define CP_USER 0
#define CP_NICE 1
#define CP_SYS 2
#define CP_INTR 3
#define CP_IDLE 4
#define CPUSTATES 5
inline void proc_find_top(struct process **cpu, struct process **mem);
static short cpu_setup = 0;
@@ -103,7 +111,7 @@ static int swapmode(int *used, int *total) {
nswap = swapctl(SWAP_NSWAP, 0, 0);
if (nswap == 0) { return 0; }
swdev = malloc(nswap * sizeof(*swdev));
swdev = (struct swapent *)malloc(nswap * sizeof(*swdev));
if (swdev == nullptr) { return 0; }
rnswap = swapctl(SWAP_STATS, swdev, nswap);
@@ -132,7 +140,7 @@ int check_mount(struct text_object *obj) {
return 0;
}
void update_uptime() {
int update_uptime() {
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
struct timeval boottime;
time_t now;
@@ -146,9 +154,11 @@ void update_uptime() {
NORM_ERR("Could not get uptime");
info.uptime = 0;
}
return 0;
}
void update_meminfo() {
int update_meminfo() {
static int mib[2] = {CTL_VM, VM_METER};
struct vmtotal vmtotal;
size_t size;
@@ -185,9 +195,11 @@ void update_meminfo() {
info.swap = 0;
info.swapfree = 0;
}
return 0;
}
void update_net_stats() {
int update_net_stats() {
struct net_stat *ns;
double delta;
long long r, t, last_recv, last_trans;
@@ -196,9 +208,9 @@ void update_net_stats() {
/* get delta */
delta = current_update_time - last_update_time;
if (delta <= 0.0001) { return; }
if (delta <= 0.0001) { return 0; }
if (getifaddrs(&ifap) < 0) { return; }
if (getifaddrs(&ifap) < 0) { return 0; }
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
ns = get_net_stat((const char *)ifa->ifa_name, nullptr, NULL);
@@ -249,33 +261,36 @@ void update_net_stats() {
}
freeifaddrs(ifap);
return 0;
}
int update_total_processes() {
int n_processes;
kvm_init();
kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes);
kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &n_processes);
info.procs = n_processes;
return 0;
}
void update_running_processes() {
struct kinfo_proc2 *p;
int update_running_processes() {
struct kinfo_proc *p;
int n_processes;
int i, cnt = 0;
kvm_init();
int max_size = sizeof(struct kinfo_proc2);
int max_size = sizeof(struct kinfo_proc);
p = kvm_getproc2(kd, KERN_PROC_ALL, 0, max_size, &n_processes);
p = kvm_getprocs(kd, KERN_PROC_ALL, 0, max_size, &n_processes);
for (i = 0; i < n_processes; i++) {
if (p[i].p_stat == SRUN) { cnt++; }
}
info.run_procs = cnt;
return 0;
}
/* new SMP code can be enabled by commenting the following line */
@@ -309,7 +324,7 @@ void get_cpu_count() {
#endif
info.cpu_count = cpu_count;
info.cpu_usage = malloc(info.cpu_count * sizeof(float));
info.cpu_usage = (float *)malloc(info.cpu_count * sizeof(float));
if (info.cpu_usage == nullptr) { CRIT_ERR("malloc"); }
#ifndef OLDCPU
@@ -321,7 +336,7 @@ void get_cpu_count() {
#endif
}
void update_cpu_usage() {
int update_cpu_usage() {
#ifdef OLDCPU
int mib[2] = {CTL_KERN, KERN_CPTIME};
long used, total;
@@ -401,12 +416,14 @@ void update_cpu_usage() {
oldtotal[i] = total;
}
#endif
return 0;
}
void free_cpu(struct text_object *) { /* no-op */
}
void update_load_average() {
int update_load_average() {
double v[3];
getloadavg(v, 3);
@@ -414,8 +431,11 @@ void update_load_average() {
info.loadavg[0] = (float)v[0];
info.loadavg[1] = (float)v[1];
info.loadavg[2] = (float)v[2];
return 0;
}
#define MAXSENSORDEVICES 128
#define OBSD_MAX_SENSORS 256
static struct obsd_sensors_struct {
int device;
@@ -428,7 +448,7 @@ static conky::simple_config_setting<int> sensor_device("sensor_device", 0,
false);
/* read sensors from sysctl */
void update_obsd_sensors() {
int update_obsd_sensors() {
int sensor_cnt, dev, numt, mib[5] = {CTL_HW, HW_SENSORS, 0, 0, 0};
struct sensor sensor;
struct sensordev sensordev;
@@ -446,10 +466,11 @@ void update_obsd_sensors() {
mib[2] = dev;
if (sysctl(mib, 3, &sensordev, &sdlen, nullptr, 0) == -1) {
if (errno != ENOENT) { warn("sysctl"); }
return;
return 0;
// continue;
}
for (type = 0; type < SENSOR_MAX_TYPES; type++) {
for (int t = 0; t < SENSOR_MAX_TYPES; t++) {
type = (enum sensor_type) t;
mib[3] = type;
for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
mib[4] = numt;
@@ -480,6 +501,8 @@ void update_obsd_sensors() {
/* } */
init_sensors = 1;
return 0;
}
void parse_obsd_sensor(struct text_object *obj, const char *arg) {
@@ -491,21 +514,24 @@ void parse_obsd_sensor(struct text_object *obj, const char *arg) {
obj->data.l = atoi(&arg[0]);
}
void print_obsd_sensors_temp(struct text_object *obj, char *p, int p_max_size) {
void print_obsd_sensors_temp(struct text_object *obj, char *p,
unsigned int p_max_size) {
obsd_sensors.device = sensor_device.get(*state);
update_obsd_sensors();
temp_print(p, p_max_size, obsd_sensors.temp[obsd_sensors.device][obj->data.l],
TEMP_CELSIUS, 1);
}
void print_obsd_sensors_fan(struct text_object *obj, char *p, int p_max_size) {
void print_obsd_sensors_fan(struct text_object *obj, char *p,
unsigned int p_max_size) {
obsd_sensors.device = sensor_device.get(*state);
update_obsd_sensors();
snprintf(p, p_max_size, "%d",
obsd_sensors.fan[obsd_sensors.device][obj->data.l]);
}
void print_obsd_sensors_volt(struct text_object *obj, char *p, int p_max_size) {
void print_obsd_sensors_volt(struct text_object *obj, char *p,
unsigned int p_max_size) {
obsd_sensors.device = sensor_device.get(*state);
update_obsd_sensors();
snprintf(p, p_max_size, "%.2f",
@@ -514,7 +540,7 @@ void print_obsd_sensors_volt(struct text_object *obj, char *p, int p_max_size) {
/* chipset vendor */
void get_obsd_vendor(struct text_object *obj, char *buf,
size_t client_buffer_size) {
unsigned int client_buffer_size) {
int mib[2];
char vendor[64];
size_t size = sizeof(vendor);
@@ -534,7 +560,7 @@ void get_obsd_vendor(struct text_object *obj, char *buf,
/* chipset name */
void get_obsd_product(struct text_object *obj, char *buf,
size_t client_buffer_size) {
unsigned int client_buffer_size) {
int mib[2];
char product[64];
size_t size = sizeof(product);
@@ -628,38 +654,40 @@ cleanup:
}
#endif
void clear_diskio_stats() {}
struct diskio_stat *prepare_diskio_stat(const char *s) {}
void update_diskio() { return; /* XXX: implement? hifi: not sure how */ }
int update_diskio() { return 0; /* XXX: implement? hifi: not sure how */ }
/* While topless is obviously better, top is also not bad. */
void get_top_info(void) {
struct kinfo_proc2 *p;
struct kinfo_proc *p;
struct process *proc;
int n_processes;
int i;
kvm_init();
p = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
p = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc),
&n_processes);
for (i = 0; i < n_processes; i++) {
if (!((p[i].p_flag & P_SYSTEM)) && p[i].p_comm != nullptr) {
proc = find_process(p[i].p_pid);
if (!proc) proc = new_process(p[i].p_pid);
if (!((p[i].p_flag & P_SYSTEM)) && p[i].p_comm[0] != 0) {
proc = get_process(p[i].p_pid);
if (!proc) continue;
proc->time_stamp = g_time;
proc->name = strndup(p[i].p_comm, text_buffer_size);
proc->name = strndup(p[i].p_comm, DEFAULT_TEXT_BUFFER_SIZE);
proc->amount = 100.0 * p[i].p_pctcpu / FSCALE;
/* TODO: vsize, rss, total_cpu_time */
}
}
}
void get_battery_short_status(char *buffer, unsigned int n, const char *bat) {
/* Not implemented */
(void)bat;
if (buffer && n > 0) memset(buffer, 0, n);
}
/* empty stubs so conky links */
void prepare_update() {}

View File

@@ -7,16 +7,19 @@
#include <sys/param.h>
#include <sys/sensors.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/mount.h>
#include "common.h"
void parse_obsd_sensor(struct text_object *, const char *);
void print_obsd_sensors_temp(struct text_object *, char *, int);
void print_obsd_sensors_fan(struct text_object *, char *, int);
void print_obsd_sensors_volt(struct text_object *, char *, int);
void print_obsd_sensors_temp(struct text_object *, char *, unsigned int);
void print_obsd_sensors_fan(struct text_object *, char *, unsigned int);
void print_obsd_sensors_volt(struct text_object *, char *, unsigned int);
void get_obsd_vendor(struct text_object *, char *buf,
size_t client_buffer_size);
unsigned int client_buffer_size);
void get_obsd_product(struct text_object *, char *buf,
size_t client_buffer_size);
unsigned int client_buffer_size);
#if defined(i386) || defined(__i386__)
typedef struct apm_power_info *apm_info_t;

View File

@@ -65,7 +65,13 @@ std::string get_invalid_environment_variable_name() {
return variable_name;
}
TEST_CASE("to_real_path becomes homedir", "[to_real_path]") {
TEST_CASE("to_real_path simplifies complex paths", "[to_real_path]") {
REQUIRE(to_real_path("/a/b/c/../d/../../e") == "/a/e");
}
TEST_CASE("to_real_path resolves variables", "[to_real_path]") {
REQUIRE(to_real_path("$HOME/test") == std::string(getenv("HOME")) + "/test");
}
TEST_CASE("to_real_path resolves `~` symbol", "[to_real_path]") {
REQUIRE(to_real_path("~/test") == std::string(getenv("HOME")) + "/test");
}