hello, The major issue for this update is that upstream started to use wordexp(3) and some workaround are needed. (The added patches are pending upstream.)
The workarounds for wordexp(3) range from manually constructing strings, to using glob(3) and even rolling wordexp(3) inline stealing an idea from musl, as other wordexp(3) implementation required either some helper programs (freebsd) or custom shell flags (glibc/newlib and bash.) The behaviour of the program is not changed except that in the `:open' command: on other systems you should be able to say `:open $(cmd)' or similar stuff with command substitution, here it only supports glob(3). tests from existing users are welcome :) thoughts/ok? Index: Makefile =================================================================== RCS file: /home/cvs/ports/graphics/imv/Makefile,v retrieving revision 1.6 diff -u -p -r1.6 Makefile --- Makefile 11 Mar 2022 19:22:33 -0000 1.6 +++ Makefile 12 Jul 2022 10:26:32 -0000 @@ -1,28 +1,48 @@ -GH_ACCOUNT = eXeC64 -GH_PROJECT = imv -GH_TAGNAME = v2.1.3 - COMMENT = simple image viewer + +V = 4.3.1 +DISTNAME = imv-v$V +PKGNAME = imv-$V + CATEGORIES = graphics x11 -REVISION = 1 + +HOMEPAGE = https://sr.ht/~exec64/imv # GPLv2+ PERMIT_PACKAGE = Yes -WANTLIB += SDL2 SDL2_ttf c fontconfig freeimage pthread +WANTLIB += GL X11 c cairo freeimage gobject-2.0 heif icuuc inih +WANTLIB += m nsgif pango-1.0 pangocairo-1.0 pthread rsvg-2 turbojpeg +WANTLIB += xcb xkbcommon xkbcommon-x11 + +MASTER_SITES = https://git.sr.ht/~exec64/imv/archive/ +DISTFILES = ${DISTNAME}{v$V}${EXTRACT_SUFX} + +MODULES = devel/meson + +CFLAGS += -D_BSD_SOURCE \ + -I${LOCALBASE}/include +LDFLAGS += -L${LOCALBASE}/lib + +MODMESON_CONFIGURE_ENV += LDFLAGS="${LDFLAGS}" + +BUILD_DEPENDS = textproc/asciidoc \ + devel/cmocka + +LIB_DEPENDS = devel/inih \ + devel/pango \ + graphics/freeimage \ + multimedia/libheif \ + textproc/icu4c,-main \ + x11/gnome/librsvg \ + x11/xkbcommon \ + www/netsurf/libnsgif -LIB_DEPENDS = devel/sdl2 \ - devel/sdl2-ttf \ - graphics/freeimage RUN_DEPENDS = devel/desktop-file-utils -TEST_DEPENDS = devel/cmocka - -MAKE_FLAGS += V=1 BUILDDIR="${WRKDIR}/build-${ARCH}" -FAKE_FLAGS += $(MAKE_FLAGS) MANPREFIX=${PREFIX}/man PREFIX=${PREFIX} -USE_GMAKE = Yes +CONFIGURE_ARGS += -Dwindows=x11 -ALL_TARGET = imv -TEST_TARGET = check +post-install: + cd ${DESTDIR} && mv etc/imv_config ${PREFIX}/share/examples/ .include <bsd.port.mk> Index: distinfo =================================================================== RCS file: /home/cvs/ports/graphics/imv/distinfo,v retrieving revision 1.2 diff -u -p -r1.2 distinfo --- distinfo 22 Oct 2016 12:26:46 -0000 1.2 +++ distinfo 12 Jul 2022 08:45:19 -0000 @@ -1,2 +1,2 @@ -SHA256 (imv-2.1.3.tar.gz) = 8Lms18/x0vcwHLXP+yYazk0K8gA9xKKT2aN+cwdJeLc= -SIZE (imv-2.1.3.tar.gz) = 27664 +SHA256 (imv-v4.3.1.tar.gz) = iNFohQF7dLWU3dagPvIClKbMBT8EzMLh7e9p81FfeZk= +SIZE (imv-v4.3.1.tar.gz) = 79123 Index: pkg/PLIST =================================================================== RCS file: /home/cvs/ports/graphics/imv/pkg/PLIST,v retrieving revision 1.3 diff -u -p -r1.3 PLIST --- pkg/PLIST 11 Mar 2022 19:22:33 -0000 1.3 +++ pkg/PLIST 12 Jul 2022 09:48:14 -0000 @@ -1,4 +1,12 @@ @bin bin/imv +bin/imv-folder +@bin bin/imv-msg +@man man/man1/imv-folder.1 +@man man/man1/imv-msg.1 @man man/man1/imv.1 +@man man/man5/imv.5 +share/applications/imv-folder.desktop share/applications/imv.desktop +share/examples/imv_config +@sample ${SYSCONFDIR}/imv_config @tag update-desktop-database Index: patches/patch-meson_build =================================================================== RCS file: patches/patch-meson_build diff -N patches/patch-meson_build --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-meson_build 6 Aug 2022 08:31:46 -0000 @@ -0,0 +1,19 @@ +don't look out for git + +Index: meson.build +--- meson.build.orig ++++ meson.build +@@ -8,13 +8,6 @@ project( + ) + + version = '@0@'.format(meson.project_version()) +-prog_git = find_program('git', required: false) +-if prog_git.found() +- git_description = run_command([prog_git.path(), 'describe', '--dirty', '--always', '--tags']) +- if git_description.returncode() == 0 +- version = git_description.stdout().strip() +- endif +-endif + add_project_arguments('-DIMV_VERSION="@0@"'.format(version), language: 'c') + + add_project_arguments('-D_XOPEN_SOURCE=700', language: 'c') Index: patches/patch-src_imv_c =================================================================== RCS file: patches/patch-src_imv_c diff -N patches/patch-src_imv_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_imv_c 6 Aug 2022 08:31:46 -0000 @@ -0,0 +1,252 @@ +work around wordexp + +Index: src/imv.c +--- src/imv.c.orig ++++ src/imv.c +@@ -1,9 +1,12 @@ + #include "imv.h" + ++#include <sys/wait.h> ++ + #include <assert.h> + #include <ctype.h> + #include <errno.h> + #include <getopt.h> ++#include <glob.h> + #include <limits.h> + #include <pthread.h> + #include <stdbool.h> +@@ -11,7 +14,6 @@ + #include <stdlib.h> + #include <time.h> + #include <unistd.h> +-#include <wordexp.h> + + #include "backend.h" + #include "binds.h" +@@ -1363,40 +1365,6 @@ static void render_window(struct imv *imv) + imv->cache_invalidated = false; + } + +-static char *get_config_path(void) +-{ +- const char *config_paths[] = { +- "$imv_config", +- "$XDG_CONFIG_HOME/imv/config", +- "$HOME/.config/imv/config", +- "$HOME/.imv_config", +- "$HOME/.imv/config", +- "/usr/local/etc/imv_config", +- "/etc/imv_config", +- }; +- +- for (size_t i = 0; i < sizeof(config_paths) / sizeof(char*); ++i) { +- wordexp_t word; +- if (wordexp(config_paths[i], &word, 0) == 0) { +- if (!word.we_wordv[0]) { +- wordfree(&word); +- continue; +- } +- +- char *path = strdup(word.we_wordv[0]); +- wordfree(&word); +- +- if (!path || access(path, R_OK) == -1) { +- free(path); +- continue; +- } +- +- return path; +- } +- } +- return NULL; +-} +- + static bool parse_bool(const char *str) + { + return ( +@@ -1557,26 +1525,80 @@ static int handle_ini_value(void *user, const char *se + return 0; + } + ++static int load_config(const char *path, struct imv *imv) ++{ ++ int err; ++ ++ err = ini_parse(path, handle_ini_value, imv); ++ if (err > 0) ++ imv_log(IMV_ERROR, "Error in config file: %s:%d\n", path, err); ++ return err; ++} ++ + bool imv_load_config(struct imv *imv) + { +- char *path = get_config_path(); +- if (!path) { +- /* no config, no problem - we have defaults */ +- return true; ++ char p[PATH_MAX]; ++ char *t; ++ int err; ++ ++ if ((t = getenv("imv_config")) != NULL) { ++ err = load_config(t, imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; + } + +- bool result = true; ++ if ((t = getenv("XDG_CONFIG_HOME")) != NULL) { ++ if (snprintf(p, sizeof(p), "%s/imv/config", t) < sizeof(p)) { ++ err = load_config(p, imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; ++ } ++ } + +- const int err = ini_parse(path, handle_ini_value, imv); +- if (err == -1) { +- imv_log(IMV_ERROR, "Unable to open config file: %s\n", path); +- result = false; +- } else if (err > 0) { +- imv_log(IMV_ERROR, "Error in config file: %s:%d\n", path, err); +- result = false; ++ if ((t = getenv("HOME")) != NULL) { ++ if (snprintf(p, sizeof(p), "%s/.config/imv/config", t) < sizeof(p)) { ++ err = load_config(p, imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; ++ } ++ ++ if (snprintf(p, sizeof(p), "%s/.imv_config", t) < sizeof(p)) { ++ err = load_config(p, imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; ++ } ++ ++ if (snprintf(p, sizeof(p), "%s/.imv/config", t) < sizeof(p)) { ++ err = load_config(p, imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; ++ } + } +- free(path); +- return result; ++ ++ err = load_config("/usr/local/etc/imv_config", imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; ++ ++ err = load_config("/etc/imv_config", imv); ++ if (err > 0) ++ return false; ++ if (err == 0) ++ return true; ++ ++ /* no config, no problem - we have defaults */ ++ return true; + } + + static void command_quit(struct list *args, const char *argstr, void *data) +@@ -1706,12 +1728,13 @@ static void command_open(struct list *args, const char + continue; + } + +- wordexp_t word; +- if (wordexp(args->items[i], &word, 0) == 0) { +- for (size_t j = 0; j < word.we_wordc; ++j) { +- imv_navigator_add(imv->navigator, word.we_wordv[j], recursive); ++ glob_t g; ++ if (glob(args->items[i], GLOB_BRACE|GLOB_TILDE, NULL, &g) == 0) { ++ char **matches; ++ for (matches = g.gl_pathv; *matches; ++matches) { ++ imv_navigator_add(imv->navigator, *matches, recursive); + } +- wordfree(&word); ++ globfree(&g); + } + } + } +@@ -1941,20 +1964,61 @@ static void update_env_vars(struct imv *imv) + + static size_t generate_env_text(struct imv *imv, char *buf, size_t buf_len, const char *format) + { ++ pid_t pid; ++ int status, p[2]; /* read end, write end */ ++ ++ assert(buf_len > 0); ++ + update_env_vars(imv); + +- size_t len = 0; +- wordexp_t word; +- if (wordexp(format, &word, 0) == 0) { +- for (size_t i = 0; i < word.we_wordc; ++i) { +- len += snprintf(buf + len, buf_len - len, "%s ", word.we_wordv[i]); ++ if (pipe(p) == -1) ++ goto err; ++ ++ switch (pid = fork()) { ++ case -1: ++ close(p[0]); ++ close(p[1]); ++ goto err; ++ case 0: /* child */ ++ close(p[0]); ++ if (dup2(p[1], 1) != -1) { ++ execl("/bin/sh", "sh", "-c", "eval \"printf '%s ' $1\"", "sh", ++ format, (char *)NULL); + } +- wordfree(&word); +- } else { +- len += snprintf(buf, buf_len, "error expanding text"); ++ _exit(1); ++ default: /* parent */ ++ close(p[1]); ++ ++ size_t r, siz = buf_len - 1, tot = 0; ++ do { ++ r = read(p[0], buf, siz); ++ if (r == -1) { ++ goto err; ++ } else if (r == 0) { ++ break; ++ } ++ tot += r; ++ buf += r; ++ siz -= r; ++ } while (siz > 0); ++ ++ buf[tot] = '\0'; ++ while (tot > 0 && isspace((unsigned char)buf[tot-1])) ++ buf[--tot] = '\0'; ++ ++ close(p[0]); ++ ++ pid_t w; ++ do { ++ w = waitpid(pid, &status, 0); ++ } while (w != -1 && errno == EINTR); ++ ++ return tot > 0 ? tot-1 : tot; /* don't count the NUL terminator */ + } + +- return len; ++err: ++ snprintf(buf, buf_len, "error expanding text: %s", strerror(errno)); ++ return strlen(buf); + } + + static size_t read_from_stdin(void **buffer)